Skip to content

Commit 1fc2590

Browse files
authored
Support Redisson batch operations (#18985)
1 parent 1352e58 commit 1fc2590

3 files changed

Lines changed: 83 additions & 7 deletions

File tree

instrumentation/redisson/redisson-common-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/redisson/common/v3_0/RedissonRequest.java

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

66
package io.opentelemetry.javaagent.instrumentation.redisson.common.v3_0;
77

8+
import static io.opentelemetry.instrumentation.api.internal.SemconvStability.emitStableDatabaseSemconv;
89
import static java.util.Collections.emptyList;
910
import static java.util.Collections.singletonList;
1011
import static java.util.logging.Level.FINE;
@@ -32,6 +33,9 @@ public abstract class RedissonRequest {
3233

3334
private static final Logger logger = Logger.getLogger(RedissonRequest.class.getName());
3435

36+
private static final String MULTI = "MULTI";
37+
private static final String PIPELINE = "PIPELINE";
38+
3539
private static final RedisCommandSanitizer sanitizer =
3640
RedisCommandSanitizer.create(
3741
DbConfig.isQuerySanitizationEnabled(GlobalOpenTelemetry.get(), "redisson"));
@@ -86,13 +90,30 @@ public String getOperationName() {
8690
return ((CommandData<?, ?>) command).getCommand().getName();
8791
} else if (command instanceof CommandsData) {
8892
CommandsData commandsData = (CommandsData) command;
89-
if (commandsData.getCommands().size() == 1) {
90-
return commandsData.getCommands().get(0).getCommand().getName();
93+
List<CommandData<?, ?>> commands = commandsData.getCommands();
94+
if (commands.size() == 1) {
95+
return commands.get(0).getCommand().getName();
9196
}
97+
return emitStableDatabaseSemconv() ? getBatchOperationName(commands) : null;
9298
}
9399
return null;
94100
}
95101

102+
@Nullable
103+
private static String getBatchOperationName(List<CommandData<?, ?>> commands) {
104+
if (commands.size() < 2) {
105+
return null;
106+
}
107+
108+
String firstCommandName = commands.get(0).getCommand().getName();
109+
String batchOperationName = firstCommandName.equals(MULTI) ? MULTI : PIPELINE;
110+
int firstBatchCommandIndex = firstCommandName.equals(MULTI) ? 1 : 0;
111+
String commonCommandName = getCommonCommandName(commands, firstBatchCommandIndex);
112+
return commonCommandName == null
113+
? batchOperationName
114+
: batchOperationName + " " + commonCommandName;
115+
}
116+
96117
@Nullable
97118
public String getQueryText() {
98119
List<String> sanitizedQueries = sanitizeQuery();
@@ -129,6 +150,23 @@ private List<String> sanitizeQuery() {
129150
return emptyList();
130151
}
131152

153+
@Nullable
154+
private static String getCommonCommandName(
155+
List<CommandData<?, ?>> commands, int firstBatchCommandIndex) {
156+
if (firstBatchCommandIndex >= commands.size()) {
157+
return null;
158+
}
159+
160+
String commonCommandName = commands.get(firstBatchCommandIndex).getCommand().getName();
161+
for (int i = firstBatchCommandIndex + 1; i < commands.size(); i++) {
162+
String commandName = commands.get(i).getCommand().getName();
163+
if (!commandName.equals(commonCommandName)) {
164+
return null;
165+
}
166+
}
167+
return commonCommandName;
168+
}
169+
132170
private static String normalizeSingleCommand(CommandData<?, ?> command) {
133171
Object[] commandParams = command.getParams();
134172
List<Object> args = new ArrayList<>(commandParams.length + 1);

instrumentation/redisson/redisson-common-3.0/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/redisson/AbstractRedissonAsyncClientTest.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import static io.opentelemetry.semconv.NetworkAttributes.NETWORK_TYPE;
2020
import static io.opentelemetry.semconv.NetworkAttributes.NetworkTypeValues.IPV4;
2121
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_OPERATION;
22+
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_OPERATION_NAME;
2223
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_STATEMENT;
2324
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_SYSTEM;
2425
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DbSystemNameIncubatingValues.REDIS;
@@ -245,13 +246,16 @@ void atomicBatchCommand() {
245246
trace.hasSpansSatisfyingExactly(
246247
span -> span.hasName("parent").hasKind(INTERNAL).hasNoParent(),
247248
span ->
248-
span.hasName(emitStableDatabaseSemconv() ? "redis" : "DB Query")
249+
span.hasName(emitStableDatabaseSemconv() ? "MULTI SET" : "DB Query")
249250
.hasKind(CLIENT)
250251
.hasAttributesSatisfyingExactly(
251252
equalTo(NETWORK_TYPE, emitOldDatabaseSemconv() ? IPV4 : null),
252253
equalTo(NETWORK_PEER_ADDRESS, ip),
253254
equalTo(NETWORK_PEER_PORT, port),
254255
equalTo(maybeStable(DB_SYSTEM), REDIS),
256+
equalTo(
257+
DB_OPERATION_NAME,
258+
emitStableDatabaseSemconv() ? "MULTI SET" : null),
255259
equalTo(maybeStable(DB_STATEMENT), "MULTI;SET batch1 ?"))
256260
.hasParent(trace.getSpan(0)),
257261
span ->

instrumentation/redisson/redisson-common-3.0/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/redisson/AbstractRedissonClientTest.java

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -258,20 +258,48 @@ void batchCommand() throws ReflectiveOperationException {
258258
trace ->
259259
trace.hasSpansSatisfyingExactly(
260260
span ->
261-
span.hasName(emitStableDatabaseSemconv() ? "redis" : "DB Query")
261+
span.hasName(emitStableDatabaseSemconv() ? "PIPELINE SET" : "DB Query")
262262
.hasKind(CLIENT)
263263
.hasAttributesSatisfyingExactly(
264264
equalTo(NETWORK_TYPE, emitOldDatabaseSemconv() ? IPV4 : null),
265265
equalTo(NETWORK_PEER_ADDRESS, ip),
266266
equalTo(NETWORK_PEER_PORT, port),
267267
equalTo(maybeStable(DB_SYSTEM), REDIS),
268+
equalTo(
269+
DB_OPERATION_NAME,
270+
emitStableDatabaseSemconv() ? "PIPELINE SET" : null),
268271
equalTo(maybeStable(DB_STATEMENT), "SET batch1 ?;SET batch2 ?"))));
269272
}
270273

271274
private static void invokeExecute(RBatch batch) throws ReflectiveOperationException {
272275
batch.getClass().getMethod("execute").invoke(batch);
273276
}
274277

278+
@Test
279+
void mixedBatchCommand() throws ReflectiveOperationException {
280+
RBatch batch = createBatch(redisson);
281+
assertThat(batch).isNotNull();
282+
batch.getBucket("batch1").setAsync("v1");
283+
batch.getBucket("batch1").getAsync();
284+
// Adapt different method signature:
285+
// `BatchResult<?> execute()` and `List<?> execute()`
286+
invokeExecute(batch);
287+
testing.waitAndAssertTraces(
288+
trace ->
289+
trace.hasSpansSatisfyingExactly(
290+
span ->
291+
span.hasName(emitStableDatabaseSemconv() ? "PIPELINE" : "DB Query")
292+
.hasKind(CLIENT)
293+
.hasAttributesSatisfyingExactly(
294+
equalTo(NETWORK_TYPE, emitOldDatabaseSemconv() ? IPV4 : null),
295+
equalTo(NETWORK_PEER_ADDRESS, ip),
296+
equalTo(NETWORK_PEER_PORT, port),
297+
equalTo(maybeStable(DB_SYSTEM), REDIS),
298+
equalTo(
299+
DB_OPERATION_NAME, emitStableDatabaseSemconv() ? "PIPELINE" : null),
300+
equalTo(maybeStable(DB_STATEMENT), "SET batch1 ?;GET batch1"))));
301+
}
302+
275303
@Test
276304
void largeBatchCommand() throws ReflectiveOperationException {
277305
RBatch batch = createBatch(redisson);
@@ -292,13 +320,16 @@ void largeBatchCommand() throws ReflectiveOperationException {
292320
trace ->
293321
trace.hasSpansSatisfyingExactly(
294322
span ->
295-
span.hasName(emitStableDatabaseSemconv() ? "redis" : "DB Query")
323+
span.hasName(emitStableDatabaseSemconv() ? "PIPELINE SET" : "DB Query")
296324
.hasKind(CLIENT)
297325
.hasAttributesSatisfyingExactly(
298326
equalTo(NETWORK_TYPE, emitOldDatabaseSemconv() ? IPV4 : null),
299327
equalTo(NETWORK_PEER_ADDRESS, ip),
300328
equalTo(NETWORK_PEER_PORT, port),
301329
equalTo(maybeStable(DB_SYSTEM), REDIS),
330+
equalTo(
331+
DB_OPERATION_NAME,
332+
emitStableDatabaseSemconv() ? "PIPELINE SET" : null),
302333
equalTo(
303334
maybeStable(DB_STATEMENT),
304335
"SET " + bucketName + " ?;SET " + bucketName + " ?"))));
@@ -324,18 +355,21 @@ void atomicBatchCommand() {
324355
batch.execute();
325356
});
326357
testing.waitAndAssertSortedTraces(
327-
orderByRootSpanName("redis", "DB Query", "SET", "EXEC"),
358+
orderByRootSpanName("MULTI SET", "DB Query", "SET", "EXEC"),
328359
trace ->
329360
trace.hasSpansSatisfyingExactly(
330361
span -> span.hasName("parent").hasNoParent().hasKind(INTERNAL),
331362
span ->
332-
span.hasName(emitStableDatabaseSemconv() ? "redis" : "DB Query")
363+
span.hasName(emitStableDatabaseSemconv() ? "MULTI SET" : "DB Query")
333364
.hasKind(CLIENT)
334365
.hasAttributesSatisfyingExactly(
335366
equalTo(NETWORK_TYPE, emitOldDatabaseSemconv() ? IPV4 : null),
336367
equalTo(NETWORK_PEER_ADDRESS, ip),
337368
equalTo(NETWORK_PEER_PORT, port),
338369
equalTo(maybeStable(DB_SYSTEM), REDIS),
370+
equalTo(
371+
DB_OPERATION_NAME,
372+
emitStableDatabaseSemconv() ? "MULTI SET" : null),
339373
equalTo(maybeStable(DB_STATEMENT), "MULTI;SET batch1 ?"))
340374
.hasParent(trace.getSpan(0)),
341375
span ->

0 commit comments

Comments
 (0)