From 3b568624245d93be53c465d2a0cf52f96bd5aed1 Mon Sep 17 00:00:00 2001 From: Sylvain Juge <763082+SylvainJuge@users.noreply.github.com> Date: Thu, 16 Oct 2025 15:08:21 +0200 Subject: [PATCH 1/2] wip --- .../ApiClientInstrumentation.java | 80 ++++++++++++------- ...KubernetesClientInstrumentationModule.java | 9 ++- 2 files changed, 57 insertions(+), 32 deletions(-) diff --git a/instrumentation/kubernetes-client-7.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/ApiClientInstrumentation.java b/instrumentation/kubernetes-client-7.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/ApiClientInstrumentation.java index 1800e32aaca4..6ad055629a68 100644 --- a/instrumentation/kubernetes-client-7.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/ApiClientInstrumentation.java +++ b/instrumentation/kubernetes-client-7.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/ApiClientInstrumentation.java @@ -20,7 +20,10 @@ import io.opentelemetry.context.Scope; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; +import javax.annotation.Nullable; import net.bytebuddy.asm.Advice; +import net.bytebuddy.asm.Advice.AssignReturned; +import net.bytebuddy.asm.Advice.AssignReturned.ToArguments.ToArgument; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; import okhttp3.Call; @@ -55,19 +58,21 @@ public void transform(TypeTransformer transformer) { @SuppressWarnings("unused") public static class BuildRequestAdvice { + @AssignReturned.ToReturned @Advice.OnMethodExit(suppress = Throwable.class) - public static void onExit(@Advice.Return(readOnly = false) Request request) { + public static Request onExit(@Advice.Return Request originalReturnValue) { Context parentContext = currentContext(); - if (!instrumenter().shouldStart(parentContext, request)) { - return; + if (!instrumenter().shouldStart(parentContext, originalReturnValue)) { + return originalReturnValue; } - Context context = instrumenter().start(parentContext, request); + Context context = instrumenter().start(parentContext, originalReturnValue); Scope scope = context.makeCurrent(); - Request.Builder requestWithPropagation = request.newBuilder(); + Request.Builder requestWithPropagation = originalReturnValue.newBuilder(); inject(context, requestWithPropagation); - request = requestWithPropagation.build(); - CurrentState.set(parentContext, context, scope, request); + Request returnValue = requestWithPropagation.build(); + CurrentState.set(parentContext, context, scope, originalReturnValue); + return returnValue; } } @@ -96,39 +101,52 @@ public static void onExit( @SuppressWarnings("unused") public static class ExecuteAsyncAdvice { + public static class AdviceScope { + private final Scope scope; + private final CurrentState current; + + private AdviceScope(CurrentState current, Scope scope) { + this.current = current; + this.scope = scope; + } + + public static AdviceScope start(CurrentState current) { + return new AdviceScope(current, current.getContext().makeCurrent()); + } + + public ApiCallback wrapCallBack(ApiCallback callback) { + return new TracingApiCallback<>( + callback, current.getParentContext(), current.getContext(), current.getRequest()); + } + + public void end(@Nullable Throwable throwable) { + scope.close(); + if (throwable != null) { + instrumenter().end(current.getContext(), current.getRequest(), null, throwable); + } + // else span will be ended in the TracingApiCallback + } + } + + @AssignReturned.ToArguments(@ToArgument(value = 2, index = 1)) @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.Argument(0) Call httpCall, - @Advice.Argument(value = 2, readOnly = false) ApiCallback callback, - @Advice.Local("otelContext") Context context, - @Advice.Local("otelScope") Scope scope, - @Advice.Local("otelRequest") Request request) { + public static Object[] onEnter( + @Advice.Argument(0) Call httpCall, @Advice.Argument(2) ApiCallback callback) { CurrentState current = CurrentState.remove(); if (current == null) { - return; + return new Object[] {null, callback}; } - - context = current.getContext(); - scope = current.getScope(); - request = current.getRequest(); - callback = new TracingApiCallback<>(callback, current.getParentContext(), context, request); + AdviceScope adviceScope = AdviceScope.start(current); + return new Object[] {adviceScope, adviceScope.wrapCallBack(callback)}; } @Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class) public static void onExit( - @Advice.Thrown Throwable throwable, - @Advice.Local("otelContext") Context context, - @Advice.Local("otelScope") Scope scope, - @Advice.Local("otelRequest") Request request) { - if (scope == null) { - return; - } - scope.close(); - - if (throwable != null) { - instrumenter().end(context, request, null, throwable); + @Advice.Thrown @Nullable Throwable throwable, @Advice.Enter Object[] enterResult) { + AdviceScope adviceScope = (AdviceScope) enterResult[0]; + if (adviceScope != null) { + adviceScope.end(throwable); } - // else span will be ended in the TracingApiCallback } } } diff --git a/instrumentation/kubernetes-client-7.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesClientInstrumentationModule.java b/instrumentation/kubernetes-client-7.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesClientInstrumentationModule.java index ea00adef7ee5..4de706a674ca 100644 --- a/instrumentation/kubernetes-client-7.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesClientInstrumentationModule.java +++ b/instrumentation/kubernetes-client-7.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesClientInstrumentationModule.java @@ -10,10 +10,12 @@ import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import io.opentelemetry.javaagent.extension.instrumentation.internal.ExperimentalInstrumentationModule; import java.util.List; @AutoService(InstrumentationModule.class) -public class KubernetesClientInstrumentationModule extends InstrumentationModule { +public class KubernetesClientInstrumentationModule extends InstrumentationModule + implements ExperimentalInstrumentationModule { public KubernetesClientInstrumentationModule() { super("kubernetes-client", "kubernetes-client-7.0"); @@ -23,4 +25,9 @@ public KubernetesClientInstrumentationModule() { public List typeInstrumentations() { return singletonList(new ApiClientInstrumentation()); } + + @Override + public boolean isIndyReady() { + return true; + } } From cec477cb3ead4f7cd2579bf30e4064b4ec958bfe Mon Sep 17 00:00:00 2001 From: Sylvain Juge <763082+SylvainJuge@users.noreply.github.com> Date: Thu, 16 Oct 2025 15:21:59 +0200 Subject: [PATCH 2/2] fix things --- .../ApiClientInstrumentation.java | 56 +++++++------------ 1 file changed, 19 insertions(+), 37 deletions(-) diff --git a/instrumentation/kubernetes-client-7.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/ApiClientInstrumentation.java b/instrumentation/kubernetes-client-7.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/ApiClientInstrumentation.java index 6ad055629a68..040c126d2c44 100644 --- a/instrumentation/kubernetes-client-7.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/ApiClientInstrumentation.java +++ b/instrumentation/kubernetes-client-7.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/ApiClientInstrumentation.java @@ -70,9 +70,9 @@ public static Request onExit(@Advice.Return Request originalReturnValue) { Scope scope = context.makeCurrent(); Request.Builder requestWithPropagation = originalReturnValue.newBuilder(); inject(context, requestWithPropagation); - Request returnValue = requestWithPropagation.build(); - CurrentState.set(parentContext, context, scope, originalReturnValue); - return returnValue; + Request request = requestWithPropagation.build(); + CurrentState.set(parentContext, context, scope, request); + return request; } } @@ -101,51 +101,33 @@ public static void onExit( @SuppressWarnings("unused") public static class ExecuteAsyncAdvice { - public static class AdviceScope { - private final Scope scope; - private final CurrentState current; - - private AdviceScope(CurrentState current, Scope scope) { - this.current = current; - this.scope = scope; - } - - public static AdviceScope start(CurrentState current) { - return new AdviceScope(current, current.getContext().makeCurrent()); - } - - public ApiCallback wrapCallBack(ApiCallback callback) { - return new TracingApiCallback<>( - callback, current.getParentContext(), current.getContext(), current.getRequest()); - } - - public void end(@Nullable Throwable throwable) { - scope.close(); - if (throwable != null) { - instrumenter().end(current.getContext(), current.getRequest(), null, throwable); - } - // else span will be ended in the TracingApiCallback - } - } - @AssignReturned.ToArguments(@ToArgument(value = 2, index = 1)) @Advice.OnMethodEnter(suppress = Throwable.class) public static Object[] onEnter( - @Advice.Argument(0) Call httpCall, @Advice.Argument(2) ApiCallback callback) { + @Advice.Argument(0) Call httpCall, @Advice.Argument(2) ApiCallback originalCallback) { CurrentState current = CurrentState.remove(); if (current == null) { - return new Object[] {null, callback}; + return new Object[] {null, originalCallback}; } - AdviceScope adviceScope = AdviceScope.start(current); - return new Object[] {adviceScope, adviceScope.wrapCallBack(callback)}; + ApiCallback callback = + new TracingApiCallback<>( + originalCallback, + current.getParentContext(), + current.getContext(), + current.getRequest()); + return new Object[] {current, callback}; } @Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class) public static void onExit( @Advice.Thrown @Nullable Throwable throwable, @Advice.Enter Object[] enterResult) { - AdviceScope adviceScope = (AdviceScope) enterResult[0]; - if (adviceScope != null) { - adviceScope.end(throwable); + CurrentState current = (CurrentState) enterResult[0]; + if (current != null) { + current.getScope().close(); + if (throwable != null) { + instrumenter().end(current.getContext(), current.getRequest(), null, throwable); + } + // else span will be ended in the TracingApiCallback } } }