Skip to content
Open
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 @@ -241,7 +241,7 @@ private Builder(PrometheusProperties properties) {
*/
@Override
public Builder name(String name) {
return super.name(stripTotalSuffix(name));
return super.nameWithOriginal(stripTotalSuffix(name), name);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ private Builder(PrometheusProperties config) {
*/
@Override
public Builder name(String name) {
return super.name(stripInfoSuffix(name));
return super.nameWithOriginal(stripInfoSuffix(name), name);
}

/** Throws an {@link UnsupportedOperationException} because Info metrics cannot have a unit. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,14 @@ public abstract class MetricWithFixedMetadata extends Metric {

protected MetricWithFixedMetadata(Builder<?, ?> builder) {
super(builder);
String name = makeName(builder.name, builder.unit);
if (builder.originalName == null) {
throw new IllegalArgumentException("Missing required field: name is null");
}
String originalName = builder.originalName;
String expositionBaseName = makeExpositionBaseName(originalName, builder.unit);
this.metadata =
new MetricMetadata(makeName(builder.name, builder.unit), builder.help, builder.unit);
new MetricMetadata(name, expositionBaseName, originalName, builder.help, builder.unit);
this.labelNames = Arrays.copyOf(builder.labelNames, builder.labelNames.length);
}

Expand All @@ -47,6 +53,18 @@ private String makeName(@Nullable String name, @Nullable Unit unit) {
return name;
}

private String makeExpositionBaseName(@Nullable String expositionBaseName, @Nullable Unit unit) {
if (expositionBaseName == null) {
throw new IllegalArgumentException("Missing required field: name is null");
}
if (unit != null) {
if (!expositionBaseName.endsWith("_" + unit) && !expositionBaseName.endsWith("." + unit)) {
expositionBaseName += "_" + unit;
}
}
return expositionBaseName;
}

@Override
public String getPrometheusName() {
return metadata.getPrometheusName();
Expand All @@ -68,6 +86,7 @@ public abstract static class Builder<B extends Builder<B, M>, M extends MetricWi
extends Metric.Builder<B, M> {

@Nullable private String name;
@Nullable private String originalName;
@Nullable private Unit unit;
@Nullable private String help;
private String[] labelNames = new String[0];
Expand All @@ -82,6 +101,25 @@ public B name(String name) {
throw new IllegalArgumentException("'" + name + "': Illegal metric name: " + error);
}
this.name = name;
this.originalName = name;
return self();
}

/**
* Set the metric name and original name separately. Used by Counter and Info builders which
* strip type suffixes from the name but preserve the original for exposition.
*/
protected B nameWithOriginal(String name, String originalName) {
String error = PrometheusNaming.validateMetricName(name);
if (error != null) {
throw new IllegalArgumentException("'" + name + "': Illegal metric name: " + error);
}
error = PrometheusNaming.validateMetricName(originalName);
if (error != null) {
throw new IllegalArgumentException("'" + originalName + "': Illegal metric name: " + error);
}
this.name = name;
this.originalName = originalName;
return self();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,12 @@ private void setMetadataUnlessEmpty(
if (nameSuffix == null) {
builder.setName(SnapshotEscaper.getMetadataName(metadata, scheme));
} else {
builder.setName(SnapshotEscaper.getMetadataName(metadata, scheme) + nameSuffix);
String expositionBaseName = SnapshotEscaper.getExpositionBaseMetadataName(metadata, scheme);
if (expositionBaseName.endsWith(nameSuffix)) {
builder.setName(expositionBaseName);
} else {
builder.setName(SnapshotEscaper.getMetadataName(metadata, scheme) + nameSuffix);
}
}
if (metadata.getHelp() != null) {
builder.setHelp(metadata.getHelp());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import static io.prometheus.metrics.expositionformats.TextFormatUtil.writeLong;
import static io.prometheus.metrics.expositionformats.TextFormatUtil.writeName;
import static io.prometheus.metrics.expositionformats.TextFormatUtil.writeOpenMetricsTimestamp;
import static io.prometheus.metrics.model.snapshots.SnapshotEscaper.getExpositionBaseMetadataName;
import static io.prometheus.metrics.model.snapshots.SnapshotEscaper.getMetadataName;
import static io.prometheus.metrics.model.snapshots.SnapshotEscaper.getSnapshotLabelName;

Expand Down Expand Up @@ -141,13 +142,14 @@ public void write(OutputStream out, MetricSnapshots metricSnapshots, EscapingSch
private void writeCounter(Writer writer, CounterSnapshot snapshot, EscapingScheme scheme)
throws IOException {
MetricMetadata metadata = snapshot.getMetadata();
writeMetadata(writer, "counter", metadata, scheme);
String counterName = resolveExpositionName(metadata, "_total", scheme);
String baseName = resolveBaseName(counterName, "_total");
writeMetadataWithName(writer, baseName, "counter", metadata);
for (CounterSnapshot.CounterDataPointSnapshot data : snapshot.getDataPoints()) {
writeNameAndLabels(
writer, getMetadataName(metadata, scheme), "_total", data.getLabels(), scheme);
writeNameAndLabels(writer, counterName, null, data.getLabels(), scheme);
writeDouble(writer, data.getValue());
writeScrapeTimestampAndExemplar(writer, data, data.getExemplar(), scheme);
writeCreated(writer, metadata, data, scheme);
writeCreated(writer, baseName, data, scheme);
}
}

Expand Down Expand Up @@ -274,10 +276,11 @@ private void writeSummary(Writer writer, SummarySnapshot snapshot, EscapingSchem
private void writeInfo(Writer writer, InfoSnapshot snapshot, EscapingScheme scheme)
throws IOException {
MetricMetadata metadata = snapshot.getMetadata();
writeMetadata(writer, "info", metadata, scheme);
String infoName = resolveExpositionName(metadata, "_info", scheme);
String baseName = resolveBaseName(infoName, "_info");
writeMetadataWithName(writer, baseName, "info", metadata);
for (InfoSnapshot.InfoDataPointSnapshot data : snapshot.getDataPoints()) {
writeNameAndLabels(
writer, getMetadataName(metadata, scheme), "_info", data.getLabels(), scheme);
writeNameAndLabels(writer, infoName, null, data.getLabels(), scheme);
writer.write("1");
writeScrapeTimestampAndExemplar(writer, data, null, scheme);
}
Expand Down Expand Up @@ -363,9 +366,14 @@ private void writeCountAndSum(
private void writeCreated(
Writer writer, MetricMetadata metadata, DataPointSnapshot data, EscapingScheme scheme)
throws IOException {
writeCreated(writer, getMetadataName(metadata, scheme), data, scheme);
}

private void writeCreated(
Writer writer, String baseName, DataPointSnapshot data, EscapingScheme scheme)
throws IOException {
if (createdTimestampsEnabled && data.hasCreatedTimestamp()) {
writeNameAndLabels(
writer, getMetadataName(metadata, scheme), "_created", data.getLabels(), scheme);
writeNameAndLabels(writer, baseName, "_created", data.getLabels(), scheme);
writeOpenMetricsTimestamp(writer, data.getCreatedTimestampMillis());
if (data.hasScrapeTimestamp()) {
writer.write(' ');
Expand Down Expand Up @@ -436,27 +444,53 @@ private void writeScrapeTimestampAndExemplar(
writer.write('\n');
}

/**
* Returns the full exposition name for a metric. If the original name already ends with the given
* suffix (e.g. "_total" for counters), uses the original name directly. Otherwise, appends the
* suffix to the base name.
*/
private static String resolveExpositionName(
MetricMetadata metadata, String suffix, EscapingScheme scheme) {
String expositionBaseName = getExpositionBaseMetadataName(metadata, scheme);
if (expositionBaseName.endsWith(suffix)) {
return expositionBaseName;
}
return getMetadataName(metadata, scheme) + suffix;
}

private void writeMetadata(
Writer writer, String typeName, MetricMetadata metadata, EscapingScheme scheme)
throws IOException {
writeMetadataWithName(writer, getMetadataName(metadata, scheme), typeName, metadata);
}

private void writeMetadataWithName(
Writer writer, String name, String typeName, MetricMetadata metadata) throws IOException {
writer.write("# TYPE ");
writeName(writer, getMetadataName(metadata, scheme), NameType.Metric);
writeName(writer, name, NameType.Metric);
writer.write(' ');
writer.write(typeName);
writer.write('\n');
if (metadata.getUnit() != null) {
writer.write("# UNIT ");
writeName(writer, getMetadataName(metadata, scheme), NameType.Metric);
writeName(writer, name, NameType.Metric);
writer.write(' ');
writeEscapedString(writer, metadata.getUnit().toString());
writer.write('\n');
}
if (metadata.getHelp() != null && !metadata.getHelp().isEmpty()) {
writer.write("# HELP ");
writeName(writer, getMetadataName(metadata, scheme), NameType.Metric);
writeName(writer, name, NameType.Metric);
writer.write(' ');
writeEscapedString(writer, metadata.getHelp());
writer.write('\n');
}
}

private static String resolveBaseName(String fullName, String suffix) {
if (fullName.endsWith(suffix)) {
return fullName.substring(0, fullName.length() - suffix.length());
}
return fullName;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import static io.prometheus.metrics.expositionformats.TextFormatUtil.writeName;
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.getMetadataName;
import static io.prometheus.metrics.model.snapshots.SnapshotEscaper.getSnapshotLabelName;

Expand Down Expand Up @@ -157,14 +158,17 @@ public void writeCreated(Writer writer, MetricSnapshot snapshot, EscapingScheme
throws IOException {
boolean metadataWritten = false;
MetricMetadata metadata = snapshot.getMetadata();
String baseName = getMetadataName(metadata, scheme);
if (snapshot instanceof CounterSnapshot) {
baseName = resolveBaseName(resolveExpositionName(metadata, "_total", scheme), "_total");
}
for (DataPointSnapshot data : snapshot.getDataPoints()) {
if (data.hasCreatedTimestamp()) {
if (!metadataWritten) {
writeMetadata(writer, "_created", "gauge", metadata, scheme);
writeMetadataWithFullName(writer, baseName + "_created", "gauge", metadata);
metadataWritten = true;
}
writeNameAndLabels(
writer, getMetadataName(metadata, scheme), "_created", data.getLabels(), scheme);
writeNameAndLabels(writer, baseName, "_created", data.getLabels(), scheme);
writePrometheusTimestamp(writer, data.getCreatedTimestampMillis(), timestampsInMs);
writeScrapeTimestampAndNewline(writer, data);
}
Expand All @@ -175,10 +179,10 @@ private void writeCounter(Writer writer, CounterSnapshot snapshot, EscapingSchem
throws IOException {
if (!snapshot.getDataPoints().isEmpty()) {
MetricMetadata metadata = snapshot.getMetadata();
writeMetadata(writer, "_total", "counter", metadata, scheme);
String counterName = resolveExpositionName(metadata, "_total", scheme);
writeMetadataWithFullName(writer, counterName, "counter", metadata);
for (CounterSnapshot.CounterDataPointSnapshot data : snapshot.getDataPoints()) {
writeNameAndLabels(
writer, getMetadataName(metadata, scheme), "_total", data.getLabels(), scheme);
writeNameAndLabels(writer, counterName, null, data.getLabels(), scheme);
writeDouble(writer, data.getValue());
writeScrapeTimestampAndNewline(writer, data);
}
Expand Down Expand Up @@ -321,10 +325,10 @@ private void writeSummary(Writer writer, SummarySnapshot snapshot, EscapingSchem
private void writeInfo(Writer writer, InfoSnapshot snapshot, EscapingScheme scheme)
throws IOException {
MetricMetadata metadata = snapshot.getMetadata();
writeMetadata(writer, "_info", "gauge", metadata, scheme);
String infoName = resolveExpositionName(metadata, "_info", scheme);
writeMetadataWithFullName(writer, infoName, "gauge", metadata);
for (InfoSnapshot.InfoDataPointSnapshot data : snapshot.getDataPoints()) {
writeNameAndLabels(
writer, getMetadataName(metadata, scheme), "_info", data.getLabels(), scheme);
writeNameAndLabels(writer, infoName, null, data.getLabels(), scheme);
writer.write("1");
writeScrapeTimestampAndNewline(writer, data);
}
Expand Down Expand Up @@ -433,6 +437,44 @@ private void writeMetadata(
writer.write('\n');
}

private void writeMetadataWithFullName(
Writer writer, String fullName, String typeString, MetricMetadata metadata)
throws IOException {
if (metadata.getHelp() != null && !metadata.getHelp().isEmpty()) {
writer.write("# HELP ");
writeName(writer, fullName, NameType.Metric);
writer.write(' ');
writeEscapedHelp(writer, metadata.getHelp());
writer.write('\n');
}
writer.write("# TYPE ");
writeName(writer, fullName, NameType.Metric);
writer.write(' ');
writer.write(typeString);
writer.write('\n');
}

/**
* Returns the full exposition name for a metric. If the original name already ends with the given
* suffix (e.g. "_total" for counters), uses the original name directly. Otherwise, appends the
* suffix to the base name.
*/
private static String resolveExpositionName(
MetricMetadata metadata, String suffix, EscapingScheme scheme) {
String expositionBaseName = getExpositionBaseMetadataName(metadata, scheme);
if (expositionBaseName.endsWith(suffix)) {
return expositionBaseName;
}
return getMetadataName(metadata, scheme) + suffix;
}

private static String resolveBaseName(String fullName, String suffix) {
if (fullName.endsWith(suffix)) {
return fullName.substring(0, fullName.length() - suffix.length());
}
return fullName;
}

private void writeEscapedHelp(Writer writer, String s) throws IOException {
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ default MetricSnapshot collect(PrometheusScrapeRequest scrapeRequest) {
@Nullable
default MetricSnapshot collect(Predicate<String> includedNames) {
MetricSnapshot result = collect();
if (includedNames.test(result.getMetadata().getPrometheusName())) {
if (includedNames.test(result.getMetadata().getPrometheusName())
|| includedNames.test(result.getMetadata().getExpositionBasePrometheusName())) {
return result;
} else {
return null;
Expand All @@ -51,7 +52,8 @@ default MetricSnapshot collect(Predicate<String> includedNames) {
default MetricSnapshot collect(
Predicate<String> includedNames, PrometheusScrapeRequest scrapeRequest) {
MetricSnapshot result = collect(scrapeRequest);
if (includedNames.test(result.getMetadata().getPrometheusName())) {
if (includedNames.test(result.getMetadata().getPrometheusName())
|| includedNames.test(result.getMetadata().getExpositionBasePrometheusName())) {
return result;
} else {
return null;
Expand Down
Loading
Loading