Skip to content

Commit dc4f216

Browse files
committed
use unified config bridge
1 parent b9369f3 commit dc4f216

File tree

7 files changed

+358
-64
lines changed

7 files changed

+358
-64
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.extension.internal;
7+
8+
import io.opentelemetry.api.incubator.config.ConfigProvider;
9+
import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
10+
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
11+
import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil;
12+
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
13+
import javax.annotation.Nullable;
14+
15+
/**
16+
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
17+
* any time.
18+
*/
19+
public final class ConfigPropertiesUtil {
20+
private ConfigPropertiesUtil() {}
21+
22+
/** Resolve {@link ConfigProperties} from the {@code autoConfiguredOpenTelemetrySdk}. */
23+
public static ConfigProperties resolveConfigProperties(
24+
AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk) {
25+
ConfigProperties sdkConfigProperties =
26+
AutoConfigureUtil.getConfig(autoConfiguredOpenTelemetrySdk);
27+
if (sdkConfigProperties != null) {
28+
return sdkConfigProperties;
29+
}
30+
ConfigProvider configProvider =
31+
AutoConfigureUtil.getConfigProvider(autoConfiguredOpenTelemetrySdk);
32+
if (configProvider != null) {
33+
return resolveInstrumentationConfig(
34+
configProvider.getInstrumentationConfig(), propertyTranslatorBuilder());
35+
}
36+
// Should never happen
37+
throw new IllegalStateException(
38+
"AutoConfiguredOpenTelemetrySdk does not have ConfigProperties or DeclarativeConfigProperties. This is likely a programming error in opentelemetry-java");
39+
}
40+
41+
public static ConfigProperties resolveInstrumentationConfig(
42+
@Nullable DeclarativeConfigProperties instrumentationConfig) {
43+
return resolveInstrumentationConfig(instrumentationConfig, propertyTranslatorBuilder());
44+
}
45+
46+
public static ConfigProperties resolveInstrumentationConfig(
47+
@Nullable DeclarativeConfigProperties instrumentationConfig,
48+
PropertyTranslatorBuilder builder) {
49+
return DeclarativeConfigPropertiesBridge.fromInstrumentationConfig(
50+
instrumentationConfig, builder.build());
51+
}
52+
53+
public static ConfigProperties resolveConfig(
54+
@Nullable DeclarativeConfigProperties config, PropertyTranslatorBuilder builder) {
55+
return DeclarativeConfigPropertiesBridge.create(config, builder.build());
56+
}
57+
58+
public static String propertyYamlPath(String propertyName) {
59+
return DeclarativeConfigPropertiesBridge.yamlPath(propertyName);
60+
}
61+
62+
public static PropertyTranslatorBuilder propertyTranslatorBuilder() {
63+
return new PropertyTranslatorBuilder();
64+
}
65+
}

javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/extension/internal/DeclarativeConfigPropertiesBridge.java

Lines changed: 66 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty;
99

10-
import io.opentelemetry.api.incubator.config.ConfigProvider;
1110
import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
1211
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
1312
import java.time.Duration;
@@ -50,36 +49,37 @@
5049
* <p>This class is internal and is hence not for public use. Its APIs are unstable and can change
5150
* at any time.
5251
*/
53-
public final class DeclarativeConfigPropertiesBridge implements ConfigProperties {
52+
final class DeclarativeConfigPropertiesBridge implements ConfigProperties {
5453

5554
private static final String OTEL_INSTRUMENTATION_PREFIX = "otel.instrumentation.";
56-
private static final String OTEL_JAVA_AGENT_PREFIX = "otel.javaagent.";
5755

58-
private static final Map<String, String> JAVA_MAPPING_RULES = new HashMap<>();
56+
private final PropertyTranslator translator;
57+
@Nullable private final DeclarativeConfigProperties baseNode;
5958

60-
// The node at .instrumentation.java
61-
private final DeclarativeConfigProperties instrumentationJavaNode;
62-
63-
static {
64-
JAVA_MAPPING_RULES.put("otel.instrumentation.common.default-enabled", "common.default.enabled");
59+
static DeclarativeConfigPropertiesBridge fromInstrumentationConfig(
60+
@Nullable DeclarativeConfigProperties instrumentationConfig, PropertyTranslator translator) {
61+
if (instrumentationConfig == null) {
62+
instrumentationConfig = DeclarativeConfigProperties.empty();
63+
}
64+
return new DeclarativeConfigPropertiesBridge(
65+
instrumentationConfig.getStructured("java", empty()), translator);
6566
}
6667

67-
private final Map<String, Object> earlyInitProperties;
68+
static DeclarativeConfigPropertiesBridge create(
69+
@Nullable DeclarativeConfigProperties node, PropertyTranslator translator) {
70+
return new DeclarativeConfigPropertiesBridge(node, translator);
71+
}
6872

69-
public DeclarativeConfigPropertiesBridge(
70-
ConfigProvider configProvider, Map<String, Object> earlyInitProperties) {
71-
this.earlyInitProperties = earlyInitProperties;
72-
DeclarativeConfigProperties inst = configProvider.getInstrumentationConfig();
73-
if (inst == null) {
74-
inst = DeclarativeConfigProperties.empty();
75-
}
76-
instrumentationJavaNode = inst.getStructured("java", empty());
73+
private DeclarativeConfigPropertiesBridge(
74+
@Nullable DeclarativeConfigProperties baseNode, PropertyTranslator translator) {
75+
this.baseNode = baseNode;
76+
this.translator = translator;
7777
}
7878

7979
@Nullable
8080
@Override
8181
public String getString(String propertyName) {
82-
Object value = earlyInitProperties.get(propertyName);
82+
Object value = translator.get(propertyName);
8383
if (value != null) {
8484
return value.toString();
8585
}
@@ -89,7 +89,7 @@ public String getString(String propertyName) {
8989
@Nullable
9090
@Override
9191
public Boolean getBoolean(String propertyName) {
92-
Object value = earlyInitProperties.get(propertyName);
92+
Object value = translator.get(propertyName);
9393
if (value != null) {
9494
return (Boolean) value;
9595
}
@@ -99,42 +99,68 @@ public Boolean getBoolean(String propertyName) {
9999
@Nullable
100100
@Override
101101
public Integer getInt(String propertyName) {
102+
Object value = translator.get(propertyName);
103+
if (value != null) {
104+
return (Integer) value;
105+
}
102106
return getPropertyValue(propertyName, DeclarativeConfigProperties::getInt);
103107
}
104108

105109
@Nullable
106110
@Override
107111
public Long getLong(String propertyName) {
112+
Object value = translator.get(propertyName);
113+
if (value != null) {
114+
return (Long) value;
115+
}
108116
return getPropertyValue(propertyName, DeclarativeConfigProperties::getLong);
109117
}
110118

111119
@Nullable
112120
@Override
113121
public Double getDouble(String propertyName) {
122+
Object value = translator.get(propertyName);
123+
if (value != null) {
124+
return (Double) value;
125+
}
114126
return getPropertyValue(propertyName, DeclarativeConfigProperties::getDouble);
115127
}
116128

117129
@Nullable
118130
@Override
119131
public Duration getDuration(String propertyName) {
132+
Object value = translator.get(propertyName);
133+
if (value != null) {
134+
return (Duration) value;
135+
}
120136
Long millis = getPropertyValue(propertyName, DeclarativeConfigProperties::getLong);
121137
if (millis == null) {
122138
return null;
123139
}
124140
return Duration.ofMillis(millis);
125141
}
126142

143+
@SuppressWarnings("unchecked")
127144
@Override
128145
public List<String> getList(String propertyName) {
146+
Object value = translator.get(propertyName);
147+
if (value != null) {
148+
return (List<String>) value;
149+
}
129150
List<String> propertyValue =
130151
getPropertyValue(
131152
propertyName,
132153
(properties, lastPart) -> properties.getScalarList(lastPart, String.class));
133154
return propertyValue == null ? Collections.emptyList() : propertyValue;
134155
}
135156

157+
@SuppressWarnings("unchecked")
136158
@Override
137159
public Map<String, String> getMap(String propertyName) {
160+
Object fixed = translator.get(propertyName);
161+
if (fixed != null) {
162+
return (Map<String, String>) fixed;
163+
}
138164
DeclarativeConfigProperties propertyValue =
139165
getPropertyValue(propertyName, DeclarativeConfigProperties::getStructured);
140166
if (propertyValue == null) {
@@ -157,38 +183,41 @@ public Map<String, String> getMap(String propertyName) {
157183
@Nullable
158184
private <T> T getPropertyValue(
159185
String property, BiFunction<DeclarativeConfigProperties, String, T> extractor) {
160-
return splitOnDot(getJavaPath(property), instrumentationJavaNode, extractor);
161-
}
186+
if (baseNode == null) {
187+
return null;
188+
}
162189

163-
private static <T> T splitOnDot(
164-
String path,
165-
DeclarativeConfigProperties target,
166-
BiFunction<DeclarativeConfigProperties, String, T> extractor) {
167-
// Split the remainder of the property on ".", and walk to the N-1 entry
168-
String[] segments = path.split("\\.");
190+
String[] segments = getSegments(translator.translateProperty(property));
169191
if (segments.length == 0) {
170192
return null;
171193
}
194+
195+
// Extract the value by walking to the N-1 entry
196+
DeclarativeConfigProperties target = baseNode;
172197
if (segments.length > 1) {
173198
for (int i = 0; i < segments.length - 1; i++) {
174199
target = target.getStructured(segments[i], empty());
175200
}
176201
}
177202
String lastPart = segments[segments.length - 1];
203+
178204
return extractor.apply(target, lastPart);
179205
}
180206

181-
private static String getJavaPath(String property) {
182-
String special = JAVA_MAPPING_RULES.get(property);
183-
if (special != null) {
184-
return special;
207+
private static String[] getSegments(String property) {
208+
if (property.startsWith(OTEL_INSTRUMENTATION_PREFIX)) {
209+
property = property.substring(OTEL_INSTRUMENTATION_PREFIX.length());
185210
}
211+
// Split the remainder of the property on "."
212+
return property.replace('-', '_').split("\\.");
213+
}
186214

187-
if (property.startsWith(OTEL_INSTRUMENTATION_PREFIX)) {
188-
return property.substring(OTEL_INSTRUMENTATION_PREFIX.length()).replace('-', '_');
189-
} else if (property.startsWith(OTEL_JAVA_AGENT_PREFIX)) {
190-
return "agent." + property.substring(OTEL_JAVA_AGENT_PREFIX.length()).replace('-', '_');
215+
static String yamlPath(String property) {
216+
String[] segments = getSegments(property);
217+
if (segments.length == 0) {
218+
throw new IllegalArgumentException("Invalid property: " + property);
191219
}
192-
return property;
220+
221+
return "'instrumentation/development' / 'java' / '" + String.join("' / '", segments) + "'";
193222
}
194223
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.extension.internal;
7+
8+
import java.util.LinkedHashMap;
9+
import java.util.Map;
10+
11+
class PropertyTranslator {
12+
// lookup order matters - we choose the first match
13+
private final LinkedHashMap<String, String> translationMap;
14+
private final Map<String, Object> fixedValues;
15+
16+
PropertyTranslator(
17+
LinkedHashMap<String, String> translationMap, Map<String, Object> fixedValues) {
18+
this.translationMap = translationMap;
19+
this.fixedValues = fixedValues;
20+
}
21+
22+
String translateProperty(String property) {
23+
for (Map.Entry<String, String> entry : translationMap.entrySet()) {
24+
if (property.startsWith(entry.getKey())) {
25+
return entry.getValue() + property.substring(entry.getKey().length());
26+
}
27+
}
28+
return property;
29+
}
30+
31+
public Object get(String propertyName) {
32+
return fixedValues.get(propertyName);
33+
}
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.extension.internal;
7+
8+
import java.util.LinkedHashMap;
9+
import java.util.Map;
10+
11+
/**
12+
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
13+
* any time.
14+
*/
15+
public class PropertyTranslatorBuilder {
16+
private final LinkedHashMap<String, String> translationMap = new LinkedHashMap<>();
17+
private final Map<String, Object> fixedValues = new LinkedHashMap<>();
18+
19+
PropertyTranslatorBuilder() {}
20+
21+
public PropertyTranslatorBuilder addTranslation(String propertyName, String yamlPath) {
22+
translationMap.put(propertyName, yamlPath);
23+
return this;
24+
}
25+
26+
public PropertyTranslatorBuilder addFixedValue(String propertyName, Object value) {
27+
fixedValues.put(propertyName, value);
28+
return this;
29+
}
30+
31+
PropertyTranslator build() {
32+
return new PropertyTranslator(translationMap, fixedValues);
33+
}
34+
}

0 commit comments

Comments
 (0)