From 13b3e1da24aa58de3eff4059ccbb2ff7843601cf Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Sun, 21 Dec 2025 00:14:10 +0100 Subject: [PATCH 1/7] update prom exporter settings --- .../prometheus/PrometheusHttpServer.java | 11 +++++++++- .../PrometheusHttpServerBuilder.java | 21 +++++++++++++++---- .../prometheus/PrometheusMetricReader.java | 2 +- .../internal/PrometheusComponentProvider.java | 9 ++++++++ 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServer.java b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServer.java index caecae015d3..9e11d3c0a44 100644 --- a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServer.java +++ b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServer.java @@ -42,6 +42,8 @@ public final class PrometheusHttpServer implements MetricReader { private final String host; private final int port; + private final boolean otelScopeLabelsEnabled; + private final boolean otelTargetInfoMetricEnabled; @Nullable private final Predicate allowedResourceAttributesFilter; private final MemoryMode memoryMode; private final DefaultAggregationSelector defaultAggregationSelector; @@ -71,6 +73,8 @@ public static PrometheusHttpServerBuilder builder() { int port, @Nullable ExecutorService executor, PrometheusRegistry prometheusRegistry, + boolean otelScopeLabelsEnabled, + boolean otelTargetInfoMetricEnabled, @Nullable Predicate allowedResourceAttributesFilter, MemoryMode memoryMode, @Nullable HttpHandler defaultHandler, @@ -78,11 +82,14 @@ public static PrometheusHttpServerBuilder builder() { @Nullable Authenticator authenticator) { this.host = host; this.port = port; + this.otelScopeLabelsEnabled = otelScopeLabelsEnabled; + this.otelTargetInfoMetricEnabled = otelTargetInfoMetricEnabled; this.allowedResourceAttributesFilter = allowedResourceAttributesFilter; this.memoryMode = memoryMode; this.defaultAggregationSelector = defaultAggregationSelector; this.builder = builder; - this.prometheusMetricReader = new PrometheusMetricReader(allowedResourceAttributesFilter); + this.prometheusMetricReader = + new PrometheusMetricReader(otelScopeLabelsEnabled, otelTargetInfoMetricEnabled, allowedResourceAttributesFilter); this.prometheusRegistry = prometheusRegistry; prometheusRegistry.register(prometheusMetricReader); // When memory mode is REUSABLE_DATA, concurrent reads lead to data corruption. To prevent this, @@ -167,6 +174,8 @@ public String toString() { StringJoiner joiner = new StringJoiner(",", "PrometheusHttpServer{", "}"); joiner.add("host=" + host); joiner.add("port=" + port); + joiner.add("otelScopeLabelsEnabled=" + otelScopeLabelsEnabled); + joiner.add("otelTargetInfoMetricEnabled=" + otelTargetInfoMetricEnabled); joiner.add("allowedResourceAttributesFilter=" + allowedResourceAttributesFilter); joiner.add("memoryMode=" + memoryMode); joiner.add( diff --git a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServerBuilder.java b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServerBuilder.java index defe4091c73..1760d517df8 100644 --- a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServerBuilder.java +++ b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServerBuilder.java @@ -30,6 +30,8 @@ public final class PrometheusHttpServerBuilder { private String host = DEFAULT_HOST; private int port = DEFAULT_PORT; private PrometheusRegistry prometheusRegistry = new PrometheusRegistry(); + private boolean otelScopeLabelsEnabled = true; + private boolean otelTargetInfoMetricEnabled = true; @Nullable private Predicate allowedResourceAttributesFilter; @Nullable private ExecutorService executor; private MemoryMode memoryMode = DEFAULT_MEMORY_MODE; @@ -44,6 +46,8 @@ public final class PrometheusHttpServerBuilder { this.host = builder.host; this.port = builder.port; this.prometheusRegistry = builder.prometheusRegistry; + this.otelScopeLabelsEnabled = builder.otelScopeLabelsEnabled; + this.otelTargetInfoMetricEnabled = builder.otelTargetInfoMetricEnabled; this.allowedResourceAttributesFilter = builder.allowedResourceAttributesFilter; this.executor = builder.executor; this.memoryMode = builder.memoryMode; @@ -83,12 +87,19 @@ public PrometheusHttpServerBuilder setPrometheusRegistry(PrometheusRegistry prom /** * Set if the {@code otel_scope_*} attributes are generated. Default is {@code true}. - * - * @deprecated {@code otel_scope_*} attributes are always generated. */ @SuppressWarnings("UnusedReturnValue") - @Deprecated - public PrometheusHttpServerBuilder setOtelScopeEnabled(boolean otelScopeEnabled) { + public PrometheusHttpServerBuilder setOtelScopeLabelsEnabled(boolean otelScopeLabelsEnabled) { + this.otelScopeLabelsEnabled = otelScopeLabelsEnabled; + return this; + } + + /** + * Set if the {@code otel_target_info} metric is generated. Default is {@code true}. + */ + @SuppressWarnings("UnusedReturnValue") + public PrometheusHttpServerBuilder setOtelTargetInfoMetricEnabled(boolean otelTargetInfoMetricEnabled) { + this.otelTargetInfoMetricEnabled = otelTargetInfoMetricEnabled; return this; } @@ -178,6 +189,8 @@ public PrometheusHttpServer build() { port, executor, prometheusRegistry, + otelScopeLabelsEnabled, + otelTargetInfoMetricEnabled, allowedResourceAttributesFilter, memoryMode, defaultHandler, diff --git a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReader.java b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReader.java index ad607390023..a3b2468a8f8 100644 --- a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReader.java +++ b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReader.java @@ -36,7 +36,7 @@ public class PrometheusMetricReader implements MetricReader, MultiCollector { @Deprecated @SuppressWarnings({"unused", "InconsistentOverloads"}) public PrometheusMetricReader( - boolean otelScopeEnabled, @Nullable Predicate allowedResourceAttributesFilter) { + boolean otelScopeLabelsEnabled, @Nullable Predicate allowedResourceAttributesFilter) { this.converter = new Otel2PrometheusConverter(allowedResourceAttributesFilter); } diff --git a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/internal/PrometheusComponentProvider.java b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/internal/PrometheusComponentProvider.java index 9968c279536..28bfc274247 100644 --- a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/internal/PrometheusComponentProvider.java +++ b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/internal/PrometheusComponentProvider.java @@ -45,6 +45,15 @@ public MetricReader create(DeclarativeConfigProperties config) { prometheusBuilder.setHost(host); } + Boolean withoutTargetInfo = config.getBoolean("without_target_info"); + if (withoutTargetInfo != null) { + prometheusBuilder.setOtelTargetInfoMetricEnabled(!withoutTargetInfo); + } + Boolean withoutScopeInfo = config.getBoolean("without_scope_info"); + if (withoutScopeInfo != null) { + prometheusBuilder.setOtelScopeLabelsEnabled(!withoutScopeInfo); + } + DeclarativeConfigProperties withResourceConstantLabels = config.getStructured("with_resource_constant_labels"); if (withResourceConstantLabels != null) { From b62ffc5970e94c1c69e28d3b373bc10e2eda053b Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Sun, 21 Dec 2025 00:33:19 +0100 Subject: [PATCH 2/7] update prom exporter settings --- .../prometheus/Otel2PrometheusConverter.java | 18 +++-- .../prometheus/PrometheusHttpServer.java | 6 +- .../PrometheusHttpServerBuilder.java | 11 ++- .../prometheus/PrometheusMetricReader.java | 62 ++++++++++++++-- .../PrometheusMetricReaderBuilder.java | 70 +++++++++++++++++++ .../Otel2PrometheusConverterTest.java | 15 +++- .../PrometheusMetricReaderTest.java | 17 +++-- 7 files changed, 172 insertions(+), 27 deletions(-) create mode 100644 exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReaderBuilder.java diff --git a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/Otel2PrometheusConverter.java b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/Otel2PrometheusConverter.java index 1e952b36a09..8de81b8e0ee 100644 --- a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/Otel2PrometheusConverter.java +++ b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/Otel2PrometheusConverter.java @@ -80,6 +80,8 @@ final class Otel2PrometheusConverter { private static final long NANOS_PER_MILLISECOND = TimeUnit.MILLISECONDS.toNanos(1); static final int MAX_CACHE_SIZE = 10; + private final boolean otelScopeLabelsEnabled; + private final boolean otelTargetInfoMetricEnabled; @Nullable private final Predicate allowedResourceAttributesFilter; /** @@ -89,12 +91,20 @@ final class Otel2PrometheusConverter { private final Map>> resourceAttributesToAllowedKeysCache; /** - * Constructor with feature flag parameter. + * Constructor with feature flag parameters. * + * @param otelScopeLabelsEnabled whether to add OpenTelemetry scope labels to exported metrics + * @param otelTargetInfoMetricEnabled whether to export the target_info metric with resource + * attributes * @param allowedResourceAttributesFilter if not {@code null}, resource attributes with keys * matching this predicate will be added as labels on each exported metric */ - Otel2PrometheusConverter(@Nullable Predicate allowedResourceAttributesFilter) { + Otel2PrometheusConverter( + boolean otelScopeLabelsEnabled, + boolean otelTargetInfoMetricEnabled, + @Nullable Predicate allowedResourceAttributesFilter) { + this.otelScopeLabelsEnabled = otelScopeLabelsEnabled; + this.otelTargetInfoMetricEnabled = otelTargetInfoMetricEnabled; this.allowedResourceAttributesFilter = allowedResourceAttributesFilter; this.resourceAttributesToAllowedKeysCache = allowedResourceAttributesFilter != null @@ -118,7 +128,7 @@ MetricSnapshots convert(@Nullable Collection metricDataCollection) { resource = metricData.getResource(); } } - if (resource != null) { + if (resource != null && otelTargetInfoMetricEnabled) { putOrMerge(snapshotsByName, makeTargetInfo(resource)); } return new MetricSnapshots(snapshotsByName.values()); @@ -457,7 +467,7 @@ private Labels convertAttributes( requireNonNull(additionalAttributes[i]), additionalAttributes[i + 1]); } - if (scope != null) { + if (scope != null && otelScopeLabelsEnabled) { labelNameToValue.putIfAbsent(OTEL_SCOPE_NAME, scope.getName()); if (scope.getVersion() != null) { labelNameToValue.putIfAbsent(OTEL_SCOPE_VERSION, scope.getVersion()); diff --git a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServer.java b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServer.java index 9e11d3c0a44..1e8d486e3f4 100644 --- a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServer.java +++ b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServer.java @@ -89,7 +89,11 @@ public static PrometheusHttpServerBuilder builder() { this.defaultAggregationSelector = defaultAggregationSelector; this.builder = builder; this.prometheusMetricReader = - new PrometheusMetricReader(otelScopeLabelsEnabled, otelTargetInfoMetricEnabled, allowedResourceAttributesFilter); + PrometheusMetricReader.builder() + .setOtelScopeLabelsEnabled(otelScopeLabelsEnabled) + .setOtelTargetInfoMetricEnabled(otelTargetInfoMetricEnabled) + .setAllowedResourceAttributesFilter(allowedResourceAttributesFilter) + .build(); this.prometheusRegistry = prometheusRegistry; prometheusRegistry.register(prometheusMetricReader); // When memory mode is REUSABLE_DATA, concurrent reads lead to data corruption. To prevent this, diff --git a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServerBuilder.java b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServerBuilder.java index 1760d517df8..eeb30f33a68 100644 --- a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServerBuilder.java +++ b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServerBuilder.java @@ -85,20 +85,17 @@ public PrometheusHttpServerBuilder setPrometheusRegistry(PrometheusRegistry prom return this; } - /** - * Set if the {@code otel_scope_*} attributes are generated. Default is {@code true}. - */ + /** Set if the {@code otel_scope_*} attributes are generated. Default is {@code true}. */ @SuppressWarnings("UnusedReturnValue") public PrometheusHttpServerBuilder setOtelScopeLabelsEnabled(boolean otelScopeLabelsEnabled) { this.otelScopeLabelsEnabled = otelScopeLabelsEnabled; return this; } - /** - * Set if the {@code otel_target_info} metric is generated. Default is {@code true}. - */ + /** Set if the {@code otel_target_info} metric is generated. Default is {@code true}. */ @SuppressWarnings("UnusedReturnValue") - public PrometheusHttpServerBuilder setOtelTargetInfoMetricEnabled(boolean otelTargetInfoMetricEnabled) { + public PrometheusHttpServerBuilder setOtelTargetInfoMetricEnabled( + boolean otelTargetInfoMetricEnabled) { this.otelTargetInfoMetricEnabled = otelTargetInfoMetricEnabled; return this; } diff --git a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReader.java b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReader.java index a3b2468a8f8..c7ba0d2ad3d 100644 --- a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReader.java +++ b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReader.java @@ -27,22 +27,66 @@ public class PrometheusMetricReader implements MetricReader, MultiCollector { private volatile CollectionRegistration collectionRegistration = CollectionRegistration.noop(); private final Otel2PrometheusConverter converter; + private final PrometheusMetricReaderBuilder builder; + + /** Returns a new {@link PrometheusMetricReader} with default configuration. */ + public static PrometheusMetricReader create() { + return builder().build(); + } + + /** Returns a new {@link PrometheusMetricReaderBuilder}. */ + public static PrometheusMetricReaderBuilder builder() { + return new PrometheusMetricReaderBuilder(); + } /** - * Deprecated. Use {@link #PrometheusMetricReader(Predicate)}. + * Deprecated. Use {@link #builder()}. * - * @deprecated use {@link #PrometheusMetricReader(Predicate)}. + * @deprecated use {@link #builder()}. */ @Deprecated @SuppressWarnings({"unused", "InconsistentOverloads"}) public PrometheusMetricReader( boolean otelScopeLabelsEnabled, @Nullable Predicate allowedResourceAttributesFilter) { - this.converter = new Otel2PrometheusConverter(allowedResourceAttributesFilter); + this.builder = + new PrometheusMetricReaderBuilder() + .setOtelScopeLabelsEnabled(otelScopeLabelsEnabled) + .setAllowedResourceAttributesFilter(allowedResourceAttributesFilter); + this.converter = + new Otel2PrometheusConverter( + otelScopeLabelsEnabled, + /* otelTargetInfoMetricEnabled= */ true, + allowedResourceAttributesFilter); } - // TODO: refactor to public static create or builder pattern to align with project style + /** + * Deprecated. Use {@link #builder()}. + * + * @deprecated use {@link #builder()}. + */ + @Deprecated public PrometheusMetricReader(@Nullable Predicate allowedResourceAttributesFilter) { - this.converter = new Otel2PrometheusConverter(allowedResourceAttributesFilter); + this.builder = + new PrometheusMetricReaderBuilder() + .setAllowedResourceAttributesFilter(allowedResourceAttributesFilter); + this.converter = + new Otel2PrometheusConverter( + /* otelScopeLabelsEnabled= */ true, + /* otelTargetInfoMetricEnabled= */ true, + allowedResourceAttributesFilter); + } + + // Package-private constructor used by builder + @SuppressWarnings("InconsistentOverloads") + PrometheusMetricReader( + @Nullable Predicate allowedResourceAttributesFilter, + PrometheusMetricReaderBuilder builder, + boolean otelScopeLabelsEnabled, + boolean otelTargetInfoMetricEnabled) { + this.builder = builder; + this.converter = + new Otel2PrometheusConverter( + otelScopeLabelsEnabled, otelTargetInfoMetricEnabled, allowedResourceAttributesFilter); } @Override @@ -69,4 +113,12 @@ public CompletableResultCode shutdown() { public MetricSnapshots collect() { return converter.convert(collectionRegistration.collectAllMetrics()); } + + /** + * Returns a new {@link PrometheusMetricReaderBuilder} with the same configuration as this + * instance. + */ + public PrometheusMetricReaderBuilder toBuilder() { + return new PrometheusMetricReaderBuilder(builder); + } } diff --git a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReaderBuilder.java b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReaderBuilder.java new file mode 100644 index 00000000000..173ad18ed0d --- /dev/null +++ b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReaderBuilder.java @@ -0,0 +1,70 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.exporter.prometheus; + +import java.util.function.Predicate; +import javax.annotation.Nullable; + +/** Builder for {@link PrometheusMetricReader}. */ +public final class PrometheusMetricReaderBuilder { + + private boolean otelScopeLabelsEnabled = true; + private boolean otelTargetInfoMetricEnabled = true; + @Nullable private Predicate allowedResourceAttributesFilter; + + PrometheusMetricReaderBuilder() {} + + // Copy constructor for toBuilder() + PrometheusMetricReaderBuilder(PrometheusMetricReaderBuilder builder) { + this.otelScopeLabelsEnabled = builder.otelScopeLabelsEnabled; + this.otelTargetInfoMetricEnabled = builder.otelTargetInfoMetricEnabled; + this.allowedResourceAttributesFilter = builder.allowedResourceAttributesFilter; + } + + /** + * Sets whether to add OpenTelemetry scope labels (otel_scope_name, otel_scope_version, etc.) to + * exported metrics. Default is {@code true}. + * + * @param otelScopeLabelsEnabled whether to add scope labels + * @return this builder + */ + public PrometheusMetricReaderBuilder setOtelScopeLabelsEnabled(boolean otelScopeLabelsEnabled) { + this.otelScopeLabelsEnabled = otelScopeLabelsEnabled; + return this; + } + + /** + * Sets whether to export the target_info metric with resource attributes. Default is {@code + * true}. + * + * @param otelTargetInfoMetricEnabled whether to export target_info metric + * @return this builder + */ + public PrometheusMetricReaderBuilder setOtelTargetInfoMetricEnabled( + boolean otelTargetInfoMetricEnabled) { + this.otelTargetInfoMetricEnabled = otelTargetInfoMetricEnabled; + return this; + } + + /** + * Sets a filter to control which resource attributes are added as labels on each exported metric. + * If {@code null}, no resource attributes will be added as labels. Default is {@code null}. + * + * @param allowedResourceAttributesFilter predicate to filter resource attributes, or {@code null} + * @return this builder + */ + public PrometheusMetricReaderBuilder setAllowedResourceAttributesFilter( + @Nullable Predicate allowedResourceAttributesFilter) { + this.allowedResourceAttributesFilter = allowedResourceAttributesFilter; + return this; + } + + /** Builds a new {@link PrometheusMetricReader}. */ + public PrometheusMetricReader build() { + return new PrometheusMetricReader( + allowedResourceAttributesFilter, this, otelScopeLabelsEnabled, otelTargetInfoMetricEnabled); + } +} diff --git a/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/Otel2PrometheusConverterTest.java b/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/Otel2PrometheusConverterTest.java index 4660d8d1ee8..7967345a572 100644 --- a/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/Otel2PrometheusConverterTest.java +++ b/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/Otel2PrometheusConverterTest.java @@ -71,7 +71,10 @@ class Otel2PrometheusConverterTest { private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); private final Otel2PrometheusConverter converter = - new Otel2PrometheusConverter(/* allowedResourceAttributesFilter= */ null); + new Otel2PrometheusConverter( + /* otelScopeLabelsEnabled= */ true, + /* otelTargetInfoMetricEnabled= */ true, + /* allowedResourceAttributesFilter= */ null); @ParameterizedTest @MethodSource("metricMetadataArgs") @@ -201,7 +204,10 @@ void resourceAttributesAddition( throws IOException { Otel2PrometheusConverter converter = - new Otel2PrometheusConverter(allowedResourceAttributesFilter); + new Otel2PrometheusConverter( + /* otelScopeLabelsEnabled= */ true, + /* otelTargetInfoMetricEnabled= */ true, + allowedResourceAttributesFilter); ByteArrayOutputStream out = new ByteArrayOutputStream(); MetricSnapshots snapshots = converter.convert(Collections.singletonList(metricData)); @@ -501,7 +507,10 @@ void validateCacheIsBounded() { }; Otel2PrometheusConverter otel2PrometheusConverter = - new Otel2PrometheusConverter(/* allowedResourceAttributesFilter= */ countPredicate); + new Otel2PrometheusConverter( + /* otelScopeLabelsEnabled= */ true, + /* otelTargetInfoMetricEnabled= */ true, + /* allowedResourceAttributesFilter= */ countPredicate); // Create 20 different metric data objects with 2 different resource attributes; Resource resource1 = Resource.builder().put("cluster", "cluster1").build(); diff --git a/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReaderTest.java b/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReaderTest.java index 12bfad8d7bc..916dbc3e688 100644 --- a/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReaderTest.java +++ b/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReaderTest.java @@ -61,7 +61,7 @@ class PrometheusMetricReaderTest { void setUp() { this.testClock.setTime(Instant.ofEpochMilli((System.currentTimeMillis() / 100) * 100)); this.createdTimestamp = convertTimestamp(testClock.now()); - this.reader = new PrometheusMetricReader(/* allowedResourceAttributesFilter= */ null); + this.reader = PrometheusMetricReader.create(); this.meter = SdkMeterProvider.builder() .setClock(testClock) @@ -775,8 +775,7 @@ void exponentialHistogramBucketConversion() { for (int i = 0; i < 100_000; i++) { int otelScale = random.nextInt(24) - 4; int prometheusScale = Math.min(otelScale, 8); - PrometheusMetricReader reader = - new PrometheusMetricReader(/* allowedResourceAttributesFilter= */ null); + PrometheusMetricReader reader = PrometheusMetricReader.create(); Meter meter = SdkMeterProvider.builder() .registerMetricReader(reader) @@ -1028,8 +1027,7 @@ void otelScopeComplete() throws IOException { @Test void otelScopeLabelsOnly() throws IOException { - PrometheusMetricReader reader = - new PrometheusMetricReader(/* allowedResourceAttributesFilter= */ null); + PrometheusMetricReader reader = PrometheusMetricReader.create(); Meter meter = SdkMeterProvider.builder() .setClock(testClock) @@ -1059,7 +1057,9 @@ void otelScopeLabelsOnly() throws IOException { @Test void addResourceAttributesWorks() throws IOException { PrometheusMetricReader reader = - new PrometheusMetricReader(/* allowedResourceAttributesFilter= */ Predicates.is("cluster")); + PrometheusMetricReader.builder() + .setAllowedResourceAttributesFilter(Predicates.is("cluster")) + .build(); Meter meter = SdkMeterProvider.builder() .setClock(testClock) @@ -1093,8 +1093,11 @@ void addResourceAttributesWorks() throws IOException { @SuppressWarnings("deprecation") // test deprecated constructor @Test void deprecatedConstructor() { - assertThat(new PrometheusMetricReader(false, null)) + // The 2-arg deprecated constructor should behave the same as the 1-arg constructor + // when otelScopeLabelsEnabled=true (which is also the default for the builder) + assertThat(new PrometheusMetricReader(/* otelScopeLabelsEnabled= */ true, null)) .usingRecursiveComparison() + .ignoringFields("builder") .isEqualTo(new PrometheusMetricReader(null)); } From b6aae9f61fd53171d82f21b6e3af4f782996879d Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Sun, 21 Dec 2025 09:34:25 +0100 Subject: [PATCH 3/7] update prom exporter settings --- .../prometheus/PrometheusMetricReader.java | 36 +++++-------------- .../PrometheusMetricReaderBuilder.java | 2 +- .../prometheus/PrometheusHttpServerTest.java | 2 ++ 3 files changed, 11 insertions(+), 29 deletions(-) diff --git a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReader.java b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReader.java index c7ba0d2ad3d..e9524c2626d 100644 --- a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReader.java +++ b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReader.java @@ -27,7 +27,6 @@ public class PrometheusMetricReader implements MetricReader, MultiCollector { private volatile CollectionRegistration collectionRegistration = CollectionRegistration.noop(); private final Otel2PrometheusConverter converter; - private final PrometheusMetricReaderBuilder builder; /** Returns a new {@link PrometheusMetricReader} with default configuration. */ public static PrometheusMetricReader create() { @@ -48,15 +47,10 @@ public static PrometheusMetricReaderBuilder builder() { @SuppressWarnings({"unused", "InconsistentOverloads"}) public PrometheusMetricReader( boolean otelScopeLabelsEnabled, @Nullable Predicate allowedResourceAttributesFilter) { - this.builder = - new PrometheusMetricReaderBuilder() - .setOtelScopeLabelsEnabled(otelScopeLabelsEnabled) - .setAllowedResourceAttributesFilter(allowedResourceAttributesFilter); - this.converter = - new Otel2PrometheusConverter( - otelScopeLabelsEnabled, - /* otelTargetInfoMetricEnabled= */ true, - allowedResourceAttributesFilter); + this( + allowedResourceAttributesFilter, + otelScopeLabelsEnabled, + /* otelTargetInfoMetricEnabled= */ true); } /** @@ -66,24 +60,18 @@ public PrometheusMetricReader( */ @Deprecated public PrometheusMetricReader(@Nullable Predicate allowedResourceAttributesFilter) { - this.builder = - new PrometheusMetricReaderBuilder() - .setAllowedResourceAttributesFilter(allowedResourceAttributesFilter); - this.converter = - new Otel2PrometheusConverter( - /* otelScopeLabelsEnabled= */ true, - /* otelTargetInfoMetricEnabled= */ true, - allowedResourceAttributesFilter); + this( + allowedResourceAttributesFilter, + /* otelScopeLabelsEnabled= */ true, + /* otelTargetInfoMetricEnabled= */ true); } // Package-private constructor used by builder @SuppressWarnings("InconsistentOverloads") PrometheusMetricReader( @Nullable Predicate allowedResourceAttributesFilter, - PrometheusMetricReaderBuilder builder, boolean otelScopeLabelsEnabled, boolean otelTargetInfoMetricEnabled) { - this.builder = builder; this.converter = new Otel2PrometheusConverter( otelScopeLabelsEnabled, otelTargetInfoMetricEnabled, allowedResourceAttributesFilter); @@ -113,12 +101,4 @@ public CompletableResultCode shutdown() { public MetricSnapshots collect() { return converter.convert(collectionRegistration.collectAllMetrics()); } - - /** - * Returns a new {@link PrometheusMetricReaderBuilder} with the same configuration as this - * instance. - */ - public PrometheusMetricReaderBuilder toBuilder() { - return new PrometheusMetricReaderBuilder(builder); - } } diff --git a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReaderBuilder.java b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReaderBuilder.java index 173ad18ed0d..e98924b1374 100644 --- a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReaderBuilder.java +++ b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReaderBuilder.java @@ -65,6 +65,6 @@ public PrometheusMetricReaderBuilder setAllowedResourceAttributesFilter( /** Builds a new {@link PrometheusMetricReader}. */ public PrometheusMetricReader build() { return new PrometheusMetricReader( - allowedResourceAttributesFilter, this, otelScopeLabelsEnabled, otelTargetInfoMetricEnabled); + allowedResourceAttributesFilter, otelScopeLabelsEnabled, otelTargetInfoMetricEnabled); } } diff --git a/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServerTest.java b/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServerTest.java index fc11be75c6d..7165f48099a 100644 --- a/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServerTest.java +++ b/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServerTest.java @@ -432,6 +432,8 @@ void stringRepresentation() { "PrometheusHttpServer{" + "host=localhost," + "port=0," + + "otelScopeLabelsEnabled=true," + + "otelTargetInfoMetricEnabled=true," + "allowedResourceAttributesFilter=null," + "memoryMode=REUSABLE_DATA," + "defaultAggregationSelector=DefaultAggregationSelector{COUNTER=default, UP_DOWN_COUNTER=default, HISTOGRAM=default, OBSERVABLE_COUNTER=default, OBSERVABLE_UP_DOWN_COUNTER=default, OBSERVABLE_GAUGE=default, GAUGE=default}" From b7b9295ea83ddfe1dc539623e590ed0ab746c35d Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Sun, 21 Dec 2025 09:39:30 +0100 Subject: [PATCH 4/7] update prom exporter settings --- .../exporter/prometheus/PrometheusMetricReader.java | 5 +++-- .../exporter/prometheus/PrometheusMetricReaderTest.java | 7 +++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReader.java b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReader.java index e9524c2626d..ed7aa59daa1 100644 --- a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReader.java +++ b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReader.java @@ -46,10 +46,11 @@ public static PrometheusMetricReaderBuilder builder() { @Deprecated @SuppressWarnings({"unused", "InconsistentOverloads"}) public PrometheusMetricReader( - boolean otelScopeLabelsEnabled, @Nullable Predicate allowedResourceAttributesFilter) { + boolean otelScopeEnabled, @Nullable Predicate allowedResourceAttributesFilter) { + // otelScopeEnabled parameter was used to control the scope info metric, not scope labels. this( allowedResourceAttributesFilter, - otelScopeLabelsEnabled, + /* otelScopeLabelsEnabled= */ true, /* otelTargetInfoMetricEnabled= */ true); } diff --git a/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReaderTest.java b/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReaderTest.java index 916dbc3e688..d3ee50e239a 100644 --- a/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReaderTest.java +++ b/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReaderTest.java @@ -1095,9 +1095,12 @@ void addResourceAttributesWorks() throws IOException { void deprecatedConstructor() { // The 2-arg deprecated constructor should behave the same as the 1-arg constructor // when otelScopeLabelsEnabled=true (which is also the default for the builder) - assertThat(new PrometheusMetricReader(/* otelScopeLabelsEnabled= */ true, null)) + assertThat(new PrometheusMetricReader(/* otelScopeEnabled= */ false, null)) + .usingRecursiveComparison() + .isEqualTo(new PrometheusMetricReader(null)); + // The 3-arg constructor should behave the same as the 2-arg deprecated constructor + assertThat(new PrometheusMetricReader(null, /* otelScopeLabelsEnabled= */ true, /* otelTargetInfoMetricEnabled */ true)) .usingRecursiveComparison() - .ignoringFields("builder") .isEqualTo(new PrometheusMetricReader(null)); } From 1576ad72ea6a481e0c1848bf11781c88ee8086b2 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Sun, 21 Dec 2025 09:56:22 +0100 Subject: [PATCH 5/7] update prom exporter settings --- .../PrometheusMetricReaderTest.java | 72 +++++++------------ 1 file changed, 26 insertions(+), 46 deletions(-) diff --git a/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReaderTest.java b/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReaderTest.java index d3ee50e239a..93b9fe1a29e 100644 --- a/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReaderTest.java +++ b/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReaderTest.java @@ -23,6 +23,7 @@ import io.opentelemetry.sdk.metrics.SdkMeterProvider; import io.opentelemetry.sdk.metrics.View; import io.opentelemetry.sdk.resources.Resource; +import io.opentelemetry.sdk.resources.ResourceBuilder; import io.opentelemetry.sdk.testing.time.TestClock; import io.opentelemetry.sdk.trace.SdkTracerProvider; import io.prometheus.metrics.expositionformats.OpenMetricsTextFormatWriter; @@ -997,28 +998,17 @@ void createdTimestamp() throws IOException { } @Test - void otelScopeComplete() throws IOException { - // There is currently no API for adding scope attributes. - // However, we can at least test the otel_scope_version attribute. - Meter meter = - SdkMeterProvider.builder() - .setClock(testClock) - .registerMetricReader(this.reader) - .setResource( - Resource.getDefault().toBuilder().put("telemetry.sdk.version", "1.x.x").build()) - .build() - .meterBuilder("test-scope") - .setInstrumentationVersion("a.b.c") - .build(); - LongCounter counter = meter.counterBuilder("test.count").build(); - counter.add(1); + void withoutScopeLabels() throws IOException { + PrometheusMetricReader reader = + PrometheusMetricReader.builder().setOtelScopeLabelsEnabled(false).build(); + addCounter(reader, Resource.getDefault().toBuilder()); String expected = "" + "# TYPE target info\n" + "target_info{service_name=\"unknown_service:java\",telemetry_sdk_language=\"java\",telemetry_sdk_name=\"opentelemetry\",telemetry_sdk_version=\"1.x.x\"} 1\n" + "# TYPE test_count counter\n" - + "test_count_total{otel_scope_name=\"test-scope\",otel_scope_version=\"a.b.c\"} 1.0\n" - + "test_count_created{otel_scope_name=\"test-scope\",otel_scope_version=\"a.b.c\"} " + + "test_count_total 1.0\n" + + "test_count_created " + createdTimestamp + "\n" + "# EOF\n"; @@ -1026,24 +1016,12 @@ void otelScopeComplete() throws IOException { } @Test - void otelScopeLabelsOnly() throws IOException { - PrometheusMetricReader reader = PrometheusMetricReader.create(); - Meter meter = - SdkMeterProvider.builder() - .setClock(testClock) - .registerMetricReader(reader) - .setResource( - Resource.getDefault().toBuilder().put("telemetry.sdk.version", "1.x.x").build()) - .build() - .meterBuilder("test-scope") - .setInstrumentationVersion("a.b.c") - .build(); - LongCounter counter = meter.counterBuilder("test.count").build(); - counter.add(1); + void withoutTargetInfoMetric() throws IOException { + PrometheusMetricReader reader = + PrometheusMetricReader.builder().setOtelTargetInfoMetricEnabled(false).build(); + addCounter(reader, Resource.getDefault().toBuilder()); String expected = "" - + "# TYPE target info\n" - + "target_info{service_name=\"unknown_service:java\",telemetry_sdk_language=\"java\",telemetry_sdk_name=\"opentelemetry\",telemetry_sdk_version=\"1.x.x\"} 1\n" + "# TYPE test_count counter\n" + "test_count_total{otel_scope_name=\"test-scope\",otel_scope_version=\"a.b.c\"} 1.0\n" + "test_count_created{otel_scope_name=\"test-scope\",otel_scope_version=\"a.b.c\"} " @@ -1053,28 +1031,28 @@ void otelScopeLabelsOnly() throws IOException { assertThat(toOpenMetrics(reader.collect())).isEqualTo(expected); } - @SuppressWarnings("resource") - @Test - void addResourceAttributesWorks() throws IOException { - PrometheusMetricReader reader = - PrometheusMetricReader.builder() - .setAllowedResourceAttributesFilter(Predicates.is("cluster")) - .build(); + private void addCounter(PrometheusMetricReader reader, ResourceBuilder builder) { Meter meter = SdkMeterProvider.builder() .setClock(testClock) .registerMetricReader(reader) - .setResource( - Resource.getDefault().toBuilder() - .put("cluster", "my.cluster") - .put("telemetry.sdk.version", "1.x.x") - .build()) + .setResource(builder.put("telemetry.sdk.version", "1.x.x").build()) .build() .meterBuilder("test-scope") .setInstrumentationVersion("a.b.c") .build(); LongCounter counter = meter.counterBuilder("test.count").build(); counter.add(1); + } + + @SuppressWarnings("resource") + @Test + void addResourceAttributesWorks() throws IOException { + PrometheusMetricReader reader = + PrometheusMetricReader.builder() + .setAllowedResourceAttributesFilter(Predicates.is("cluster")) + .build(); + addCounter(reader, Resource.getDefault().toBuilder().put("cluster", "my.cluster")); String expected = "" + "# TYPE target info\n" @@ -1099,7 +1077,9 @@ void deprecatedConstructor() { .usingRecursiveComparison() .isEqualTo(new PrometheusMetricReader(null)); // The 3-arg constructor should behave the same as the 2-arg deprecated constructor - assertThat(new PrometheusMetricReader(null, /* otelScopeLabelsEnabled= */ true, /* otelTargetInfoMetricEnabled */ true)) + assertThat( + new PrometheusMetricReader( + null, /* otelScopeLabelsEnabled= */ true, /* otelTargetInfoMetricEnabled */ true)) .usingRecursiveComparison() .isEqualTo(new PrometheusMetricReader(null)); } From 2792235a1f30c85c0348317aee0ed730bfeb8e14 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Sun, 21 Dec 2025 10:21:12 +0100 Subject: [PATCH 6/7] update prom exporter settings --- .../incubator/fileconfig/MetricReaderFactoryTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/MetricReaderFactoryTest.java b/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/MetricReaderFactoryTest.java index bc63ca7bdcb..1cc7fe94c81 100644 --- a/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/MetricReaderFactoryTest.java +++ b/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/MetricReaderFactoryTest.java @@ -189,7 +189,8 @@ void create_PullPrometheusConfigured() throws IOException { new IncludeExcludeModel() .withIncluded(singletonList("foo")) .withExcluded(singletonList("bar"))) - .withWithoutScopeInfo(true) + .withWithoutScopeInfo(false) + .withWithoutTargetInfo(false) .withTranslationStrategy( ExperimentalPrometheusMetricExporterModel .ExperimentalPrometheusTranslationStrategy From 57bbd9c42df32e9bd7628637c8ff82c9dc54b718 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Sun, 21 Dec 2025 10:30:14 +0100 Subject: [PATCH 7/7] update prom exporter settings --- .../exporter/prometheus/PrometheusMetricReaderBuilder.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReaderBuilder.java b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReaderBuilder.java index e98924b1374..1998f34565b 100644 --- a/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReaderBuilder.java +++ b/exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusMetricReaderBuilder.java @@ -17,13 +17,6 @@ public final class PrometheusMetricReaderBuilder { PrometheusMetricReaderBuilder() {} - // Copy constructor for toBuilder() - PrometheusMetricReaderBuilder(PrometheusMetricReaderBuilder builder) { - this.otelScopeLabelsEnabled = builder.otelScopeLabelsEnabled; - this.otelTargetInfoMetricEnabled = builder.otelTargetInfoMetricEnabled; - this.allowedResourceAttributesFilter = builder.allowedResourceAttributesFilter; - } - /** * Sets whether to add OpenTelemetry scope labels (otel_scope_name, otel_scope_version, etc.) to * exported metrics. Default is {@code true}.