From ca4dc54be27230d34ad3f81e82a03417ff8033a8 Mon Sep 17 00:00:00 2001 From: Sylvain Juge <763082+SylvainJuge@users.noreply.github.com> Date: Fri, 24 Oct 2025 11:15:46 +0200 Subject: [PATCH 1/3] make methods indy-ready --- .../methods/MethodInstrumentation.java | 49 ++++++++++--------- .../methods/MethodInstrumentationModule.java | 9 +++- 2 files changed, 35 insertions(+), 23 deletions(-) diff --git a/instrumentation/methods/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodInstrumentation.java b/instrumentation/methods/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodInstrumentation.java index 20f055e0b4ec..0701ffef5dc5 100644 --- a/instrumentation/methods/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodInstrumentation.java +++ b/instrumentation/methods/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodInstrumentation.java @@ -26,6 +26,7 @@ import java.util.Collection; import java.util.Map; import net.bytebuddy.asm.Advice; +import net.bytebuddy.asm.Advice.AssignReturned; import net.bytebuddy.description.enumeration.EnumerationDescription; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.implementation.bytecode.assign.Assigner; @@ -91,42 +92,46 @@ public void transform(TypeTransformer transformer) { @SuppressWarnings("unused") public static class MethodAdvice { + public static class AdviceLocals { + public MethodAndType classAndMethod; + public Context context; + public Scope scope; + } + @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( + public static AdviceLocals onEnter( @MethodSpanKind SpanKind spanKind, @Advice.Origin("#t") Class declaringClass, - @Advice.Origin("#m") String methodName, - @Advice.Local("otelMethod") MethodAndType classAndMethod, - @Advice.Local("otelContext") Context context, - @Advice.Local("otelScope") Scope scope) { + @Advice.Origin("#m") String methodName) { + + AdviceLocals locals = new AdviceLocals(); Context parentContext = currentContext(); - classAndMethod = + locals.classAndMethod = MethodAndType.create(ClassAndMethod.create(declaringClass, methodName), spanKind); - if (!instrumenter().shouldStart(parentContext, classAndMethod)) { - return; + if (!instrumenter().shouldStart(parentContext, locals.classAndMethod)) { + return locals; } - context = instrumenter().start(parentContext, classAndMethod); - scope = context.makeCurrent(); + locals.context = instrumenter().start(parentContext, locals.classAndMethod); + locals.scope = locals.context.makeCurrent(); + return locals; } + @AssignReturned.ToReturned @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( + public static Object stopSpan( @MethodReturnType Class methodReturnType, - @Advice.Local("otelMethod") MethodAndType classAndMethod, - @Advice.Local("otelContext") Context context, - @Advice.Local("otelScope") Scope scope, - @Advice.Return(typing = Assigner.Typing.DYNAMIC, readOnly = false) Object returnValue, - @Advice.Thrown Throwable throwable) { - if (scope == null) { - return; + @Advice.Return(typing = Assigner.Typing.DYNAMIC) Object returnValue, + @Advice.Thrown Throwable throwable, + @Advice.Enter AdviceLocals locals) { + if (locals.scope == null) { + return returnValue; } - scope.close(); + locals.scope.close(); - returnValue = - AsyncOperationEndSupport.create(instrumenter(), Void.class, methodReturnType) - .asyncEnd(context, classAndMethod, returnValue, throwable); + return AsyncOperationEndSupport.create(instrumenter(), Void.class, methodReturnType) + .asyncEnd(locals.context, locals.classAndMethod, returnValue, throwable); } } } diff --git a/instrumentation/methods/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodInstrumentationModule.java b/instrumentation/methods/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodInstrumentationModule.java index 3106c332c8da..71fe619da4db 100644 --- a/instrumentation/methods/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodInstrumentationModule.java +++ b/instrumentation/methods/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodInstrumentationModule.java @@ -15,6 +15,7 @@ import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import io.opentelemetry.javaagent.extension.instrumentation.internal.ExperimentalInstrumentationModule; import io.opentelemetry.javaagent.tooling.config.MethodsConfigurationParser; import java.util.List; import java.util.Map; @@ -22,7 +23,8 @@ import java.util.stream.Collectors; @AutoService(InstrumentationModule.class) -public class MethodInstrumentationModule extends InstrumentationModule { +public class MethodInstrumentationModule extends InstrumentationModule + implements ExperimentalInstrumentationModule { private static final String TRACE_METHODS_CONFIG = "otel.instrumentation.methods.include"; @@ -66,4 +68,9 @@ private static List parseConfigProperties() { public List typeInstrumentations() { return typeInstrumentations; } + + @Override + public boolean isIndyReady() { + return true; + } } From e6d34e7413d33642417bee7b345a767266787ba9 Mon Sep 17 00:00:00 2001 From: Sylvain Juge <763082+SylvainJuge@users.noreply.github.com> Date: Fri, 24 Oct 2025 13:57:24 +0200 Subject: [PATCH 2/3] post-review changes --- .../methods/MethodInstrumentation.java | 67 ++++++++++++------- 1 file changed, 41 insertions(+), 26 deletions(-) diff --git a/instrumentation/methods/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodInstrumentation.java b/instrumentation/methods/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodInstrumentation.java index 0701ffef5dc5..dd0926d4704c 100644 --- a/instrumentation/methods/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodInstrumentation.java +++ b/instrumentation/methods/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodInstrumentation.java @@ -25,6 +25,7 @@ import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; import java.util.Collection; import java.util.Map; +import javax.annotation.Nullable; import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice.AssignReturned; import net.bytebuddy.description.enumeration.EnumerationDescription; @@ -92,30 +93,46 @@ public void transform(TypeTransformer transformer) { @SuppressWarnings("unused") public static class MethodAdvice { - public static class AdviceLocals { - public MethodAndType classAndMethod; - public Context context; - public Scope scope; + public static class AdviceScope { + private final MethodAndType classAndMethod; + private final Context context; + private final Scope scope; + + public AdviceScope(MethodAndType classAndMethod, Context context, Scope scope) { + this.classAndMethod = classAndMethod; + this.context = context; + this.scope = scope; + } + + @Nullable + public static AdviceScope start( + SpanKind spanKind, Class declaringClass, String methodName) { + Context parentContext = currentContext(); + MethodAndType methodAndType = + MethodAndType.create(ClassAndMethod.create(declaringClass, methodName), spanKind); + + if (!instrumenter().shouldStart(parentContext, methodAndType)) { + return null; + } + Context context = instrumenter().start(parentContext, methodAndType); + return new AdviceScope(methodAndType, context, context.makeCurrent()); + } + + public Object end( + Class methodReturnType, Object returnValue, @Nullable Throwable throwable) { + scope.close(); + return AsyncOperationEndSupport.create(instrumenter(), Void.class, methodReturnType) + .asyncEnd(context, classAndMethod, returnValue, throwable); + } } + @Nullable @Advice.OnMethodEnter(suppress = Throwable.class) - public static AdviceLocals onEnter( + public static AdviceScope onEnter( @MethodSpanKind SpanKind spanKind, @Advice.Origin("#t") Class declaringClass, @Advice.Origin("#m") String methodName) { - - AdviceLocals locals = new AdviceLocals(); - Context parentContext = currentContext(); - locals.classAndMethod = - MethodAndType.create(ClassAndMethod.create(declaringClass, methodName), spanKind); - - if (!instrumenter().shouldStart(parentContext, locals.classAndMethod)) { - return locals; - } - - locals.context = instrumenter().start(parentContext, locals.classAndMethod); - locals.scope = locals.context.makeCurrent(); - return locals; + return AdviceScope.start(spanKind, declaringClass, methodName); } @AssignReturned.ToReturned @@ -123,15 +140,13 @@ public static AdviceLocals onEnter( public static Object stopSpan( @MethodReturnType Class methodReturnType, @Advice.Return(typing = Assigner.Typing.DYNAMIC) Object returnValue, - @Advice.Thrown Throwable throwable, - @Advice.Enter AdviceLocals locals) { - if (locals.scope == null) { - return returnValue; - } - locals.scope.close(); + @Advice.Thrown @Nullable Throwable throwable, + @Advice.Enter @Nullable AdviceScope adviceScope) { - return AsyncOperationEndSupport.create(instrumenter(), Void.class, methodReturnType) - .asyncEnd(locals.context, locals.classAndMethod, returnValue, throwable); + if (adviceScope != null) { + return adviceScope.end(methodReturnType, returnValue, throwable); + } + return returnValue; } } } From 4eb48b84c41279fd00d5f7cb3659c0a0f0e84441 Mon Sep 17 00:00:00 2001 From: Sylvain Juge <763082+SylvainJuge@users.noreply.github.com> Date: Fri, 24 Oct 2025 14:06:29 +0200 Subject: [PATCH 3/3] another minor fix --- .../instrumentation/methods/MethodInstrumentation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation/methods/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodInstrumentation.java b/instrumentation/methods/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodInstrumentation.java index dd0926d4704c..fbdf52bdf5a0 100644 --- a/instrumentation/methods/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodInstrumentation.java +++ b/instrumentation/methods/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodInstrumentation.java @@ -98,7 +98,7 @@ public static class AdviceScope { private final Context context; private final Scope scope; - public AdviceScope(MethodAndType classAndMethod, Context context, Scope scope) { + private AdviceScope(MethodAndType classAndMethod, Context context, Scope scope) { this.classAndMethod = classAndMethod; this.context = context; this.scope = scope;