Skip to content

Commit 748b190

Browse files
authored
Fix escaping (#1668)
Fixes #1666 --------- Signed-off-by: Gregor Zeitlinger <[email protected]>
1 parent 8a8cf33 commit 748b190

File tree

3 files changed

+65
-29
lines changed

3 files changed

+65
-29
lines changed

prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/PrometheusTextFormatWriter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ private void writeNameAndLabels(
396396
boolean metricInsideBraces = false;
397397
// If the name does not pass the legacy validity check, we must put the
398398
// metric name inside the braces.
399-
if (!PrometheusNaming.isValidLegacyLabelName(name)) {
399+
if (!PrometheusNaming.isValidLegacyMetricName(name)) {
400400
metricInsideBraces = true;
401401
writer.write('{');
402402
}

prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/TextFormatUtil.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ static void writeLabels(
123123
writer.write("\"");
124124
}
125125
if (additionalLabelName != null) {
126-
if (!labels.isEmpty()) {
126+
if (!labels.isEmpty() || metricInsideBraces) {
127127
writer.write(",");
128128
}
129129
writer.write(additionalLabelName);

prometheus-metrics-exposition-textformats/src/test/java/io/prometheus/metrics/expositionformats/ExpositionFormatsTest.java

Lines changed: 63 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -111,78 +111,78 @@ void init() {
111111
@Test
112112
public void testCounterComplete() throws IOException {
113113
String openMetricsText =
114-
"# TYPE service_time_seconds counter\n"
115-
+ "# UNIT service_time_seconds seconds\n"
116-
+ "# HELP service_time_seconds total time spent serving\n"
117-
+ "service_time_seconds_total{path=\"/hello\",status=\"200\"} 0.8 "
114+
"# TYPE service:time_seconds counter\n"
115+
+ "# UNIT service:time_seconds seconds\n"
116+
+ "# HELP service:time_seconds total time spent serving\n"
117+
+ "service:time_seconds_total{path=\"/hello\",status=\"200\"} 0.8 "
118118
+ scrapeTimestamp1s
119119
+ " # "
120120
+ exemplar1String
121121
+ "\n"
122-
+ "service_time_seconds_created{path=\"/hello\",status=\"200\"} "
122+
+ "service:time_seconds_created{path=\"/hello\",status=\"200\"} "
123123
+ createdTimestamp1s
124124
+ " "
125125
+ scrapeTimestamp1s
126126
+ "\n"
127-
+ "service_time_seconds_total{path=\"/hello\",status=\"500\"} 0.9 "
127+
+ "service:time_seconds_total{path=\"/hello\",status=\"500\"} 0.9 "
128128
+ scrapeTimestamp2s
129129
+ " # "
130130
+ exemplar2String
131131
+ "\n"
132-
+ "service_time_seconds_created{path=\"/hello\",status=\"500\"} "
132+
+ "service:time_seconds_created{path=\"/hello\",status=\"500\"} "
133133
+ createdTimestamp2s
134134
+ " "
135135
+ scrapeTimestamp2s
136136
+ "\n"
137137
+ "# EOF\n";
138138
String prometheusText =
139-
"# HELP service_time_seconds_total total time spent serving\n"
140-
+ "# TYPE service_time_seconds_total counter\n"
141-
+ "service_time_seconds_total{path=\"/hello\",status=\"200\"} 0.8 "
139+
"# HELP service:time_seconds_total total time spent serving\n"
140+
+ "# TYPE service:time_seconds_total counter\n"
141+
+ "service:time_seconds_total{path=\"/hello\",status=\"200\"} 0.8 "
142142
+ scrapeTimestamp1s
143143
+ "\n"
144-
+ "service_time_seconds_total{path=\"/hello\",status=\"500\"} 0.9 "
144+
+ "service:time_seconds_total{path=\"/hello\",status=\"500\"} 0.9 "
145145
+ scrapeTimestamp2s
146146
+ "\n"
147-
+ "# HELP service_time_seconds_created total time spent serving\n"
148-
+ "# TYPE service_time_seconds_created gauge\n"
149-
+ "service_time_seconds_created{path=\"/hello\",status=\"200\"} "
147+
+ "# HELP service:time_seconds_created total time spent serving\n"
148+
+ "# TYPE service:time_seconds_created gauge\n"
149+
+ "service:time_seconds_created{path=\"/hello\",status=\"200\"} "
150150
+ createdTimestamp1s
151151
+ " "
152152
+ scrapeTimestamp1s
153153
+ "\n"
154-
+ "service_time_seconds_created{path=\"/hello\",status=\"500\"} "
154+
+ "service:time_seconds_created{path=\"/hello\",status=\"500\"} "
155155
+ createdTimestamp2s
156156
+ " "
157157
+ scrapeTimestamp2s
158158
+ "\n";
159159
String openMetricsTextWithoutCreated =
160-
"# TYPE service_time_seconds counter\n"
161-
+ "# UNIT service_time_seconds seconds\n"
162-
+ "# HELP service_time_seconds total time spent serving\n"
163-
+ "service_time_seconds_total{path=\"/hello\",status=\"200\"} 0.8 "
160+
"# TYPE service:time_seconds counter\n"
161+
+ "# UNIT service:time_seconds seconds\n"
162+
+ "# HELP service:time_seconds total time spent serving\n"
163+
+ "service:time_seconds_total{path=\"/hello\",status=\"200\"} 0.8 "
164164
+ scrapeTimestamp1s
165165
+ " # "
166166
+ exemplar1String
167167
+ "\n"
168-
+ "service_time_seconds_total{path=\"/hello\",status=\"500\"} 0.9 "
168+
+ "service:time_seconds_total{path=\"/hello\",status=\"500\"} 0.9 "
169169
+ scrapeTimestamp2s
170170
+ " # "
171171
+ exemplar2String
172172
+ "\n"
173173
+ "# EOF\n";
174174
String prometheusTextWithoutCreated =
175-
"# HELP service_time_seconds_total total time spent serving\n"
176-
+ "# TYPE service_time_seconds_total counter\n"
177-
+ "service_time_seconds_total{path=\"/hello\",status=\"200\"} 0.8 "
175+
"# HELP service:time_seconds_total total time spent serving\n"
176+
+ "# TYPE service:time_seconds_total counter\n"
177+
+ "service:time_seconds_total{path=\"/hello\",status=\"200\"} 0.8 "
178178
+ scrapeTimestamp1s
179179
+ "\n"
180-
+ "service_time_seconds_total{path=\"/hello\",status=\"500\"} 0.9 "
180+
+ "service:time_seconds_total{path=\"/hello\",status=\"500\"} 0.9 "
181181
+ scrapeTimestamp2s
182182
+ "\n";
183183
String prometheusProtobuf =
184184
// @formatter:off
185-
"name: \"service_time_seconds_total\" "
185+
"name: \"service:time_seconds_total\" "
186186
+ "help: \"total time spent serving\" "
187187
+ "type: COUNTER "
188188
+ "metric { "
@@ -211,7 +211,7 @@ public void testCounterComplete() throws IOException {
211211

212212
CounterSnapshot counter =
213213
CounterSnapshot.builder()
214-
.name("service_time_seconds")
214+
.name("service:time_seconds")
215215
.help("total time spent serving")
216216
.unit(Unit.SECONDS)
217217
.dataPoint(
@@ -1426,6 +1426,37 @@ public void testClassicHistogramMinimal() throws Exception {
14261426
assertPrometheusProtobuf(prometheusProtobuf, histogram);
14271427
}
14281428

1429+
@Test
1430+
public void testClassicHistogramMinimalWithDots() throws Exception {
1431+
String openMetricsText =
1432+
"""
1433+
# TYPE "request.latency_seconds" histogram
1434+
{"request.latency_seconds_bucket",le="+Inf"} 2
1435+
# EOF
1436+
""";
1437+
String prometheusText =
1438+
"""
1439+
# TYPE request_latency_seconds histogram
1440+
request_latency_seconds_bucket{le="+Inf"} 2
1441+
request_latency_seconds_count 2
1442+
""";
1443+
HistogramSnapshot histogram =
1444+
HistogramSnapshot.builder()
1445+
.name("request.latency_seconds")
1446+
.dataPoint(
1447+
HistogramSnapshot.HistogramDataPointSnapshot.builder()
1448+
.classicHistogramBuckets(
1449+
ClassicHistogramBuckets.builder()
1450+
.bucket(Double.POSITIVE_INFINITY, 2)
1451+
.build())
1452+
.build())
1453+
.build();
1454+
// test that the name and label are separated with commas
1455+
assertOpenMetricsText(openMetricsText, histogram, EscapingScheme.ALLOW_UTF8);
1456+
assertPrometheusText(prometheusText, histogram);
1457+
assertPrometheusTextWithoutCreated(prometheusText, histogram);
1458+
}
1459+
14291460
@Test
14301461
public void testClassicHistogramCountAndSum() throws Exception {
14311462
String openMetricsText =
@@ -2822,10 +2853,15 @@ public void testWrite() throws IOException {
28222853
}
28232854

28242855
private void assertOpenMetricsText(String expected, MetricSnapshot snapshot) throws IOException {
2856+
assertOpenMetricsText(expected, snapshot, EscapingScheme.VALUE_ENCODING_ESCAPING);
2857+
}
2858+
2859+
private void assertOpenMetricsText(
2860+
String expected, MetricSnapshot snapshot, EscapingScheme escapingScheme) throws IOException {
28252861
ByteArrayOutputStream out = new ByteArrayOutputStream();
28262862
OpenMetricsTextFormatWriter writer =
28272863
OpenMetricsTextFormatWriter.builder().setCreatedTimestampsEnabled(true).build();
2828-
writer.write(out, MetricSnapshots.of(snapshot), EscapingScheme.VALUE_ENCODING_ESCAPING);
2864+
writer.write(out, MetricSnapshots.of(snapshot), escapingScheme);
28292865
assertThat(out).hasToString(expected);
28302866
}
28312867

0 commit comments

Comments
 (0)