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