Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ public String toDebugString(MetricSnapshots metricSnapshots, EscapingScheme esca
for (MetricSnapshot s : merged) {
MetricSnapshot snapshot = SnapshotEscaper.escapeMetricSnapshot(s, escapingScheme);
if (!snapshot.getDataPoints().isEmpty()) {
stringBuilder.append(TextFormat.printer().printToString(convert(snapshot, escapingScheme)));
stringBuilder.append(
TextFormat.printer()
.printToString(
convert(snapshot, s.getMetadata().getOriginalName(), escapingScheme)));
}
}
return stringBuilder.toString();
Expand All @@ -64,12 +67,17 @@ public void write(
for (MetricSnapshot s : merged) {
MetricSnapshot snapshot = SnapshotEscaper.escapeMetricSnapshot(s, escapingScheme);
if (!snapshot.getDataPoints().isEmpty()) {
convert(snapshot, escapingScheme).writeDelimitedTo(out);
convert(snapshot, s.getMetadata().getOriginalName(), escapingScheme).writeDelimitedTo(out);
}
}
}

public Metrics.MetricFamily convert(MetricSnapshot snapshot, EscapingScheme scheme) {
return convert(snapshot, snapshot.getMetadata().getOriginalName(), scheme);
}

private Metrics.MetricFamily convert(
MetricSnapshot snapshot, String rawOriginalName, EscapingScheme scheme) {
Metrics.MetricFamily.Builder builder = Metrics.MetricFamily.newBuilder();
if (snapshot instanceof CounterSnapshot) {
for (CounterDataPointSnapshot data : ((CounterSnapshot) snapshot).getDataPoints()) {
Expand All @@ -82,7 +90,13 @@ public Metrics.MetricFamily convert(MetricSnapshot snapshot, EscapingScheme sche
builder.addMetric(convert(data, scheme));
}
setMetadataUnlessEmpty(
builder, snapshot.getMetadata(), null, Metrics.MetricType.GAUGE, scheme);
builder,
snapshot.getMetadata(),
rawOriginalName,
null,
Metrics.MetricType.GAUGE,
scheme,
true);
} else if (snapshot instanceof HistogramSnapshot) {
HistogramSnapshot histogram = (HistogramSnapshot) snapshot;
for (HistogramSnapshot.HistogramDataPointSnapshot data : histogram.getDataPoints()) {
Expand Down Expand Up @@ -290,25 +304,49 @@ private void setMetadataUnlessEmpty(
@Nullable String nameSuffix,
Metrics.MetricType type,
EscapingScheme scheme) {
setMetadataUnlessEmpty(
builder, metadata, metadata.getOriginalName(), nameSuffix, type, scheme, false);
}

private void setMetadataUnlessEmpty(
Metrics.MetricFamily.Builder builder,
MetricMetadata metadata,
String rawOriginalName,
@Nullable String nameSuffix,
Metrics.MetricType type,
EscapingScheme scheme,
boolean normalizeLegacyGaugeName) {
if (builder.getMetricCount() == 0) {
return;
}
if (nameSuffix == null) {
builder.setName(SnapshotEscaper.getMetadataName(metadata, scheme));
} else {
String expositionBaseName = SnapshotEscaper.getExpositionBaseMetadataName(metadata, scheme);
if (expositionBaseName.endsWith(nameSuffix)) {
builder.setName(expositionBaseName);
} else {
builder.setName(SnapshotEscaper.getMetadataName(metadata, scheme) + nameSuffix);
}
}
builder.setName(
resolveMetricFamilyName(
metadata, rawOriginalName, nameSuffix, scheme, normalizeLegacyGaugeName));
if (metadata.getHelp() != null) {
builder.setHelp(metadata.getHelp());
}
builder.setType(type);
}

private String resolveMetricFamilyName(
MetricMetadata metadata,
String rawOriginalName,
@Nullable String nameSuffix,
EscapingScheme scheme,
boolean normalizeLegacyGaugeName) {
if (normalizeLegacyGaugeName) {
return SnapshotEscaper.getLegacyGaugeName(metadata, rawOriginalName, scheme);
}
if (nameSuffix == null) {
return SnapshotEscaper.getMetadataName(metadata, scheme);
}
String expositionBaseName = SnapshotEscaper.getExpositionBaseMetadataName(metadata, scheme);
if (expositionBaseName.endsWith(nameSuffix)) {
return expositionBaseName;
}
return SnapshotEscaper.getMetadataName(metadata, scheme) + nameSuffix;
}

private long getNativeCount(HistogramSnapshot.HistogramDataPointSnapshot data) {
if (data.hasCount()) {
return data.getCount();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,53 @@ void testDifferentMetrics_producesSeparateMetricFamilies() throws IOException {
assertThat(gaugeFamily.getMetric(0).getGauge().getValue()).isEqualTo(50.0);
}

@Test
void testLegacyGaugeNameWithAlternateEscapingSchemes_usesBaseName() throws IOException {
MetricSnapshots snapshots =
MetricSnapshots.of(
GaugeSnapshot.builder()
.name("legacy.name.total")
.dataPoint(GaugeSnapshot.GaugeDataPointSnapshot.builder().value(7).build())
.build());

assertThat(getSingleMetricFamilyName(snapshots, EscapingScheme.DOTS_ESCAPING))
.isEqualTo("legacy_dot_name");
assertThat(getSingleMetricFamilyName(snapshots, EscapingScheme.VALUE_ENCODING_ESCAPING))
.isEqualTo("U__legacy_2e_name");
}

@Test
void testLegacyGaugeNameWithDotTotal_usesBaseName() throws IOException {
MetricSnapshots snapshots =
MetricSnapshots.of(
GaugeSnapshot.builder()
.name("legacy.total")
.dataPoint(GaugeSnapshot.GaugeDataPointSnapshot.builder().value(7).build())
.build());
ByteArrayOutputStream out = new ByteArrayOutputStream();
PrometheusProtobufWriterImpl writer = new PrometheusProtobufWriterImpl();
writer.write(out, snapshots, EscapingScheme.UNDERSCORE_ESCAPING);

List<Metrics.MetricFamily> metricFamilies = parseProtobufOutput(out);

assertThat(metricFamilies).hasSize(1);
Metrics.MetricFamily family = metricFamilies.get(0);
assertThat(family.getName()).isEqualTo("legacy");
assertThat(family.getType()).isEqualTo(Metrics.MetricType.GAUGE);
assertThat(family.getMetricCount()).isEqualTo(1);
assertThat(family.getMetric(0).getGauge().getValue()).isEqualTo(7.0);
}

private static String getSingleMetricFamilyName(
MetricSnapshots snapshots, EscapingScheme escapingScheme) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
PrometheusProtobufWriterImpl writer = new PrometheusProtobufWriterImpl();
writer.write(out, snapshots, escapingScheme);
List<Metrics.MetricFamily> metricFamilies = parseProtobufOutput(out);
assertThat(metricFamilies).hasSize(1);
return metricFamilies.get(0).getName();
}

private static MetricSnapshots getMetricSnapshots() {
PrometheusRegistry registry = new PrometheusRegistry();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import static io.prometheus.metrics.expositionformats.TextFormatUtil.writePrometheusTimestamp;
import static io.prometheus.metrics.model.snapshots.SnapshotEscaper.escapeMetricSnapshot;
import static io.prometheus.metrics.model.snapshots.SnapshotEscaper.getExpositionBaseMetadataName;
import static io.prometheus.metrics.model.snapshots.SnapshotEscaper.getLegacyGaugeName;
import static io.prometheus.metrics.model.snapshots.SnapshotEscaper.getMetadataName;
import static io.prometheus.metrics.model.snapshots.SnapshotEscaper.getSnapshotLabelName;

Expand Down Expand Up @@ -123,7 +124,7 @@ public void write(OutputStream out, MetricSnapshots metricSnapshots, EscapingSch
if (snapshot instanceof CounterSnapshot) {
writeCounter(writer, (CounterSnapshot) snapshot, scheme);
} else if (snapshot instanceof GaugeSnapshot) {
writeGauge(writer, (GaugeSnapshot) snapshot, scheme);
writeGauge(writer, (GaugeSnapshot) snapshot, s.getMetadata().getOriginalName(), scheme);
} else if (snapshot instanceof HistogramSnapshot) {
writeHistogram(writer, (HistogramSnapshot) snapshot, scheme);
} else if (snapshot instanceof SummarySnapshot) {
Expand Down Expand Up @@ -189,13 +190,14 @@ private void writeCounter(Writer writer, CounterSnapshot snapshot, EscapingSchem
}
}

private void writeGauge(Writer writer, GaugeSnapshot snapshot, EscapingScheme scheme)
private void writeGauge(
Writer writer, GaugeSnapshot snapshot, String rawOriginalName, EscapingScheme scheme)
throws IOException {
MetricMetadata metadata = snapshot.getMetadata();
writeMetadata(writer, null, "gauge", metadata, scheme);
String name = getMetadataName(metadata, scheme);
String gaugeName = getLegacyGaugeName(metadata, rawOriginalName, scheme);
writeMetadataWithFullName(writer, gaugeName, "gauge", metadata);
for (GaugeSnapshot.GaugeDataPointSnapshot data : snapshot.getDataPoints()) {
writeNameAndLabels(writer, name, null, data.getLabels(), scheme);
writeNameAndLabels(writer, gaugeName, null, data.getLabels(), scheme);
writeDouble(writer, data.getValue());
writeScrapeTimestampAndNewline(writer, data);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,86 @@ void testGaugeWithDots() throws IOException {
assertPrometheusProtobuf(prometheusProtobuf, gauge);
}

@Test
void testGaugeReservedSuffixCompatibilityWithAlternateEscapingSchemes() throws IOException {
GaugeSnapshot totalGauge =
GaugeSnapshot.builder()
.name("legacy.name.total")
.dataPoint(GaugeDataPointSnapshot.builder().value(6).build())
.build();
assertPrometheusText(
"""
# TYPE legacy_dot_name gauge
legacy_dot_name 6.0
""",
totalGauge,
EscapingScheme.DOTS_ESCAPING);
assertPrometheusText(
"""
# TYPE U__legacy_2e_name gauge
U__legacy_2e_name 6.0
""",
totalGauge,
EscapingScheme.VALUE_ENCODING_ESCAPING);
}

@Test
void testGaugeReservedSuffixCompatibilityOutsideOpenMetrics() throws IOException {
GaugeSnapshot createdGauge =
GaugeSnapshot.builder()
.name("test3.created")
.dataPoint(GaugeDataPointSnapshot.builder().value(3).build())
.build();
assertOpenMetricsText(
"""
# TYPE U__test3_2e_created gauge
U__test3_2e_created 3.0
# EOF
""",
createdGauge);
assertPrometheusText(
"""
# TYPE test3 gauge
test3 3.0
""",
createdGauge);
assertPrometheusTextWithoutCreated(
"""
# TYPE test3 gauge
test3 3.0
""",
createdGauge);
assertPrometheusProtobuf(
"name: \"test3\" type: GAUGE metric { gauge { value: 3.0 } }", createdGauge);

GaugeSnapshot totalGauge =
GaugeSnapshot.builder()
.name("test6.total")
.dataPoint(GaugeDataPointSnapshot.builder().value(6).build())
.build();
assertOpenMetricsText(
"""
# TYPE U__test6_2e_total gauge
U__test6_2e_total 6.0
# EOF
""",
totalGauge);
assertPrometheusText(
"""
# TYPE test6 gauge
test6 6.0
""",
totalGauge);
assertPrometheusTextWithoutCreated(
"""
# TYPE test6 gauge
test6 6.0
""",
totalGauge);
assertPrometheusProtobuf(
"name: \"test6\" type: GAUGE metric { gauge { value: 6.0 } }", totalGauge);
}

@Test
void testGaugeUTF8() throws IOException {
String prometheusText =
Expand Down Expand Up @@ -3088,9 +3168,14 @@ private void assertOpenMetricsTextWithoutCreated(String expected, MetricSnapshot
}

private void assertPrometheusText(String expected, MetricSnapshot snapshot) throws IOException {
assertPrometheusText(expected, snapshot, EscapingScheme.UNDERSCORE_ESCAPING);
}

private void assertPrometheusText(
String expected, MetricSnapshot snapshot, EscapingScheme escapingScheme) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
getPrometheusWriter(PrometheusTextFormatWriter.builder().setIncludeCreatedTimestamps(true))
.write(out, MetricSnapshots.of(snapshot), EscapingScheme.UNDERSCORE_ESCAPING);
.write(out, MetricSnapshots.of(snapshot), escapingScheme);
assertThat(out).hasToString(expected);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,26 @@ public static String getOriginalMetadataName(MetricMetadata metadata, EscapingSc
}
}

public static String getLegacyGaugeName(
MetricMetadata metadata, String rawOriginalName, EscapingScheme scheme) {
String legacyGaugeBaseName = stripLegacyGaugeSuffix(rawOriginalName);
if (legacyGaugeBaseName != null) {
return PrometheusNaming.escapeName(legacyGaugeBaseName, scheme);
}
return getMetadataName(metadata, scheme);
}

@Nullable
private static String stripLegacyGaugeSuffix(String rawOriginalName) {
Comment thread
jaydeluca marked this conversation as resolved.
if (rawOriginalName.endsWith(".created")) {
return rawOriginalName.substring(0, rawOriginalName.length() - ".created".length());
}
if (rawOriginalName.endsWith(".total")) {
return rawOriginalName.substring(0, rawOriginalName.length() - ".total".length());
}
return null;
}

public static Labels escapeLabels(Labels labels, EscapingScheme scheme) {
Labels.Builder outLabelsBuilder = Labels.builder();

Expand Down