Skip to content

Commit e5d9bbc

Browse files
committed
Extend prometheus declarative config support to include without_scope_info, with_resource_constant_labels
1 parent 2e8bf7f commit e5d9bbc

File tree

13 files changed

+348
-131
lines changed

13 files changed

+348
-131
lines changed

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

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.io.IOException;
2626
import java.io.UncheckedIOException;
2727
import java.net.InetSocketAddress;
28+
import java.util.StringJoiner;
2829
import java.util.concurrent.ExecutorService;
2930
import java.util.concurrent.LinkedBlockingQueue;
3031
import java.util.concurrent.ThreadPoolExecutor;
@@ -38,13 +39,17 @@
3839
*/
3940
public final class PrometheusHttpServer implements MetricReader {
4041

42+
private final String host;
43+
private final int port;
44+
private final boolean otelScopeEnabled;
45+
@Nullable private final Predicate<String> allowedResourceAttributesFilter;
46+
private final MemoryMode memoryMode;
47+
private final DefaultAggregationSelector defaultAggregationSelector;
48+
4149
private final PrometheusHttpServerBuilder builder;
4250
private final HTTPServer httpServer;
4351
private final PrometheusMetricReader prometheusMetricReader;
4452
private final PrometheusRegistry prometheusRegistry;
45-
private final String host;
46-
private final MemoryMode memoryMode;
47-
private final DefaultAggregationSelector defaultAggregationSelector;
4853

4954
/**
5055
* Returns a new {@link PrometheusHttpServer} which can be registered to an {@link
@@ -71,11 +76,16 @@ public static PrometheusHttpServerBuilder builder() {
7176
MemoryMode memoryMode,
7277
@Nullable HttpHandler defaultHandler,
7378
DefaultAggregationSelector defaultAggregationSelector) {
79+
this.host = host;
80+
this.port = port;
81+
this.otelScopeEnabled = otelScopeEnabled;
82+
this.allowedResourceAttributesFilter = allowedResourceAttributesFilter;
83+
this.memoryMode = memoryMode;
84+
this.defaultAggregationSelector = defaultAggregationSelector;
85+
7486
this.builder = builder;
7587
this.prometheusMetricReader =
7688
new PrometheusMetricReader(otelScopeEnabled, allowedResourceAttributesFilter);
77-
this.host = host;
78-
this.memoryMode = memoryMode;
7989
this.prometheusRegistry = prometheusRegistry;
8090
prometheusRegistry.register(prometheusMetricReader);
8191
// When memory mode is REUSABLE_DATA, concurrent reads lead to data corruption. To prevent this,
@@ -103,7 +113,6 @@ public static PrometheusHttpServerBuilder builder() {
103113
} catch (IOException e) {
104114
throw new UncheckedIOException("Could not create Prometheus HTTP server", e);
105115
}
106-
this.defaultAggregationSelector = defaultAggregationSelector;
107116
}
108117

109118
@Override
@@ -157,7 +166,16 @@ public void close() {
157166

158167
@Override
159168
public String toString() {
160-
return "PrometheusHttpServer{address=" + getAddress() + "}";
169+
StringJoiner joiner = new StringJoiner(",", "PrometheusHttpServer{", "}");
170+
joiner.add("host=" + host);
171+
joiner.add("port=" + port);
172+
joiner.add("otelScopeEnabled=" + otelScopeEnabled);
173+
joiner.add("allowedResourceAttributesFilter=" + allowedResourceAttributesFilter);
174+
joiner.add("memoryMode=" + memoryMode);
175+
joiner.add(
176+
"defaultAggregationSelector="
177+
+ DefaultAggregationSelector.asString(defaultAggregationSelector));
178+
return joiner.toString();
161179
}
162180

163181
/**

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
import io.opentelemetry.exporter.prometheus.PrometheusHttpServerBuilder;
1010
import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider;
1111
import io.opentelemetry.sdk.autoconfigure.spi.internal.StructuredConfigProperties;
12+
import io.opentelemetry.sdk.internal.IncludeExcludePredicate;
1213
import io.opentelemetry.sdk.metrics.export.MetricReader;
14+
import java.util.List;
1315

1416
/**
1517
* Declarative configuration SPI implementation for {@link PrometheusHttpServer}.
@@ -37,11 +39,28 @@ public MetricReader create(StructuredConfigProperties config) {
3739
if (port != null) {
3840
prometheusBuilder.setPort(port);
3941
}
42+
4043
String host = config.getString("host");
4144
if (host != null) {
4245
prometheusBuilder.setHost(host);
4346
}
4447

48+
Boolean withoutScopeInfo = config.getBoolean("without_scope_info");
49+
if (withoutScopeInfo != null) {
50+
prometheusBuilder.setOtelScopeEnabled(!withoutScopeInfo);
51+
}
52+
53+
StructuredConfigProperties withResourceConstantLabels =
54+
config.getStructured("with_resource_constant_labels");
55+
if (withResourceConstantLabels != null) {
56+
List<String> included = withResourceConstantLabels.getScalarList("included", String.class);
57+
List<String> excluded = withResourceConstantLabels.getScalarList("excluded", String.class);
58+
if (included != null || excluded != null) {
59+
prometheusBuilder.setAllowedResourceAttributesFilter(
60+
IncludeExcludePredicate.createPatternMatching(included, excluded));
61+
}
62+
}
63+
4564
return prometheusBuilder.build();
4665
}
4766
}

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,15 @@ void fetch_DuplicateMetrics() {
405405
@Test
406406
void stringRepresentation() {
407407
assertThat(prometheusServer.toString())
408-
.isEqualTo("PrometheusHttpServer{address=" + prometheusServer.getAddress() + "}");
408+
.isEqualTo(
409+
"PrometheusHttpServer{"
410+
+ "host=localhost,"
411+
+ "port=0,"
412+
+ "otelScopeEnabled=true,"
413+
+ "allowedResourceAttributesFilter=null,"
414+
+ "memoryMode=REUSABLE_DATA,"
415+
+ "defaultAggregationSelector=DefaultAggregationSelector{COUNTER=default, UP_DOWN_COUNTER=default, HISTOGRAM=default, OBSERVABLE_COUNTER=default, OBSERVABLE_UP_DOWN_COUNTER=default, OBSERVABLE_GAUGE=default, GAUGE=default}"
416+
+ "}");
409417
}
410418

411419
@Test

sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/ResourceFactory.java

Lines changed: 11 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55

66
package io.opentelemetry.sdk.extension.incubator.fileconfig;
77

8-
import static io.opentelemetry.sdk.internal.GlobUtil.toGlobPatternPredicate;
9-
108
import io.opentelemetry.sdk.autoconfigure.ResourceConfiguration;
119
import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper;
1210
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
@@ -17,6 +15,7 @@
1715
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.AttributeNameValueModel;
1816
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.DetectorAttributesModel;
1917
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.DetectorsModel;
18+
import io.opentelemetry.sdk.internal.IncludeExcludePredicate;
2019
import io.opentelemetry.sdk.resources.Resource;
2120
import io.opentelemetry.sdk.resources.ResourceBuilder;
2221
import java.io.Closeable;
@@ -147,47 +146,16 @@ private static boolean matchAll(String attributeKey) {
147146

148147
private static Predicate<String> detectorAttributeFilter(
149148
@Nullable DetectorsModel detectorsModel) {
150-
if (detectorsModel == null) {
151-
return ResourceFactory::matchAll;
152-
}
153-
DetectorAttributesModel detectorAttributesModel = detectorsModel.getAttributes();
154-
if (detectorAttributesModel == null) {
155-
return ResourceFactory::matchAll;
156-
}
157-
List<String> included = detectorAttributesModel.getIncluded();
158-
List<String> excluded = detectorAttributesModel.getExcluded();
159-
if (included == null && excluded == null) {
160-
return ResourceFactory::matchAll;
161-
}
162-
if (included == null) {
163-
return excludedPredicate(excluded);
164-
}
165-
if (excluded == null) {
166-
return includedPredicate(included);
167-
}
168-
return includedPredicate(included).and(excludedPredicate(excluded));
169-
}
170-
171-
/**
172-
* Returns a predicate which matches strings matching any of the {@code included} glob patterns.
173-
*/
174-
private static Predicate<String> includedPredicate(List<String> included) {
175-
Predicate<String> result = attributeKey -> false;
176-
for (String include : included) {
177-
result = result.or(toGlobPatternPredicate(include));
178-
}
179-
return result;
180-
}
181-
182-
/**
183-
* Returns a predicate which matches strings NOT matching any of the {@code excluded} glob
184-
* patterns.
185-
*/
186-
private static Predicate<String> excludedPredicate(List<String> excluded) {
187-
Predicate<String> result = attributeKey -> true;
188-
for (String exclude : excluded) {
189-
result = result.and(toGlobPatternPredicate(exclude).negate());
149+
if (detectorsModel != null) {
150+
DetectorAttributesModel attributesModel = detectorsModel.getAttributes();
151+
if (attributesModel != null) {
152+
List<String> included = attributesModel.getIncluded();
153+
List<String> excluded = attributesModel.getExcluded();
154+
if (included != null || excluded != null) {
155+
return IncludeExcludePredicate.createPatternMatching(included, excluded);
156+
}
157+
}
190158
}
191-
return result;
159+
return ResourceFactory::matchAll;
192160
}
193161
}

sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/ViewFactory.java

Lines changed: 6 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,11 @@
88
import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper;
99
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.IncludeExcludeModel;
1010
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.StreamModel;
11+
import io.opentelemetry.sdk.internal.IncludeExcludePredicate;
1112
import io.opentelemetry.sdk.metrics.View;
1213
import io.opentelemetry.sdk.metrics.ViewBuilder;
1314
import java.io.Closeable;
14-
import java.util.HashSet;
1515
import java.util.List;
16-
import java.util.Set;
17-
import javax.annotation.Nullable;
1816

1917
final class ViewFactory implements Factory<StreamModel, View> {
2018

@@ -37,33 +35,16 @@ public View create(StreamModel model, SpiHelper spiHelper, List<Closeable> close
3735
}
3836
IncludeExcludeModel attributeKeys = model.getAttributeKeys();
3937
if (attributeKeys != null) {
40-
addAttributeKeyFilter(builder, attributeKeys.getIncluded(), attributeKeys.getExcluded());
38+
List<String> included = attributeKeys.getIncluded();
39+
List<String> excluded = attributeKeys.getExcluded();
40+
if (included != null || excluded != null) {
41+
builder.setAttributeFilter(IncludeExcludePredicate.createExactMatching(included, excluded));
42+
}
4143
}
4244
if (model.getAggregation() != null) {
4345
builder.setAggregation(
4446
AggregationFactory.getInstance().create(model.getAggregation(), spiHelper, closeables));
4547
}
4648
return builder.build();
4749
}
48-
49-
private static void addAttributeKeyFilter(
50-
ViewBuilder builder, @Nullable List<String> included, @Nullable List<String> excluded) {
51-
if (included == null && excluded == null) {
52-
return;
53-
}
54-
if (included == null) {
55-
Set<String> excludedKeys = new HashSet<>(excluded);
56-
// TODO: set predicate with useful toString implementation
57-
builder.setAttributeFilter(attributeKey -> !excludedKeys.contains(attributeKey));
58-
return;
59-
}
60-
if (excluded == null) {
61-
Set<String> includedKeys = new HashSet<>(included);
62-
builder.setAttributeFilter(includedKeys);
63-
return;
64-
}
65-
Set<String> includedKeys = new HashSet<>(included);
66-
excluded.forEach(includedKeys::remove);
67-
builder.setAttributeFilter(includedKeys);
68-
}
6950
}

sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/MetricReaderFactoryTest.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
package io.opentelemetry.sdk.extension.incubator.fileconfig;
77

88
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
9+
import static java.util.Collections.singletonList;
910
import static org.assertj.core.api.Assertions.assertThatThrownBy;
1011
import static org.mockito.Mockito.spy;
1112
import static org.mockito.Mockito.verify;
@@ -17,13 +18,15 @@
1718
import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper;
1819
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
1920
import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider;
21+
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.IncludeExcludeModel;
2022
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.MetricReaderModel;
2123
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OtlpMetricModel;
2224
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.PeriodicMetricReaderModel;
2325
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.PrometheusModel;
2426
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.PullMetricExporterModel;
2527
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.PullMetricReaderModel;
2628
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.PushMetricExporterModel;
29+
import io.opentelemetry.sdk.internal.IncludeExcludePredicate;
2730
import java.io.Closeable;
2831
import java.io.IOException;
2932
import java.net.ServerSocket;
@@ -144,7 +147,14 @@ void create_PullPrometheusConfigured() throws IOException {
144147
spiHelper = spy(spiHelper);
145148
List<Closeable> closeables = new ArrayList<>();
146149
PrometheusHttpServer expectedReader =
147-
PrometheusHttpServer.builder().setHost("localhost").setPort(port).build();
150+
PrometheusHttpServer.builder()
151+
.setHost("localhost")
152+
.setPort(port)
153+
.setOtelScopeEnabled(false)
154+
.setAllowedResourceAttributesFilter(
155+
IncludeExcludePredicate.createPatternMatching(
156+
singletonList("foo"), singletonList("bar")))
157+
.build();
148158
// Close the reader to avoid port conflict with the new instance created by MetricReaderFactory
149159
expectedReader.close();
150160

@@ -159,7 +169,14 @@ void create_PullPrometheusConfigured() throws IOException {
159169
.withPrometheus(
160170
new PrometheusModel()
161171
.withHost("localhost")
162-
.withPort(port)))),
172+
.withPort(port)
173+
.withWithResourceConstantLabels(
174+
new IncludeExcludeModel()
175+
.withIncluded(singletonList("foo"))
176+
.withExcluded(singletonList("bar")))
177+
.withWithoutScopeInfo(true)
178+
.withWithoutTypeSuffix(true)
179+
.withWithoutUnits(true)))),
163180
spiHelper,
164181
closeables);
165182
cleanup.addCloseable(reader);

sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/ViewFactoryTest.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@
1313
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExplicitBucketHistogramModel;
1414
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.IncludeExcludeModel;
1515
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.StreamModel;
16+
import io.opentelemetry.sdk.internal.IncludeExcludePredicate;
1617
import io.opentelemetry.sdk.metrics.View;
1718
import java.util.Arrays;
1819
import java.util.Collections;
19-
import java.util.HashSet;
2020
import org.junit.jupiter.api.Test;
2121

2222
class ViewFactoryTest {
@@ -41,7 +41,9 @@ void create() {
4141
View.builder()
4242
.setName("name")
4343
.setDescription("description")
44-
.setAttributeFilter(new HashSet<>(Arrays.asList("foo", "bar")))
44+
.setAttributeFilter(
45+
IncludeExcludePredicate.createExactMatching(
46+
Arrays.asList("foo", "bar"), Collections.singletonList("baz")))
4547
.setAggregation(
4648
io.opentelemetry.sdk.metrics.Aggregation.explicitBucketHistogram(
4749
Arrays.asList(1.0, 2.0)))
@@ -54,7 +56,9 @@ void create() {
5456
.withName("name")
5557
.withDescription("description")
5658
.withAttributeKeys(
57-
new IncludeExcludeModel().withIncluded(Arrays.asList("foo", "bar")))
59+
new IncludeExcludeModel()
60+
.withIncluded(Arrays.asList("foo", "bar"))
61+
.withExcluded(Collections.singletonList("baz")))
5862
.withAggregation(
5963
new AggregationModel()
6064
.withExplicitBucketHistogram(

0 commit comments

Comments
 (0)