Skip to content

Commit 2f0d232

Browse files
authored
Vendor specific instrumentation config options handling (#14016)
1 parent a236b69 commit 2f0d232

File tree

10 files changed

+159
-36
lines changed

10 files changed

+159
-36
lines changed

instrumentation/jmx-metrics/javaagent/src/main/java/io/opentelemetry/instrumentation/javaagent/jmx/JmxMetricInsightInstaller.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import io.opentelemetry.instrumentation.jmx.engine.MetricConfiguration;
1515
import io.opentelemetry.instrumentation.jmx.yaml.RuleParser;
1616
import io.opentelemetry.javaagent.extension.AgentListener;
17+
import io.opentelemetry.javaagent.extension.ConfigPropertiesUtil;
1718
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
1819
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
1920
import java.io.InputStream;
@@ -28,7 +29,7 @@ public class JmxMetricInsightInstaller implements AgentListener {
2829

2930
@Override
3031
public void afterAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredSdk) {
31-
ConfigProperties config = AgentListener.resolveConfigProperties(autoConfiguredSdk);
32+
ConfigProperties config = ConfigPropertiesUtil.resolveConfigProperties(autoConfiguredSdk);
3233

3334
if (config.getBoolean("otel.jmx.enabled", true)) {
3435
JmxMetricInsight service =

instrumentation/oshi/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/oshi/OshiMetricsInstaller.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import com.google.auto.service.AutoService;
99
import io.opentelemetry.javaagent.extension.AgentListener;
10+
import io.opentelemetry.javaagent.extension.ConfigPropertiesUtil;
1011
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
1112
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
1213
import java.lang.reflect.Method;
@@ -20,7 +21,7 @@ public class OshiMetricsInstaller implements AgentListener {
2021

2122
@Override
2223
public void afterAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredSdk) {
23-
ConfigProperties config = AgentListener.resolveConfigProperties(autoConfiguredSdk);
24+
ConfigProperties config = ConfigPropertiesUtil.resolveConfigProperties(autoConfiguredSdk);
2425

2526
boolean defaultEnabled = config.getBoolean("otel.instrumentation.common.default-enabled", true);
2627
if (!config.getBoolean("otel.instrumentation.oshi.enabled", defaultEnabled)) {

instrumentation/runtime-telemetry/runtime-telemetry-java8/javaagent/src/main/java/io/opentelemetry/instrumentation/javaagent/runtimemetrics/java8/JarAnalyzerInstaller.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import com.google.auto.service.AutoService;
99
import io.opentelemetry.javaagent.bootstrap.InstrumentationHolder;
10-
import io.opentelemetry.javaagent.extension.AgentListener;
10+
import io.opentelemetry.javaagent.extension.ConfigPropertiesUtil;
1111
import io.opentelemetry.javaagent.tooling.BeforeAgentListener;
1212
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
1313
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
@@ -19,7 +19,8 @@ public class JarAnalyzerInstaller implements BeforeAgentListener {
1919

2020
@Override
2121
public void beforeAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk) {
22-
ConfigProperties config = AgentListener.resolveConfigProperties(autoConfiguredOpenTelemetrySdk);
22+
ConfigProperties config =
23+
ConfigPropertiesUtil.resolveConfigProperties(autoConfiguredOpenTelemetrySdk);
2324

2425
boolean enabled =
2526
config.getBoolean("otel.instrumentation.runtime-telemetry.package-emitter.enabled", false);

javaagent-extension-api/build.gradle.kts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,8 @@ dependencies {
2222
// Used by byte-buddy but not brought in as a transitive dependency.
2323
compileOnly("com.google.code.findbugs:annotations")
2424
}
25+
26+
// Needed by mockito
27+
configurations.testRuntimeClasspath {
28+
exclude(group = "net.bytebuddy", module = "byte-buddy-dep")
29+
}

javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/extension/AgentListener.java

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,7 @@
55

66
package io.opentelemetry.javaagent.extension;
77

8-
import io.opentelemetry.api.incubator.config.ConfigProvider;
9-
import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
108
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
11-
import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil;
12-
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
139
import io.opentelemetry.sdk.autoconfigure.spi.Ordered;
1410
import java.lang.instrument.Instrumentation;
1511
import net.bytebuddy.agent.builder.AgentBuilder;
@@ -29,26 +25,4 @@ public interface AgentListener extends Ordered {
2925
* on an {@link Instrumentation}.
3026
*/
3127
void afterAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk);
32-
33-
/** Resolve {@link ConfigProperties} from the {@code autoConfiguredOpenTelemetrySdk}. */
34-
static ConfigProperties resolveConfigProperties(
35-
AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk) {
36-
ConfigProperties sdkConfigProperties =
37-
AutoConfigureUtil.getConfig(autoConfiguredOpenTelemetrySdk);
38-
if (sdkConfigProperties != null) {
39-
return sdkConfigProperties;
40-
}
41-
ConfigProvider configProvider =
42-
AutoConfigureUtil.getConfigProvider(autoConfiguredOpenTelemetrySdk);
43-
if (configProvider != null) {
44-
DeclarativeConfigProperties instrumentationConfig = configProvider.getInstrumentationConfig();
45-
46-
if (instrumentationConfig != null) {
47-
return new DeclarativeConfigPropertiesBridge(instrumentationConfig);
48-
}
49-
}
50-
// Should never happen
51-
throw new IllegalStateException(
52-
"AutoConfiguredOpenTelemetrySdk does not have ConfigProperties or DeclarativeConfigProperties. This is likely a programming error in opentelemetry-java");
53-
}
5428
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.extension;
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+
14+
public class ConfigPropertiesUtil {
15+
private ConfigPropertiesUtil() {}
16+
17+
/** Resolve {@link ConfigProperties} from the {@code autoConfiguredOpenTelemetrySdk}. */
18+
public static ConfigProperties resolveConfigProperties(
19+
AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk) {
20+
ConfigProperties sdkConfigProperties =
21+
AutoConfigureUtil.getConfig(autoConfiguredOpenTelemetrySdk);
22+
if (sdkConfigProperties != null) {
23+
return sdkConfigProperties;
24+
}
25+
ConfigProvider configProvider =
26+
AutoConfigureUtil.getConfigProvider(autoConfiguredOpenTelemetrySdk);
27+
if (configProvider != null) {
28+
DeclarativeConfigProperties instrumentationConfig = configProvider.getInstrumentationConfig();
29+
30+
if (instrumentationConfig == null) {
31+
instrumentationConfig = DeclarativeConfigProperties.empty();
32+
}
33+
34+
return new DeclarativeConfigPropertiesBridge(instrumentationConfig);
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+
}

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

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,22 +130,28 @@ public Map<String, String> getMap(String propertyName) {
130130
@Nullable
131131
private <T> T getPropertyValue(
132132
String property, BiFunction<DeclarativeConfigProperties, String, T> extractor) {
133-
if (!property.startsWith(OTEL_INSTRUMENTATION_PREFIX)) {
133+
if (instrumentationJavaNode == null) {
134134
return null;
135135
}
136-
String suffix = property.substring(OTEL_INSTRUMENTATION_PREFIX.length());
137-
// Split the remainder of the property on ".", and walk to the N-1 entry
138-
String[] segments = suffix.split("\\.");
136+
137+
if (property.startsWith(OTEL_INSTRUMENTATION_PREFIX)) {
138+
property = property.substring(OTEL_INSTRUMENTATION_PREFIX.length());
139+
}
140+
// Split the remainder of the property on "."
141+
String[] segments = property.split("\\.");
139142
if (segments.length == 0) {
140143
return null;
141144
}
145+
146+
// Extract the value by walking to the N-1 entry
142147
DeclarativeConfigProperties target = instrumentationJavaNode;
143148
if (segments.length > 1) {
144149
for (int i = 0; i < segments.length - 1; i++) {
145150
target = target.getStructured(segments[i], empty());
146151
}
147152
}
148153
String lastPart = segments[segments.length - 1];
154+
149155
return extractor.apply(target, lastPart);
150156
}
151157
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.extension;
7+
8+
import static org.assertj.core.api.Assertions.assertThat;
9+
import static org.mockito.ArgumentMatchers.any;
10+
import static org.mockito.ArgumentMatchers.eq;
11+
import static org.mockito.Mockito.mock;
12+
import static org.mockito.Mockito.when;
13+
14+
import io.opentelemetry.api.incubator.config.ConfigProvider;
15+
import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
16+
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
17+
import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil;
18+
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
19+
import org.junit.jupiter.api.Test;
20+
import org.mockito.MockedStatic;
21+
import org.mockito.Mockito;
22+
23+
@SuppressWarnings("DoNotMockAutoValue")
24+
class ConfigPropertiesUtilTest {
25+
@Test
26+
void shouldUseConfigPropertiesForAutoConfiguration() {
27+
ConfigProperties configPropertiesMock = mock(ConfigProperties.class);
28+
AutoConfiguredOpenTelemetrySdk sdkMock = mock(AutoConfiguredOpenTelemetrySdk.class);
29+
try (MockedStatic<AutoConfigureUtil> autoConfigureUtilMock =
30+
Mockito.mockStatic(AutoConfigureUtil.class)) {
31+
autoConfigureUtilMock
32+
.when(() -> AutoConfigureUtil.getConfig(sdkMock))
33+
.thenReturn(configPropertiesMock);
34+
35+
ConfigProperties configProperties = ConfigPropertiesUtil.resolveConfigProperties(sdkMock);
36+
37+
assertThat(configProperties).isSameAs(configPropertiesMock);
38+
}
39+
}
40+
41+
@Test
42+
void shouldUseConfigProviderForDeclarativeConfiguration() {
43+
String propertyName = "testProperty";
44+
String expectedValue = "the value";
45+
DeclarativeConfigProperties javaNodeMock = mock(DeclarativeConfigProperties.class);
46+
when(javaNodeMock.getString(propertyName)).thenReturn(expectedValue);
47+
48+
DeclarativeConfigProperties instrumentationConfigMock = mock(DeclarativeConfigProperties.class);
49+
when(instrumentationConfigMock.getStructured(eq("java"), any())).thenReturn(javaNodeMock);
50+
51+
ConfigProvider configProviderMock = mock(ConfigProvider.class);
52+
when(configProviderMock.getInstrumentationConfig()).thenReturn(instrumentationConfigMock);
53+
54+
AutoConfiguredOpenTelemetrySdk sdkMock = mock(AutoConfiguredOpenTelemetrySdk.class);
55+
56+
try (MockedStatic<AutoConfigureUtil> autoConfigureUtilMock =
57+
Mockito.mockStatic(AutoConfigureUtil.class)) {
58+
autoConfigureUtilMock.when(() -> AutoConfigureUtil.getConfig(sdkMock)).thenReturn(null);
59+
autoConfigureUtilMock
60+
.when(() -> AutoConfigureUtil.getConfigProvider(sdkMock))
61+
.thenReturn(configProviderMock);
62+
63+
ConfigProperties configProperties = ConfigPropertiesUtil.resolveConfigProperties(sdkMock);
64+
65+
assertThat(configProperties.getString(propertyName)).isEqualTo(expectedValue);
66+
}
67+
}
68+
69+
@Test
70+
void shouldUseConfigProviderForDeclarativeConfiguration_noInstrumentationConfig() {
71+
AutoConfiguredOpenTelemetrySdk sdkMock = mock(AutoConfiguredOpenTelemetrySdk.class);
72+
ConfigProvider configProviderMock = mock(ConfigProvider.class);
73+
when(configProviderMock.getInstrumentationConfig()).thenReturn(null);
74+
75+
try (MockedStatic<AutoConfigureUtil> autoConfigureUtilMock =
76+
Mockito.mockStatic(AutoConfigureUtil.class)) {
77+
autoConfigureUtilMock.when(() -> AutoConfigureUtil.getConfig(sdkMock)).thenReturn(null);
78+
autoConfigureUtilMock
79+
.when(() -> AutoConfigureUtil.getConfigProvider(sdkMock))
80+
.thenReturn(configProviderMock);
81+
82+
ConfigProperties configProperties = ConfigPropertiesUtil.resolveConfigProperties(sdkMock);
83+
84+
assertThat(configProperties.getString("testProperty")).isEqualTo(null);
85+
}
86+
}
87+
}

javaagent-extension-api/src/test/java/io/opentelemetry/javaagent/extension/DeclarativeConfigPropertiesBridgeTest.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,10 @@ class DeclarativeConfigPropertiesBridgeTest {
4444
+ " map_key:\n"
4545
+ " string_key1: value1\n"
4646
+ " string_key2: value2\n"
47-
+ " bool_key: true\n";
47+
+ " bool_key: true\n"
48+
+ " acme:\n"
49+
+ " full_name:\n"
50+
+ " preserved: true";
4851

4952
private ConfigProperties bridge;
5053
private ConfigProperties emptyBridge;
@@ -132,5 +135,9 @@ void getProperties() {
132135
.isEqualTo(Arrays.asList("value1", "value2"));
133136
assertThat(bridge.getMap("otel.instrumentation.other-instrumentation.map_key", expectedMap))
134137
.isEqualTo(expectedMap);
138+
139+
// verify vendor specific property names are preserved in unchanged form (prefix is not stripped
140+
// as for otel.instrumentation.*)
141+
assertThat(bridge.getBoolean("acme.full_name.preserved")).isTrue();
135142
}
136143
}

javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentInstaller.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig;
3232
import io.opentelemetry.javaagent.bootstrap.internal.ConfiguredResourceAttributesHolder;
3333
import io.opentelemetry.javaagent.extension.AgentListener;
34+
import io.opentelemetry.javaagent.extension.ConfigPropertiesUtil;
3435
import io.opentelemetry.javaagent.extension.ignore.IgnoredTypesConfigurer;
3536
import io.opentelemetry.javaagent.extension.instrumentation.internal.EarlyInstrumentationModule;
3637
import io.opentelemetry.javaagent.tooling.asyncannotationsupport.WeakRefAsyncOperationEndStrategies;
@@ -166,7 +167,7 @@ private static void installBytebuddyAgent(
166167
AutoConfiguredOpenTelemetrySdk autoConfiguredSdk =
167168
installOpenTelemetrySdk(extensionClassLoader);
168169

169-
ConfigProperties sdkConfig = AgentListener.resolveConfigProperties(autoConfiguredSdk);
170+
ConfigProperties sdkConfig = ConfigPropertiesUtil.resolveConfigProperties(autoConfiguredSdk);
170171
AgentInstrumentationConfig.internalInitializeConfig(
171172
new ConfigPropertiesBridge(
172173
sdkConfig, AutoConfigureUtil.getConfigProvider(autoConfiguredSdk)));

0 commit comments

Comments
 (0)