Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,9 @@
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
Expand All @@ -82,7 +80,6 @@ final class Otel2PrometheusConverter {
private static final long NANOS_PER_MILLISECOND = TimeUnit.MILLISECONDS.toNanos(1);
static final int MAX_CACHE_SIZE = 10;

private final boolean otelScopeEnabled;
@Nullable private final Predicate<String> allowedResourceAttributesFilter;

/**
Expand All @@ -94,14 +91,10 @@ final class Otel2PrometheusConverter {
/**
* Constructor with feature flag parameter.
*
* @param otelScopeEnabled enable generation of the OpenTelemetry instrumentation scope info
* metric and labels.
* @param allowedResourceAttributesFilter if not {@code null}, resource attributes with keys
* matching this predicate will be added as labels on each exported metric
*/
Otel2PrometheusConverter(
boolean otelScopeEnabled, @Nullable Predicate<String> allowedResourceAttributesFilter) {
this.otelScopeEnabled = otelScopeEnabled;
Otel2PrometheusConverter(@Nullable Predicate<String> allowedResourceAttributesFilter) {
this.allowedResourceAttributesFilter = allowedResourceAttributesFilter;
this.resourceAttributesToAllowedKeysCache =
allowedResourceAttributesFilter != null
Expand All @@ -115,7 +108,6 @@ MetricSnapshots convert(@Nullable Collection<MetricData> metricDataCollection) {
}
Map<String, MetricSnapshot> snapshotsByName = new HashMap<>(metricDataCollection.size());
Resource resource = null;
Set<InstrumentationScopeInfo> scopes = new LinkedHashSet<>();
for (MetricData metricData : metricDataCollection) {
MetricSnapshot snapshot = convert(metricData);
if (snapshot == null) {
Expand All @@ -125,16 +117,10 @@ MetricSnapshots convert(@Nullable Collection<MetricData> metricDataCollection) {
if (resource == null) {
resource = metricData.getResource();
}
if (otelScopeEnabled && !metricData.getInstrumentationScopeInfo().getAttributes().isEmpty()) {
scopes.add(metricData.getInstrumentationScopeInfo());
}
}
if (resource != null) {
putOrMerge(snapshotsByName, makeTargetInfo(resource));
}
if (otelScopeEnabled && !scopes.isEmpty()) {
putOrMerge(snapshotsByName, makeScopeInfo(scopes));
}
return new MetricSnapshots(snapshotsByName.values());
}

Expand Down Expand Up @@ -440,25 +426,11 @@ private InfoSnapshot makeTargetInfo(Resource resource) {
resource.getAttributes()))));
}

private InfoSnapshot makeScopeInfo(Set<InstrumentationScopeInfo> scopes) {
List<InfoDataPointSnapshot> prometheusScopeInfos = new ArrayList<>(scopes.size());
for (InstrumentationScopeInfo scope : scopes) {
prometheusScopeInfos.add(
new InfoDataPointSnapshot(
convertAttributes(
null, // resource attributes are only copied for point's attributes
scope,
scope.getAttributes())));
}
return new InfoSnapshot(new MetricMetadata("otel_scope"), prometheusScopeInfos);
}

/**
* Convert OpenTelemetry attributes to Prometheus labels.
*
* @param resource optional resource (attributes) to be converted.
* @param scope will be converted to {@code otel_scope_*} labels if {@code otelScopeEnabled} is
* {@code true}.
* @param scope will be converted to {@code otel_scope_*} labels.
* @param attributes the attributes to be converted.
* @param additionalAttributes optional list of key/value pairs, may be empty.
*/
Expand All @@ -485,7 +457,7 @@ private Labels convertAttributes(
requireNonNull(additionalAttributes[i]), additionalAttributes[i + 1]);
}

if (otelScopeEnabled && scope != null) {
if (scope != null) {
labelNameToValue.putIfAbsent(OTEL_SCOPE_NAME, scope.getName());
if (scope.getVersion() != null) {
labelNameToValue.putIfAbsent(OTEL_SCOPE_VERSION, scope.getVersion());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ public final class PrometheusHttpServer implements MetricReader {

private final String host;
private final int port;
private final boolean otelScopeEnabled;
@Nullable private final Predicate<String> allowedResourceAttributesFilter;
private final MemoryMode memoryMode;
private final DefaultAggregationSelector defaultAggregationSelector;
Expand Down Expand Up @@ -72,21 +71,18 @@ public static PrometheusHttpServerBuilder builder() {
int port,
@Nullable ExecutorService executor,
PrometheusRegistry prometheusRegistry,
boolean otelScopeEnabled,
@Nullable Predicate<String> allowedResourceAttributesFilter,
MemoryMode memoryMode,
@Nullable HttpHandler defaultHandler,
DefaultAggregationSelector defaultAggregationSelector,
@Nullable Authenticator authenticator) {
this.host = host;
this.port = port;
this.otelScopeEnabled = otelScopeEnabled;
this.allowedResourceAttributesFilter = allowedResourceAttributesFilter;
this.memoryMode = memoryMode;
this.defaultAggregationSelector = defaultAggregationSelector;
this.builder = builder;
this.prometheusMetricReader =
new PrometheusMetricReader(otelScopeEnabled, allowedResourceAttributesFilter);
this.prometheusMetricReader = new PrometheusMetricReader(allowedResourceAttributesFilter);
this.prometheusRegistry = prometheusRegistry;
prometheusRegistry.register(prometheusMetricReader);
// When memory mode is REUSABLE_DATA, concurrent reads lead to data corruption. To prevent this,
Expand Down Expand Up @@ -171,7 +167,6 @@ public String toString() {
StringJoiner joiner = new StringJoiner(",", "PrometheusHttpServer{", "}");
joiner.add("host=" + host);
joiner.add("port=" + port);
joiner.add("otelScopeEnabled=" + otelScopeEnabled);
joiner.add("allowedResourceAttributesFilter=" + allowedResourceAttributesFilter);
joiner.add("memoryMode=" + memoryMode);
joiner.add(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ public final class PrometheusHttpServerBuilder {
private String host = DEFAULT_HOST;
private int port = DEFAULT_PORT;
private PrometheusRegistry prometheusRegistry = new PrometheusRegistry();
private boolean otelScopeEnabled = true;
@Nullable private Predicate<String> allowedResourceAttributesFilter;
@Nullable private ExecutorService executor;
private MemoryMode memoryMode = DEFAULT_MEMORY_MODE;
Expand All @@ -45,7 +44,6 @@ public final class PrometheusHttpServerBuilder {
this.host = builder.host;
this.port = builder.port;
this.prometheusRegistry = builder.prometheusRegistry;
this.otelScopeEnabled = builder.otelScopeEnabled;
this.allowedResourceAttributesFilter = builder.allowedResourceAttributesFilter;
this.executor = builder.executor;
this.memoryMode = builder.memoryMode;
Expand Down Expand Up @@ -83,10 +81,14 @@ 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}.
*
* @deprecated {@code otel_scope_*} attributes are always generated.
*/
@SuppressWarnings("UnusedReturnValue")
@Deprecated
public PrometheusHttpServerBuilder setOtelScopeEnabled(boolean otelScopeEnabled) {
this.otelScopeEnabled = otelScopeEnabled;
return this;
}

Expand Down Expand Up @@ -176,7 +178,6 @@ public PrometheusHttpServer build() {
port,
executor,
prometheusRegistry,
otelScopeEnabled,
allowedResourceAttributesFilter,
memoryMode,
defaultHandler,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,21 @@ public class PrometheusMetricReader implements MetricReader, MultiCollector {
private volatile CollectionRegistration collectionRegistration = CollectionRegistration.noop();
private final Otel2PrometheusConverter converter;

// TODO: refactor to public static create or builder pattern to align with project style
/** See {@link Otel2PrometheusConverter#Otel2PrometheusConverter(boolean, Predicate)}. */
/**
* Deprecated. Use {@link #PrometheusMetricReader(Predicate)}.
*
* @deprecated use {@link #PrometheusMetricReader(Predicate)}.
*/
@Deprecated
@SuppressWarnings({"unused", "InconsistentOverloads"})
public PrometheusMetricReader(
boolean otelScopeEnabled, @Nullable Predicate<String> allowedResourceAttributesFilter) {
this.converter =
new Otel2PrometheusConverter(otelScopeEnabled, allowedResourceAttributesFilter);
this.converter = new Otel2PrometheusConverter(allowedResourceAttributesFilter);
}

// TODO: refactor to public static create or builder pattern to align with project style
public PrometheusMetricReader(@Nullable Predicate<String> allowedResourceAttributesFilter) {
this.converter = new Otel2PrometheusConverter(allowedResourceAttributesFilter);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,6 @@ public MetricReader create(DeclarativeConfigProperties config) {
prometheusBuilder.setHost(host);
}

Boolean withoutScopeInfo = config.getBoolean("without_scope_info");
if (withoutScopeInfo != null) {
prometheusBuilder.setOtelScopeEnabled(!withoutScopeInfo);
}

DeclarativeConfigProperties withResourceConstantLabels =
config.getStructured("with_resource_constant_labels");
if (withResourceConstantLabels != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class Otel2PrometheusConverterTest {
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

private final Otel2PrometheusConverter converter =
new Otel2PrometheusConverter(true, /* allowedResourceAttributesFilter= */ null);
new Otel2PrometheusConverter(/* allowedResourceAttributesFilter= */ null);

@ParameterizedTest
@MethodSource("metricMetadataArgs")
Expand Down Expand Up @@ -201,7 +201,7 @@ void resourceAttributesAddition(
throws IOException {

Otel2PrometheusConverter converter =
new Otel2PrometheusConverter(true, allowedResourceAttributesFilter);
new Otel2PrometheusConverter(allowedResourceAttributesFilter);

ByteArrayOutputStream out = new ByteArrayOutputStream();
MetricSnapshots snapshots = converter.convert(Collections.singletonList(metricData));
Expand Down Expand Up @@ -501,7 +501,7 @@ void validateCacheIsBounded() {
};

Otel2PrometheusConverter otel2PrometheusConverter =
new Otel2PrometheusConverter(true, /* allowedResourceAttributesFilter= */ countPredicate);
new Otel2PrometheusConverter(/* allowedResourceAttributesFilter= */ countPredicate);

// Create 20 different metric data objects with 2 different resource attributes;
Resource resource1 = Resource.builder().put("cluster", "cluster1").build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,6 @@ void stringRepresentation() {
"PrometheusHttpServer{"
+ "host=localhost,"
+ "port=0,"
+ "otelScopeEnabled=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}"
Expand Down Expand Up @@ -528,7 +527,6 @@ void toBuilder() {
PrometheusHttpServerBuilder builder = PrometheusHttpServer.builder();
builder.setHost("localhost");
builder.setPort(1234);
builder.setOtelScopeEnabled(false);

Predicate<String> resourceAttributesFilter = s -> false;
builder.setAllowedResourceAttributesFilter(resourceAttributesFilter);
Expand All @@ -555,7 +553,6 @@ public Result authenticate(HttpExchange exchange) {
.isInstanceOf(PrometheusHttpServerBuilder.class)
.hasFieldOrPropertyWithValue("host", "localhost")
.hasFieldOrPropertyWithValue("port", 1234)
.hasFieldOrPropertyWithValue("otelScopeEnabled", false)
.hasFieldOrPropertyWithValue("allowedResourceAttributesFilter", resourceAttributesFilter)
.hasFieldOrPropertyWithValue("executor", executor)
.hasFieldOrPropertyWithValue("prometheusRegistry", prometheusRegistry)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(true, /* allowedResourceAttributesFilter= */ null);
this.reader = new PrometheusMetricReader(/* allowedResourceAttributesFilter= */ null);
this.meter =
SdkMeterProvider.builder()
.setClock(testClock)
Expand Down Expand Up @@ -776,7 +776,7 @@ void exponentialHistogramBucketConversion() {
int otelScale = random.nextInt(24) - 4;
int prometheusScale = Math.min(otelScale, 8);
PrometheusMetricReader reader =
new PrometheusMetricReader(true, /* allowedResourceAttributesFilter= */ null);
new PrometheusMetricReader(/* allowedResourceAttributesFilter= */ null);
Meter meter =
SdkMeterProvider.builder()
.registerMetricReader(reader)
Expand Down Expand Up @@ -1027,9 +1027,9 @@ void otelScopeComplete() throws IOException {
}

@Test
void otelScopeDisabled() throws IOException {
void otelScopeLabelsOnly() throws IOException {
PrometheusMetricReader reader =
new PrometheusMetricReader(false, /* allowedResourceAttributesFilter= */ null);
new PrometheusMetricReader(/* allowedResourceAttributesFilter= */ null);
Meter meter =
SdkMeterProvider.builder()
.setClock(testClock)
Expand All @@ -1047,8 +1047,8 @@ void otelScopeDisabled() throws IOException {
+ "# 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 1.0\n"
+ "test_count_created "
+ "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\"} "
+ createdTimestamp
+ "\n"
+ "# EOF\n";
Expand All @@ -1059,8 +1059,7 @@ void otelScopeDisabled() throws IOException {
@Test
void addResourceAttributesWorks() throws IOException {
PrometheusMetricReader reader =
new PrometheusMetricReader(
true, /* allowedResourceAttributesFilter= */ Predicates.is("cluster"));
new PrometheusMetricReader(/* allowedResourceAttributesFilter= */ Predicates.is("cluster"));
Meter meter =
SdkMeterProvider.builder()
.setClock(testClock)
Expand Down Expand Up @@ -1091,6 +1090,14 @@ void addResourceAttributesWorks() throws IOException {
assertThat(toOpenMetrics(reader.collect())).isEqualTo(expected);
}

@SuppressWarnings("deprecation") // test deprecated constructor
@Test
void deprecatedConstructor() {
assertThat(new PrometheusMetricReader(false, null))
.usingRecursiveComparison()
.isEqualTo(new PrometheusMetricReader(null));
}

/**
* Unfortunately there is no easy way to use {@link TestClock} for Exemplar timestamps. Test if
* {@code expected} equals {@code actual} but {@code <timestamp>} matches arbitrary timestamps.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,6 @@ void create_PullPrometheusConfigured() throws IOException {
PrometheusHttpServer.builder()
.setHost("localhost")
.setPort(port)
.setOtelScopeEnabled(false)
.setAllowedResourceAttributesFilter(
IncludeExcludePredicate.createPatternMatching(
singletonList("foo"), singletonList("bar")))
Expand Down
Loading