Skip to content

Commit 034ad7a

Browse files
committed
Fix OM2 classic histogram names
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
1 parent d95b631 commit 034ad7a

2 files changed

Lines changed: 116 additions & 3 deletions

File tree

prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/OpenMetrics2TextFormatWriterTest.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,35 @@ void counterPreservesOriginalNameWhenUnitIsConfigured() throws IOException {
4040
.doesNotContain("my_counter_seconds");
4141
}
4242

43+
@Test
44+
void classicHistogramPreservesOriginalNameWhenUnitIsConfigured() throws IOException {
45+
Histogram histogram =
46+
Histogram.builder()
47+
.name("request_duration")
48+
.unit(Unit.SECONDS)
49+
.help("Request duration in seconds")
50+
.labelNames("path")
51+
.classicOnly()
52+
.classicUpperBounds(10.0)
53+
.build();
54+
histogram.labelValues("/hello").observe(3.2);
55+
MetricSnapshots snapshots = MetricSnapshots.of(histogram.collect());
56+
57+
String om1Output = writeWithOM1(snapshots);
58+
String om2Output = writeWithOM2(snapshots);
59+
60+
assertThat(om1Output).contains("request_duration_seconds_bucket");
61+
assertThat(om2Output)
62+
.contains("# TYPE request_duration histogram\n")
63+
.contains("# UNIT request_duration seconds\n")
64+
.contains("# HELP request_duration Request duration in seconds\n")
65+
.contains("request_duration_bucket{path=\"/hello\",le=\"10.0\"} 1\n")
66+
.contains("request_duration_bucket{path=\"/hello\",le=\"+Inf\"} 1\n")
67+
.contains("request_duration_count{path=\"/hello\"} 1\n")
68+
.contains("request_duration_sum{path=\"/hello\"} 3.2\n")
69+
.doesNotContain("request_duration_seconds");
70+
}
71+
4372
@Test
4473
void nativeHistogramPreservesOriginalNameWhenUnitIsConfigured() throws IOException {
4574
Histogram histogram =

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

Lines changed: 87 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ public OpenMetrics2TextFormatWriter build() {
8989
public static final String CONTENT_TYPE =
9090
"application/openmetrics-text; version=2.0.0; charset=utf-8";
9191
private final OpenMetrics2Properties openMetrics2Properties;
92+
private final boolean createdTimestampsEnabled;
9293
private final boolean exemplarsOnAllMetricTypesEnabled;
9394
private final OpenMetricsTextFormatWriter om1Writer;
9495

@@ -102,6 +103,7 @@ public OpenMetrics2TextFormatWriter(
102103
boolean createdTimestampsEnabled,
103104
boolean exemplarsOnAllMetricTypesEnabled) {
104105
this.openMetrics2Properties = openMetrics2Properties;
106+
this.createdTimestampsEnabled = createdTimestampsEnabled;
105107
this.exemplarsOnAllMetricTypesEnabled = exemplarsOnAllMetricTypesEnabled;
106108
this.om1Writer =
107109
new OpenMetricsTextFormatWriter(createdTimestampsEnabled, exemplarsOnAllMetricTypesEnabled);
@@ -209,12 +211,12 @@ private void writeHistogram(Writer writer, HistogramSnapshot snapshot, EscapingS
209211
throws IOException {
210212
boolean compositeHistogram =
211213
openMetrics2Properties.getCompositeValues() || openMetrics2Properties.getNativeHistograms();
214+
MetricMetadata metadata = snapshot.getMetadata();
215+
String name = getOriginalMetadataName(metadata, scheme);
212216
if (!compositeHistogram && !openMetrics2Properties.getExemplarCompliance()) {
213-
om1Writer.writeHistogram(writer, snapshot, scheme);
217+
writeClassicHistogram(writer, name, snapshot, scheme);
214218
return;
215219
}
216-
MetricMetadata metadata = snapshot.getMetadata();
217-
String name = getOriginalMetadataName(metadata, scheme);
218220
if (snapshot.isGaugeHistogram()) {
219221
writeMetadataWithName(writer, name, "gaugehistogram", metadata);
220222
for (HistogramSnapshot.HistogramDataPointSnapshot data : snapshot.getDataPoints()) {
@@ -236,6 +238,88 @@ private void writeHistogram(Writer writer, HistogramSnapshot snapshot, EscapingS
236238
}
237239
}
238240

241+
private void writeClassicHistogram(
242+
Writer writer, String name, HistogramSnapshot snapshot, EscapingScheme scheme)
243+
throws IOException {
244+
if (snapshot.isGaugeHistogram()) {
245+
writeMetadataWithName(writer, name, "gaugehistogram", snapshot.getMetadata());
246+
writeClassicHistogramDataPoints(writer, name, "_gcount", "_gsum", snapshot, scheme);
247+
} else {
248+
writeMetadataWithName(writer, name, "histogram", snapshot.getMetadata());
249+
writeClassicHistogramDataPoints(writer, name, "_count", "_sum", snapshot, scheme);
250+
}
251+
}
252+
253+
private void writeClassicHistogramDataPoints(
254+
Writer writer,
255+
String name,
256+
String countSuffix,
257+
String sumSuffix,
258+
HistogramSnapshot snapshot,
259+
EscapingScheme scheme)
260+
throws IOException {
261+
for (HistogramSnapshot.HistogramDataPointSnapshot data : snapshot.getDataPoints()) {
262+
ClassicHistogramBuckets buckets = getClassicBuckets(data);
263+
Exemplars exemplars = data.getExemplars();
264+
long cumulativeCount = 0;
265+
for (int i = 0; i < buckets.size(); i++) {
266+
cumulativeCount += buckets.getCount(i);
267+
writeNameAndLabels(
268+
writer, name, "_bucket", data.getLabels(), scheme, "le", buckets.getUpperBound(i));
269+
writeLong(writer, cumulativeCount);
270+
Exemplar exemplar;
271+
if (i == 0) {
272+
exemplar = exemplars.get(Double.NEGATIVE_INFINITY, buckets.getUpperBound(i));
273+
} else {
274+
exemplar = exemplars.get(buckets.getUpperBound(i - 1), buckets.getUpperBound(i));
275+
}
276+
writeScrapeTimestampAndExemplar(writer, data, exemplar, scheme);
277+
}
278+
if (data.hasCount() && data.hasSum()) {
279+
writeClassicCountAndSum(writer, name, data, countSuffix, sumSuffix, exemplars, scheme);
280+
}
281+
writeClassicCreated(writer, name, data, scheme);
282+
}
283+
}
284+
285+
private void writeClassicCountAndSum(
286+
Writer writer,
287+
String name,
288+
HistogramSnapshot.HistogramDataPointSnapshot data,
289+
String countSuffix,
290+
String sumSuffix,
291+
Exemplars exemplars,
292+
EscapingScheme scheme)
293+
throws IOException {
294+
writeNameAndLabels(writer, name, countSuffix, data.getLabels(), scheme);
295+
writeLong(writer, data.getCount());
296+
if (exemplarsOnAllMetricTypesEnabled) {
297+
writeScrapeTimestampAndExemplar(writer, data, exemplars.getLatest(), scheme);
298+
} else {
299+
writeScrapeTimestampAndExemplar(writer, data, null, scheme);
300+
}
301+
writeNameAndLabels(writer, name, sumSuffix, data.getLabels(), scheme);
302+
writeDouble(writer, data.getSum());
303+
writeScrapeTimestampAndExemplar(writer, data, null, scheme);
304+
}
305+
306+
private void writeClassicCreated(
307+
Writer writer,
308+
String name,
309+
HistogramSnapshot.HistogramDataPointSnapshot data,
310+
EscapingScheme scheme)
311+
throws IOException {
312+
if (createdTimestampsEnabled && data.hasCreatedTimestamp()) {
313+
writeNameAndLabels(writer, name, "_created", data.getLabels(), scheme);
314+
writeOpenMetricsTimestamp(writer, data.getCreatedTimestampMillis());
315+
if (data.hasScrapeTimestamp()) {
316+
writer.write(' ');
317+
writeOpenMetricsTimestamp(writer, data.getScrapeTimestampMillis());
318+
}
319+
writer.write('\n');
320+
}
321+
}
322+
239323
private void writeCompositeHistogramDataPoint(
240324
Writer writer,
241325
String name,

0 commit comments

Comments
 (0)