Skip to content
Closed
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 numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
package io.prometheus.metrics.config;

import java.util.Map;

public class NamingProperties {

private static final String VALIDATION_SCHEME = "validationScheme";
private final String validationScheme;

private NamingProperties(String validation) {
this.validationScheme = validation;
}

public String getValidationScheme() {
return validationScheme;
}

static NamingProperties load(String prefix, Map<Object, Object> properties) throws PrometheusPropertiesException {
String validationScheme = Util.loadString(prefix + "." + VALIDATION_SCHEME, properties);
return new NamingProperties(validationScheme);
}

public static Builder builder() {
return new Builder();
}

public static class Builder {

private String validationScheme;

private Builder() {}

public Builder validation(String validationScheme) {
this.validationScheme = validationScheme;
return this;
}

public NamingProperties build() {
return new NamingProperties(validationScheme);
}
}

}
Original file line numberDiff line numberDiff line change
Expand Up@@ -19,6 +19,7 @@ public class PrometheusProperties {
private final ExporterFilterProperties exporterFilterProperties;
private final ExporterHttpServerProperties exporterHttpServerProperties;
private final ExporterOpenTelemetryProperties exporterOpenTelemetryProperties;
private final NamingProperties namingProperties;

/**
* Get the properties instance. When called for the first time, {@code get()} loads the properties from the following locations:
Expand All@@ -39,14 +40,16 @@ public PrometheusProperties(
ExporterProperties exporterProperties,
ExporterFilterProperties exporterFilterProperties,
ExporterHttpServerProperties httpServerConfig,
ExporterOpenTelemetryProperties otelConfig) {
ExporterOpenTelemetryProperties otelConfig,
NamingProperties namingProperties) {
this.defaultMetricsProperties = defaultMetricsProperties;
this.metricProperties.putAll(metricProperties);
this.exemplarProperties = exemplarProperties;
this.exporterProperties = exporterProperties;
this.exporterFilterProperties = exporterFilterProperties;
this.exporterHttpServerProperties = httpServerConfig;
this.exporterOpenTelemetryProperties = otelConfig;
this.namingProperties = namingProperties;
}

/**
Expand DownExpand Up@@ -83,4 +86,8 @@ public ExporterHttpServerProperties getExporterHttpServerProperties() {
public ExporterOpenTelemetryProperties getExporterOpenTelemetryProperties() {
return exporterOpenTelemetryProperties;
}

public NamingProperties getNamingProperties() {
return namingProperties;
}
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -33,8 +33,9 @@ public static PrometheusProperties load() throws PrometheusPropertiesException {
ExporterFilterProperties exporterFilterProperties = ExporterFilterProperties.load("io.prometheus.exporter.filter", properties);
ExporterHttpServerProperties exporterHttpServerProperties = ExporterHttpServerProperties.load("io.prometheus.exporter.httpServer", properties);
ExporterOpenTelemetryProperties exporterOpenTelemetryProperties = ExporterOpenTelemetryProperties.load("io.prometheus.exporter.opentelemetry", properties);
NamingProperties namingProperties = NamingProperties.load("io.prometheus.naming", properties);
validateAllPropertiesProcessed(properties);
return new PrometheusProperties(defaultMetricsProperties, metricsConfigs, exemplarConfig, exporterProperties, exporterFilterProperties, exporterHttpServerProperties, exporterOpenTelemetryProperties);
return new PrometheusProperties(defaultMetricsProperties, metricsConfigs, exemplarConfig, exporterProperties, exporterFilterProperties, exporterHttpServerProperties, exporterOpenTelemetryProperties, namingProperties);
}

// This will remove entries from properties when they are processed.
Expand Down
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,12 @@
package io.prometheus.metrics.core.metrics;

import io.prometheus.metrics.model.snapshots.*;
import io.prometheus.metrics.shaded.com_google_protobuf_3_21_7.TextFormat;
import io.prometheus.metrics.core.datapoints.DistributionDataPoint;
import io.prometheus.metrics.core.exemplars.ExemplarSamplerConfigTestUtil;
import io.prometheus.metrics.expositionformats.OpenMetricsTextFormatWriter;
import io.prometheus.metrics.expositionformats.PrometheusProtobufWriter;
import io.prometheus.metrics.expositionformats.generated.com_google_protobuf_3_21_7.Metrics;
import io.prometheus.metrics.model.snapshots.ClassicHistogramBucket;
import io.prometheus.metrics.model.snapshots.Exemplar;
import io.prometheus.metrics.model.snapshots.Exemplars;
import io.prometheus.metrics.model.snapshots.HistogramSnapshot;
import io.prometheus.metrics.model.snapshots.Labels;
import io.prometheus.metrics.model.snapshots.MetricSnapshots;
import io.prometheus.metrics.tracer.common.SpanContext;
import io.prometheus.metrics.tracer.initializer.SpanContextSupplier;
import org.junit.After;
Expand DownExpand Up@@ -723,7 +718,7 @@ public void testDefaults() throws IOException {
// text
ByteArrayOutputStream out = new ByteArrayOutputStream();
OpenMetricsTextFormatWriter writer = new OpenMetricsTextFormatWriter(false, true);
writer.write(out, MetricSnapshots.of(snapshot));
writer.write(out, MetricSnapshots.of(snapshot), EscapingScheme.NO_ESCAPING);
Assert.assertEquals(expectedTextFormat, out.toString());
}

Expand Down
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
package io.prometheus.metrics.core.metrics;

import io.prometheus.metrics.expositionformats.OpenMetricsTextFormatWriter;
import io.prometheus.metrics.model.snapshots.EscapingScheme;
import io.prometheus.metrics.model.snapshots.Labels;
import io.prometheus.metrics.model.snapshots.MetricSnapshots;
import io.prometheus.metrics.shaded.com_google_protobuf_3_21_7.TextFormat;
Expand DownExpand Up@@ -98,7 +99,7 @@ public void testConstLabelsDuplicate2() {
private void assertTextFormat(String expected, Info info) throws IOException {
OpenMetricsTextFormatWriter writer = new OpenMetricsTextFormatWriter(true, true);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
writer.write(outputStream, MetricSnapshots.of(info.collect()));
writer.write(outputStream, MetricSnapshots.of(info.collect()), EscapingScheme.NO_ESCAPING);
String result = outputStream.toString(StandardCharsets.UTF_8.name());
if (!result.contains(expected)) {
throw new AssertionError(expected + " is not contained in the following output:\n" + result);
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -6,6 +6,7 @@
import io.prometheus.metrics.expositionformats.ExpositionFormats;
import io.prometheus.metrics.model.registry.MetricNameFilter;
import io.prometheus.metrics.model.registry.PrometheusRegistry;
import io.prometheus.metrics.model.snapshots.EscapingScheme;
import io.prometheus.metrics.model.snapshots.MetricSnapshots;

import java.io.ByteArrayOutputStream;
Expand DownExpand Up@@ -51,15 +52,16 @@ public void handleRequest(PrometheusHttpExchange exchange) throws IOException {
PrometheusHttpRequest request = exchange.getRequest();
PrometheusHttpResponse response = exchange.getResponse();
MetricSnapshots snapshots = scrape(request);
if (writeDebugResponse(snapshots, exchange)) {
String acceptHeader = request.getHeader("Accept");
EscapingScheme escapingScheme = EscapingScheme.fromAcceptHeader(acceptHeader);
if (writeDebugResponse(snapshots, exchange, escapingScheme)) {
return;
}
ByteArrayOutputStream responseBuffer = new ByteArrayOutputStream(lastResponseSize.get() + 1024);
String acceptHeader = request.getHeader("Accept");
ExpositionFormatWriter writer = expositionFormats.findWriter(acceptHeader);
writer.write(responseBuffer, snapshots);
writer.write(responseBuffer, snapshots, escapingScheme);
lastResponseSize.set(responseBuffer.size());
response.setHeader("Content-Type", writer.getContentType());
response.setHeader("Content-Type", writer.getContentType() + escapingScheme.toHeaderFormat());

if (shouldUseCompression(request)) {
response.setHeader("Content-Encoding", "gzip");
Expand DownExpand Up@@ -126,7 +128,7 @@ private Predicate<String> makeNameFilter(String[] includedNames) {
return result;
}

private boolean writeDebugResponse(MetricSnapshots snapshots, PrometheusHttpExchange exchange) throws IOException {
private boolean writeDebugResponse(MetricSnapshots snapshots, PrometheusHttpExchange exchange, EscapingScheme escapingScheme) throws IOException {
String debugParam = exchange.getRequest().getParameter("debug");
PrometheusHttpResponse response = exchange.getResponse();
if (debugParam == null) {
Expand All@@ -138,10 +140,10 @@ private boolean writeDebugResponse(MetricSnapshots snapshots, PrometheusHttpExch
OutputStream body = response.sendHeadersAndGetBody(responseStatus, 0);
switch (debugParam) {
case "openmetrics":
expositionFormats.getOpenMetricsTextFormatWriter().write(body, snapshots);
expositionFormats.getOpenMetricsTextFormatWriter().write(body, snapshots, escapingScheme);
break;
case "text":
expositionFormats.getPrometheusTextFormatWriter().write(body, snapshots);
expositionFormats.getPrometheusTextFormatWriter().write(body, snapshots, escapingScheme);
break;
case "prometheus-protobuf":
String debugString = expositionFormats.getPrometheusProtobufWriter().toDebugString(snapshots);
Expand Down
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
package io.prometheus.metrics.expositionformats;

import io.prometheus.metrics.model.snapshots.EscapingScheme;
import io.prometheus.metrics.model.snapshots.MetricSnapshots;

import java.io.IOException;
Expand All@@ -11,6 +12,6 @@ public interface ExpositionFormatWriter {
/**
* Text formats use UTF-8 encoding.
*/
void write(OutputStream out, MetricSnapshots metricSnapshots) throws IOException;
void write(OutputStream out, MetricSnapshots metricSnapshots, EscapingScheme escapingScheme) throws IOException;
String getContentType();
}
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,14 @@
package io.prometheus.metrics.expositionformats;

import io.prometheus.metrics.model.snapshots.ClassicHistogramBuckets;
import io.prometheus.metrics.model.snapshots.CounterSnapshot;
import io.prometheus.metrics.model.snapshots.DataPointSnapshot;
import io.prometheus.metrics.model.snapshots.DistributionDataPointSnapshot;
import io.prometheus.metrics.model.snapshots.Exemplar;
import io.prometheus.metrics.model.snapshots.Exemplars;
import io.prometheus.metrics.model.snapshots.GaugeSnapshot;
import io.prometheus.metrics.model.snapshots.HistogramSnapshot;
import io.prometheus.metrics.model.snapshots.InfoSnapshot;
import io.prometheus.metrics.model.snapshots.Labels;
import io.prometheus.metrics.model.snapshots.MetricMetadata;
import io.prometheus.metrics.model.snapshots.MetricSnapshot;
import io.prometheus.metrics.model.snapshots.MetricSnapshots;
import io.prometheus.metrics.model.snapshots.Quantile;
import io.prometheus.metrics.model.snapshots.StateSetSnapshot;
import io.prometheus.metrics.model.snapshots.SummarySnapshot;
import io.prometheus.metrics.model.snapshots.UnknownSnapshot;
import io.prometheus.metrics.model.snapshots.*;

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.util.List;

import static io.prometheus.metrics.expositionformats.TextFormatUtil.writeDouble;
import static io.prometheus.metrics.expositionformats.TextFormatUtil.writeEscapedLabelValue;
import static io.prometheus.metrics.expositionformats.TextFormatUtil.writeLabels;
import static io.prometheus.metrics.expositionformats.TextFormatUtil.writeLong;
import static io.prometheus.metrics.expositionformats.TextFormatUtil.writeTimestamp;
import static io.prometheus.metrics.expositionformats.TextFormatUtil.*;

/**
* Write the OpenMetrics text format as defined on <a href="https://openmetrics.io/">https://openmetrics.io</a>.
Expand DownExpand Up@@ -60,9 +40,11 @@ public String getContentType() {
return CONTENT_TYPE;
}

public void write(OutputStream out, MetricSnapshots metricSnapshots) throws IOException {
public void write(OutputStream out, MetricSnapshots metricSnapshots, EscapingScheme escapingScheme) throws IOException {
OutputStreamWriter writer = new OutputStreamWriter(out, StandardCharsets.UTF_8);
for (MetricSnapshot snapshot : metricSnapshots) {
for (MetricSnapshot s : metricSnapshots) {
MetricSnapshot snapshot = PrometheusNaming.escapeMetricSnapshot(s, escapingScheme);

if (snapshot.getDataPoints().size() > 0) {
if (snapshot instanceof CounterSnapshot) {
writeCounter(writer, (CounterSnapshot) snapshot);
Expand DownExpand Up@@ -214,15 +196,15 @@ private void writeStateSet(OutputStreamWriter writer, StateSetSnapshot snapshot)
}
writer.write(data.getLabels().getPrometheusName(j));
writer.write("=\"");
writeEscapedLabelValue(writer, data.getLabels().getValue(j));
writeEscapedString(writer, data.getLabels().getValue(j));
writer.write("\"");
}
if (!data.getLabels().isEmpty()) {
writer.write(",");
}
writer.write(metadata.getPrometheusName());
writer.write("=\"");
writeEscapedLabelValue(writer, data.getName(i));
writeEscapedString(writer, data.getName(i));
writer.write("\"} ");
if (data.isTrue(i)) {
writer.write("1");
Expand DownExpand Up@@ -289,13 +271,21 @@ private void writeNameAndLabels(OutputStreamWriter writer, String name, String s

private void writeNameAndLabels(OutputStreamWriter writer, String name, String suffix, Labels labels,
String additionalLabelName, double additionalLabelValue) throws IOException {
writer.write(name);
if (suffix != null) {
writer.write(suffix);
boolean metricInsideBraces = false;
// If the name does not pass the legacy validity check, we must put the
// metric name inside the braces.
if (PrometheusNaming.validateLegacyMetricName(name) != null) {
metricInsideBraces = true;
writer.write('{');
}
writeName(writer, name + (suffix != null ? suffix : ""), NameType.Metric);

if (!labels.isEmpty() || additionalLabelName != null) {
writeLabels(writer, labels, additionalLabelName, additionalLabelValue);
writeLabels(writer, labels, additionalLabelName, additionalLabelValue, metricInsideBraces);
} else if (metricInsideBraces) {
writer.write('}');
}

writer.write(' ');
}

Expand All@@ -306,7 +296,7 @@ private void writeScrapeTimestampAndExemplar(OutputStreamWriter writer, DataPoin
}
if (exemplar != null) {
writer.write(" # ");
writeLabels(writer, exemplar.getLabels(), null, 0);
writeLabels(writer, exemplar.getLabels(), null, 0, false);
writer.write(' ');
writeDouble(writer, exemplar.getValue());
if (exemplar.hasTimestamp()) {
Expand All@@ -319,22 +309,22 @@ private void writeScrapeTimestampAndExemplar(OutputStreamWriter writer, DataPoin

private void writeMetadata(OutputStreamWriter writer, String typeName, MetricMetadata metadata) throws IOException {
writer.write("# TYPE ");
writer.write(metadata.getPrometheusName());
writeName(writer, metadata.getPrometheusName(), NameType.Metric);
writer.write(' ');
writer.write(typeName);
writer.write('\n');
if (metadata.getUnit() != null) {
writer.write("# UNIT ");
writer.write(metadata.getPrometheusName());
writeName(writer, metadata.getPrometheusName(), NameType.Metric);
writer.write(' ');
writeEscapedLabelValue(writer, metadata.getUnit().toString());
writeEscapedString(writer, metadata.getUnit().toString());
writer.write('\n');
}
if (metadata.getHelp() != null && !metadata.getHelp().isEmpty()) {
writer.write("# HELP ");
writer.write(metadata.getPrometheusName());
writeName(writer, metadata.getPrometheusName(), NameType.Metric);
writer.write(' ');
writeEscapedLabelValue(writer, metadata.getHelp());
writeEscapedString(writer, metadata.getHelp());
writer.write('\n');
}
}
Expand Down
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,9 @@
package io.prometheus.metrics.expositionformats;

import io.prometheus.metrics.model.snapshots.*;
import io.prometheus.metrics.shaded.com_google_protobuf_3_21_7.TextFormat;
import io.prometheus.metrics.expositionformats.generated.com_google_protobuf_3_21_7.Metrics;
import io.prometheus.metrics.model.snapshots.ClassicHistogramBuckets;
import io.prometheus.metrics.model.snapshots.CounterSnapshot;
import io.prometheus.metrics.model.snapshots.CounterSnapshot.CounterDataPointSnapshot;
import io.prometheus.metrics.model.snapshots.Exemplar;
import io.prometheus.metrics.model.snapshots.GaugeSnapshot;
import io.prometheus.metrics.model.snapshots.HistogramSnapshot;
import io.prometheus.metrics.model.snapshots.InfoSnapshot;
import io.prometheus.metrics.model.snapshots.Labels;
import io.prometheus.metrics.model.snapshots.DataPointSnapshot;
import io.prometheus.metrics.model.snapshots.MetricMetadata;
import io.prometheus.metrics.model.snapshots.MetricSnapshot;
import io.prometheus.metrics.model.snapshots.MetricSnapshots;
import io.prometheus.metrics.model.snapshots.NativeHistogramBuckets;
import io.prometheus.metrics.model.snapshots.Quantiles;
import io.prometheus.metrics.model.snapshots.StateSetSnapshot;
import io.prometheus.metrics.model.snapshots.SummarySnapshot;
import io.prometheus.metrics.model.snapshots.UnknownSnapshot;

import java.io.IOException;
import java.io.OutputStream;
Expand DownExpand Up@@ -61,7 +46,7 @@ public String toDebugString(MetricSnapshots metricSnapshots) {
}

@Override
public void write(OutputStream out, MetricSnapshots metricSnapshots) throws IOException {
public void write(OutputStream out, MetricSnapshots metricSnapshots, EscapingScheme escapingScheme) throws IOException {
for (MetricSnapshot snapshot : metricSnapshots) {
if (snapshot.getDataPoints().size() > 0) {
convert(snapshot).writeDelimitedTo(out);
Expand Down
Loading