Skip to content

Commit adf834e

Browse files
authored
convert dynamic config to use the new SdkTracerProvider.setTracerConfigurator (#565)
* convert dynamic config to use the new SdkTracerProvider.setTracerConfigurator * cleanup and spotless
1 parent 623e8d5 commit adf834e

File tree

4 files changed

+18
-100
lines changed

4 files changed

+18
-100
lines changed

custom/src/main/java/co/elastic/otel/dynamicconfig/DynamicConfiguration.java

+5-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
*/
1919
package co.elastic.otel.dynamicconfig;
2020

21-
import static co.elastic.otel.dynamicconfig.DynamicInstrumentation.updateTracerConfigurations;
21+
import static co.elastic.otel.dynamicconfig.DynamicInstrumentation.setProviderTracerConfigurator;
2222

2323
import io.opentelemetry.api.GlobalOpenTelemetry;
2424
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
@@ -111,14 +111,16 @@ public void reenableTracesFor(String instrumentationName) {
111111
UpdatableConfigurator.INSTANCE.put(
112112
InstrumentationScopeInfo.create(INSTRUMENTATION_NAME_PREPEND + instrumentationName),
113113
TracerConfig.enabled());
114-
updateTracerConfigurations(GlobalOpenTelemetry.getTracerProvider());
114+
setProviderTracerConfigurator(
115+
GlobalOpenTelemetry.getTracerProvider(), UpdatableConfigurator.INSTANCE);
115116
}
116117

117118
public void disableTracesFor(String instrumentationName) {
118119
UpdatableConfigurator.INSTANCE.put(
119120
InstrumentationScopeInfo.create(INSTRUMENTATION_NAME_PREPEND + instrumentationName),
120121
TracerConfig.disabled());
121-
updateTracerConfigurations(GlobalOpenTelemetry.getTracerProvider());
122+
setProviderTracerConfigurator(
123+
GlobalOpenTelemetry.getTracerProvider(), UpdatableConfigurator.INSTANCE);
122124
}
123125

124126
public void disableAllTraces() {

custom/src/main/java/co/elastic/otel/dynamicconfig/DynamicInstrumentation.java

+10-90
Original file line numberDiff line numberDiff line change
@@ -18,36 +18,23 @@
1818
*/
1919
package co.elastic.otel.dynamicconfig;
2020

21-
import static co.elastic.otel.dynamicconfig.DynamicConfiguration.INSTRUMENTATION_NAME_PREPEND;
22-
23-
import io.opentelemetry.api.trace.Tracer;
2421
import io.opentelemetry.api.trace.TracerProvider;
25-
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
26-
import io.opentelemetry.sdk.internal.ComponentRegistry;
2722
import io.opentelemetry.sdk.internal.ScopeConfigurator;
2823
import io.opentelemetry.sdk.trace.SdkTracerProvider;
2924
import io.opentelemetry.sdk.trace.SdkTracerProviderBuilder;
3025
import io.opentelemetry.sdk.trace.internal.TracerConfig;
3126
import java.lang.reflect.Field;
3227
import java.lang.reflect.InvocationTargetException;
3328
import java.lang.reflect.Method;
34-
import java.util.ArrayList;
35-
import java.util.List;
36-
import java.util.logging.Level;
37-
import java.util.logging.Logger;
3829

3930
/**
4031
* Notes: 1. The instrumentation can't have been disabled by configuration, eg using
4132
* -Dotel.instrumentation.[name].enabled=false as in that case it is never initialized so can't be
42-
* "re-enabled" 2. The specific instrumentation name is used, you can see these by setting this
43-
* class logging level to j.u.l.Level.CONFIG 3. The disable/re-enable is eventually consistent,
44-
* needing the application to pass a synchronization barrier to take effect - but for most
45-
* applications these are very frequent
33+
* "re-enabled" 2. The disable/re-enable is eventually consistent, needing the application to pass a
34+
* synchronization barrier to take effect - but for most applications these are very frequent
4635
*/
4736
public class DynamicInstrumentation {
4837

49-
private static final Logger logger = Logger.getLogger(DynamicInstrumentation.class.getName());
50-
5138
private static Object getField(String fieldname, Object target) {
5239
try {
5340
Field field = target.getClass().getDeclaredField(fieldname);
@@ -59,17 +46,6 @@ private static Object getField(String fieldname, Object target) {
5946
}
6047
}
6148

62-
private static Object call(String methodname, Object target) {
63-
try {
64-
Method method = target.getClass().getDeclaredMethod(methodname);
65-
method.setAccessible(true);
66-
return method.invoke(target);
67-
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
68-
throw new IllegalStateException(
69-
"Error calling " + methodname + " on " + target.getClass(), e);
70-
}
71-
}
72-
7349
private static <T> Object call(
7450
String methodname, Object target, T arg1, Class<? super T> arg1Class) {
7551
try {
@@ -91,75 +67,19 @@ public static SdkTracerProviderBuilder setTracerConfigurator(
9167
return sdkTracerProviderBuilder;
9268
}
9369

94-
// SdkTracerProvider.getTracerConfig(InstrumentationScopeInfo instrumentationScopeInfo)
95-
// here because it's not currently public
96-
private static TracerConfig getTracerConfig(
97-
SdkTracerProvider provider, InstrumentationScopeInfo instrumentationScopeInfo) {
98-
return (TracerConfig)
99-
call("getTracerConfig", provider, instrumentationScopeInfo, InstrumentationScopeInfo.class);
100-
}
101-
102-
// SdkTracer.getInstrumentationScopeInfo()
70+
// SdkTracerProvider.setTracerConfigurator(ScopeConfigurator tracerConfigurator)
10371
// here because it's not currently public
104-
private static InstrumentationScopeInfo getInstrumentationScopeInfo(Tracer sdkTracer)
105-
throws NoSuchFieldException, IllegalAccessException {
106-
return (InstrumentationScopeInfo) call("getInstrumentationScopeInfo", sdkTracer);
107-
}
108-
109-
// Not an existing method
110-
// SdkTracerProvider.updateTracerConfigurations()
111-
// updates all tracers with the current SdkTracerProvider.tracerConfigurator
112-
// Code implementation equivalent to
113-
// this.tracerSdkComponentRegistry
114-
// .getComponents()
115-
// .forEach(
116-
// sdkTracer ->
117-
// sdkTracer.updateTracerConfig(
118-
// getTracerConfig(sdkTracer.getInstrumentationScopeInfo())));
119-
// where SdkTracer.updateTracerConfig(TracerConfig tracerConfig) is equivalent to
120-
// this.tracerEnabled = tracerConfig.isEnabled();
121-
static void updateTracerConfigurations(TracerProvider provider) {
72+
public static TracerConfig setProviderTracerConfigurator(
73+
TracerProvider provider, ScopeConfigurator<TracerConfig> tracerConfigurator) {
12274
if (!(provider instanceof SdkTracerProvider)) {
12375
provider = (TracerProvider) getField("delegate", provider);
12476
}
125-
ComponentRegistry<Tracer> tracerSdkComponentRegistry =
126-
(ComponentRegistry<Tracer>) getField("tracerSdkComponentRegistry", provider);
127-
SdkTracerProvider finalProvider = (SdkTracerProvider) provider;
128-
final List<String> activatedTracers;
129-
if (logger.isLoggable(Level.CONFIG)) {
130-
activatedTracers = new ArrayList<>();
77+
if (provider instanceof SdkTracerProvider) {
78+
return (TracerConfig)
79+
call("setTracerConfigurator", provider, tracerConfigurator, ScopeConfigurator.class);
13180
} else {
132-
activatedTracers = null;
133-
}
134-
tracerSdkComponentRegistry
135-
.getComponents()
136-
.forEach(
137-
sdkTracer -> {
138-
try {
139-
InstrumentationScopeInfo instrumentationScopeInfo =
140-
getInstrumentationScopeInfo(sdkTracer);
141-
TracerConfig tConfig = getTracerConfig(finalProvider, instrumentationScopeInfo);
142-
Field tracerEnabledField = sdkTracer.getClass().getDeclaredField("tracerEnabled");
143-
tracerEnabledField.setAccessible(true);
144-
// Update is synced but the reader is NOT necessarily so this is eventual
145-
// consistency, takes effect when the application passes a sync boundary
146-
synchronized (sdkTracer) {
147-
tracerEnabledField.set(sdkTracer, tConfig.isEnabled());
148-
}
149-
if (logger.isLoggable(Level.CONFIG)) {
150-
String name = instrumentationScopeInfo.getName();
151-
if (name.startsWith(INSTRUMENTATION_NAME_PREPEND)) {
152-
name = name.substring(INSTRUMENTATION_NAME_PREPEND.length());
153-
}
154-
activatedTracers.add(name);
155-
activatedTracers.add(tConfig.isEnabled() ? "enabled" : "disabled");
156-
}
157-
} catch (NoSuchFieldException | IllegalAccessException e) {
158-
throw new RuntimeException(e);
159-
}
160-
});
161-
if (logger.isLoggable(Level.CONFIG)) {
162-
logger.log(Level.CONFIG, "Activated Tracers: " + activatedTracers);
81+
throw new IllegalStateException(
82+
"Expected SdkTracerProvider but got " + provider.getClass().getName());
16383
}
16484
}
16585

custom/src/test/java/co/elastic/otel/config/DynamicInstrumentationTest.java

+3-4
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
package co.elastic.otel.config;
2020

2121
import static org.assertj.core.api.Assertions.assertThat;
22-
import static org.assertj.core.api.Assertions.assertThatThrownBy;
2322

2423
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
2524
import io.opentelemetry.sdk.internal.ScopeConfigurator;
@@ -50,8 +49,8 @@ public void checkForPublicImplementations() throws NoSuchMethodException, ClassN
5049
Method method3 = sdkTracer.getDeclaredMethod("getInstrumentationScopeInfo");
5150
assertThat(Modifier.toString(method3.getModifiers())).isNotEqualTo("public");
5251

53-
assertThatThrownBy(
54-
() -> SdkTracerProvider.class.getDeclaredMethod("updateTracerConfigurations"))
55-
.isInstanceOf(NoSuchMethodException.class);
52+
Method method4 =
53+
SdkTracerProvider.class.getDeclaredMethod("setTracerConfigurator", ScopeConfigurator.class);
54+
assertThat(Modifier.toString(method4.getModifiers())).isNotEqualTo("public");
5655
}
5756
}

smoke-tests/src/test/java/com/example/javaagent/smoketest/DynamicInstrumentationSmokeTest.java

-3
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
import org.junit.jupiter.api.AfterAll;
2828
import org.junit.jupiter.api.AfterEach;
2929
import org.junit.jupiter.api.BeforeAll;
30-
import org.junit.jupiter.api.Disabled;
3130
import org.junit.jupiter.api.Test;
3231

3332
class DynamicInstrumentationSmokeTest extends TestAppSmokeTest {
@@ -59,13 +58,11 @@ public void endTest() throws InterruptedException {
5958
}
6059

6160
@Test
62-
@Disabled // https://github.com/elastic/elastic-otel-java/issues/562
6361
public void flipMethodInstrumentation() throws InterruptedException {
6462
dynamicFlipInstrumentation("Methods", 1);
6563
}
6664

6765
@Test
68-
@Disabled // https://github.com/elastic/elastic-otel-java/issues/562
6966
public void flipAllInstrumentation() throws InterruptedException {
7067
dynamicFlipInstrumentation("All", 0);
7168
}

0 commit comments

Comments
 (0)