feat: add OTel preserve_names for scrape-time suffix handling by zeitlinger · Pull Request #1956 · prometheus/client_java · GitHub
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 @@ -41,6 +41,7 @@ public static class Builder {
@Nullable String serviceInstanceId;
@Nullable String serviceVersion;
final Map<String, String> resourceAttributes = new HashMap<>();
@Nullable Boolean preserveNames;

private Builder(PrometheusProperties config) {
this.config = config;
Expand Down Expand Up @@ -194,6 +195,15 @@ public Builder resourceAttribute(String name, String value) {
return this;
}

/**
* When {@code true}, metric names are preserved as-is (including suffixes like {@code _total}).
* When {@code false} (default), standard OTel name normalization is applied.
*/
public Builder preserveNames(boolean preserveNames) {
this.preserveNames = preserveNames;
return this;
}

public OpenTelemetryExporter buildAndStart() {
if (registry == null) {
registry = PrometheusRegistry.defaultRegistry;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,10 @@ static MetricReader createReader(
instrumentationScopeInfo);

MetricReader reader = requireNonNull(readerRef.get());
boolean preserveNames = resolvePreserveNames(builder, config);
reader.register(
new PrometheusMetricProducer(registry, instrumentationScopeInfo, getResourceField(sdk)));
new PrometheusMetricProducer(
registry, instrumentationScopeInfo, getResourceField(sdk), preserveNames));
return reader;
}

Expand Down Expand Up @@ -107,6 +109,15 @@ private static Attributes otelResourceAttributes(
return builder.build();
}

static boolean resolvePreserveNames(
OpenTelemetryExporter.Builder builder, PrometheusProperties config) {
if (builder.preserveNames != null) {
return builder.preserveNames;
}
Boolean fromConfig = config.getExporterOpenTelemetryProperties().getPreserveNames();
return fromConfig != null && fromConfig;
}

static Resource getResourceField(AutoConfiguredOpenTelemetrySdk sdk) {
try {
Method method = AutoConfiguredOpenTelemetrySdk.class.getDeclaredMethod("getResource");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,17 @@ class PrometheusMetricProducer implements CollectionRegistration {
private final PrometheusRegistry registry;
private final Resource resource;
private final InstrumentationScopeInfo instrumentationScopeInfo;
private final boolean preserveNames;

public PrometheusMetricProducer(
PrometheusRegistry registry,
InstrumentationScopeInfo instrumentationScopeInfo,
Resource resource) {
Resource resource,
boolean preserveNames) {
this.registry = registry;
this.instrumentationScopeInfo = instrumentationScopeInfo;
this.resource = resource;
this.preserveNames = preserveNames;
}

@Override
Expand All @@ -57,7 +60,8 @@ public Collection<MetricData> collectAllMetrics() {
new MetricDataFactory(
resourceWithTargetInfo,
scopeFromInfo != null ? scopeFromInfo : instrumentationScopeInfo,
System.currentTimeMillis());
System.currentTimeMillis(),
preserveNames);
for (MetricSnapshot snapshot : snapshots) {
if (snapshot instanceof CounterSnapshot) {
addUnlessNull(result, factory.create((CounterSnapshot) snapshot));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,17 @@ public class MetricDataFactory {
private final Resource resource;
private final InstrumentationScopeInfo instrumentationScopeInfo;
private final long currentTimeMillis;
private final boolean preserveNames;

public MetricDataFactory(
Resource resource,
InstrumentationScopeInfo instrumentationScopeInfo,
long currentTimeMillis) {
long currentTimeMillis,
boolean preserveNames) {
this.resource = resource;
this.instrumentationScopeInfo = instrumentationScopeInfo;
this.currentTimeMillis = currentTimeMillis;
this.preserveNames = preserveNames;
}

@Nullable
Expand All @@ -36,7 +39,8 @@ public MetricData create(CounterSnapshot snapshot) {
snapshot.getMetadata(),
new PrometheusCounter(snapshot, currentTimeMillis),
instrumentationScopeInfo,
resource);
resource,
preserveNames);
}

@Nullable
Expand All @@ -48,7 +52,8 @@ public MetricData create(GaugeSnapshot snapshot) {
snapshot.getMetadata(),
new PrometheusGauge(snapshot, currentTimeMillis),
instrumentationScopeInfo,
resource);
resource,
preserveNames);
}

@Nullable
Expand All @@ -60,13 +65,15 @@ public MetricData create(HistogramSnapshot snapshot) {
snapshot.getMetadata(),
new PrometheusNativeHistogram(snapshot, currentTimeMillis),
instrumentationScopeInfo,
resource);
resource,
preserveNames);
} else if (firstDataPoint.hasClassicHistogramData()) {
return new PrometheusMetricData<>(
snapshot.getMetadata(),
new PrometheusClassicHistogram(snapshot, currentTimeMillis),
instrumentationScopeInfo,
resource);
resource,
preserveNames);
}
}
return null;
Expand All @@ -81,7 +88,8 @@ public MetricData create(SummarySnapshot snapshot) {
snapshot.getMetadata(),
new PrometheusSummary(snapshot, currentTimeMillis),
instrumentationScopeInfo,
resource);
resource,
preserveNames);
}

@Nullable
Expand All @@ -93,7 +101,8 @@ public MetricData create(InfoSnapshot snapshot) {
snapshot.getMetadata(),
new PrometheusInfo(snapshot, currentTimeMillis),
instrumentationScopeInfo,
resource);
resource,
preserveNames);
}

@Nullable
Expand All @@ -105,7 +114,8 @@ public MetricData create(StateSetSnapshot snapshot) {
snapshot.getMetadata(),
new PrometheusStateSet(snapshot, currentTimeMillis),
instrumentationScopeInfo,
resource);
resource,
preserveNames);
}

@Nullable
Expand All @@ -117,6 +127,7 @@ public MetricData create(UnknownSnapshot snapshot) {
snapshot.getMetadata(),
new PrometheusUnknown(snapshot, currentTimeMillis),
instrumentationScopeInfo,
resource);
resource,
preserveNames);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@ class PrometheusMetricData<T extends PrometheusData<?>> implements MetricData {
MetricMetadata metricMetadata,
T data,
InstrumentationScopeInfo instrumentationScopeInfo,
Resource resource) {
Resource resource,
boolean preserveNames) {
this.instrumentationScopeInfo = instrumentationScopeInfo;
this.resource = resource;
this.name = getNameWithoutUnit(metricMetadata);
this.name =
preserveNames ? metricMetadata.getOriginalName() : getNameWithoutUnit(metricMetadata);
this.description = metricMetadata.getHelp();
this.unit = convertUnit(metricMetadata.getUnit());
this.data = data;
Expand Down
Loading
Loading