Skip to content

Commit 49e271d

Browse files
committed
add config bridge based on ExtendedOpenTelemetry
1 parent 56b179f commit 49e271d

File tree

17 files changed

+342
-227
lines changed

17 files changed

+342
-227
lines changed

declarative-config-bridge/src/main/java/io/opentelemetry/instrumentation/config/bridge/ConfigPropertiesUtil.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public static String propertyYamlPath(String propertyName) {
1313
}
1414

1515
static String yamlPath(String property) {
16-
String[] segments = DeclarativeConfigPropertiesBridge.getSegments(property);
16+
String[] segments = SimpleDeclarativeConfigPropertiesBridge.getSegments(property);
1717
if (segments.length == 0) {
1818
throw new IllegalArgumentException("Invalid property: " + property);
1919
}

declarative-config-bridge/src/main/java/io/opentelemetry/instrumentation/config/bridge/DeclarativeConfigPropertiesBridge.java

Lines changed: 3 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,9 @@
55

66
package io.opentelemetry.instrumentation.config.bridge;
77

8-
import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty;
9-
108
import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
119
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
12-
import java.time.Duration;
13-
import java.util.Collections;
14-
import java.util.HashMap;
15-
import java.util.List;
1610
import java.util.Map;
17-
import java.util.Objects;
18-
import java.util.function.BiFunction;
19-
import javax.annotation.Nullable;
2011

2112
/**
2213
* A {@link ConfigProperties} which resolves properties based on {@link
@@ -47,142 +38,13 @@
4738
* string_key: value
4839
* </pre>
4940
*/
50-
final class DeclarativeConfigPropertiesBridge implements ConfigProperties {
51-
52-
private static final String OTEL_INSTRUMENTATION_PREFIX = "otel.instrumentation.";
53-
54-
private final DeclarativeConfigProperties baseNode;
55-
56-
// lookup order matters - we choose the first match
57-
private final Map<String, String> mappings;
58-
private final Map<String, Object> overrideValues;
41+
final class DeclarativeConfigPropertiesBridge extends SimpleDeclarativeConfigPropertiesBridge
42+
implements ConfigProperties {
5943

6044
DeclarativeConfigPropertiesBridge(
6145
DeclarativeConfigProperties baseNode,
6246
Map<String, String> mappings,
6347
Map<String, Object> overrideValues) {
64-
this.baseNode = Objects.requireNonNull(baseNode);
65-
this.mappings = mappings;
66-
this.overrideValues = overrideValues;
67-
}
68-
69-
@Nullable
70-
@Override
71-
public String getString(String propertyName) {
72-
return getPropertyValue(propertyName, String.class, DeclarativeConfigProperties::getString);
73-
}
74-
75-
@Nullable
76-
@Override
77-
public Boolean getBoolean(String propertyName) {
78-
return getPropertyValue(propertyName, Boolean.class, DeclarativeConfigProperties::getBoolean);
79-
}
80-
81-
@Nullable
82-
@Override
83-
public Integer getInt(String propertyName) {
84-
return getPropertyValue(propertyName, Integer.class, DeclarativeConfigProperties::getInt);
85-
}
86-
87-
@Nullable
88-
@Override
89-
public Long getLong(String propertyName) {
90-
return getPropertyValue(propertyName, Long.class, DeclarativeConfigProperties::getLong);
91-
}
92-
93-
@Nullable
94-
@Override
95-
public Double getDouble(String propertyName) {
96-
return getPropertyValue(propertyName, Double.class, DeclarativeConfigProperties::getDouble);
97-
}
98-
99-
@Nullable
100-
@Override
101-
public Duration getDuration(String propertyName) {
102-
Long millis = getPropertyValue(propertyName, Long.class, DeclarativeConfigProperties::getLong);
103-
if (millis == null) {
104-
return null;
105-
}
106-
return Duration.ofMillis(millis);
107-
}
108-
109-
@SuppressWarnings("unchecked")
110-
@Override
111-
public List<String> getList(String propertyName) {
112-
List<String> propertyValue =
113-
getPropertyValue(
114-
propertyName,
115-
List.class,
116-
(properties, lastPart) -> properties.getScalarList(lastPart, String.class));
117-
return propertyValue == null ? Collections.emptyList() : propertyValue;
118-
}
119-
120-
@SuppressWarnings("unchecked")
121-
@Override
122-
public Map<String, String> getMap(String propertyName) {
123-
DeclarativeConfigProperties propertyValue =
124-
getPropertyValue(
125-
propertyName,
126-
DeclarativeConfigProperties.class,
127-
DeclarativeConfigProperties::getStructured);
128-
if (propertyValue == null) {
129-
return Collections.emptyMap();
130-
}
131-
Map<String, String> result = new HashMap<>();
132-
propertyValue
133-
.getPropertyKeys()
134-
.forEach(
135-
key -> {
136-
String value = propertyValue.getString(key);
137-
if (value == null) {
138-
return;
139-
}
140-
result.put(key, value);
141-
});
142-
return Collections.unmodifiableMap(result);
143-
}
144-
145-
@Nullable
146-
private <T> T getPropertyValue(
147-
String property,
148-
Class<T> clazz,
149-
BiFunction<DeclarativeConfigProperties, String, T> extractor) {
150-
T override = clazz.cast(overrideValues.get(property));
151-
if (override != null) {
152-
return override;
153-
}
154-
155-
String[] segments = getSegments(translateProperty(property));
156-
if (segments.length == 0) {
157-
return null;
158-
}
159-
160-
// Extract the value by walking to the N-1 entry
161-
DeclarativeConfigProperties target = baseNode;
162-
if (segments.length > 1) {
163-
for (int i = 0; i < segments.length - 1; i++) {
164-
target = target.getStructured(segments[i], empty());
165-
}
166-
}
167-
String lastPart = segments[segments.length - 1];
168-
169-
return extractor.apply(target, lastPart);
170-
}
171-
172-
static String[] getSegments(String property) {
173-
if (property.startsWith(OTEL_INSTRUMENTATION_PREFIX)) {
174-
property = property.substring(OTEL_INSTRUMENTATION_PREFIX.length());
175-
}
176-
// Split the remainder of the property on "."
177-
return property.replace('-', '_').split("\\.");
178-
}
179-
180-
private String translateProperty(String property) {
181-
for (Map.Entry<String, String> entry : mappings.entrySet()) {
182-
if (property.startsWith(entry.getKey())) {
183-
return entry.getValue() + property.substring(entry.getKey().length());
184-
}
185-
}
186-
return property;
48+
super(baseNode, mappings, overrideValues);
18749
}
18850
}

declarative-config-bridge/src/main/java/io/opentelemetry/instrumentation/config/bridge/DeclarativeConfigPropertiesBridgeBuilder.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,12 @@ public ConfigProperties build(@Nullable DeclarativeConfigProperties node) {
9090
node == null ? empty() : node, mappings, overrideValues);
9191
}
9292

93+
public SimpleDeclarativeConfigPropertiesBridge buildSimple(
94+
@Nullable DeclarativeConfigProperties node) {
95+
return new SimpleDeclarativeConfigPropertiesBridge(
96+
node == null ? empty() : node, mappings, overrideValues);
97+
}
98+
9399
/**
94100
* Build {@link ConfigProperties} from the {@link DeclarativeConfigProperties} provided by the
95101
* instrumentation configuration.
@@ -105,4 +111,10 @@ public ConfigProperties buildFromInstrumentationConfig(
105111
return build(
106112
instrumentationConfig == null ? null : instrumentationConfig.getStructured("java"));
107113
}
114+
115+
public SimpleDeclarativeConfigPropertiesBridge buildSimpleFromInstrumentationConfig(
116+
@Nullable DeclarativeConfigProperties instrumentationConfig) {
117+
return buildSimple(
118+
instrumentationConfig == null ? null : instrumentationConfig.getStructured("java"));
119+
}
108120
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.instrumentation.config.bridge;
7+
8+
import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty;
9+
10+
import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
11+
import java.time.Duration;
12+
import java.util.Collections;
13+
import java.util.HashMap;
14+
import java.util.List;
15+
import java.util.Map;
16+
import java.util.Objects;
17+
import java.util.function.BiFunction;
18+
import javax.annotation.Nullable;
19+
20+
public class SimpleDeclarativeConfigPropertiesBridge {
21+
private static final String OTEL_INSTRUMENTATION_PREFIX = "otel.instrumentation.";
22+
protected final DeclarativeConfigProperties baseNode;
23+
// lookup order matters - we choose the first match
24+
protected final Map<String, String> mappings;
25+
protected final Map<String, Object> overrideValues;
26+
27+
public SimpleDeclarativeConfigPropertiesBridge(
28+
DeclarativeConfigProperties baseNode,
29+
Map<String, String> mappings,
30+
Map<String, Object> overrideValues) {
31+
this.baseNode = Objects.requireNonNull(baseNode);
32+
this.mappings = mappings;
33+
this.overrideValues = overrideValues;
34+
}
35+
36+
@Nullable
37+
public String getString(String propertyName) {
38+
return getPropertyValue(propertyName, String.class, DeclarativeConfigProperties::getString);
39+
}
40+
41+
@Nullable
42+
public Boolean getBoolean(String propertyName) {
43+
return getPropertyValue(propertyName, Boolean.class, DeclarativeConfigProperties::getBoolean);
44+
}
45+
46+
@Nullable
47+
public Integer getInt(String propertyName) {
48+
return getPropertyValue(propertyName, Integer.class, DeclarativeConfigProperties::getInt);
49+
}
50+
51+
@Nullable
52+
public Long getLong(String propertyName) {
53+
return getPropertyValue(propertyName, Long.class, DeclarativeConfigProperties::getLong);
54+
}
55+
56+
@Nullable
57+
public Double getDouble(String propertyName) {
58+
return getPropertyValue(propertyName, Double.class, DeclarativeConfigProperties::getDouble);
59+
}
60+
61+
@Nullable
62+
public Duration getDuration(String propertyName) {
63+
Long millis = getPropertyValue(propertyName, Long.class, DeclarativeConfigProperties::getLong);
64+
if (millis == null) {
65+
return null;
66+
}
67+
return Duration.ofMillis(millis);
68+
}
69+
70+
@SuppressWarnings("unchecked")
71+
public List<String> getList(String propertyName) {
72+
List<String> propertyValue =
73+
getPropertyValue(
74+
propertyName,
75+
List.class,
76+
(properties, lastPart) -> properties.getScalarList(lastPart, String.class));
77+
return propertyValue == null ? Collections.emptyList() : propertyValue;
78+
}
79+
80+
@SuppressWarnings("unchecked")
81+
public Map<String, String> getMap(String propertyName) {
82+
DeclarativeConfigProperties propertyValue =
83+
getPropertyValue(
84+
propertyName,
85+
DeclarativeConfigProperties.class,
86+
DeclarativeConfigProperties::getStructured);
87+
if (propertyValue == null) {
88+
return Collections.emptyMap();
89+
}
90+
Map<String, String> result = new HashMap<>();
91+
propertyValue
92+
.getPropertyKeys()
93+
.forEach(
94+
key -> {
95+
String value = propertyValue.getString(key);
96+
if (value == null) {
97+
return;
98+
}
99+
result.put(key, value);
100+
});
101+
return Collections.unmodifiableMap(result);
102+
}
103+
104+
@Nullable
105+
private <T> T getPropertyValue(
106+
String property,
107+
Class<T> clazz,
108+
BiFunction<DeclarativeConfigProperties, String, T> extractor) {
109+
T override = clazz.cast(overrideValues.get(property));
110+
if (override != null) {
111+
return override;
112+
}
113+
114+
String[] segments = getSegments(translateProperty(property));
115+
if (segments.length == 0) {
116+
return null;
117+
}
118+
119+
// Extract the value by walking to the N-1 entry
120+
DeclarativeConfigProperties target = baseNode;
121+
if (segments.length > 1) {
122+
for (int i = 0; i < segments.length - 1; i++) {
123+
target = target.getStructured(segments[i], empty());
124+
}
125+
}
126+
String lastPart = segments[segments.length - 1];
127+
128+
return extractor.apply(target, lastPart);
129+
}
130+
131+
static String[] getSegments(String property) {
132+
if (property.startsWith(OTEL_INSTRUMENTATION_PREFIX)) {
133+
property = property.substring(OTEL_INSTRUMENTATION_PREFIX.length());
134+
}
135+
// Split the remainder of the property on "."
136+
return property.replace('-', '_').split("\\.");
137+
}
138+
139+
private String translateProperty(String property) {
140+
for (Map.Entry<String, String> entry : mappings.entrySet()) {
141+
if (property.startsWith(entry.getKey())) {
142+
return entry.getValue() + property.substring(entry.getKey().length());
143+
}
144+
}
145+
return property;
146+
}
147+
}

dependencyManagement/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ plugins {
55
data class DependencySet(val group: String, val version: String, val modules: List<String>)
66

77
// this line is managed by .github/scripts/update-sdk-version.sh
8-
val otelSdkVersion = "1.54.1"
8+
val otelSdkVersion = "1.55.0-SNAPSHOT" // todo revert after next SDK release
99
val otelContribVersion = "1.49.0-alpha"
1010
val otelSdkAlphaVersion = otelSdkVersion.replaceFirst("(-SNAPSHOT)?$".toRegex(), "-alpha$1")
1111

instrumentation-api/build.gradle.kts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ dependencies {
1616
api("io.opentelemetry:opentelemetry-api")
1717
implementation("io.opentelemetry:opentelemetry-api-incubator")
1818
implementation("io.opentelemetry.semconv:opentelemetry-semconv")
19+
implementation(project(":declarative-config-bridge")) {
20+
exclude(group = "io.opentelemetry", module = "opentelemetry-sdk-extension-autoconfigure-spi")
21+
}
1922

2023
compileOnly("com.google.auto.value:auto-value-annotations")
2124
annotationProcessor("com.google.auto.value:auto-value")

instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import io.opentelemetry.context.Context;
2020
import io.opentelemetry.context.propagation.TextMapGetter;
2121
import io.opentelemetry.context.propagation.TextMapSetter;
22-
import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil;
22+
import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesSimpleBridge;
2323
import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties;
2424
import io.opentelemetry.instrumentation.api.internal.Experimental;
2525
import io.opentelemetry.instrumentation.api.internal.InstrumenterBuilderAccess;
@@ -49,11 +49,6 @@ public final class InstrumenterBuilder<REQUEST, RESPONSE> {
4949

5050
private static final Logger logger = Logger.getLogger(InstrumenterBuilder.class.getName());
5151

52-
private static final SpanSuppressionStrategy spanSuppressionStrategy =
53-
SpanSuppressionStrategy.fromConfig(
54-
ConfigPropertiesUtil.getString(
55-
"otel.instrumentation.experimental.span-suppression-strategy"));
56-
5752
final OpenTelemetry openTelemetry;
5853
final String instrumentationName;
5954
SpanNameExtractor<? super REQUEST> spanNameExtractor;
@@ -374,7 +369,10 @@ private String getSchemaUrl() {
374369

375370
SpanSuppressor buildSpanSuppressor() {
376371
return new SpanSuppressors.ByContextKey(
377-
spanSuppressionStrategy.create(getSpanKeysFromAttributesExtractors()));
372+
SpanSuppressionStrategy.fromConfig(
373+
new ConfigPropertiesSimpleBridge(openTelemetry)
374+
.getString("otel.instrumentation.experimental.span-suppression-strategy"))
375+
.create(getSpanKeysFromAttributesExtractors()));
378376
}
379377

380378
private Set<SpanKey> getSpanKeysFromAttributesExtractors() {

0 commit comments

Comments
 (0)