make lettuce indy-ready (#14663)
This commit is contained in:
		
							parent
							
								
									ecdaa63cde
								
							
						
					
					
						commit
						d1a74373c5
					
				|  | @ -5,6 +5,7 @@ | |||
| 
 | ||||
| package io.opentelemetry.javaagent.instrumentation.lettuce.v4_0; | ||||
| 
 | ||||
| import static io.opentelemetry.javaagent.instrumentation.lettuce.v4_0.LettuceSingletons.CONTEXT; | ||||
| import static net.bytebuddy.matcher.ElementMatchers.isConstructor; | ||||
| import static net.bytebuddy.matcher.ElementMatchers.named; | ||||
| import static net.bytebuddy.matcher.ElementMatchers.namedOneOf; | ||||
|  | @ -12,7 +13,6 @@ import static net.bytebuddy.matcher.ElementMatchers.namedOneOf; | |||
| import com.lambdaworks.redis.protocol.AsyncCommand; | ||||
| import io.opentelemetry.context.Context; | ||||
| import io.opentelemetry.context.Scope; | ||||
| import io.opentelemetry.instrumentation.api.util.VirtualField; | ||||
| import io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge; | ||||
| import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; | ||||
| import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; | ||||
|  | @ -44,7 +44,7 @@ public class LettuceAsyncCommandInstrumentation implements TypeInstrumentation { | |||
|       Context context = Java8BytecodeBridge.currentContext(); | ||||
|       // get the context that submitted this command and attach it, it will be used to run callbacks | ||||
|       context = context.get(LettuceSingletons.COMMAND_CONTEXT_KEY); | ||||
|       VirtualField.find(AsyncCommand.class, Context.class).set(asyncCommand, context); | ||||
|       CONTEXT.set(asyncCommand, context); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|  | @ -52,14 +52,13 @@ public class LettuceAsyncCommandInstrumentation implements TypeInstrumentation { | |||
|   public static class RestoreContextAdvice { | ||||
| 
 | ||||
|     @Advice.OnMethodEnter(suppress = Throwable.class) | ||||
|     public static void onEnter( | ||||
|         @Advice.This AsyncCommand<?, ?, ?> asyncCommand, @Advice.Local("otelScope") Scope scope) { | ||||
|       Context context = VirtualField.find(AsyncCommand.class, Context.class).get(asyncCommand); | ||||
|       scope = context.makeCurrent(); | ||||
|     public static Scope onEnter(@Advice.This AsyncCommand<?, ?, ?> asyncCommand) { | ||||
|       Context context = CONTEXT.get(asyncCommand); | ||||
|       return context.makeCurrent(); | ||||
|     } | ||||
| 
 | ||||
|     @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) | ||||
|     public static void onExit(@Advice.Local("otelScope") Scope scope) { | ||||
|     public static void onExit(@Advice.Enter Scope scope) { | ||||
|       scope.close(); | ||||
|     } | ||||
|   } | ||||
|  |  | |||
|  | @ -17,6 +17,7 @@ import io.opentelemetry.context.Context; | |||
| 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.description.type.TypeDescription; | ||||
| import net.bytebuddy.matcher.ElementMatcher; | ||||
|  | @ -40,16 +41,32 @@ public class LettuceAsyncCommandsInstrumentation implements TypeInstrumentation | |||
|   @SuppressWarnings("unused") | ||||
|   public static class DispatchAdvice { | ||||
| 
 | ||||
|     public static class AdviceScope { | ||||
|       private final Context context; | ||||
|       private final Scope scope; | ||||
| 
 | ||||
|       public AdviceScope(Context context, Scope scope) { | ||||
|         this.context = context; | ||||
|         this.scope = scope; | ||||
|       } | ||||
| 
 | ||||
|       public void end( | ||||
|           @Nullable Throwable throwable, | ||||
|           RedisCommand<?, ?, ?> command, | ||||
|           AsyncCommand<?, ?, ?> asyncCommand) { | ||||
|         scope.close(); | ||||
|         InstrumentationPoints.afterCommand(command, context, throwable, asyncCommand); | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     @Advice.OnMethodEnter(suppress = Throwable.class) | ||||
|     public static void onEnter( | ||||
|         @Advice.Argument(0) RedisCommand<?, ?, ?> command, | ||||
|         @Advice.Local("otelContext") Context context, | ||||
|         @Advice.Local("otelScope") Scope scope) { | ||||
|     public static AdviceScope onEnter(@Advice.Argument(0) RedisCommand<?, ?, ?> command) { | ||||
| 
 | ||||
|       Context parentContext = currentContext(); | ||||
|       context = instrumenter().start(parentContext, command); | ||||
|       Context context = instrumenter().start(parentContext, command); | ||||
|       // remember the context that called dispatch, it is used in LettuceAsyncCommandInstrumentation | ||||
|       context = context.with(LettuceSingletons.COMMAND_CONTEXT_KEY, parentContext); | ||||
|       scope = context.makeCurrent(); | ||||
|       return new AdviceScope(context, context.makeCurrent()); | ||||
|     } | ||||
| 
 | ||||
|     @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) | ||||
|  | @ -57,10 +74,8 @@ public class LettuceAsyncCommandsInstrumentation implements TypeInstrumentation | |||
|         @Advice.Argument(0) RedisCommand<?, ?, ?> command, | ||||
|         @Advice.Thrown Throwable throwable, | ||||
|         @Advice.Return AsyncCommand<?, ?, ?> asyncCommand, | ||||
|         @Advice.Local("otelContext") Context context, | ||||
|         @Advice.Local("otelScope") Scope scope) { | ||||
|       scope.close(); | ||||
|       InstrumentationPoints.afterCommand(command, context, throwable, asyncCommand); | ||||
|         @Advice.Enter AdviceScope adviceScope) { | ||||
|       adviceScope.end(throwable, command, asyncCommand); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -15,6 +15,7 @@ import io.opentelemetry.context.Context; | |||
| 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.description.type.TypeDescription; | ||||
| import net.bytebuddy.matcher.ElementMatcher; | ||||
|  | @ -36,23 +37,33 @@ public class LettuceConnectInstrumentation implements TypeInstrumentation { | |||
|   @SuppressWarnings("unused") | ||||
|   public static class ConnectAdvice { | ||||
| 
 | ||||
|     public static class AdviceScope { | ||||
|       private final Context context; | ||||
|       private final Scope scope; | ||||
| 
 | ||||
|       public AdviceScope(Context context, Scope scope) { | ||||
|         this.context = context; | ||||
|         this.scope = scope; | ||||
|       } | ||||
| 
 | ||||
|       public void end(Throwable throwable, RedisURI redisUri) { | ||||
|         scope.close(); | ||||
|         connectInstrumenter().end(context, redisUri, null, throwable); | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     @Advice.OnMethodEnter(suppress = Throwable.class) | ||||
|     public static void onEnter( | ||||
|         @Advice.Argument(1) RedisURI redisUri, | ||||
|         @Advice.Local("otelContext") Context context, | ||||
|         @Advice.Local("otelScope") Scope scope) { | ||||
|       context = connectInstrumenter().start(currentContext(), redisUri); | ||||
|       scope = context.makeCurrent(); | ||||
|     public static AdviceScope onEnter(@Advice.Argument(1) RedisURI redisUri) { | ||||
|       Context context = connectInstrumenter().start(currentContext(), redisUri); | ||||
|       return new AdviceScope(context, context.makeCurrent()); | ||||
|     } | ||||
| 
 | ||||
|     @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) | ||||
|     public static void onExit( | ||||
|         @Advice.Argument(1) RedisURI redisUri, | ||||
|         @Advice.Thrown Throwable throwable, | ||||
|         @Advice.Local("otelContext") Context context, | ||||
|         @Advice.Local("otelScope") Scope scope) { | ||||
|       scope.close(); | ||||
|       connectInstrumenter().end(context, redisUri, null, throwable); | ||||
|         @Advice.Thrown @Nullable Throwable throwable, | ||||
|         @Advice.Enter AdviceScope adviceScope) { | ||||
|       adviceScope.end(throwable, redisUri); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -10,10 +10,12 @@ import static java.util.Arrays.asList; | |||
| 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 LettuceInstrumentationModule extends InstrumentationModule { | ||||
| public class LettuceInstrumentationModule extends InstrumentationModule | ||||
|     implements ExperimentalInstrumentationModule { | ||||
|   public LettuceInstrumentationModule() { | ||||
|     super("lettuce", "lettuce-4.0"); | ||||
|   } | ||||
|  | @ -25,4 +27,9 @@ public class LettuceInstrumentationModule extends InstrumentationModule { | |||
|         new LettuceAsyncCommandsInstrumentation(), | ||||
|         new LettuceConnectInstrumentation()); | ||||
|   } | ||||
| 
 | ||||
|   @Override | ||||
|   public boolean isIndyReady() { | ||||
|     return true; | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ | |||
| package io.opentelemetry.javaagent.instrumentation.lettuce.v4_0; | ||||
| 
 | ||||
| import com.lambdaworks.redis.RedisURI; | ||||
| import com.lambdaworks.redis.protocol.AsyncCommand; | ||||
| import com.lambdaworks.redis.protocol.RedisCommand; | ||||
| import io.opentelemetry.api.GlobalOpenTelemetry; | ||||
| import io.opentelemetry.context.Context; | ||||
|  | @ -17,6 +18,7 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.net.PeerServiceAtt | |||
| import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; | ||||
| import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; | ||||
| import io.opentelemetry.instrumentation.api.semconv.network.ServerAttributesExtractor; | ||||
| import io.opentelemetry.instrumentation.api.util.VirtualField; | ||||
| import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; | ||||
| import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; | ||||
| 
 | ||||
|  | @ -29,6 +31,9 @@ public final class LettuceSingletons { | |||
|   public static final ContextKey<Context> COMMAND_CONTEXT_KEY = | ||||
|       ContextKey.named("opentelemetry-lettuce-v4_0-context-key"); | ||||
| 
 | ||||
|   public static final VirtualField<AsyncCommand<?, ?, ?>, Context> CONTEXT = | ||||
|       VirtualField.find(AsyncCommand.class, Context.class); | ||||
| 
 | ||||
|   static { | ||||
|     LettuceDbAttributesGetter dbAttributesGetter = new LettuceDbAttributesGetter(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ | |||
| 
 | ||||
| package io.opentelemetry.javaagent.instrumentation.lettuce.v5_0; | ||||
| 
 | ||||
| import static io.opentelemetry.javaagent.instrumentation.lettuce.v5_0.LettuceSingletons.CONTEXT; | ||||
| import static net.bytebuddy.matcher.ElementMatchers.isConstructor; | ||||
| import static net.bytebuddy.matcher.ElementMatchers.named; | ||||
| import static net.bytebuddy.matcher.ElementMatchers.namedOneOf; | ||||
|  | @ -12,7 +13,6 @@ import static net.bytebuddy.matcher.ElementMatchers.namedOneOf; | |||
| import io.lettuce.core.protocol.AsyncCommand; | ||||
| import io.opentelemetry.context.Context; | ||||
| import io.opentelemetry.context.Scope; | ||||
| import io.opentelemetry.instrumentation.api.util.VirtualField; | ||||
| import io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge; | ||||
| import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; | ||||
| import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; | ||||
|  | @ -44,7 +44,7 @@ public class LettuceAsyncCommandInstrumentation implements TypeInstrumentation { | |||
|       Context context = Java8BytecodeBridge.currentContext(); | ||||
|       // get the context that submitted this command and attach it, it will be used to run callbacks | ||||
|       context = context.get(LettuceSingletons.COMMAND_CONTEXT_KEY); | ||||
|       VirtualField.find(AsyncCommand.class, Context.class).set(asyncCommand, context); | ||||
|       CONTEXT.set(asyncCommand, context); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|  | @ -52,14 +52,14 @@ public class LettuceAsyncCommandInstrumentation implements TypeInstrumentation { | |||
|   public static class RestoreContextAdvice { | ||||
| 
 | ||||
|     @Advice.OnMethodEnter(suppress = Throwable.class) | ||||
|     public static void onEnter( | ||||
|         @Advice.This AsyncCommand<?, ?, ?> asyncCommand, @Advice.Local("otelScope") Scope scope) { | ||||
|       Context context = VirtualField.find(AsyncCommand.class, Context.class).get(asyncCommand); | ||||
|       scope = context.makeCurrent(); | ||||
|     public static Scope onEnter(@Advice.This AsyncCommand<?, ?, ?> asyncCommand) { | ||||
| 
 | ||||
|       Context context = CONTEXT.get(asyncCommand); | ||||
|       return context.makeCurrent(); | ||||
|     } | ||||
| 
 | ||||
|     @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) | ||||
|     public static void onExit(@Advice.Local("otelScope") Scope scope) { | ||||
|     public static void onExit(@Advice.Enter Scope scope) { | ||||
|       scope.close(); | ||||
|     } | ||||
|   } | ||||
|  |  | |||
|  | @ -18,6 +18,7 @@ import io.opentelemetry.context.Context; | |||
| 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.description.type.TypeDescription; | ||||
| import net.bytebuddy.matcher.ElementMatcher; | ||||
|  | @ -41,39 +42,53 @@ public class LettuceAsyncCommandsInstrumentation implements TypeInstrumentation | |||
|   @SuppressWarnings("unused") | ||||
|   public static class DispatchAdvice { | ||||
| 
 | ||||
|     public static class AdviceScope { | ||||
|       private final Context context; | ||||
|       private final Scope scope; | ||||
| 
 | ||||
|       public AdviceScope(Context context, Scope scope) { | ||||
|         this.context = context; | ||||
|         this.scope = scope; | ||||
|       } | ||||
| 
 | ||||
|       public void end( | ||||
|           @Nullable Throwable throwable, | ||||
|           RedisCommand<?, ?, ?> command, | ||||
|           AsyncCommand<?, ?, ?> asyncCommand) { | ||||
|         scope.close(); | ||||
| 
 | ||||
|         if (throwable != null) { | ||||
|           instrumenter().end(context, command, null, throwable); | ||||
|           return; | ||||
|         } | ||||
| 
 | ||||
|         // close spans on error or normal completion | ||||
|         if (expectsResponse(command)) { | ||||
|           asyncCommand.handleAsync(new EndCommandAsyncBiFunction<>(context, command)); | ||||
|         } else { | ||||
|           instrumenter().end(context, command, null, null); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     @Advice.OnMethodEnter(suppress = Throwable.class) | ||||
|     public static void onEnter( | ||||
|         @Advice.Argument(0) RedisCommand<?, ?, ?> command, | ||||
|         @Advice.Local("otelContext") Context context, | ||||
|         @Advice.Local("otelScope") Scope scope) { | ||||
|     public static AdviceScope onEnter(@Advice.Argument(0) RedisCommand<?, ?, ?> command) { | ||||
| 
 | ||||
|       Context parentContext = currentContext(); | ||||
|       context = instrumenter().start(parentContext, command); | ||||
|       Context context = instrumenter().start(parentContext, command); | ||||
|       // remember the context that called dispatch, it is used in LettuceAsyncCommandInstrumentation | ||||
|       context = context.with(LettuceSingletons.COMMAND_CONTEXT_KEY, parentContext); | ||||
|       scope = context.makeCurrent(); | ||||
|       return new AdviceScope(context, context.makeCurrent()); | ||||
|     } | ||||
| 
 | ||||
|     @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) | ||||
|     public static void stopSpan( | ||||
|         @Advice.Argument(0) RedisCommand<?, ?, ?> command, | ||||
|         @Advice.Thrown Throwable throwable, | ||||
|         @Advice.Thrown @Nullable Throwable throwable, | ||||
|         @Advice.Return AsyncCommand<?, ?, ?> asyncCommand, | ||||
|         @Advice.Local("otelContext") Context context, | ||||
|         @Advice.Local("otelScope") Scope scope) { | ||||
|       scope.close(); | ||||
|         @Advice.Enter AdviceScope adviceScope) { | ||||
| 
 | ||||
|       if (throwable != null) { | ||||
|         instrumenter().end(context, command, null, throwable); | ||||
|         return; | ||||
|       } | ||||
| 
 | ||||
|       // close spans on error or normal completion | ||||
|       if (expectsResponse(command)) { | ||||
|         asyncCommand.handleAsync(new EndCommandAsyncBiFunction<>(context, command)); | ||||
|       } else { | ||||
|         instrumenter().end(context, command, null, null); | ||||
|       } | ||||
|       adviceScope.end(throwable, command, asyncCommand); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -21,6 +21,7 @@ import io.opentelemetry.context.Context; | |||
| 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.description.type.TypeDescription; | ||||
| import net.bytebuddy.matcher.ElementMatcher; | ||||
|  | @ -47,29 +48,41 @@ public class LettuceClientInstrumentation implements TypeInstrumentation { | |||
|   @SuppressWarnings("unused") | ||||
|   public static class ConnectAdvice { | ||||
| 
 | ||||
|     public static class AdviceScope { | ||||
|       private final Context context; | ||||
|       private final Scope scope; | ||||
| 
 | ||||
|       public AdviceScope(Context context, Scope scope) { | ||||
|         this.context = context; | ||||
|         this.scope = scope; | ||||
|       } | ||||
| 
 | ||||
|       public void end( | ||||
|           @Nullable Throwable throwable, RedisURI redisUri, ConnectionFuture<?> connectionFuture) { | ||||
| 
 | ||||
|         scope.close(); | ||||
| 
 | ||||
|         if (throwable != null) { | ||||
|           connectInstrumenter().end(context, redisUri, null, throwable); | ||||
|           return; | ||||
|         } | ||||
|         connectionFuture.handleAsync(new EndConnectAsyncBiFunction<>(context, redisUri)); | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     @Advice.OnMethodEnter(suppress = Throwable.class) | ||||
|     public static void onEnter( | ||||
|         @Advice.Argument(1) RedisURI redisUri, | ||||
|         @Advice.Local("otelContext") Context context, | ||||
|         @Advice.Local("otelScope") Scope scope) { | ||||
|       context = connectInstrumenter().start(currentContext(), redisUri); | ||||
|       scope = context.makeCurrent(); | ||||
|     public static AdviceScope onEnter(@Advice.Argument(1) RedisURI redisUri) { | ||||
|       Context context = connectInstrumenter().start(currentContext(), redisUri); | ||||
|       return new AdviceScope(context, context.makeCurrent()); | ||||
|     } | ||||
| 
 | ||||
|     @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) | ||||
|     public static void stopSpan( | ||||
|         @Advice.Argument(1) RedisURI redisUri, | ||||
|         @Advice.Thrown Throwable throwable, | ||||
|         @Advice.Thrown @Nullable Throwable throwable, | ||||
|         @Advice.Return ConnectionFuture<?> connectionFuture, | ||||
|         @Advice.Local("otelContext") Context context, | ||||
|         @Advice.Local("otelScope") Scope scope) { | ||||
|       scope.close(); | ||||
| 
 | ||||
|       if (throwable != null) { | ||||
|         connectInstrumenter().end(context, redisUri, null, throwable); | ||||
|         return; | ||||
|       } | ||||
|       connectionFuture.handleAsync(new EndConnectAsyncBiFunction<>(context, redisUri)); | ||||
|         @Advice.Enter AdviceScope adviceScope) { | ||||
|       adviceScope.end(throwable, redisUri, connectionFuture); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -12,12 +12,14 @@ import static net.bytebuddy.matcher.ElementMatchers.not; | |||
| 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 io.opentelemetry.javaagent.instrumentation.lettuce.v5_0.rx.LettuceReactiveCommandsInstrumentation; | ||||
| import java.util.List; | ||||
| import net.bytebuddy.matcher.ElementMatcher; | ||||
| 
 | ||||
| @AutoService(InstrumentationModule.class) | ||||
| public class LettuceInstrumentationModule extends InstrumentationModule { | ||||
| public class LettuceInstrumentationModule extends InstrumentationModule | ||||
|     implements ExperimentalInstrumentationModule { | ||||
|   public LettuceInstrumentationModule() { | ||||
|     super("lettuce", "lettuce-5.0"); | ||||
|   } | ||||
|  | @ -35,4 +37,9 @@ public class LettuceInstrumentationModule extends InstrumentationModule { | |||
|         new LettuceClientInstrumentation(), | ||||
|         new LettuceReactiveCommandsInstrumentation()); | ||||
|   } | ||||
| 
 | ||||
|   @Override | ||||
|   public boolean isIndyReady() { | ||||
|     return true; | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ | |||
| package io.opentelemetry.javaagent.instrumentation.lettuce.v5_0; | ||||
| 
 | ||||
| import io.lettuce.core.RedisURI; | ||||
| import io.lettuce.core.protocol.AsyncCommand; | ||||
| import io.lettuce.core.protocol.RedisCommand; | ||||
| import io.opentelemetry.api.GlobalOpenTelemetry; | ||||
| import io.opentelemetry.context.Context; | ||||
|  | @ -17,6 +18,7 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.net.PeerServiceAtt | |||
| import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; | ||||
| import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; | ||||
| import io.opentelemetry.instrumentation.api.semconv.network.ServerAttributesExtractor; | ||||
| import io.opentelemetry.instrumentation.api.util.VirtualField; | ||||
| import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; | ||||
| import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; | ||||
| 
 | ||||
|  | @ -29,6 +31,9 @@ public final class LettuceSingletons { | |||
|   public static final ContextKey<Context> COMMAND_CONTEXT_KEY = | ||||
|       ContextKey.named("opentelemetry-lettuce-v5_0-context-key"); | ||||
| 
 | ||||
|   public static final VirtualField<AsyncCommand<?, ?, ?>, Context> CONTEXT = | ||||
|       VirtualField.find(AsyncCommand.class, Context.class); | ||||
| 
 | ||||
|   static { | ||||
|     LettuceDbAttributesGetter dbAttributesGetter = new LettuceDbAttributesGetter(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -19,6 +19,7 @@ import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; | |||
| import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; | ||||
| import java.util.function.Supplier; | ||||
| import net.bytebuddy.asm.Advice; | ||||
| import net.bytebuddy.asm.Advice.AssignReturned; | ||||
| import net.bytebuddy.description.type.TypeDescription; | ||||
| import net.bytebuddy.matcher.ElementMatcher; | ||||
| import org.reactivestreams.Subscription; | ||||
|  | @ -61,10 +62,11 @@ public class LettuceReactiveCommandsInstrumentation implements TypeInstrumentati | |||
| 
 | ||||
|     // throwables wouldn't matter here, because no spans have been started due to redis command not | ||||
|     // being run until the user subscribes to the Mono publisher | ||||
|     @AssignReturned.ToReturned | ||||
|     @Advice.OnMethodExit(suppress = Throwable.class) | ||||
|     public static <K, V, T> void monitorSpan( | ||||
|         @Advice.Enter RedisCommand<K, V, T> command, | ||||
|         @Advice.Return(readOnly = false) Mono<T> publisher) { | ||||
|     public static <K, V, T> Mono<T> monitorSpan( | ||||
|         @Advice.Return Mono<T> originalPublisher, @Advice.Enter RedisCommand<K, V, T> command) { | ||||
|       Mono<T> publisher = originalPublisher; | ||||
|       boolean finishSpanOnClose = !expectsResponse(command); | ||||
|       LettuceMonoDualConsumer<? super Subscription, T> mdc = | ||||
|           new LettuceMonoDualConsumer<>(command, finishSpanOnClose); | ||||
|  | @ -73,6 +75,7 @@ public class LettuceReactiveCommandsInstrumentation implements TypeInstrumentati | |||
|       if (!finishSpanOnClose) { | ||||
|         publisher = publisher.doOnSuccessOrError(mdc); | ||||
|       } | ||||
|       return publisher; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|  | @ -86,10 +89,11 @@ public class LettuceReactiveCommandsInstrumentation implements TypeInstrumentati | |||
|     } | ||||
| 
 | ||||
|     // if there is an exception thrown, then don't make spans | ||||
|     @AssignReturned.ToReturned | ||||
|     @Advice.OnMethodExit(suppress = Throwable.class) | ||||
|     public static <K, V, T> void monitorSpan( | ||||
|         @Advice.Enter RedisCommand<K, V, T> command, | ||||
|         @Advice.Return(readOnly = false) Flux<T> publisher) { | ||||
|     public static <K, V, T> Flux<T> monitorSpan( | ||||
|         @Advice.Return Flux<T> originalPublisher, @Advice.Enter RedisCommand<K, V, T> command) { | ||||
|       Flux<T> publisher = originalPublisher; | ||||
| 
 | ||||
|       boolean expectsResponse = expectsResponse(command); | ||||
|       LettuceFluxTerminationRunnable handler = | ||||
|  | @ -102,6 +106,7 @@ public class LettuceReactiveCommandsInstrumentation implements TypeInstrumentati | |||
|         publisher = publisher.doOnEach(handler); | ||||
|         publisher = publisher.doOnCancel(handler); | ||||
|       } | ||||
|       return publisher; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ | |||
| 
 | ||||
| package io.opentelemetry.javaagent.instrumentation.lettuce.v5_1; | ||||
| 
 | ||||
| import static io.opentelemetry.javaagent.instrumentation.lettuce.v5_1.LettuceSingletons.CONTEXT; | ||||
| import static net.bytebuddy.matcher.ElementMatchers.isConstructor; | ||||
| import static net.bytebuddy.matcher.ElementMatchers.named; | ||||
| import static net.bytebuddy.matcher.ElementMatchers.namedOneOf; | ||||
|  | @ -12,7 +13,6 @@ import static net.bytebuddy.matcher.ElementMatchers.namedOneOf; | |||
| import io.lettuce.core.protocol.AsyncCommand; | ||||
| import io.opentelemetry.context.Context; | ||||
| import io.opentelemetry.context.Scope; | ||||
| import io.opentelemetry.instrumentation.api.util.VirtualField; | ||||
| import io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge; | ||||
| import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; | ||||
| import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; | ||||
|  | @ -42,7 +42,7 @@ public class LettuceAsyncCommandInstrumentation implements TypeInstrumentation { | |||
|     @Advice.OnMethodExit(suppress = Throwable.class) | ||||
|     public static void saveContext(@Advice.This AsyncCommand<?, ?, ?> asyncCommand) { | ||||
|       Context context = Java8BytecodeBridge.currentContext(); | ||||
|       VirtualField.find(AsyncCommand.class, Context.class).set(asyncCommand, context); | ||||
|       CONTEXT.set(asyncCommand, context); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|  | @ -50,14 +50,13 @@ public class LettuceAsyncCommandInstrumentation implements TypeInstrumentation { | |||
|   public static class RestoreContextAdvice { | ||||
| 
 | ||||
|     @Advice.OnMethodEnter(suppress = Throwable.class) | ||||
|     public static void onEnter( | ||||
|         @Advice.This AsyncCommand<?, ?, ?> asyncCommand, @Advice.Local("otelScope") Scope scope) { | ||||
|       Context context = VirtualField.find(AsyncCommand.class, Context.class).get(asyncCommand); | ||||
|       scope = context.makeCurrent(); | ||||
|     public static Scope onEnter(@Advice.This AsyncCommand<?, ?, ?> asyncCommand) { | ||||
|       Context context = CONTEXT.get(asyncCommand); | ||||
|       return context.makeCurrent(); | ||||
|     } | ||||
| 
 | ||||
|     @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) | ||||
|     public static void onExit(@Advice.Local("otelScope") Scope scope) { | ||||
|     public static void onExit(@Advice.Enter Scope scope) { | ||||
|       scope.close(); | ||||
|     } | ||||
|   } | ||||
|  |  | |||
|  | @ -11,11 +11,13 @@ import static java.util.Arrays.asList; | |||
| 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; | ||||
| import net.bytebuddy.matcher.ElementMatcher; | ||||
| 
 | ||||
| @AutoService(InstrumentationModule.class) | ||||
| public class LettuceInstrumentationModule extends InstrumentationModule { | ||||
| public class LettuceInstrumentationModule extends InstrumentationModule | ||||
|     implements ExperimentalInstrumentationModule { | ||||
| 
 | ||||
|   public LettuceInstrumentationModule() { | ||||
|     super("lettuce", "lettuce-5.1"); | ||||
|  | @ -36,4 +38,9 @@ public class LettuceInstrumentationModule extends InstrumentationModule { | |||
|     return asList( | ||||
|         new DefaultClientResourcesInstrumentation(), new LettuceAsyncCommandInstrumentation()); | ||||
|   } | ||||
| 
 | ||||
|   @Override | ||||
|   public boolean isIndyReady() { | ||||
|     return true; | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,18 @@ | |||
| /* | ||||
|  * Copyright The OpenTelemetry Authors | ||||
|  * SPDX-License-Identifier: Apache-2.0 | ||||
|  */ | ||||
| 
 | ||||
| package io.opentelemetry.javaagent.instrumentation.lettuce.v5_1; | ||||
| 
 | ||||
| import io.lettuce.core.protocol.AsyncCommand; | ||||
| import io.opentelemetry.context.Context; | ||||
| import io.opentelemetry.instrumentation.api.util.VirtualField; | ||||
| 
 | ||||
| public class LettuceSingletons { | ||||
| 
 | ||||
|   public static final VirtualField<AsyncCommand<?, ?, ?>, Context> CONTEXT = | ||||
|       VirtualField.find(AsyncCommand.class, Context.class); | ||||
| 
 | ||||
|   private LettuceSingletons() {} | ||||
| } | ||||
		Loading…
	
		Reference in New Issue