@@ -903,6 +903,152 @@ describe("PrometheusFormatter", () => {
903903 } ) ;
904904 } ) ;
905905
906+ describe ( "encoding" , ( ) => {
907+ let metrics : MetricsImpl ;
908+ let formatter : PrometheusFormatterImpl ;
909+
910+ beforeEach ( ( ) => {
911+ metrics = new MetricsImpl ( { enableInternalMetrics : false } ) ;
912+ formatter = new PrometheusFormatterImpl ( metrics ) ;
913+ } ) ;
914+
915+ describe ( "label values" , ( ) => {
916+ it ( "should escape double quotes" , async ( ) => {
917+ // Arrange
918+ const counter = metrics . createCounter ( "counter" , "description" ) ;
919+ counter . increment ( { key : 'value"with"double"quotes' } , 5 ) ;
920+
921+ // Act
922+ const stream = formatter . writeMetrics ( ) ;
923+ const result = await consumeAsyncStringGenerator ( stream ) ;
924+
925+ // Assert
926+ expect ( result ) . toBe ( dedent `
927+ # HELP counter description
928+ # TYPE counter counter
929+ counter{key="value\"with\"double\"quotes"} 5\n
930+ ` ) ;
931+ } ) ;
932+
933+ it ( "should escape backslashes" , async ( ) => {
934+ // Arrange
935+ const counter = metrics . createCounter ( "counter" , "description" ) ;
936+ counter . increment ( { key : "value\\with\\backslashes" } , 5 ) ;
937+
938+ // Act
939+ const stream = formatter . writeMetrics ( ) ;
940+ const result = await consumeAsyncStringGenerator ( stream ) ;
941+
942+ // Assert
943+ expect ( result ) . toBe ( dedent `
944+ # HELP counter description
945+ # TYPE counter counter
946+ counter{key="value\\with\\backslashes"} 5\n
947+ ` ) ;
948+ } ) ;
949+
950+ it ( "should escape newlines" , async ( ) => {
951+ // Arrange
952+ const counter = metrics . createCounter ( "counter" , "description" ) ;
953+ counter . increment ( { key : "value\nwith\nnewlines" } , 5 ) ;
954+
955+ // Act
956+ const stream = formatter . writeMetrics ( ) ;
957+ const result = await consumeAsyncStringGenerator ( stream ) ;
958+
959+ // Assert
960+ expect ( result ) . toBe (
961+ dedent ( `
962+ # HELP counter description
963+ # TYPE counter counter
964+ counter{key="value\\nwith\\nnewlines"} 5` ) + "\n" ,
965+ ) ;
966+ } ) ;
967+
968+ it ( "should replace undefined values with empty strings" , async ( ) => {
969+ // Arrange
970+ const counter = metrics . createCounter ( "counter" , "description" ) ;
971+ counter . increment ( { key : undefined } , 5 ) ;
972+
973+ // Act
974+ const stream = formatter . writeMetrics ( ) ;
975+ const result = await consumeAsyncStringGenerator ( stream ) ;
976+
977+ // Assert
978+ expect ( result ) . toBe ( dedent `
979+ # HELP counter description
980+ # TYPE counter counter
981+ counter{key=""} 5\n` ) ;
982+ } ) ;
983+
984+ it ( "should throw error if label value is not a string" , async ( ) => {
985+ // Arrange
986+ const counter = metrics . createCounter ( "counter" , "description" ) ;
987+
988+ // @ts -expect-error - label value is not a string
989+ counter . increment ( { key : null } , 5 ) ;
990+
991+ // Act
992+ const stream = formatter . writeMetrics ( ) ;
993+
994+ // Assert
995+ await expect ( consumeAsyncStringGenerator ( stream ) ) . rejects . toThrow ( ) ;
996+ } ) ;
997+ } ) ;
998+
999+ describe ( "metric values" , ( ) => {
1000+ it ( "should encode NaN" , async ( ) => {
1001+ // Arrange
1002+ const gauge = metrics . createGauge ( "gauge" , "description" ) ;
1003+ gauge . set ( NaN ) ;
1004+ // Act
1005+ const stream = formatter . writeMetrics ( ) ;
1006+ const result = await consumeAsyncStringGenerator ( stream ) ;
1007+
1008+ // Assert
1009+ expect ( result ) . toBe ( dedent `
1010+ # HELP gauge description
1011+ # TYPE gauge gauge
1012+ gauge NaN\n
1013+ ` ) ;
1014+ } ) ;
1015+
1016+ it ( "should encode Infinity" , async ( ) => {
1017+ // Arrange
1018+ const gauge = metrics . createGauge ( "gauge" , "description" ) ;
1019+ gauge . set ( Infinity ) ;
1020+
1021+ // Act
1022+ const stream = formatter . writeMetrics ( ) ;
1023+ const result = await consumeAsyncStringGenerator ( stream ) ;
1024+
1025+ // Assert
1026+ expect ( result ) . toBe ( dedent `
1027+ # HELP gauge description
1028+ # TYPE gauge gauge
1029+ gauge +Inf\n
1030+ ` ) ;
1031+ } ) ;
1032+
1033+ it ( "should encode -Infinity" , async ( ) => {
1034+ // Arrange
1035+ const gauge = metrics . createGauge ( "gauge" , "description" ) ;
1036+ gauge . set ( - Infinity ) ;
1037+
1038+ // Act
1039+ const stream = formatter . writeMetrics ( ) ;
1040+ const result = await consumeAsyncStringGenerator ( stream ) ;
1041+
1042+ // Assert
1043+ expect ( result ) . toBe ( dedent `
1044+ # HELP gauge description
1045+ # TYPE gauge gauge
1046+ gauge -Inf\n
1047+ ` ) ;
1048+ } ) ;
1049+ } ) ;
1050+ } ) ;
1051+
9061052 describe ( "async collect" , ( ) => {
9071053 let metrics : MetricsImpl ;
9081054 let formatter : PrometheusFormatterImpl ;
0 commit comments