Skip to content

Commit 6267222

Browse files
committed
Add support for resource detectors
1 parent ea98d80 commit 6267222

File tree

12 files changed

+115
-118
lines changed

12 files changed

+115
-118
lines changed

sdk-extensions/incubator/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ dependencies {
6262
// it was needed after 0.3.0 release because file_format in the examples weren't updated prior to the release tag
6363
// val configurationTag = "0.3.0"
6464
// val configurationRef = "refs/tags/v$configurationTag" // Replace with commit SHA to point to experiment with a specific commit
65-
val configurationRef = "8425d9b03344ff96df181b9c46ec57ebdbc185e2"
65+
val configurationRef = "25da6659f5f214a737ad92a28097418536334518"
6666
val configurationRepoZip = "https://github.com/open-telemetry/opentelemetry-configuration/archive/$configurationRef.zip"
6767
val buildDirectory = layout.buildDirectory.asFile.get()
6868

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.sdk.extension.incubator.fileconfig;
7+
8+
import static java.util.stream.Collectors.joining;
9+
10+
import io.opentelemetry.api.incubator.config.DeclarativeConfigException;
11+
import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper;
12+
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExperimentalResourceDetectorModel;
13+
import io.opentelemetry.sdk.resources.Resource;
14+
import java.io.Closeable;
15+
import java.util.List;
16+
import java.util.Map;
17+
18+
final class ResourceDetectorFactory
19+
implements Factory<ExperimentalResourceDetectorModel, Resource> {
20+
21+
private static final ResourceDetectorFactory INSTANCE = new ResourceDetectorFactory();
22+
23+
private ResourceDetectorFactory() {}
24+
25+
static ResourceDetectorFactory getInstance() {
26+
return INSTANCE;
27+
}
28+
29+
@Override
30+
public Resource create(
31+
ExperimentalResourceDetectorModel model, SpiHelper spiHelper, List<Closeable> closeables) {
32+
Map<String, Object> additionalProperties = model.getAdditionalProperties();
33+
if (!additionalProperties.isEmpty()) {
34+
if (additionalProperties.size() > 1) {
35+
throw new DeclarativeConfigException(
36+
"Invalid configuration - multiple resource detectors set: "
37+
+ additionalProperties.keySet().stream().collect(joining(",", "[", "]")));
38+
}
39+
Map.Entry<String, Object> detectorKeyValue =
40+
additionalProperties.entrySet().stream()
41+
.findFirst()
42+
.orElseThrow(
43+
() ->
44+
new IllegalStateException("Missing detector. This is a programming error."));
45+
Resource resource =
46+
FileConfigUtil.loadComponent(
47+
spiHelper, Resource.class, detectorKeyValue.getKey(), detectorKeyValue.getValue());
48+
return resource;
49+
} else {
50+
throw new DeclarativeConfigException("resource detector must be set");
51+
}
52+
}
53+
}

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

Lines changed: 24 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,21 @@
77

88
import static io.opentelemetry.sdk.internal.GlobUtil.toGlobPatternPredicate;
99

10-
import io.opentelemetry.api.incubator.config.DeclarativeConfigException;
11-
import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
10+
import io.opentelemetry.api.common.Attributes;
1211
import io.opentelemetry.sdk.autoconfigure.ResourceConfiguration;
1312
import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper;
14-
import io.opentelemetry.sdk.autoconfigure.spi.Ordered;
15-
import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider;
1613
import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties;
1714
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.AttributeNameValueModel;
18-
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExperimentalDetectorsModel;
15+
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExperimentalResourceDetectionModel;
16+
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExperimentalResourceDetectorModel;
1917
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.IncludeExcludeModel;
2018
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ResourceModel;
2119
import io.opentelemetry.sdk.resources.Resource;
2220
import io.opentelemetry.sdk.resources.ResourceBuilder;
2321
import java.io.Closeable;
24-
import java.util.ArrayList;
2522
import java.util.Collections;
26-
import java.util.Comparator;
2723
import java.util.List;
2824
import java.util.function.Predicate;
29-
import java.util.stream.Collectors;
3025
import javax.annotation.Nullable;
3126

3227
final class ResourceFactory implements Factory<ResourceModel, Resource> {
@@ -43,19 +38,27 @@ static ResourceFactory getInstance() {
4338
public Resource create(ResourceModel model, SpiHelper spiHelper, List<Closeable> closeables) {
4439
ResourceBuilder builder = Resource.getDefault().toBuilder();
4540

46-
ResourceBuilder detectedResourceBuilder = Resource.builder();
47-
List<Resource> resourceDetectorResources = loadFromResourceDetectors(spiHelper);
48-
for (Resource resourceProviderResource : resourceDetectorResources) {
49-
detectedResourceBuilder.putAll(resourceProviderResource);
41+
ExperimentalResourceDetectionModel detectionModel = model.getDetectionDevelopment();
42+
if (detectionModel != null) {
43+
ResourceBuilder detectedResourceBuilder = Resource.builder();
44+
45+
List<ExperimentalResourceDetectorModel> detectorModels = detectionModel.getDetectors();
46+
if (detectorModels != null) {
47+
for (ExperimentalResourceDetectorModel detectorModel : detectorModels) {
48+
detectedResourceBuilder.putAll(
49+
ResourceDetectorFactory.getInstance().create(detectorModel, spiHelper, closeables));
50+
}
51+
}
52+
53+
Predicate<String> detectorAttributeFilter =
54+
detectorAttributeFilter(detectionModel.getAttributes());
55+
Attributes filteredDetectedAttributes =
56+
detectedResourceBuilder.build().getAttributes().toBuilder()
57+
.removeIf(attributeKey -> !detectorAttributeFilter.test(attributeKey.getKey()))
58+
.build();
59+
60+
builder.putAll(filteredDetectedAttributes);
5061
}
51-
Predicate<String> detectorAttributeFilter =
52-
detectorAttributeFilter(model.getDetectorsDevelopment());
53-
builder
54-
.putAll(
55-
detectedResourceBuilder.build().getAttributes().toBuilder()
56-
.removeIf(attributeKey -> !detectorAttributeFilter.test(attributeKey.getKey()))
57-
.build())
58-
.build();
5962

6063
String attributeList = model.getAttributesList();
6164
if (attributeList != null) {
@@ -77,72 +80,12 @@ public Resource create(ResourceModel model, SpiHelper spiHelper, List<Closeable>
7780
return builder.build();
7881
}
7982

80-
/**
81-
* Load resources from resource detectors, in order of lowest priority to highest priority.
82-
*
83-
* <p>In declarative configuration, a resource detector is a {@link ComponentProvider} with {@link
84-
* ComponentProvider#getType()} set to {@link Resource}. Unlike other {@link ComponentProvider}s,
85-
* the resource detector version does not use {@link ComponentProvider#getName()} (except for
86-
* debug messages), and {@link ComponentProvider#create(DeclarativeConfigProperties)} is called
87-
* with an empty instance. Additionally, the {@link Ordered#order()} value is respected for
88-
* resource detectors which implement {@link Ordered}.
89-
*/
90-
@SuppressWarnings("rawtypes")
91-
private static List<Resource> loadFromResourceDetectors(SpiHelper spiHelper) {
92-
List<ComponentProvider> componentProviders = spiHelper.load(ComponentProvider.class);
93-
List<ResourceAndOrder> resourceAndOrders = new ArrayList<>();
94-
for (ComponentProvider<?> componentProvider : componentProviders) {
95-
if (componentProvider.getType() != Resource.class) {
96-
continue;
97-
}
98-
Resource resource;
99-
try {
100-
resource = (Resource) componentProvider.create(DeclarativeConfigProperties.empty());
101-
} catch (Throwable throwable) {
102-
throw new DeclarativeConfigException(
103-
"Error configuring "
104-
+ Resource.class.getName()
105-
+ " with name \""
106-
+ componentProvider.getName()
107-
+ "\"",
108-
throwable);
109-
}
110-
int order =
111-
(componentProvider instanceof Ordered) ? ((Ordered) componentProvider).order() : 0;
112-
resourceAndOrders.add(new ResourceAndOrder(resource, order));
113-
}
114-
resourceAndOrders.sort(Comparator.comparing(ResourceAndOrder::order));
115-
return resourceAndOrders.stream().map(ResourceAndOrder::resource).collect(Collectors.toList());
116-
}
117-
118-
private static final class ResourceAndOrder {
119-
private final Resource resource;
120-
private final int order;
121-
122-
private ResourceAndOrder(Resource resource, int order) {
123-
this.resource = resource;
124-
this.order = order;
125-
}
126-
127-
private Resource resource() {
128-
return resource;
129-
}
130-
131-
private int order() {
132-
return order;
133-
}
134-
}
135-
13683
private static boolean matchAll(String attributeKey) {
13784
return true;
13885
}
13986

14087
private static Predicate<String> detectorAttributeFilter(
141-
@Nullable ExperimentalDetectorsModel detectorsModel) {
142-
if (detectorsModel == null) {
143-
return ResourceFactory::matchAll;
144-
}
145-
IncludeExcludeModel includedExcludeModel = detectorsModel.getAttributes();
88+
@Nullable IncludeExcludeModel includedExcludeModel) {
14689
if (includedExcludeModel == null) {
14790
return ResourceFactory::matchAll;
14891
}

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,9 +176,7 @@ void create_ModelCustomizer() {
176176
"resource=Resource{schemaUrl=null, attributes={"
177177
+ "color=\"blue\", "
178178
+ "foo=\"bar\", "
179-
+ "order=\"second\", "
180179
+ "service.name=\"unknown_service:java\", "
181-
+ "shape=\"square\", "
182180
+ "telemetry.sdk.language=\"java\", "
183181
+ "telemetry.sdk.name=\"opentelemetry\", "
184182
+ "telemetry.sdk.version=\"");

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@
1818
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.BatchSpanProcessorModel;
1919
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ClientModel;
2020
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ConsoleExporterModel;
21-
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExperimentalDetectorsModel;
2221
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExperimentalGeneralInstrumentationModel;
2322
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExperimentalHttpInstrumentationModel;
2423
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExperimentalLanguageSpecificInstrumentationModel;
2524
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExperimentalPeerInstrumentationModel;
2625
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExperimentalPrometheusMetricExporterModel;
26+
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExperimentalResourceDetectionModel;
2727
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExplicitBucketHistogramAggregationModel;
2828
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.IncludeExcludeModel;
2929
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.InstrumentationModel;
@@ -137,8 +137,8 @@ void parse_KitchenSinkExampleFile() throws IOException {
137137
.withValue(Arrays.asList(1.1, 2.2))
138138
.withType(AttributeNameValueModel.AttributeType.DOUBLE_ARRAY)))
139139
.withAttributesList("service.namespace=my-namespace,service.version=1.0.0")
140-
.withDetectorsDevelopment(
141-
new ExperimentalDetectorsModel()
140+
.withDetectionDevelopment(
141+
new ExperimentalResourceDetectionModel()
142142
.withAttributes(
143143
new IncludeExcludeModel()
144144
.withIncluded(Collections.singletonList("process.*"))

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.AttributeNameValueModel;
2828
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.BatchLogRecordProcessorModel;
2929
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.BatchSpanProcessorModel;
30+
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExperimentalResourceDetectionModel;
31+
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExperimentalResourceDetectorModel;
3032
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.LogRecordExporterModel;
3133
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.LogRecordLimitsModel;
3234
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.LogRecordProcessorModel;
@@ -215,6 +217,16 @@ void create_Configured() {
215217
.withCompositeList("tracecontext,baggage,ottrace,b3multi,b3,jaeger"))
216218
.withResource(
217219
new ResourceModel()
220+
.withDetectionDevelopment(
221+
new ExperimentalResourceDetectionModel()
222+
.withDetectors(
223+
Arrays.asList(
224+
new ExperimentalResourceDetectorModel()
225+
.withAdditionalProperty("order_first", null),
226+
new ExperimentalResourceDetectorModel()
227+
.withAdditionalProperty("order_second", null),
228+
new ExperimentalResourceDetectorModel()
229+
.withAdditionalProperty("shape_color", null))))
218230
.withAttributes(
219231
Arrays.asList(
220232
new AttributeNameValueModel()

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

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010

1111
import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper;
1212
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.AttributeNameValueModel;
13-
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExperimentalDetectorsModel;
13+
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExperimentalResourceDetectionModel;
14+
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExperimentalResourceDetectorModel;
1415
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.IncludeExcludeModel;
1516
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ResourceModel;
1617
import io.opentelemetry.sdk.resources.Resource;
@@ -48,14 +49,9 @@ void create() {
4849
Collections.emptyList()))
4950
.isEqualTo(
5051
Resource.getDefault().toBuilder()
52+
.put("shape", "circle")
5153
.put("service.name", "my-service")
5254
.put("key", "val")
53-
.put("shape", "circle")
54-
// From ResourceComponentProvider
55-
.put("color", "red")
56-
// From ResourceOrderedSecondComponentProvider, which takes priority over
57-
// ResourceOrderedFirstComponentProvider
58-
.put("order", "second")
5955
.build());
6056
}
6157

@@ -65,8 +61,16 @@ void createWithDetectors(
6561
@Nullable List<String> included, @Nullable List<String> excluded, Resource expectedResource) {
6662
ResourceModel resourceModel =
6763
new ResourceModel()
68-
.withDetectorsDevelopment(
69-
new ExperimentalDetectorsModel()
64+
.withDetectionDevelopment(
65+
new ExperimentalResourceDetectionModel()
66+
.withDetectors(
67+
Arrays.asList(
68+
new ExperimentalResourceDetectorModel()
69+
.withAdditionalProperty("order_first", null),
70+
new ExperimentalResourceDetectorModel()
71+
.withAdditionalProperty("order_second", null),
72+
new ExperimentalResourceDetectorModel()
73+
.withAdditionalProperty("shape_color", null)))
7074
.withAttributes(
7175
new IncludeExcludeModel().withIncluded(included).withExcluded(excluded)));
7276
Resource resource =

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@ public void customize(DeclarativeConfigurationCustomizer customizer) {
2929
attributes.add(
3030
new AttributeNameValueModel()
3131
.withName("foo")
32-
.withType(AttributeNameValueModel.Type.STRING)
32+
.withType(AttributeNameValueModel.AttributeType.STRING)
3333
.withValue("bar"));
3434
attributes.add(
3535
new AttributeNameValueModel()
3636
.withName("color")
37-
.withType(AttributeNameValueModel.Type.STRING)
37+
.withType(AttributeNameValueModel.AttributeType.STRING)
3838
.withValue("blue"));
3939
return model;
4040
});

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public Class<Resource> getType() {
1717

1818
@Override
1919
public String getName() {
20-
return "unused";
20+
return "shape_color";
2121
}
2222

2323
@Override

sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/component/ResourceOrderedFirstComponentProvider.java renamed to sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/component/ResourceFirstComponentProvider.java

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

88
import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
9-
import io.opentelemetry.sdk.autoconfigure.spi.Ordered;
109
import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider;
1110
import io.opentelemetry.sdk.resources.Resource;
1211

13-
public class ResourceOrderedFirstComponentProvider implements ComponentProvider<Resource>, Ordered {
12+
public class ResourceFirstComponentProvider implements ComponentProvider<Resource> {
1413
@Override
1514
public Class<Resource> getType() {
1615
return Resource.class;
1716
}
1817

1918
@Override
2019
public String getName() {
21-
return "unused";
20+
return "order_first";
2221
}
2322

2423
@Override
2524
public Resource create(DeclarativeConfigProperties config) {
2625
return Resource.builder().put("order", "first").build();
2726
}
28-
29-
@Override
30-
public int order() {
31-
return 1;
32-
}
3327
}

0 commit comments

Comments
 (0)