Add strict context stressor testing option
@@ -11,6 +11,9 @@ import static io.opentelemetry.javaagent.tooling.SafeServiceLoader.loadOrdered;
import static io.opentelemetry.javaagent.tooling.Utils.getResourceName;
import static net.bytebuddy.matcher.ElementMatchers.any;
+import io.opentelemetry.context.Context;
+import io.opentelemetry.context.ContextStorage;
+import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.api.config.Config;
import io.opentelemetry.javaagent.bootstrap.AgentClassLoader;
import io.opentelemetry.javaagent.extension.AgentExtension;
@@ -45,6 +48,7 @@ import net.bytebuddy.description.type.TypeDefinition;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.utility.JavaModule;
+import org.checkerframework.checker.nullness.qual.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -61,6 +65,9 @@ public class AgentInstaller {
private static final String FORCE_SYNCHRONOUS_AGENT_LISTENERS_CONFIG =
"otel.javaagent.experimental.force-synchronous-agent-listeners";
+ private static final String STRICT_CONTEXT_STRESSOR_MILLIS =
+ "otel.javaagent.testing.strict-context-stressor-millis";
+
private static final Map<String, List<Runnable>> CLASS_LOAD_CALLBACKS = new HashMap<>();
static {
@@ -87,6 +94,12 @@ public class AgentInstaller {
// caffeine uses AtomicReferenceArray, ensure it is loaded to avoid ClassCircularityError during
// transform.
AtomicReferenceArray.class.getName();
+
+ Integer strictContextStressorMillis = Integer.getInteger(STRICT_CONTEXT_STRESSOR_MILLIS);
+ if (strictContextStressorMillis != null) {
+ io.opentelemetry.context.ContextStorage.addWrapper(
+ storage -> new StrictContextStressor(storage, strictContextStressorMillis));
+ }
}
public static void installBytebuddyAgent(Instrumentation inst) {
@@ -485,4 +498,44 @@ public class AgentInstaller {
}
private AgentInstaller() {}
+
+ private static class StrictContextStressor implements ContextStorage, AutoCloseable {
+
+ private final ContextStorage contextStorage;
+ private final int sleepMillis;
+
+ private StrictContextStressor(ContextStorage contextStorage, int sleepMillis) {
+ this.contextStorage = contextStorage;
+ this.sleepMillis = sleepMillis;
+ }
+
+ @Override
+ public Scope attach(Context toAttach) {
+ return wrap(contextStorage.attach(toAttach));
+ }
+
+ @Nullable
+ @Override
+ public Context current() {
+ return contextStorage.current();
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (contextStorage instanceof AutoCloseable) {
+ ((AutoCloseable) contextStorage).close();
+ }
+ }
+
+ private Scope wrap(Scope scope) {
+ return () -> {
+ try {
+ Thread.sleep(sleepMillis);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ scope.close();
+ };
+ }
+ }
}
