Skip to content

Commit 8240a5f

Browse files
authored
End jedis span when operation actually ends (#5256)
* End jedis span when operation actually ends * address review comments
1 parent fbf0076 commit 8240a5f

File tree

16 files changed

+330
-20
lines changed

16 files changed

+330
-20
lines changed

instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/db/RedisCommandSanitizer.java

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,21 +52,31 @@ public final class RedisCommandSanitizer {
5252
CommandSanitizer setMultiField = new MultiKeyValue(0);
5353

5454
// Cluster
55-
for (String command : asList("CLUSTER", "READONLY", "READWRITE")) {
55+
for (String command : asList("CLUSTER", "FAILOVER", "READONLY", "READWRITE")) {
5656
sanitizers.put(command, KeepAllArgs.INSTANCE);
5757
}
5858

5959
// Connection
6060
sanitizers.put("AUTH", DEFAULT);
6161
// HELLO can contain AUTH data
6262
sanitizers.put("HELLO", keepTwoArgs);
63-
for (String command : asList("CLIENT", "ECHO", "PING", "QUIT", "SELECT")) {
63+
for (String command : asList("CLIENT", "ECHO", "PING", "QUIT", "RESET", "SELECT")) {
6464
sanitizers.put(command, KeepAllArgs.INSTANCE);
6565
}
6666

6767
// Geo
6868
for (String command :
69-
asList("GEOADD", "GEODIST", "GEOHASH", "GEOPOS", "GEORADIUS", "GEORADIUSBYMEMBER")) {
69+
asList(
70+
"GEOADD",
71+
"GEODIST",
72+
"GEOHASH",
73+
"GEOPOS",
74+
"GEORADIUS",
75+
"GEORADIUS_RO",
76+
"GEORADIUSBYMEMBER",
77+
"GEORADIUSBYMEMBER_RO",
78+
"GEOSEARCH",
79+
"GEOSEARCHSTORE")) {
7080
sanitizers.put(command, KeepAllArgs.INSTANCE);
7181
}
7282

@@ -85,6 +95,7 @@ public final class RedisCommandSanitizer {
8595
"HKEYS",
8696
"HLEN",
8797
"HMGET",
98+
"HRANDFIELD",
8899
"HSCAN",
89100
"HSTRLEN",
90101
"HVALS")) {
@@ -103,23 +114,27 @@ public final class RedisCommandSanitizer {
103114
sanitizers.put("RESTORE", keepTwoArgs);
104115
for (String command :
105116
asList(
117+
"COPY",
106118
"DEL",
107119
"DUMP",
108120
"EXISTS",
109121
"EXPIRE",
110122
"EXPIREAT",
123+
"EXPIRETIME",
111124
"KEYS",
112125
"MOVE",
113126
"OBJECT",
114127
"PERSIST",
115128
"PEXPIRE",
116129
"PEXPIREAT",
130+
"PEXPIRETIME",
117131
"PTTL",
118132
"RANDOMKEY",
119133
"RENAME",
120134
"RENAMENX",
121135
"SCAN",
122136
"SORT",
137+
"SORT_RO",
123138
"TOUCH",
124139
"TTL",
125140
"TYPE",
@@ -140,12 +155,14 @@ public final class RedisCommandSanitizer {
140155
for (String command :
141156
asList(
142157
"BLMOVE",
158+
"BLMPOP",
143159
"BLPOP",
144160
"BRPOP",
145161
"BRPOPLPUSH",
146162
"LINDEX",
147163
"LLEN",
148164
"LMOVE",
165+
"LMPOP",
149166
"LPOP",
150167
"LRANGE",
151168
"LTRIM",
@@ -157,13 +174,23 @@ public final class RedisCommandSanitizer {
157174
// Pub/Sub
158175
sanitizers.put("PUBLISH", keepOneArg);
159176
for (String command :
160-
asList("PSUBSCRIBE", "PUBSUB", "PUNSUBSCRIBE", "SUBSCRIBE", "UNSUBSCRIBE")) {
177+
asList(
178+
"PSUBSCRIBE",
179+
"PUBSUB",
180+
"PUNSUBSCRIBE",
181+
"SPUBLISH",
182+
"SSUBSCRIBE",
183+
"SUBSCRIBE",
184+
"SUNSUBSCRIBE",
185+
"UNSUBSCRIBE")) {
161186
sanitizers.put(command, KeepAllArgs.INSTANCE);
162187
}
163188

164189
// Scripting
165190
sanitizers.put("EVAL", Eval.INSTANCE);
191+
sanitizers.put("EVAL_RO", Eval.INSTANCE);
166192
sanitizers.put("EVALSHA", Eval.INSTANCE);
193+
sanitizers.put("EVALSHA_RO", Eval.INSTANCE);
167194
sanitizers.put("SCRIPT", KeepAllArgs.INSTANCE);
168195

169196
// Server
@@ -211,6 +238,7 @@ public final class RedisCommandSanitizer {
211238
"SDIFF",
212239
"SDIFFSTORE",
213240
"SINTER",
241+
"SINTERCARD",
214242
"SINTERSTORE",
215243
"SMEMBERS",
216244
"SPOP",
@@ -239,14 +267,21 @@ public final class RedisCommandSanitizer {
239267
sanitizers.put("ZSCORE", keepOneArg);
240268
for (String command :
241269
asList(
270+
"BZMPOP",
242271
"BZPOPMAX",
243272
"BZPOPMIN",
244273
"ZCARD",
274+
"ZDIFF",
275+
"ZDIFFSTORE",
245276
"ZINTER",
277+
"ZINTERCARD",
246278
"ZINTERSTORE",
279+
"ZMPOP",
247280
"ZPOPMAX",
248281
"ZPOPMIN",
282+
"ZRANDMEMBER",
249283
"ZRANGE",
284+
"ZRANGESTORE",
250285
"ZREMRANGEBYRANK",
251286
"ZREVRANGE",
252287
"ZSCAN",
@@ -260,6 +295,7 @@ public final class RedisCommandSanitizer {
260295
for (String command :
261296
asList(
262297
"XACK",
298+
"XAUTOCLAIM",
263299
"XCLAIM",
264300
"XDEL",
265301
"XGROUP",
@@ -288,16 +324,20 @@ public final class RedisCommandSanitizer {
288324
asList(
289325
"BITCOUNT",
290326
"BITFIELD",
327+
"BITFIELD_RO",
291328
"BITOP",
292329
"BITPOS",
293330
"DECR",
294331
"DECRBY",
295332
"GET",
296333
"GETBIT",
334+
"GETDEL",
335+
"GETEX",
297336
"GETRANGE",
298337
"INCR",
299338
"INCRBY",
300339
"INCRBYFLOAT",
340+
"LCS",
301341
"MGET",
302342
"SETBIT",
303343
"STRALGO",
@@ -329,7 +369,7 @@ static String argToString(Object arg) {
329369
if (arg instanceof byte[]) {
330370
return new String((byte[]) arg, StandardCharsets.UTF_8);
331371
} else {
332-
return arg.toString();
372+
return String.valueOf(arg);
333373
}
334374
}
335375

instrumentation/jedis/jedis-1.4/javaagent/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ dependencies {
1717
compileOnly("com.google.auto.value:auto-value-annotations")
1818
annotationProcessor("com.google.auto.value:auto-value")
1919

20+
implementation(project(":instrumentation:jedis:jedis-common:javaagent"))
21+
2022
testInstrumentation(project(":instrumentation:jedis:jedis-3.0:javaagent"))
2123
testInstrumentation(project(":instrumentation:jedis:jedis-4.0:javaagent"))
2224

instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisConnectionInstrumentation.java

Lines changed: 3 additions & 4 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 io.opentelemetry.javaagent.instrumentation.jedis.JedisRequestContext;
2122
import net.bytebuddy.asm.Advice;
2223
import net.bytebuddy.description.type.TypeDescription;
2324
import net.bytebuddy.matcher.ElementMatcher;
@@ -32,8 +33,6 @@ public ElementMatcher<TypeDescription> typeMatcher() {
3233

3334
@Override
3435
public void transform(TypeTransformer transformer) {
35-
// FIXME: This instrumentation only incorporates sending the command, not processing the
36-
// result.
3736
transformer.applyAdviceToMethod(
3837
isMethod()
3938
.and(named("sendCommand"))
@@ -80,7 +79,7 @@ public static void stopSpan(
8079
}
8180

8281
scope.close();
83-
instrumenter().end(context, request, null, throwable);
82+
JedisRequestContext.endIfNotAttached(instrumenter(), context, request, throwable);
8483
}
8584
}
8685

@@ -116,7 +115,7 @@ public static void stopSpan(
116115
}
117116

118117
scope.close();
119-
instrumenter().end(context, request, null, throwable);
118+
JedisRequestContext.endIfNotAttached(instrumenter(), context, request, throwable);
120119
}
121120
}
122121
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.instrumentation.jedis.v1_4;
7+
8+
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
9+
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
10+
import static net.bytebuddy.matcher.ElementMatchers.isStatic;
11+
import static net.bytebuddy.matcher.ElementMatchers.namedOneOf;
12+
import static net.bytebuddy.matcher.ElementMatchers.not;
13+
14+
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
15+
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
16+
import io.opentelemetry.javaagent.instrumentation.jedis.JedisRequestContext;
17+
import net.bytebuddy.asm.Advice;
18+
import net.bytebuddy.description.type.TypeDescription;
19+
import net.bytebuddy.matcher.ElementMatcher;
20+
21+
public class JedisInstrumentation implements TypeInstrumentation {
22+
@Override
23+
public ElementMatcher<TypeDescription> typeMatcher() {
24+
return namedOneOf("redis.clients.jedis.Jedis", "redis.clients.jedis.BinaryJedis");
25+
}
26+
27+
@Override
28+
public void transform(TypeTransformer transformer) {
29+
transformer.applyAdviceToMethod(
30+
isMethod()
31+
.and(isPublic())
32+
.and(not(isStatic()))
33+
.and(
34+
not(
35+
namedOneOf(
36+
"close",
37+
"setDataSource",
38+
"getDB",
39+
"isConnected",
40+
"connect",
41+
"resetState",
42+
"getClient",
43+
"disconnect"))),
44+
this.getClass().getName() + "$JedisMethodAdvice");
45+
}
46+
47+
@SuppressWarnings("unused")
48+
public static class JedisMethodAdvice {
49+
50+
@Advice.OnMethodEnter(suppress = Throwable.class)
51+
public static JedisRequestContext<JedisRequest> onEnter() {
52+
return JedisRequestContext.attach();
53+
}
54+
55+
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
56+
public static void onExit(@Advice.Enter JedisRequestContext<JedisRequest> requestContext) {
57+
if (requestContext != null) {
58+
requestContext.detachAndEnd();
59+
}
60+
}
61+
}
62+
}

instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisInstrumentationModule.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
package io.opentelemetry.javaagent.instrumentation.jedis.v1_4;
77

88
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
9-
import static java.util.Collections.singletonList;
9+
import static java.util.Arrays.asList;
1010
import static net.bytebuddy.matcher.ElementMatchers.not;
1111

1212
import com.google.auto.service.AutoService;
@@ -30,6 +30,6 @@ public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
3030

3131
@Override
3232
public List<TypeInstrumentation> typeInstrumentations() {
33-
return singletonList(new JedisConnectionInstrumentation());
33+
return asList(new JedisConnectionInstrumentation(), new JedisInstrumentation());
3434
}
3535
}

instrumentation/jedis/jedis-3.0/javaagent/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ dependencies {
1818
compileOnly("com.google.auto.value:auto-value-annotations")
1919
annotationProcessor("com.google.auto.value:auto-value")
2020

21+
implementation(project(":instrumentation:jedis:jedis-common:javaagent"))
22+
2123
// ensures jedis-1.4 instrumentation does not load with jedis 3.0+ by failing
2224
// the tests in the event it does. The tests will end up with double spans
2325
testInstrumentation(project(":instrumentation:jedis:jedis-1.4:javaagent"))

instrumentation/jedis/jedis-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v3_0/JedisConnectionInstrumentation.java

Lines changed: 2 additions & 2 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 io.opentelemetry.javaagent.instrumentation.jedis.JedisRequestContext;
2122
import net.bytebuddy.asm.Advice;
2223
import net.bytebuddy.description.type.TypeDescription;
2324
import net.bytebuddy.matcher.ElementMatcher;
@@ -39,7 +40,6 @@ public void transform(TypeTransformer transformer) {
3940
.and(takesArgument(0, named("redis.clients.jedis.commands.ProtocolCommand")))
4041
.and(takesArgument(1, is(byte[][].class))),
4142
this.getClass().getName() + "$SendCommandAdvice");
42-
// FIXME: This instrumentation only incorporates sending the command, not processing the result.
4343
}
4444

4545
@SuppressWarnings("unused")
@@ -74,7 +74,7 @@ public static void stopSpan(
7474
}
7575

7676
scope.close();
77-
instrumenter().end(context, request, null, throwable);
77+
JedisRequestContext.endIfNotAttached(instrumenter(), context, request, throwable);
7878
}
7979
}
8080
}

0 commit comments

Comments
 (0)