Skip to content

Commit 46fdadc

Browse files
adds config to enable default exponential histogram
1 parent fe8a7f4 commit 46fdadc

File tree

5 files changed

+80
-2
lines changed

5 files changed

+80
-2
lines changed

exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServer.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@
1414
import io.opentelemetry.sdk.common.CompletableResultCode;
1515
import io.opentelemetry.sdk.common.export.MemoryMode;
1616
import io.opentelemetry.sdk.internal.DaemonThreadFactory;
17+
import io.opentelemetry.sdk.metrics.Aggregation;
1718
import io.opentelemetry.sdk.metrics.InstrumentType;
1819
import io.opentelemetry.sdk.metrics.data.AggregationTemporality;
1920
import io.opentelemetry.sdk.metrics.export.CollectionRegistration;
21+
import io.opentelemetry.sdk.metrics.export.DefaultAggregationSelector;
2022
import io.opentelemetry.sdk.metrics.export.MetricReader;
2123
import io.prometheus.metrics.exporter.httpserver.HTTPServer;
2224
import io.prometheus.metrics.model.registry.PrometheusRegistry;
@@ -41,6 +43,7 @@ public final class PrometheusHttpServer implements MetricReader {
4143
private final PrometheusRegistry prometheusRegistry;
4244
private final String host;
4345
private final MemoryMode memoryMode;
46+
private final DefaultAggregationSelector defaultAggregationSelector;
4447

4548
/**
4649
* Returns a new {@link PrometheusHttpServer} which can be registered to an {@link
@@ -65,7 +68,8 @@ public static PrometheusHttpServerBuilder builder() {
6568
boolean otelScopeEnabled,
6669
@Nullable Predicate<String> allowedResourceAttributesFilter,
6770
MemoryMode memoryMode,
68-
@Nullable HttpHandler defaultHandler) {
71+
@Nullable HttpHandler defaultHandler,
72+
DefaultAggregationSelector defaultAggregationSelector) {
6973
this.builder = builder;
7074
this.prometheusMetricReader =
7175
new PrometheusMetricReader(otelScopeEnabled, allowedResourceAttributesFilter);
@@ -92,13 +96,19 @@ public static PrometheusHttpServerBuilder builder() {
9296
} catch (IOException e) {
9397
throw new UncheckedIOException("Could not create Prometheus HTTP server", e);
9498
}
99+
this.defaultAggregationSelector = defaultAggregationSelector;
95100
}
96101

97102
@Override
98103
public AggregationTemporality getAggregationTemporality(InstrumentType instrumentType) {
99104
return prometheusMetricReader.getAggregationTemporality(instrumentType);
100105
}
101106

107+
@Override
108+
public Aggregation getDefaultAggregation(InstrumentType instrumentType) {
109+
return defaultAggregationSelector.getDefaultAggregation(instrumentType);
110+
}
111+
102112
@Override
103113
public MemoryMode getMemoryMode() {
104114
return memoryMode;

exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServerBuilder.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010

1111
import com.sun.net.httpserver.HttpHandler;
1212
import io.opentelemetry.sdk.common.export.MemoryMode;
13+
import io.opentelemetry.sdk.metrics.InstrumentType;
14+
import io.opentelemetry.sdk.metrics.export.DefaultAggregationSelector;
15+
import io.opentelemetry.sdk.metrics.export.MetricExporter;
1316
import io.prometheus.metrics.model.registry.PrometheusRegistry;
1417
import java.util.concurrent.ExecutorService;
1518
import java.util.concurrent.Executors;
@@ -31,6 +34,8 @@ public final class PrometheusHttpServerBuilder {
3134
@Nullable private ExecutorService executor;
3235
private MemoryMode memoryMode = DEFAULT_MEMORY_MODE;
3336
@Nullable private HttpHandler defaultHandler;
37+
private DefaultAggregationSelector defaultAggregationSelector =
38+
DefaultAggregationSelector.getDefault();
3439

3540
PrometheusHttpServerBuilder() {}
3641

@@ -126,6 +131,19 @@ public PrometheusHttpServerBuilder setDefaultHandler(HttpHandler defaultHandler)
126131
return this;
127132
}
128133

134+
/**
135+
* Set the {@link DefaultAggregationSelector} used for {@link
136+
* MetricExporter#getDefaultAggregation(InstrumentType)}.
137+
*
138+
* <p>If unset, defaults to {@link DefaultAggregationSelector#getDefault()}.
139+
*/
140+
public PrometheusHttpServerBuilder setDefaultAggregationSelector(
141+
DefaultAggregationSelector defaultAggregationSelector) {
142+
requireNonNull(defaultAggregationSelector, "defaultAggregationSelector");
143+
this.defaultAggregationSelector = defaultAggregationSelector;
144+
return this;
145+
}
146+
129147
/**
130148
* Returns a new {@link PrometheusHttpServer} with the configuration of this builder which can be
131149
* registered with a {@link io.opentelemetry.sdk.metrics.SdkMeterProvider}.
@@ -140,6 +158,7 @@ public PrometheusHttpServer build() {
140158
otelScopeEnabled,
141159
allowedResourceAttributesFilter,
142160
memoryMode,
143-
defaultHandler);
161+
defaultHandler,
162+
defaultAggregationSelector);
144163
}
145164
}

exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/internal/PrometheusMetricReaderProvider.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,19 @@
55

66
package io.opentelemetry.exporter.prometheus.internal;
77

8+
import static io.opentelemetry.sdk.metrics.Aggregation.explicitBucketHistogram;
9+
810
import io.opentelemetry.exporter.internal.ExporterBuilderUtil;
911
import io.opentelemetry.exporter.prometheus.PrometheusHttpServer;
1012
import io.opentelemetry.exporter.prometheus.PrometheusHttpServerBuilder;
1113
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
14+
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
1215
import io.opentelemetry.sdk.autoconfigure.spi.internal.ConfigurableMetricReaderProvider;
16+
import io.opentelemetry.sdk.metrics.Aggregation;
17+
import io.opentelemetry.sdk.metrics.InstrumentType;
18+
import io.opentelemetry.sdk.metrics.export.DefaultAggregationSelector;
1319
import io.opentelemetry.sdk.metrics.export.MetricReader;
20+
import io.opentelemetry.sdk.metrics.internal.aggregator.AggregationUtil;
1421

1522
/**
1623
* SPI implementation for {@link PrometheusHttpServer}.
@@ -32,6 +39,20 @@ public MetricReader createMetricReader(ConfigProperties config) {
3239
if (host != null) {
3340
prometheusBuilder.setHost(host);
3441
}
42+
String defaultHistogramAggregation =
43+
config.getString("otel.exporter.prometheus.metrics.default.histogram.aggregation");
44+
if (defaultHistogramAggregation != null) {
45+
if (AggregationUtil.aggregationName(Aggregation.base2ExponentialBucketHistogram())
46+
.equalsIgnoreCase(defaultHistogramAggregation)) {
47+
prometheusBuilder.setDefaultAggregationSelector(
48+
DefaultAggregationSelector.getDefault()
49+
.with(InstrumentType.HISTOGRAM, Aggregation.base2ExponentialBucketHistogram()));
50+
} else if (!AggregationUtil.aggregationName(explicitBucketHistogram())
51+
.equalsIgnoreCase(defaultHistogramAggregation)) {
52+
throw new ConfigurationException(
53+
"Unrecognized default histogram aggregation: " + defaultHistogramAggregation);
54+
}
55+
}
3556

3657
ExporterBuilderUtil.configureExporterMemoryMode(config, prometheusBuilder::setMemoryMode);
3758

exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServerTest.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ void invalidConfig() {
113113
assertThatThrownBy(() -> PrometheusHttpServer.builder().setHost(""))
114114
.isInstanceOf(IllegalArgumentException.class)
115115
.hasMessage("host must not be empty");
116+
assertThatThrownBy(() -> PrometheusHttpServer.builder().setDefaultAggregationSelector(null))
117+
.isInstanceOf(NullPointerException.class)
118+
.hasMessage("defaultAggregationSelector");
116119
}
117120

118121
@Test

exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/internal/PrometheusMetricReaderProviderTest.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,18 @@
77

88
import static org.assertj.core.api.Assertions.as;
99
import static org.assertj.core.api.Assertions.assertThat;
10+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
1011
import static org.mockito.ArgumentMatchers.any;
1112
import static org.mockito.Mockito.when;
1213

1314
import com.sun.net.httpserver.HttpServer;
1415
import io.opentelemetry.exporter.prometheus.PrometheusHttpServer;
1516
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
17+
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
1618
import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties;
1719
import io.opentelemetry.sdk.common.export.MemoryMode;
20+
import io.opentelemetry.sdk.metrics.Aggregation;
21+
import io.opentelemetry.sdk.metrics.InstrumentType;
1822
import io.opentelemetry.sdk.metrics.export.MetricReader;
1923
import io.prometheus.metrics.exporter.httpserver.HTTPServer;
2024
import java.io.IOException;
@@ -59,6 +63,8 @@ void createMetricReader_Default() throws IOException {
5963
assertThat(server.getAddress().getPort()).isEqualTo(9464);
6064
});
6165
assertThat(metricReader.getMemoryMode()).isEqualTo(MemoryMode.IMMUTABLE_DATA);
66+
assertThat(metricReader.getDefaultAggregation(InstrumentType.HISTOGRAM))
67+
.isEqualTo(Aggregation.defaultAggregation());
6268
}
6369
}
6470

@@ -76,6 +82,9 @@ void createMetricReader_WithConfiguration() throws IOException {
7682
config.put("otel.exporter.prometheus.host", "localhost");
7783
config.put("otel.exporter.prometheus.port", String.valueOf(port));
7884
config.put("otel.java.experimental.exporter.memory_mode", "reusable_data");
85+
config.put(
86+
"otel.exporter.prometheus.metrics.default.histogram.aggregation",
87+
"BASE2_EXPONENTIAL_BUCKET_HISTOGRAM");
7988

8089
when(configProperties.getInt(any())).thenReturn(null);
8190
when(configProperties.getString(any())).thenReturn(null);
@@ -91,6 +100,22 @@ void createMetricReader_WithConfiguration() throws IOException {
91100
assertThat(server.getAddress().getPort()).isEqualTo(port);
92101
});
93102
assertThat(metricReader.getMemoryMode()).isEqualTo(MemoryMode.REUSABLE_DATA);
103+
assertThat(metricReader.getDefaultAggregation(InstrumentType.HISTOGRAM))
104+
.isEqualTo(Aggregation.base2ExponentialBucketHistogram());
94105
}
95106
}
107+
108+
@Test
109+
void createMetricReader_WithWrongConfiguration() throws IOException {
110+
Map<String, String> config = new HashMap<>();
111+
config.put("otel.exporter.prometheus.metrics.default.histogram.aggregation", "foo");
112+
113+
when(configProperties.getInt(any())).thenReturn(null);
114+
when(configProperties.getString(any())).thenReturn(null);
115+
116+
assertThatThrownBy(
117+
() -> provider.createMetricReader(DefaultConfigProperties.createFromMap(config)))
118+
.isInstanceOf(ConfigurationException.class)
119+
.hasMessageContaining("Unrecognized default histogram aggregation:");
120+
}
96121
}

0 commit comments

Comments
 (0)