Skip to content

Commit 4c76d37

Browse files
committed
lettuce-5.0
1 parent ab14103 commit 4c76d37

File tree

6 files changed

+96
-51
lines changed

6 files changed

+96
-51
lines changed

instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceAsyncCommandInstrumentation.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55

66
package io.opentelemetry.javaagent.instrumentation.lettuce.v5_0;
77

8+
import static io.opentelemetry.javaagent.instrumentation.lettuce.v5_0.LettuceSingletons.CONTEXT;
89
import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
910
import static net.bytebuddy.matcher.ElementMatchers.named;
1011
import static net.bytebuddy.matcher.ElementMatchers.namedOneOf;
1112

1213
import io.lettuce.core.protocol.AsyncCommand;
1314
import io.opentelemetry.context.Context;
1415
import io.opentelemetry.context.Scope;
15-
import io.opentelemetry.instrumentation.api.util.VirtualField;
1616
import io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge;
1717
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
1818
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
@@ -44,22 +44,22 @@ public static void saveContext(@Advice.This AsyncCommand<?, ?, ?> asyncCommand)
4444
Context context = Java8BytecodeBridge.currentContext();
4545
// get the context that submitted this command and attach it, it will be used to run callbacks
4646
context = context.get(LettuceSingletons.COMMAND_CONTEXT_KEY);
47-
VirtualField.find(AsyncCommand.class, Context.class).set(asyncCommand, context);
47+
CONTEXT.set(asyncCommand, context);
4848
}
4949
}
5050

5151
@SuppressWarnings("unused")
5252
public static class RestoreContextAdvice {
5353

5454
@Advice.OnMethodEnter(suppress = Throwable.class)
55-
public static void onEnter(
56-
@Advice.This AsyncCommand<?, ?, ?> asyncCommand, @Advice.Local("otelScope") Scope scope) {
57-
Context context = VirtualField.find(AsyncCommand.class, Context.class).get(asyncCommand);
58-
scope = context.makeCurrent();
55+
public static Scope onEnter(@Advice.This AsyncCommand<?, ?, ?> asyncCommand) {
56+
57+
Context context = CONTEXT.get(asyncCommand);
58+
return context.makeCurrent();
5959
}
6060

6161
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
62-
public static void onExit(@Advice.Local("otelScope") Scope scope) {
62+
public static void onExit(@Advice.Enter Scope scope) {
6363
scope.close();
6464
}
6565
}

instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceAsyncCommandsInstrumentation.java

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import io.opentelemetry.context.Scope;
1919
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
2020
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
21+
import javax.annotation.Nullable;
2122
import net.bytebuddy.asm.Advice;
2223
import net.bytebuddy.description.type.TypeDescription;
2324
import net.bytebuddy.matcher.ElementMatcher;
@@ -41,39 +42,53 @@ public void transform(TypeTransformer transformer) {
4142
@SuppressWarnings("unused")
4243
public static class DispatchAdvice {
4344

45+
public static class AdviceScope {
46+
private final Context context;
47+
private final Scope scope;
48+
49+
public AdviceScope(Context context, Scope scope) {
50+
this.context = context;
51+
this.scope = scope;
52+
}
53+
54+
public void end(
55+
@Nullable Throwable throwable,
56+
RedisCommand<?, ?, ?> command,
57+
AsyncCommand<?, ?, ?> asyncCommand) {
58+
scope.close();
59+
60+
if (throwable != null) {
61+
instrumenter().end(context, command, null, throwable);
62+
return;
63+
}
64+
65+
// close spans on error or normal completion
66+
if (expectsResponse(command)) {
67+
asyncCommand.handleAsync(new EndCommandAsyncBiFunction<>(context, command));
68+
} else {
69+
instrumenter().end(context, command, null, null);
70+
}
71+
}
72+
}
73+
4474
@Advice.OnMethodEnter(suppress = Throwable.class)
45-
public static void onEnter(
46-
@Advice.Argument(0) RedisCommand<?, ?, ?> command,
47-
@Advice.Local("otelContext") Context context,
48-
@Advice.Local("otelScope") Scope scope) {
75+
public static AdviceScope onEnter(@Advice.Argument(0) RedisCommand<?, ?, ?> command) {
4976

5077
Context parentContext = currentContext();
51-
context = instrumenter().start(parentContext, command);
78+
Context context = instrumenter().start(parentContext, command);
5279
// remember the context that called dispatch, it is used in LettuceAsyncCommandInstrumentation
5380
context = context.with(LettuceSingletons.COMMAND_CONTEXT_KEY, parentContext);
54-
scope = context.makeCurrent();
81+
return new AdviceScope(context, context.makeCurrent());
5582
}
5683

5784
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
5885
public static void stopSpan(
5986
@Advice.Argument(0) RedisCommand<?, ?, ?> command,
60-
@Advice.Thrown Throwable throwable,
87+
@Advice.Thrown @Nullable Throwable throwable,
6188
@Advice.Return AsyncCommand<?, ?, ?> asyncCommand,
62-
@Advice.Local("otelContext") Context context,
63-
@Advice.Local("otelScope") Scope scope) {
64-
scope.close();
89+
@Advice.Enter AdviceScope adviceScope) {
6590

66-
if (throwable != null) {
67-
instrumenter().end(context, command, null, throwable);
68-
return;
69-
}
70-
71-
// close spans on error or normal completion
72-
if (expectsResponse(command)) {
73-
asyncCommand.handleAsync(new EndCommandAsyncBiFunction<>(context, command));
74-
} else {
75-
instrumenter().end(context, command, null, null);
76-
}
91+
adviceScope.end(throwable, command, asyncCommand);
7792
}
7893
}
7994
}

instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceClientInstrumentation.java

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import io.opentelemetry.context.Scope;
2222
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
2323
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
24+
import javax.annotation.Nullable;
2425
import net.bytebuddy.asm.Advice;
2526
import net.bytebuddy.description.type.TypeDescription;
2627
import net.bytebuddy.matcher.ElementMatcher;
@@ -47,29 +48,41 @@ public void transform(TypeTransformer transformer) {
4748
@SuppressWarnings("unused")
4849
public static class ConnectAdvice {
4950

51+
public static class AdviceScope {
52+
private final Context context;
53+
private final Scope scope;
54+
55+
public AdviceScope(Context context, Scope scope) {
56+
this.context = context;
57+
this.scope = scope;
58+
}
59+
60+
public void end(
61+
@Nullable Throwable throwable, RedisURI redisUri, ConnectionFuture<?> connectionFuture) {
62+
63+
scope.close();
64+
65+
if (throwable != null) {
66+
connectInstrumenter().end(context, redisUri, null, throwable);
67+
return;
68+
}
69+
connectionFuture.handleAsync(new EndConnectAsyncBiFunction<>(context, redisUri));
70+
}
71+
}
72+
5073
@Advice.OnMethodEnter(suppress = Throwable.class)
51-
public static void onEnter(
52-
@Advice.Argument(1) RedisURI redisUri,
53-
@Advice.Local("otelContext") Context context,
54-
@Advice.Local("otelScope") Scope scope) {
55-
context = connectInstrumenter().start(currentContext(), redisUri);
56-
scope = context.makeCurrent();
74+
public static AdviceScope onEnter(@Advice.Argument(1) RedisURI redisUri) {
75+
Context context = connectInstrumenter().start(currentContext(), redisUri);
76+
return new AdviceScope(context, context.makeCurrent());
5777
}
5878

5979
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
6080
public static void stopSpan(
6181
@Advice.Argument(1) RedisURI redisUri,
62-
@Advice.Thrown Throwable throwable,
82+
@Advice.Thrown @Nullable Throwable throwable,
6383
@Advice.Return ConnectionFuture<?> connectionFuture,
64-
@Advice.Local("otelContext") Context context,
65-
@Advice.Local("otelScope") Scope scope) {
66-
scope.close();
67-
68-
if (throwable != null) {
69-
connectInstrumenter().end(context, redisUri, null, throwable);
70-
return;
71-
}
72-
connectionFuture.handleAsync(new EndConnectAsyncBiFunction<>(context, redisUri));
84+
@Advice.Enter AdviceScope adviceScope) {
85+
adviceScope.end(throwable, redisUri, connectionFuture);
7386
}
7487
}
7588
}

instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceInstrumentationModule.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@
1212
import com.google.auto.service.AutoService;
1313
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
1414
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
15+
import io.opentelemetry.javaagent.extension.instrumentation.internal.ExperimentalInstrumentationModule;
1516
import io.opentelemetry.javaagent.instrumentation.lettuce.v5_0.rx.LettuceReactiveCommandsInstrumentation;
1617
import java.util.List;
1718
import net.bytebuddy.matcher.ElementMatcher;
1819

1920
@AutoService(InstrumentationModule.class)
20-
public class LettuceInstrumentationModule extends InstrumentationModule {
21+
public class LettuceInstrumentationModule extends InstrumentationModule
22+
implements ExperimentalInstrumentationModule {
2123
public LettuceInstrumentationModule() {
2224
super("lettuce", "lettuce-5.0");
2325
}
@@ -35,4 +37,9 @@ public List<TypeInstrumentation> typeInstrumentations() {
3537
new LettuceClientInstrumentation(),
3638
new LettuceReactiveCommandsInstrumentation());
3739
}
40+
41+
@Override
42+
public boolean isIndyReady() {
43+
return true;
44+
}
3845
}

instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceSingletons.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
package io.opentelemetry.javaagent.instrumentation.lettuce.v5_0;
77

88
import io.lettuce.core.RedisURI;
9+
import io.lettuce.core.protocol.AsyncCommand;
910
import io.lettuce.core.protocol.RedisCommand;
1011
import io.opentelemetry.api.GlobalOpenTelemetry;
1112
import io.opentelemetry.context.Context;
@@ -17,6 +18,7 @@
1718
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
1819
import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor;
1920
import io.opentelemetry.instrumentation.api.semconv.network.ServerAttributesExtractor;
21+
import io.opentelemetry.instrumentation.api.util.VirtualField;
2022
import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig;
2123
import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig;
2224

@@ -29,6 +31,9 @@ public final class LettuceSingletons {
2931
public static final ContextKey<Context> COMMAND_CONTEXT_KEY =
3032
ContextKey.named("opentelemetry-lettuce-v5_0-context-key");
3133

34+
public static final VirtualField<AsyncCommand<?, ?, ?>, Context> CONTEXT =
35+
VirtualField.find(AsyncCommand.class, Context.class);
36+
3237
static {
3338
LettuceDbAttributesGetter dbAttributesGetter = new LettuceDbAttributesGetter();
3439

instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/rx/LettuceReactiveCommandsInstrumentation.java

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
2020
import java.util.function.Supplier;
2121
import net.bytebuddy.asm.Advice;
22+
import net.bytebuddy.asm.Advice.AssignReturned;
2223
import net.bytebuddy.description.type.TypeDescription;
2324
import net.bytebuddy.matcher.ElementMatcher;
2425
import org.reactivestreams.Subscription;
@@ -61,10 +62,11 @@ public static <K, V, T> RedisCommand<K, V, T> extractCommandName(
6162

6263
// throwables wouldn't matter here, because no spans have been started due to redis command not
6364
// being run until the user subscribes to the Mono publisher
65+
@AssignReturned.ToReturned
6466
@Advice.OnMethodExit(suppress = Throwable.class)
65-
public static <K, V, T> void monitorSpan(
66-
@Advice.Enter RedisCommand<K, V, T> command,
67-
@Advice.Return(readOnly = false) Mono<T> publisher) {
67+
public static <K, V, T> Mono<T> monitorSpan(
68+
@Advice.Return Mono<T> originalPublisher, @Advice.Enter RedisCommand<K, V, T> command) {
69+
Mono<T> publisher = originalPublisher;
6870
boolean finishSpanOnClose = !expectsResponse(command);
6971
LettuceMonoDualConsumer<? super Subscription, T> mdc =
7072
new LettuceMonoDualConsumer<>(command, finishSpanOnClose);
@@ -73,6 +75,7 @@ public static <K, V, T> void monitorSpan(
7375
if (!finishSpanOnClose) {
7476
publisher = publisher.doOnSuccessOrError(mdc);
7577
}
78+
return publisher;
7679
}
7780
}
7881

@@ -86,10 +89,11 @@ public static <K, V, T> RedisCommand<K, V, T> extractCommandName(
8689
}
8790

8891
// if there is an exception thrown, then don't make spans
92+
@AssignReturned.ToReturned
8993
@Advice.OnMethodExit(suppress = Throwable.class)
90-
public static <K, V, T> void monitorSpan(
91-
@Advice.Enter RedisCommand<K, V, T> command,
92-
@Advice.Return(readOnly = false) Flux<T> publisher) {
94+
public static <K, V, T> Flux<T> monitorSpan(
95+
@Advice.Return Flux<T> originalPublisher, @Advice.Enter RedisCommand<K, V, T> command) {
96+
Flux<T> publisher = originalPublisher;
9397

9498
boolean expectsResponse = expectsResponse(command);
9599
LettuceFluxTerminationRunnable handler =
@@ -102,6 +106,7 @@ public static <K, V, T> void monitorSpan(
102106
publisher = publisher.doOnEach(handler);
103107
publisher = publisher.doOnCancel(handler);
104108
}
109+
return publisher;
105110
}
106111
}
107112
}

0 commit comments

Comments
 (0)