Skip to content

Commit

Permalink
add disable all instrumentations option (#471)
Browse files Browse the repository at this point in the history
* add disable all instrumentations option

* shift comment
  • Loading branch information
jackshirazi authored Dec 6, 2024
1 parent 9126096 commit a6f0128
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,14 @@
*/
public class DynamicInstrumentation {

private static final Logger logger = Logger.getLogger(DynamicInstrumentation.class.getName());
public static final String INSTRUMENTATION_NAME_PREPEND = "io.opentelemetry.";
public static final String ALL_INSTRUMENTATION = "_ALL_";
// note the option can't be an env because no OSes support changing envs while the program runs
public static final String INSTRUMENTATION_DISABLE_OPTION =
"elastic.otel.java.disable_instrumentations";
private static final String ALL_INSTRUMENTATION_FULL_NAME =
INSTRUMENTATION_NAME_PREPEND + ALL_INSTRUMENTATION;
private static final Logger logger = Logger.getLogger(DynamicInstrumentation.class.getName());

private static Object getField(String fieldname, Object target) {
try {
Expand Down Expand Up @@ -186,6 +189,14 @@ public static void disableTracesFor(String instrumentationName) {
updateTracerConfigurations(GlobalOpenTelemetry.getTracerProvider());
}

public static void disableAllTraces() {
disableTracesFor(ALL_INSTRUMENTATION);
}

public static void stopDisablingAllTraces() {
reenableTracesFor(ALL_INSTRUMENTATION);
}

public static class UpdatableConfigurator implements ScopeConfigurator<TracerConfig> {
public static final UpdatableConfigurator INSTANCE = new UpdatableConfigurator();
private final ConcurrentMap<String, TracerConfig> map = new ConcurrentHashMap<>();
Expand All @@ -194,6 +205,11 @@ private UpdatableConfigurator() {}

@Override
public TracerConfig apply(InstrumentationScopeInfo scopeInfo) {
// If key "_ALL_" is set to disabled, then always return disabled
// otherwise fallback to the individual instrumentation
if (!map.getOrDefault(ALL_INSTRUMENTATION_FULL_NAME, TracerConfig.enabled()).isEnabled()) {
return TracerConfig.disabled();
}
return map.getOrDefault(scopeInfo.getName(), TracerConfig.defaultConfig());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import io.opentelemetry.proto.trace.v1.Span;
import java.util.List;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

Expand All @@ -36,7 +37,7 @@ public static void start() {
(container) -> {
container.addEnv(
"OTEL_INSTRUMENTATION_METHODS_INCLUDE",
"co.elastic.otel.test.DynamicInstrumentationController[flipMethods]");
"co.elastic.otel.test.DynamicInstrumentationController[flipMethods,flipAll]");
container.addEnv("ELASTIC_OTEL_JAVA_DISABLE_INSTRUMENTATIONS_CHECKER", "true");
container.addEnv("OTEL_JAVAAGENT_DEBUG", "true");
});
Expand All @@ -47,28 +48,53 @@ public static void end() {
stopApp();
}

@AfterEach
public void endTest() throws InterruptedException {
doRequest(getUrl("/dynamic/reset"), okResponseBody("reset"));
Thread.sleep(2000L); // give the reset time to be applied
}

@Test
public void flipMethodInstrumentation() throws InterruptedException {
doRequest(getUrl("/dynamic"), okResponseBody("enabled"));
dynamicFlipInstrumentation("Methods", 1);
}

@Test
public void flipAllInstrumentation() throws InterruptedException {
dynamicFlipInstrumentation("All", 0);
}

private void dynamicFlipInstrumentation(String extensionName, int SpanCountWhenDisabled)
throws InterruptedException {
doRequest(getUrl("/dynamic/flip" + extensionName), okResponseBody("enabled"));
List<ExportTraceServiceRequest> traces = waitForTraces();
List<Span> spans = getSpans(traces).toList();
assertThat(spans)
.hasSize(2)
.extracting("name")
.containsOnly("GET /dynamic", "DynamicInstrumentationController.flipMethods");
.containsOnly(
"GET /dynamic/flip" + extensionName,
"DynamicInstrumentationController.flip" + extensionName);
ByteString firstTraceID = spans.get(0).getTraceId();

Thread.sleep(2000L); // give the flip time to be applied

doRequest(getUrl("/dynamic"), okResponseBody("disabled"));
doRequest(getUrl("/dynamic/flip" + extensionName), okResponseBody("disabled"));
traces = waitForTraces();
spans = getSpans(traces).dropWhile(span -> span.getTraceId().equals(firstTraceID)).toList();
assertThat(spans).hasSize(1).extracting("name").containsOnly("GET /dynamic");
ByteString secondTraceID = spans.get(0).getTraceId();
if (SpanCountWhenDisabled > 0) {
assertThat(spans)
.hasSize(SpanCountWhenDisabled)
.extracting("name")
.containsOnly("GET /dynamic/flip" + extensionName);
} else {
assertThat(spans).hasSize(0);
}
ByteString secondTraceID = SpanCountWhenDisabled > 0 ? spans.get(0).getTraceId() : firstTraceID;

Thread.sleep(2000L); // give the flip time to be applied

doRequest(getUrl("/dynamic"), okResponseBody("enabled"));
doRequest(getUrl("/dynamic/flip" + extensionName), okResponseBody("enabled"));
traces = waitForTraces();
spans =
getSpans(traces)
Expand All @@ -80,6 +106,8 @@ public void flipMethodInstrumentation() throws InterruptedException {
assertThat(spans)
.hasSize(2)
.extracting("name")
.containsOnly("GET /dynamic", "DynamicInstrumentationController.flipMethods");
.containsOnly(
"GET /dynamic/flip" + extensionName,
"DynamicInstrumentationController.flip" + extensionName);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,33 @@ public class DynamicInstrumentationController {
"elastic.otel.java.disable_instrumentations";

// note synchronized to make enable/disable faster with DynamicInstrumentation
@GetMapping
@GetMapping("/flipMethods")
public synchronized String flipMethods() {
String old = System.getProperty(INSTRUMENTATION_DISABLE_OPTION, "");
if (old.isEmpty()) {
System.setProperty(INSTRUMENTATION_DISABLE_OPTION, "methods");
return "enabled";
} else {
System.setProperty(INSTRUMENTATION_DISABLE_OPTION, "");
return "disabled";
}
return old.isEmpty() ? "enabled" : "disabled";
}

@RequestMapping("/flipAll")
public synchronized String flipAll() {
String old = System.getProperty(INSTRUMENTATION_DISABLE_OPTION, "");
if (old.isEmpty()) {
System.setProperty(INSTRUMENTATION_DISABLE_OPTION, "_ALL_");
return "enabled";
} else {
System.setProperty(INSTRUMENTATION_DISABLE_OPTION, "");
return "disabled";
}
}

@RequestMapping("/reset")
public synchronized String reset() {
System.setProperty(INSTRUMENTATION_DISABLE_OPTION, "");
return "reset";
}
}

0 comments on commit a6f0128

Please sign in to comment.