Skip to content

Commit d1a7437

Browse files
authored
make lettuce indy-ready (#14663)
1 parent ecdaa63 commit d1a7437

File tree

14 files changed

+194
-88
lines changed

14 files changed

+194
-88
lines changed

instrumentation/lettuce/lettuce-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceAsyncCommandInstrumentation.java

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

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

8+
import static io.opentelemetry.javaagent.instrumentation.lettuce.v4_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 com.lambdaworks.redis.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,21 @@ 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+
Context context = CONTEXT.get(asyncCommand);
57+
return context.makeCurrent();
5958
}
6059

6160
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
62-
public static void onExit(@Advice.Local("otelScope") Scope scope) {
61+
public static void onExit(@Advice.Enter Scope scope) {
6362
scope.close();
6463
}
6564
}

instrumentation/lettuce/lettuce-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceAsyncCommandsInstrumentation.java

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import io.opentelemetry.context.Scope;
1818
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
1919
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
20+
import javax.annotation.Nullable;
2021
import net.bytebuddy.asm.Advice;
2122
import net.bytebuddy.description.type.TypeDescription;
2223
import net.bytebuddy.matcher.ElementMatcher;
@@ -40,27 +41,41 @@ public void transform(TypeTransformer transformer) {
4041
@SuppressWarnings("unused")
4142
public static class DispatchAdvice {
4243

44+
public static class AdviceScope {
45+
private final Context context;
46+
private final Scope scope;
47+
48+
public AdviceScope(Context context, Scope scope) {
49+
this.context = context;
50+
this.scope = scope;
51+
}
52+
53+
public void end(
54+
@Nullable Throwable throwable,
55+
RedisCommand<?, ?, ?> command,
56+
AsyncCommand<?, ?, ?> asyncCommand) {
57+
scope.close();
58+
InstrumentationPoints.afterCommand(command, context, throwable, asyncCommand);
59+
}
60+
}
61+
4362
@Advice.OnMethodEnter(suppress = Throwable.class)
44-
public static void onEnter(
45-
@Advice.Argument(0) RedisCommand<?, ?, ?> command,
46-
@Advice.Local("otelContext") Context context,
47-
@Advice.Local("otelScope") Scope scope) {
63+
public static AdviceScope onEnter(@Advice.Argument(0) RedisCommand<?, ?, ?> command) {
64+
4865
Context parentContext = currentContext();
49-
context = instrumenter().start(parentContext, command);
66+
Context context = instrumenter().start(parentContext, command);
5067
// remember the context that called dispatch, it is used in LettuceAsyncCommandInstrumentation
5168
context = context.with(LettuceSingletons.COMMAND_CONTEXT_KEY, parentContext);
52-
scope = context.makeCurrent();
69+
return new AdviceScope(context, context.makeCurrent());
5370
}
5471

5572
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
5673
public static void onExit(
5774
@Advice.Argument(0) RedisCommand<?, ?, ?> command,
5875
@Advice.Thrown Throwable throwable,
5976
@Advice.Return AsyncCommand<?, ?, ?> asyncCommand,
60-
@Advice.Local("otelContext") Context context,
61-
@Advice.Local("otelScope") Scope scope) {
62-
scope.close();
63-
InstrumentationPoints.afterCommand(command, context, throwable, asyncCommand);
77+
@Advice.Enter AdviceScope adviceScope) {
78+
adviceScope.end(throwable, command, asyncCommand);
6479
}
6580
}
6681
}

instrumentation/lettuce/lettuce-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceConnectInstrumentation.java

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import io.opentelemetry.context.Scope;
1616
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
1717
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
18+
import javax.annotation.Nullable;
1819
import net.bytebuddy.asm.Advice;
1920
import net.bytebuddy.description.type.TypeDescription;
2021
import net.bytebuddy.matcher.ElementMatcher;
@@ -36,23 +37,33 @@ public void transform(TypeTransformer transformer) {
3637
@SuppressWarnings("unused")
3738
public static class ConnectAdvice {
3839

40+
public static class AdviceScope {
41+
private final Context context;
42+
private final Scope scope;
43+
44+
public AdviceScope(Context context, Scope scope) {
45+
this.context = context;
46+
this.scope = scope;
47+
}
48+
49+
public void end(Throwable throwable, RedisURI redisUri) {
50+
scope.close();
51+
connectInstrumenter().end(context, redisUri, null, throwable);
52+
}
53+
}
54+
3955
@Advice.OnMethodEnter(suppress = Throwable.class)
40-
public static void onEnter(
41-
@Advice.Argument(1) RedisURI redisUri,
42-
@Advice.Local("otelContext") Context context,
43-
@Advice.Local("otelScope") Scope scope) {
44-
context = connectInstrumenter().start(currentContext(), redisUri);
45-
scope = context.makeCurrent();
56+
public static AdviceScope onEnter(@Advice.Argument(1) RedisURI redisUri) {
57+
Context context = connectInstrumenter().start(currentContext(), redisUri);
58+
return new AdviceScope(context, context.makeCurrent());
4659
}
4760

4861
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
4962
public static void onExit(
5063
@Advice.Argument(1) RedisURI redisUri,
51-
@Advice.Thrown Throwable throwable,
52-
@Advice.Local("otelContext") Context context,
53-
@Advice.Local("otelScope") Scope scope) {
54-
scope.close();
55-
connectInstrumenter().end(context, redisUri, null, throwable);
64+
@Advice.Thrown @Nullable Throwable throwable,
65+
@Advice.Enter AdviceScope adviceScope) {
66+
adviceScope.end(throwable, redisUri);
5667
}
5768
}
5869
}

instrumentation/lettuce/lettuce-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceInstrumentationModule.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010
import com.google.auto.service.AutoService;
1111
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
1212
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
13+
import io.opentelemetry.javaagent.extension.instrumentation.internal.ExperimentalInstrumentationModule;
1314
import java.util.List;
1415

1516
@AutoService(InstrumentationModule.class)
16-
public class LettuceInstrumentationModule extends InstrumentationModule {
17+
public class LettuceInstrumentationModule extends InstrumentationModule
18+
implements ExperimentalInstrumentationModule {
1719
public LettuceInstrumentationModule() {
1820
super("lettuce", "lettuce-4.0");
1921
}
@@ -25,4 +27,9 @@ public List<TypeInstrumentation> typeInstrumentations() {
2527
new LettuceAsyncCommandsInstrumentation(),
2628
new LettuceConnectInstrumentation());
2729
}
30+
31+
@Override
32+
public boolean isIndyReady() {
33+
return true;
34+
}
2835
}

instrumentation/lettuce/lettuce-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_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.v4_0;
77

88
import com.lambdaworks.redis.RedisURI;
9+
import com.lambdaworks.redis.protocol.AsyncCommand;
910
import com.lambdaworks.redis.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-v4_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/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
}

0 commit comments

Comments
 (0)