Lettuce 5.1 instrumentation should log normalised commands as db.statement (#1405)
This commit is contained in:
parent
a5475b23a4
commit
f077b23c9f
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
package io.opentelemetry.instrumentation.api.tracer.utils;
|
package io.opentelemetry.instrumentation.api.tracer.utils;
|
||||||
|
|
||||||
|
import io.opentelemetry.common.AttributeKey;
|
||||||
import io.opentelemetry.instrumentation.api.config.Config;
|
import io.opentelemetry.instrumentation.api.config.Config;
|
||||||
import io.opentelemetry.trace.Span;
|
import io.opentelemetry.trace.Span;
|
||||||
import io.opentelemetry.trace.attributes.SemanticAttributes;
|
import io.opentelemetry.trace.attributes.SemanticAttributes;
|
||||||
|
@ -30,13 +31,15 @@ public final class NetPeerUtils {
|
||||||
setNetPeer(span, remoteAddress, remoteConnection.getPort());
|
setNetPeer(span, remoteAddress, remoteConnection.getPort());
|
||||||
} else {
|
} else {
|
||||||
// Failed DNS lookup, the host string is the name.
|
// Failed DNS lookup, the host string is the name.
|
||||||
setNetPeer(span, remoteConnection.getHostString(), null, remoteConnection.getPort());
|
setNetPeer(
|
||||||
|
span::setAttribute, remoteConnection.getHostString(), null, remoteConnection.getPort());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setNetPeer(Span span, InetAddress remoteAddress, int port) {
|
public static void setNetPeer(Span span, InetAddress remoteAddress, int port) {
|
||||||
setNetPeer(span, remoteAddress.getHostName(), remoteAddress.getHostAddress(), port);
|
setNetPeer(
|
||||||
|
span::setAttribute, remoteAddress.getHostName(), remoteAddress.getHostAddress(), port);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setNetPeer(Span span, String nameOrIp, int port) {
|
public static void setNetPeer(Span span, String nameOrIp, int port) {
|
||||||
|
@ -45,16 +48,20 @@ public final class NetPeerUtils {
|
||||||
setNetPeer(span, address);
|
setNetPeer(span, address);
|
||||||
} catch (IllegalArgumentException iae) {
|
} catch (IllegalArgumentException iae) {
|
||||||
// can't create address, try setting directly
|
// can't create address, try setting directly
|
||||||
setNetPeer(span, nameOrIp, null, port);
|
setNetPeer(span::setAttribute, nameOrIp, null, port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setNetPeer(Span span, String peerName, String peerIp) {
|
public static void setNetPeer(Span span, String peerName, String peerIp) {
|
||||||
setNetPeer(span, peerName, peerIp, -1);
|
setNetPeer(span::setAttribute, peerName, peerIp, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setNetPeer(Span span, String peerName, String peerIp, int port) {
|
public static void setNetPeer(Span span, String peerName, String peerIp, int port) {
|
||||||
|
setNetPeer(span::setAttribute, peerName, peerIp, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setNetPeer(
|
||||||
|
SpanAttributeSetter span, String peerName, String peerIp, int port) {
|
||||||
if (peerName != null && !peerName.equals(peerIp)) {
|
if (peerName != null && !peerName.equals(peerIp)) {
|
||||||
span.setAttribute(SemanticAttributes.NET_PEER_NAME, peerName);
|
span.setAttribute(SemanticAttributes.NET_PEER_NAME, peerName);
|
||||||
}
|
}
|
||||||
|
@ -81,4 +88,12 @@ public final class NetPeerUtils {
|
||||||
|
|
||||||
return ENDPOINT_PEER_SERVICE_MAPPING.get(endpoint);
|
return ENDPOINT_PEER_SERVICE_MAPPING.get(endpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This helper interface allows setting attributes on both {@link Span} and {@link Span.Builder}.
|
||||||
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface SpanAttributeSetter {
|
||||||
|
<T> void setAttribute(AttributeKey<T> key, @Nullable T value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.javaagent.instrumentation.lettuce.v5_1;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
|
public final class LettuceArgSplitter {
|
||||||
|
private static final Pattern KEY_PATTERN =
|
||||||
|
Pattern.compile("((key|value)<(?<wrapped>[^>]+)>|(?<plain>[0-9A-Za-z=]+))(\\s+|$)");
|
||||||
|
|
||||||
|
// this method removes the key|value<...> wrappers around redis keys or values and splits the args
|
||||||
|
// string
|
||||||
|
public static List<String> splitArgs(@Nullable String args) {
|
||||||
|
if (args == null || args.isEmpty()) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> argsList = new ArrayList<>();
|
||||||
|
Matcher m = KEY_PATTERN.matcher(args);
|
||||||
|
while (m.find()) {
|
||||||
|
String wrapped = m.group("wrapped");
|
||||||
|
if (wrapped != null) {
|
||||||
|
argsList.add(wrapped);
|
||||||
|
} else {
|
||||||
|
argsList.add(m.group("plain"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return argsList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private LettuceArgSplitter() {}
|
||||||
|
}
|
|
@ -41,6 +41,13 @@ public class LettuceClientResourcesInstrumentation extends Instrumenter.Default
|
||||||
@Override
|
@Override
|
||||||
public String[] helperClassNames() {
|
public String[] helperClassNames() {
|
||||||
return new String[] {
|
return new String[] {
|
||||||
|
packageName + ".RedisCommandNormalizer",
|
||||||
|
packageName + ".RedisCommandNormalizer$CommandNormalizer",
|
||||||
|
packageName + ".RedisCommandNormalizer$CommandNormalizer$KeepAllArgs",
|
||||||
|
packageName + ".RedisCommandNormalizer$CommandNormalizer$CommandAndNumArgs",
|
||||||
|
packageName + ".RedisCommandNormalizer$CommandNormalizer$MultiKeyValue",
|
||||||
|
packageName + ".RedisCommandNormalizer$CommandNormalizer$Eval",
|
||||||
|
packageName + ".LettuceArgSplitter",
|
||||||
packageName + ".OpenTelemetryTracing",
|
packageName + ".OpenTelemetryTracing",
|
||||||
packageName + ".OpenTelemetryTracing$OpenTelemetryTracerProvider",
|
packageName + ".OpenTelemetryTracing$OpenTelemetryTracerProvider",
|
||||||
packageName + ".OpenTelemetryTracing$OpenTelemetryTraceContextProvider",
|
packageName + ".OpenTelemetryTracing$OpenTelemetryTraceContextProvider",
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
|
|
||||||
package io.opentelemetry.javaagent.instrumentation.lettuce.v5_1;
|
package io.opentelemetry.javaagent.instrumentation.lettuce.v5_1;
|
||||||
|
|
||||||
|
import static io.opentelemetry.javaagent.instrumentation.lettuce.v5_1.LettuceArgSplitter.splitArgs;
|
||||||
|
|
||||||
import io.grpc.Context;
|
import io.grpc.Context;
|
||||||
import io.lettuce.core.tracing.TraceContext;
|
import io.lettuce.core.tracing.TraceContext;
|
||||||
import io.lettuce.core.tracing.TraceContextProvider;
|
import io.lettuce.core.tracing.TraceContextProvider;
|
||||||
|
@ -12,6 +14,8 @@ import io.lettuce.core.tracing.Tracer;
|
||||||
import io.lettuce.core.tracing.TracerProvider;
|
import io.lettuce.core.tracing.TracerProvider;
|
||||||
import io.lettuce.core.tracing.Tracing;
|
import io.lettuce.core.tracing.Tracing;
|
||||||
import io.opentelemetry.OpenTelemetry;
|
import io.opentelemetry.OpenTelemetry;
|
||||||
|
import io.opentelemetry.instrumentation.api.tracer.utils.NetPeerUtils;
|
||||||
|
import io.opentelemetry.instrumentation.api.tracer.utils.NetPeerUtils.SpanAttributeSetter;
|
||||||
import io.opentelemetry.javaagent.instrumentation.api.jdbc.DbSystem;
|
import io.opentelemetry.javaagent.instrumentation.api.jdbc.DbSystem;
|
||||||
import io.opentelemetry.trace.Span;
|
import io.opentelemetry.trace.Span;
|
||||||
import io.opentelemetry.trace.Span.Kind;
|
import io.opentelemetry.trace.Span.Kind;
|
||||||
|
@ -23,7 +27,7 @@ import java.time.Instant;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import reactor.util.annotation.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
public enum OpenTelemetryTracing implements Tracing {
|
public enum OpenTelemetryTracing implements Tracing {
|
||||||
INSTANCE;
|
INSTANCE;
|
||||||
|
@ -57,8 +61,8 @@ public enum OpenTelemetryTracing implements Tracing {
|
||||||
if (socketAddress instanceof InetSocketAddress) {
|
if (socketAddress instanceof InetSocketAddress) {
|
||||||
InetSocketAddress address = (InetSocketAddress) socketAddress;
|
InetSocketAddress address = (InetSocketAddress) socketAddress;
|
||||||
|
|
||||||
return new OpenTelemetryEndpoint(
|
String ip = address.getAddress() == null ? null : address.getAddress().getHostAddress();
|
||||||
address.getAddress().getHostAddress(), address.getPort(), address.getHostString());
|
return new OpenTelemetryEndpoint(ip, address.getPort(), address.getHostString());
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -96,18 +100,14 @@ public enum OpenTelemetryTracing implements Tracing {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class OpenTelemetryEndpoint implements Endpoint {
|
private static class OpenTelemetryEndpoint implements Endpoint {
|
||||||
final String ip;
|
@Nullable final String ip;
|
||||||
final int port;
|
final int port;
|
||||||
@Nullable final String name;
|
@Nullable final String name;
|
||||||
|
|
||||||
OpenTelemetryEndpoint(String ip, int port, @Nullable String name) {
|
OpenTelemetryEndpoint(@Nullable String ip, int port, @Nullable String name) {
|
||||||
this.ip = ip;
|
this.ip = ip;
|
||||||
this.port = port;
|
this.port = port;
|
||||||
if (!ip.equals(name)) {
|
this.name = name;
|
||||||
this.name = name;
|
|
||||||
} else {
|
|
||||||
this.name = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,9 +175,9 @@ public enum OpenTelemetryTracing implements Tracing {
|
||||||
public synchronized Tracer.Span remoteEndpoint(Endpoint endpoint) {
|
public synchronized Tracer.Span remoteEndpoint(Endpoint endpoint) {
|
||||||
if (endpoint instanceof OpenTelemetryEndpoint) {
|
if (endpoint instanceof OpenTelemetryEndpoint) {
|
||||||
if (span != null) {
|
if (span != null) {
|
||||||
fillEndpoint(span, (OpenTelemetryEndpoint) endpoint);
|
fillEndpoint(span::setAttribute, (OpenTelemetryEndpoint) endpoint);
|
||||||
} else {
|
} else {
|
||||||
fillEndpoint(spanBuilder, (OpenTelemetryEndpoint) endpoint);
|
fillEndpoint(spanBuilder::setAttribute, (OpenTelemetryEndpoint) endpoint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
|
@ -249,50 +249,20 @@ public enum OpenTelemetryTracing implements Tracing {
|
||||||
public synchronized void finish() {
|
public synchronized void finish() {
|
||||||
if (span != null) {
|
if (span != null) {
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
String statement =
|
String statement = RedisCommandNormalizer.normalize(name, splitArgs(args));
|
||||||
(args != null && !args.isEmpty()) && !name.equals("AUTH") ? name + " " + args : name;
|
|
||||||
span.setAttribute(SemanticAttributes.DB_STATEMENT, statement);
|
span.setAttribute(SemanticAttributes.DB_STATEMENT, statement);
|
||||||
}
|
}
|
||||||
span.end();
|
span.end();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void fillEndpoint(Span.Builder span, OpenTelemetryEndpoint endpoint) {
|
private static void fillEndpoint(SpanAttributeSetter span, OpenTelemetryEndpoint endpoint) {
|
||||||
span.setAttribute(SemanticAttributes.NET_TRANSPORT, "IP.TCP");
|
span.setAttribute(SemanticAttributes.NET_TRANSPORT, "IP.TCP");
|
||||||
span.setAttribute(SemanticAttributes.NET_PEER_IP, endpoint.ip);
|
NetPeerUtils.setNetPeer(span, endpoint.name, endpoint.ip, endpoint.port);
|
||||||
|
|
||||||
StringBuilder redisUrl = new StringBuilder("redis://");
|
StringBuilder redisUrl =
|
||||||
|
new StringBuilder("redis://").append(endpoint.name != null ? endpoint.name : endpoint.ip);
|
||||||
if (endpoint.name != null) {
|
if (endpoint.port > 0) {
|
||||||
span.setAttribute(SemanticAttributes.NET_PEER_NAME, endpoint.name);
|
|
||||||
redisUrl.append(endpoint.name);
|
|
||||||
} else {
|
|
||||||
redisUrl.append(endpoint.ip);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (endpoint.port != 0) {
|
|
||||||
span.setAttribute(SemanticAttributes.NET_PEER_PORT, (long) endpoint.port);
|
|
||||||
redisUrl.append(":").append(endpoint.port);
|
|
||||||
}
|
|
||||||
|
|
||||||
span.setAttribute(SemanticAttributes.DB_CONNECTION_STRING, redisUrl.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void fillEndpoint(Span span, OpenTelemetryEndpoint endpoint) {
|
|
||||||
span.setAttribute(SemanticAttributes.NET_TRANSPORT, "IP.TCP");
|
|
||||||
span.setAttribute(SemanticAttributes.NET_PEER_IP, endpoint.ip);
|
|
||||||
|
|
||||||
StringBuilder redisUrl = new StringBuilder("redis://");
|
|
||||||
|
|
||||||
if (endpoint.name != null) {
|
|
||||||
span.setAttribute(SemanticAttributes.NET_PEER_NAME, endpoint.name);
|
|
||||||
redisUrl.append(endpoint.name);
|
|
||||||
} else {
|
|
||||||
redisUrl.append(endpoint.ip);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (endpoint.port != 0) {
|
|
||||||
span.setAttribute(SemanticAttributes.NET_PEER_PORT, (long) endpoint.port);
|
|
||||||
redisUrl.append(":").append(endpoint.port);
|
redisUrl.append(":").append(endpoint.port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,412 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.javaagent.instrumentation.lettuce.v5_1;
|
||||||
|
|
||||||
|
import static java.util.Arrays.asList;
|
||||||
|
import static java.util.Collections.unmodifiableMap;
|
||||||
|
|
||||||
|
import io.opentelemetry.javaagent.instrumentation.lettuce.v5_1.RedisCommandNormalizer.CommandNormalizer.CommandAndNumArgs;
|
||||||
|
import io.opentelemetry.javaagent.instrumentation.lettuce.v5_1.RedisCommandNormalizer.CommandNormalizer.Eval;
|
||||||
|
import io.opentelemetry.javaagent.instrumentation.lettuce.v5_1.RedisCommandNormalizer.CommandNormalizer.KeepAllArgs;
|
||||||
|
import io.opentelemetry.javaagent.instrumentation.lettuce.v5_1.RedisCommandNormalizer.CommandNormalizer.MultiKeyValue;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is responsible for masking potentially sensitive data in Redis commands.
|
||||||
|
*
|
||||||
|
* <p>Examples:
|
||||||
|
*
|
||||||
|
* <table>
|
||||||
|
* <tr>
|
||||||
|
* <th>Raw command</th>
|
||||||
|
* <th>Normalized command</th>
|
||||||
|
* </tr>
|
||||||
|
* <tr>
|
||||||
|
* <td>{@code AUTH password}</td>
|
||||||
|
* <td>{@code AUTH ?}</td>
|
||||||
|
* </tr>
|
||||||
|
* <tr>
|
||||||
|
* <td>{@code HMSET hash creditcard 1234567887654321 address asdf}</td>
|
||||||
|
* <td>{@code HMSET hash creditcard ? address ?}</td>
|
||||||
|
* </tr>
|
||||||
|
* </table>
|
||||||
|
*/
|
||||||
|
public final class RedisCommandNormalizer {
|
||||||
|
|
||||||
|
private static final Map<String, CommandNormalizer> NORMALIZERS;
|
||||||
|
private static final CommandNormalizer DEFAULT = new CommandAndNumArgs(0);
|
||||||
|
|
||||||
|
static {
|
||||||
|
Map<String, CommandNormalizer> normalizers = new HashMap<>();
|
||||||
|
|
||||||
|
CommandNormalizer keepOneArg = new CommandAndNumArgs(1);
|
||||||
|
CommandNormalizer keepTwoArgs = new CommandAndNumArgs(2);
|
||||||
|
CommandNormalizer setMultiHashField = new MultiKeyValue(1);
|
||||||
|
CommandNormalizer setMultiField = new MultiKeyValue(0);
|
||||||
|
|
||||||
|
// Cluster
|
||||||
|
for (String command : asList("CLUSTER", "READONLY", "READWRITE")) {
|
||||||
|
normalizers.put(command, KeepAllArgs.INSTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connection
|
||||||
|
normalizers.put("AUTH", DEFAULT);
|
||||||
|
// HELLO can contain AUTH data
|
||||||
|
normalizers.put("HELLO", keepTwoArgs);
|
||||||
|
for (String command : asList("CLIENT", "ECHO", "PING", "QUIT", "SELECT")) {
|
||||||
|
normalizers.put(command, KeepAllArgs.INSTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Geo
|
||||||
|
for (String command :
|
||||||
|
asList("GEOADD", "GEODIST", "GEOHASH", "GEOPOS", "GEORADIUS", "GEORADIUSBYMEMBER")) {
|
||||||
|
normalizers.put(command, KeepAllArgs.INSTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hashes
|
||||||
|
normalizers.put("HMSET", setMultiHashField);
|
||||||
|
normalizers.put("HSET", setMultiHashField);
|
||||||
|
normalizers.put("HSETNX", keepTwoArgs);
|
||||||
|
for (String command :
|
||||||
|
asList(
|
||||||
|
"HDEL",
|
||||||
|
"HEXISTS",
|
||||||
|
"HGET",
|
||||||
|
"HGETALL",
|
||||||
|
"HINCRBY",
|
||||||
|
"HINCRBYFLOAT",
|
||||||
|
"HKEYS",
|
||||||
|
"HLEN",
|
||||||
|
"HMGET",
|
||||||
|
"HSCAN",
|
||||||
|
"HSTRLEN",
|
||||||
|
"HVALS")) {
|
||||||
|
normalizers.put(command, KeepAllArgs.INSTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// HyperLogLog
|
||||||
|
normalizers.put("PFADD", keepOneArg);
|
||||||
|
for (String command : asList("PFCOUNT", "PFMERGE")) {
|
||||||
|
normalizers.put(command, KeepAllArgs.INSTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keys
|
||||||
|
// MIGRATE can contain AUTH data
|
||||||
|
normalizers.put("MIGRATE", new CommandAndNumArgs(6));
|
||||||
|
normalizers.put("RESTORE", keepTwoArgs);
|
||||||
|
for (String command :
|
||||||
|
asList(
|
||||||
|
"DEL",
|
||||||
|
"DUMP",
|
||||||
|
"EXISTS",
|
||||||
|
"EXPIRE",
|
||||||
|
"EXPIREAT",
|
||||||
|
"KEYS",
|
||||||
|
"MOVE",
|
||||||
|
"OBJECT",
|
||||||
|
"PERSIST",
|
||||||
|
"PEXPIRE",
|
||||||
|
"PEXPIREAT",
|
||||||
|
"PTTL",
|
||||||
|
"RANDOMKEY",
|
||||||
|
"RENAME",
|
||||||
|
"RENAMENX",
|
||||||
|
"SCAN",
|
||||||
|
"SORT",
|
||||||
|
"TOUCH",
|
||||||
|
"TTL",
|
||||||
|
"TYPE",
|
||||||
|
"UNLINK",
|
||||||
|
"WAIT")) {
|
||||||
|
normalizers.put(command, KeepAllArgs.INSTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lists
|
||||||
|
normalizers.put("LINSERT", keepTwoArgs);
|
||||||
|
normalizers.put("LPOS", keepOneArg);
|
||||||
|
normalizers.put("LPUSH", keepOneArg);
|
||||||
|
normalizers.put("LPUSHX", keepOneArg);
|
||||||
|
normalizers.put("LREM", keepOneArg);
|
||||||
|
normalizers.put("LSET", keepOneArg);
|
||||||
|
normalizers.put("RPUSH", keepOneArg);
|
||||||
|
normalizers.put("RPUSHX", keepOneArg);
|
||||||
|
for (String command :
|
||||||
|
asList(
|
||||||
|
"BLMOVE",
|
||||||
|
"BLPOP",
|
||||||
|
"BRPOP",
|
||||||
|
"BRPOPLPUSH",
|
||||||
|
"LINDEX",
|
||||||
|
"LLEN",
|
||||||
|
"LMOVE",
|
||||||
|
"LPOP",
|
||||||
|
"LRANGE",
|
||||||
|
"LTRIM",
|
||||||
|
"RPOP",
|
||||||
|
"RPOPLPUSH")) {
|
||||||
|
normalizers.put(command, KeepAllArgs.INSTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pub/Sub
|
||||||
|
normalizers.put("PUBLISH", keepOneArg);
|
||||||
|
for (String command :
|
||||||
|
asList("PSUBSCRIBE", "PUBSUB", "PUNSUBSCRIBE", "SUBSCRIBE", "UNSUBSCRIBE")) {
|
||||||
|
normalizers.put(command, KeepAllArgs.INSTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scripting
|
||||||
|
normalizers.put("EVAL", Eval.INSTANCE);
|
||||||
|
normalizers.put("EVALSHA", Eval.INSTANCE);
|
||||||
|
normalizers.put("SCRIPT", KeepAllArgs.INSTANCE);
|
||||||
|
|
||||||
|
// Server
|
||||||
|
// CONFIG SET can set any property, including the master password
|
||||||
|
normalizers.put("CONFIG", keepTwoArgs);
|
||||||
|
for (String command :
|
||||||
|
asList(
|
||||||
|
"ACL",
|
||||||
|
"BGREWRITEAOF",
|
||||||
|
"BGSAVE",
|
||||||
|
"COMMAND",
|
||||||
|
"DBSIZE",
|
||||||
|
"DEBUG",
|
||||||
|
"FLUSHALL",
|
||||||
|
"FLUSHDB",
|
||||||
|
"INFO",
|
||||||
|
"LASTSAVE",
|
||||||
|
"LATENCY",
|
||||||
|
"LOLWUT",
|
||||||
|
"MEMORY",
|
||||||
|
"MODULE",
|
||||||
|
"MONITOR",
|
||||||
|
"PSYNC",
|
||||||
|
"REPLICAOF",
|
||||||
|
"ROLE",
|
||||||
|
"SAVE",
|
||||||
|
"SHUTDOWN",
|
||||||
|
"SLAVEOF",
|
||||||
|
"SLOWLOG",
|
||||||
|
"SWAPDB",
|
||||||
|
"SYNC",
|
||||||
|
"TIME")) {
|
||||||
|
normalizers.put(command, KeepAllArgs.INSTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets
|
||||||
|
normalizers.put("SADD", keepOneArg);
|
||||||
|
normalizers.put("SISMEMBER", keepOneArg);
|
||||||
|
normalizers.put("SMISMEMBER", keepOneArg);
|
||||||
|
normalizers.put("SMOVE", keepTwoArgs);
|
||||||
|
normalizers.put("SREM", keepOneArg);
|
||||||
|
for (String command :
|
||||||
|
asList(
|
||||||
|
"SCARD",
|
||||||
|
"SDIFF",
|
||||||
|
"SDIFFSTORE",
|
||||||
|
"SINTER",
|
||||||
|
"SINTERSTORE",
|
||||||
|
"SMEMBERS",
|
||||||
|
"SPOP",
|
||||||
|
"SRANDMEMBER",
|
||||||
|
"SSCAN",
|
||||||
|
"SUNION",
|
||||||
|
"SUNIONSTORE")) {
|
||||||
|
normalizers.put(command, KeepAllArgs.INSTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sorted Sets
|
||||||
|
normalizers.put("ZADD", keepOneArg);
|
||||||
|
normalizers.put("ZCOUNT", keepOneArg);
|
||||||
|
normalizers.put("ZINCRBY", keepOneArg);
|
||||||
|
normalizers.put("ZLEXCOUNT", keepOneArg);
|
||||||
|
normalizers.put("ZMSCORE", keepOneArg);
|
||||||
|
normalizers.put("ZRANGEBYLEX", keepOneArg);
|
||||||
|
normalizers.put("ZRANGEBYSCORE", keepOneArg);
|
||||||
|
normalizers.put("ZRANK", keepOneArg);
|
||||||
|
normalizers.put("ZREM", keepOneArg);
|
||||||
|
normalizers.put("ZREMRANGEBYLEX", keepOneArg);
|
||||||
|
normalizers.put("ZREMRANGEBYSCORE", keepOneArg);
|
||||||
|
normalizers.put("ZREVRANGEBYLEX", keepOneArg);
|
||||||
|
normalizers.put("ZREVRANGEBYSCORE", keepOneArg);
|
||||||
|
normalizers.put("ZREVRANK", keepOneArg);
|
||||||
|
normalizers.put("ZSCORE", keepOneArg);
|
||||||
|
for (String command :
|
||||||
|
asList(
|
||||||
|
"BZPOPMAX",
|
||||||
|
"BZPOPMIN",
|
||||||
|
"ZCARD",
|
||||||
|
"ZINTER",
|
||||||
|
"ZINTERSTORE",
|
||||||
|
"ZPOPMAX",
|
||||||
|
"ZPOPMIN",
|
||||||
|
"ZRANGE",
|
||||||
|
"ZREMRANGEBYRANK",
|
||||||
|
"ZREVRANGE",
|
||||||
|
"ZSCAN",
|
||||||
|
"ZUNION",
|
||||||
|
"ZUNIONSTORE")) {
|
||||||
|
normalizers.put(command, KeepAllArgs.INSTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Streams
|
||||||
|
normalizers.put("XADD", new MultiKeyValue(2));
|
||||||
|
for (String command :
|
||||||
|
asList(
|
||||||
|
"XACK",
|
||||||
|
"XCLAIM",
|
||||||
|
"XDEL",
|
||||||
|
"XGROUP",
|
||||||
|
"XINFO",
|
||||||
|
"XLEN",
|
||||||
|
"XPENDING",
|
||||||
|
"XRANGE",
|
||||||
|
"XREAD",
|
||||||
|
"XREADGROUP",
|
||||||
|
"XREVRANGE",
|
||||||
|
"XTRIM")) {
|
||||||
|
normalizers.put(command, KeepAllArgs.INSTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strings
|
||||||
|
normalizers.put("APPEND", keepOneArg);
|
||||||
|
normalizers.put("GETSET", keepOneArg);
|
||||||
|
normalizers.put("MSET", setMultiField);
|
||||||
|
normalizers.put("MSETNX", setMultiField);
|
||||||
|
normalizers.put("PSETEX", keepTwoArgs);
|
||||||
|
normalizers.put("SET", keepOneArg);
|
||||||
|
normalizers.put("SETEX", keepTwoArgs);
|
||||||
|
normalizers.put("SETNX", keepOneArg);
|
||||||
|
normalizers.put("SETRANGE", keepOneArg);
|
||||||
|
for (String command :
|
||||||
|
asList(
|
||||||
|
"BITCOUNT",
|
||||||
|
"BITFIELD",
|
||||||
|
"BITOP",
|
||||||
|
"BITPOS",
|
||||||
|
"DECR",
|
||||||
|
"DECRBY",
|
||||||
|
"GET",
|
||||||
|
"GETBIT",
|
||||||
|
"GETRANGE",
|
||||||
|
"INCR",
|
||||||
|
"INCRBY",
|
||||||
|
"INCRBYFLOAT",
|
||||||
|
"MGET",
|
||||||
|
"SETBIT",
|
||||||
|
"STRALGO",
|
||||||
|
"STRLEN")) {
|
||||||
|
normalizers.put(command, KeepAllArgs.INSTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transactions
|
||||||
|
for (String command : asList("DISCARD", "EXEC", "MULTI", "UNWATCH", "WATCH")) {
|
||||||
|
normalizers.put(command, KeepAllArgs.INSTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
NORMALIZERS = unmodifiableMap(normalizers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String normalize(String command, List<String> args) {
|
||||||
|
return NORMALIZERS.getOrDefault(command.toUpperCase(), DEFAULT).normalize(command, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface CommandNormalizer {
|
||||||
|
String normalize(String command, List<String> args);
|
||||||
|
|
||||||
|
enum KeepAllArgs implements CommandNormalizer {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String normalize(String command, List<String> args) {
|
||||||
|
StringBuilder normalised = new StringBuilder(command);
|
||||||
|
for (String arg : args) {
|
||||||
|
normalised.append(" ").append(arg);
|
||||||
|
}
|
||||||
|
return normalised.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// keeps only a chosen number of arguments
|
||||||
|
// example for num=2: CMD arg1 arg2 ? ?
|
||||||
|
class CommandAndNumArgs implements CommandNormalizer {
|
||||||
|
private final int numOfArgsToKeep;
|
||||||
|
|
||||||
|
public CommandAndNumArgs(int numOfArgsToKeep) {
|
||||||
|
this.numOfArgsToKeep = numOfArgsToKeep;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String normalize(String command, List<String> args) {
|
||||||
|
StringBuilder normalised = new StringBuilder(command);
|
||||||
|
for (int i = 0; i < numOfArgsToKeep && i < args.size(); ++i) {
|
||||||
|
normalised.append(" ").append(args.get(i));
|
||||||
|
}
|
||||||
|
for (int i = numOfArgsToKeep; i < args.size(); ++i) {
|
||||||
|
normalised.append(" ?");
|
||||||
|
}
|
||||||
|
return normalised.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// keeps only chosen number of arguments and then every second one
|
||||||
|
// example for num=2: CMD arg1 arg2 key1 ? key2 ?
|
||||||
|
class MultiKeyValue implements CommandNormalizer {
|
||||||
|
private final int numOfArgsBeforeKeyValue;
|
||||||
|
|
||||||
|
public MultiKeyValue(int numOfArgsBeforeKeyValue) {
|
||||||
|
this.numOfArgsBeforeKeyValue = numOfArgsBeforeKeyValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String normalize(String command, List<String> args) {
|
||||||
|
StringBuilder normalised = new StringBuilder(command);
|
||||||
|
// append all "initial" arguments before key-value pairs start
|
||||||
|
for (int i = 0; i < numOfArgsBeforeKeyValue && i < args.size(); ++i) {
|
||||||
|
normalised.append(" ").append(args.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
// loop over keys only
|
||||||
|
for (int i = numOfArgsBeforeKeyValue; i < args.size(); i += 2) {
|
||||||
|
normalised.append(" ").append(args.get(i)).append(" ?");
|
||||||
|
}
|
||||||
|
return normalised.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Eval implements CommandNormalizer {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String normalize(String command, List<String> args) {
|
||||||
|
StringBuilder normalised = new StringBuilder(command);
|
||||||
|
|
||||||
|
// get the number of keys passed from the command itself (second arg)
|
||||||
|
int numberOfKeys = 0;
|
||||||
|
if (args.size() > 2) {
|
||||||
|
try {
|
||||||
|
numberOfKeys = Integer.parseInt(args.get(1));
|
||||||
|
} catch (NumberFormatException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
// log the script, number of keys and all keys
|
||||||
|
for (; i < (numberOfKeys + 2) && i < args.size(); ++i) {
|
||||||
|
normalised.append(" ").append(args.get(i));
|
||||||
|
}
|
||||||
|
// mask the rest
|
||||||
|
for (; i < args.size(); ++i) {
|
||||||
|
normalised.append(" ?");
|
||||||
|
}
|
||||||
|
return normalised.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private RedisCommandNormalizer() {}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.javaagent.instrumentation.lettuce.v5_1
|
||||||
|
|
||||||
|
import spock.lang.Specification
|
||||||
|
import spock.lang.Unroll
|
||||||
|
|
||||||
|
class LettuceArgSplitterTest extends Specification {
|
||||||
|
@Unroll
|
||||||
|
def "should properly split #desc"() {
|
||||||
|
expect:
|
||||||
|
LettuceArgSplitter.splitArgs(args) == result
|
||||||
|
|
||||||
|
where:
|
||||||
|
desc | args | result
|
||||||
|
"a null value" | null | []
|
||||||
|
"an empty value" | "" | []
|
||||||
|
"a single key" | "key<key>" | ["key"]
|
||||||
|
"a single value" | "value<value>" | ["value"]
|
||||||
|
"a plain string" | "teststring" | ["teststring"]
|
||||||
|
"an integer" | "42" | ["42"]
|
||||||
|
"a base64 value" | "TeST123==" | ["TeST123=="]
|
||||||
|
"a complex list of args" | "key<key> aSDFgh4321= 5 test value<val>" | ["key", "aSDFgh4321=", "5", "test", "val"]
|
||||||
|
}
|
||||||
|
}
|
|
@ -152,12 +152,12 @@ class LettuceAsyncClientTest extends AgentTestRunner {
|
||||||
kind CLIENT
|
kind CLIENT
|
||||||
errored false
|
errored false
|
||||||
attributes {
|
attributes {
|
||||||
"${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP"
|
"${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP"
|
||||||
"${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1"
|
"${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1"
|
||||||
"${SemanticAttributes.NET_PEER_PORT.key()}" port
|
"${SemanticAttributes.NET_PEER_PORT.key}" port
|
||||||
"${SemanticAttributes.DB_CONNECTION_STRING.key()}" "redis://127.0.0.1:$port"
|
"${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port"
|
||||||
"${SemanticAttributes.DB_SYSTEM.key()}" "redis"
|
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
|
||||||
"${SemanticAttributes.DB_STATEMENT.key()}" "SET key<TESTSETKEY> value<TESTSETVAL>"
|
"${SemanticAttributes.DB_STATEMENT.key}" "SET TESTSETKEY ?"
|
||||||
}
|
}
|
||||||
event(0) {
|
event(0) {
|
||||||
eventName "redis.encode.start"
|
eventName "redis.encode.start"
|
||||||
|
@ -195,12 +195,12 @@ class LettuceAsyncClientTest extends AgentTestRunner {
|
||||||
kind CLIENT
|
kind CLIENT
|
||||||
errored false
|
errored false
|
||||||
attributes {
|
attributes {
|
||||||
"${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP"
|
"${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP"
|
||||||
"${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1"
|
"${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1"
|
||||||
"${SemanticAttributes.NET_PEER_PORT.key()}" port
|
"${SemanticAttributes.NET_PEER_PORT.key}" port
|
||||||
"${SemanticAttributes.DB_CONNECTION_STRING.key()}" "redis://127.0.0.1:$port"
|
"${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port"
|
||||||
"${SemanticAttributes.DB_SYSTEM.key()}" "redis"
|
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
|
||||||
"${SemanticAttributes.DB_STATEMENT.key()}" "GET key<TESTKEY>"
|
"${SemanticAttributes.DB_STATEMENT.key}" "GET TESTKEY"
|
||||||
}
|
}
|
||||||
event(0) {
|
event(0) {
|
||||||
eventName "redis.encode.start"
|
eventName "redis.encode.start"
|
||||||
|
@ -252,12 +252,12 @@ class LettuceAsyncClientTest extends AgentTestRunner {
|
||||||
kind CLIENT
|
kind CLIENT
|
||||||
errored false
|
errored false
|
||||||
attributes {
|
attributes {
|
||||||
"${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP"
|
"${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP"
|
||||||
"${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1"
|
"${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1"
|
||||||
"${SemanticAttributes.NET_PEER_PORT.key()}" port
|
"${SemanticAttributes.NET_PEER_PORT.key}" port
|
||||||
"${SemanticAttributes.DB_CONNECTION_STRING.key()}" "redis://127.0.0.1:$port"
|
"${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port"
|
||||||
"${SemanticAttributes.DB_SYSTEM.key()}" "redis"
|
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
|
||||||
"${SemanticAttributes.DB_STATEMENT.key()}" "GET key<NON_EXISTENT_KEY>"
|
"${SemanticAttributes.DB_STATEMENT.key}" "GET NON_EXISTENT_KEY"
|
||||||
}
|
}
|
||||||
event(0) {
|
event(0) {
|
||||||
eventName "redis.encode.start"
|
eventName "redis.encode.start"
|
||||||
|
@ -295,12 +295,12 @@ class LettuceAsyncClientTest extends AgentTestRunner {
|
||||||
kind CLIENT
|
kind CLIENT
|
||||||
errored false
|
errored false
|
||||||
attributes {
|
attributes {
|
||||||
"${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP"
|
"${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP"
|
||||||
"${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1"
|
"${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1"
|
||||||
"${SemanticAttributes.NET_PEER_PORT.key()}" port
|
"${SemanticAttributes.NET_PEER_PORT.key}" port
|
||||||
"${SemanticAttributes.DB_CONNECTION_STRING.key()}" "redis://127.0.0.1:$port"
|
"${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port"
|
||||||
"${SemanticAttributes.DB_STATEMENT.key()}" "RANDOMKEY"
|
"${SemanticAttributes.DB_STATEMENT.key}" "RANDOMKEY"
|
||||||
"${SemanticAttributes.DB_SYSTEM.key()}" "redis"
|
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
|
||||||
}
|
}
|
||||||
event(0) {
|
event(0) {
|
||||||
eventName "redis.encode.start"
|
eventName "redis.encode.start"
|
||||||
|
@ -356,12 +356,12 @@ class LettuceAsyncClientTest extends AgentTestRunner {
|
||||||
kind CLIENT
|
kind CLIENT
|
||||||
errored false
|
errored false
|
||||||
attributes {
|
attributes {
|
||||||
"${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP"
|
"${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP"
|
||||||
"${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1"
|
"${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1"
|
||||||
"${SemanticAttributes.NET_PEER_PORT.key()}" port
|
"${SemanticAttributes.NET_PEER_PORT.key}" port
|
||||||
"${SemanticAttributes.DB_CONNECTION_STRING.key()}" "redis://127.0.0.1:$port"
|
"${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port"
|
||||||
"${SemanticAttributes.DB_SYSTEM.key()}" "redis"
|
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
|
||||||
"${SemanticAttributes.DB_STATEMENT.key()}" "HMSET key<TESTHM> key<firstname> value<John> key<lastname> value<Doe> key<age> value<53>"
|
"${SemanticAttributes.DB_STATEMENT.key}" "HMSET TESTHM firstname ? lastname ? age ?"
|
||||||
}
|
}
|
||||||
event(0) {
|
event(0) {
|
||||||
eventName "redis.encode.start"
|
eventName "redis.encode.start"
|
||||||
|
@ -377,12 +377,12 @@ class LettuceAsyncClientTest extends AgentTestRunner {
|
||||||
kind CLIENT
|
kind CLIENT
|
||||||
errored false
|
errored false
|
||||||
attributes {
|
attributes {
|
||||||
"${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP"
|
"${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP"
|
||||||
"${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1"
|
"${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1"
|
||||||
"${SemanticAttributes.NET_PEER_PORT.key()}" port
|
"${SemanticAttributes.NET_PEER_PORT.key}" port
|
||||||
"${SemanticAttributes.DB_CONNECTION_STRING.key()}" "redis://127.0.0.1:$port"
|
"${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port"
|
||||||
"${SemanticAttributes.DB_SYSTEM.key()}" "redis"
|
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
|
||||||
"${SemanticAttributes.DB_STATEMENT.key()}" "HGETALL key<TESTHM>"
|
"${SemanticAttributes.DB_STATEMENT.key}" "HGETALL TESTHM"
|
||||||
}
|
}
|
||||||
event(0) {
|
event(0) {
|
||||||
eventName "redis.encode.start"
|
eventName "redis.encode.start"
|
||||||
|
|
|
@ -102,12 +102,12 @@ class LettuceReactiveClientTest extends AgentTestRunner {
|
||||||
kind CLIENT
|
kind CLIENT
|
||||||
errored false
|
errored false
|
||||||
attributes {
|
attributes {
|
||||||
"${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP"
|
"${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP"
|
||||||
"${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1"
|
"${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1"
|
||||||
"${SemanticAttributes.NET_PEER_PORT.key()}" port
|
"${SemanticAttributes.NET_PEER_PORT.key}" port
|
||||||
"${SemanticAttributes.DB_CONNECTION_STRING.key()}" "redis://127.0.0.1:$port"
|
"${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port"
|
||||||
"${SemanticAttributes.DB_SYSTEM.key()}" "redis"
|
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
|
||||||
"${SemanticAttributes.DB_STATEMENT.key()}" "SET key<TESTSETKEY> value<TESTSETVAL>"
|
"${SemanticAttributes.DB_STATEMENT.key}" "SET TESTSETKEY ?"
|
||||||
}
|
}
|
||||||
event(0) {
|
event(0) {
|
||||||
eventName "redis.encode.start"
|
eventName "redis.encode.start"
|
||||||
|
@ -136,12 +136,12 @@ class LettuceReactiveClientTest extends AgentTestRunner {
|
||||||
kind CLIENT
|
kind CLIENT
|
||||||
errored false
|
errored false
|
||||||
attributes {
|
attributes {
|
||||||
"${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP"
|
"${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP"
|
||||||
"${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1"
|
"${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1"
|
||||||
"${SemanticAttributes.NET_PEER_PORT.key()}" port
|
"${SemanticAttributes.NET_PEER_PORT.key}" port
|
||||||
"${SemanticAttributes.DB_CONNECTION_STRING.key()}" "redis://127.0.0.1:$port"
|
"${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port"
|
||||||
"${SemanticAttributes.DB_SYSTEM.key()}" "redis"
|
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
|
||||||
"${SemanticAttributes.DB_STATEMENT.key()}" "GET key<TESTKEY>"
|
"${SemanticAttributes.DB_STATEMENT.key}" "GET TESTKEY"
|
||||||
}
|
}
|
||||||
event(0) {
|
event(0) {
|
||||||
eventName "redis.encode.start"
|
eventName "redis.encode.start"
|
||||||
|
@ -178,12 +178,12 @@ class LettuceReactiveClientTest extends AgentTestRunner {
|
||||||
kind CLIENT
|
kind CLIENT
|
||||||
errored false
|
errored false
|
||||||
attributes {
|
attributes {
|
||||||
"${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP"
|
"${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP"
|
||||||
"${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1"
|
"${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1"
|
||||||
"${SemanticAttributes.NET_PEER_PORT.key()}" port
|
"${SemanticAttributes.NET_PEER_PORT.key}" port
|
||||||
"${SemanticAttributes.DB_CONNECTION_STRING.key()}" "redis://127.0.0.1:$port"
|
"${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port"
|
||||||
"${SemanticAttributes.DB_SYSTEM.key()}" "redis"
|
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
|
||||||
"${SemanticAttributes.DB_STATEMENT.key()}" "GET key<NON_EXISTENT_KEY>"
|
"${SemanticAttributes.DB_STATEMENT.key}" "GET NON_EXISTENT_KEY"
|
||||||
}
|
}
|
||||||
event(0) {
|
event(0) {
|
||||||
eventName "redis.encode.start"
|
eventName "redis.encode.start"
|
||||||
|
@ -218,12 +218,12 @@ class LettuceReactiveClientTest extends AgentTestRunner {
|
||||||
kind CLIENT
|
kind CLIENT
|
||||||
errored false
|
errored false
|
||||||
attributes {
|
attributes {
|
||||||
"${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP"
|
"${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP"
|
||||||
"${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1"
|
"${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1"
|
||||||
"${SemanticAttributes.NET_PEER_PORT.key()}" port
|
"${SemanticAttributes.NET_PEER_PORT.key}" port
|
||||||
"${SemanticAttributes.DB_CONNECTION_STRING.key()}" "redis://127.0.0.1:$port"
|
"${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port"
|
||||||
"${SemanticAttributes.DB_STATEMENT.key()}" "RANDOMKEY"
|
"${SemanticAttributes.DB_STATEMENT.key}" "RANDOMKEY"
|
||||||
"${SemanticAttributes.DB_SYSTEM.key()}" "redis"
|
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
|
||||||
}
|
}
|
||||||
event(0) {
|
event(0) {
|
||||||
eventName "redis.encode.start"
|
eventName "redis.encode.start"
|
||||||
|
@ -248,12 +248,12 @@ class LettuceReactiveClientTest extends AgentTestRunner {
|
||||||
kind CLIENT
|
kind CLIENT
|
||||||
errored false
|
errored false
|
||||||
attributes {
|
attributes {
|
||||||
"${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP"
|
"${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP"
|
||||||
"${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1"
|
"${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1"
|
||||||
"${SemanticAttributes.NET_PEER_PORT.key()}" port
|
"${SemanticAttributes.NET_PEER_PORT.key}" port
|
||||||
"${SemanticAttributes.DB_CONNECTION_STRING.key()}" "redis://127.0.0.1:$port"
|
"${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port"
|
||||||
"${SemanticAttributes.DB_STATEMENT.key()}" "COMMAND"
|
"${SemanticAttributes.DB_STATEMENT.key}" "COMMAND"
|
||||||
"${SemanticAttributes.DB_SYSTEM.key()}" "redis"
|
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
|
||||||
}
|
}
|
||||||
event(0) {
|
event(0) {
|
||||||
eventName "redis.encode.start"
|
eventName "redis.encode.start"
|
||||||
|
@ -301,12 +301,12 @@ class LettuceReactiveClientTest extends AgentTestRunner {
|
||||||
errored false
|
errored false
|
||||||
childOf span(0)
|
childOf span(0)
|
||||||
attributes {
|
attributes {
|
||||||
"${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP"
|
"${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP"
|
||||||
"${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1"
|
"${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1"
|
||||||
"${SemanticAttributes.NET_PEER_PORT.key()}" port
|
"${SemanticAttributes.NET_PEER_PORT.key}" port
|
||||||
"${SemanticAttributes.DB_CONNECTION_STRING.key()}" "redis://127.0.0.1:$port"
|
"${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port"
|
||||||
"${SemanticAttributes.DB_SYSTEM.key()}" "redis"
|
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
|
||||||
"${SemanticAttributes.DB_STATEMENT.key()}" "SET key<a> value<1>"
|
"${SemanticAttributes.DB_STATEMENT.key}" "SET a ?"
|
||||||
}
|
}
|
||||||
event(0) {
|
event(0) {
|
||||||
eventName "redis.encode.start"
|
eventName "redis.encode.start"
|
||||||
|
@ -321,12 +321,12 @@ class LettuceReactiveClientTest extends AgentTestRunner {
|
||||||
errored false
|
errored false
|
||||||
childOf span(0)
|
childOf span(0)
|
||||||
attributes {
|
attributes {
|
||||||
"${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP"
|
"${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP"
|
||||||
"${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1"
|
"${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1"
|
||||||
"${SemanticAttributes.NET_PEER_PORT.key()}" port
|
"${SemanticAttributes.NET_PEER_PORT.key}" port
|
||||||
"${SemanticAttributes.DB_CONNECTION_STRING.key()}" "redis://127.0.0.1:$port"
|
"${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port"
|
||||||
"${SemanticAttributes.DB_SYSTEM.key()}" "redis"
|
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
|
||||||
"${SemanticAttributes.DB_STATEMENT.key()}" "GET key<a>"
|
"${SemanticAttributes.DB_STATEMENT.key}" "GET a"
|
||||||
}
|
}
|
||||||
event(0) {
|
event(0) {
|
||||||
eventName "redis.encode.start"
|
eventName "redis.encode.start"
|
||||||
|
@ -362,12 +362,12 @@ class LettuceReactiveClientTest extends AgentTestRunner {
|
||||||
errored false
|
errored false
|
||||||
childOf span(0)
|
childOf span(0)
|
||||||
attributes {
|
attributes {
|
||||||
"${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP"
|
"${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP"
|
||||||
"${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1"
|
"${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1"
|
||||||
"${SemanticAttributes.NET_PEER_PORT.key()}" port
|
"${SemanticAttributes.NET_PEER_PORT.key}" port
|
||||||
"${SemanticAttributes.DB_CONNECTION_STRING.key()}" "redis://127.0.0.1:$port"
|
"${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port"
|
||||||
"${SemanticAttributes.DB_SYSTEM.key()}" "redis"
|
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
|
||||||
"${SemanticAttributes.DB_STATEMENT.key()}" "SET key<a> value<1>"
|
"${SemanticAttributes.DB_STATEMENT.key}" "SET a ?"
|
||||||
}
|
}
|
||||||
event(0) {
|
event(0) {
|
||||||
eventName "redis.encode.start"
|
eventName "redis.encode.start"
|
||||||
|
@ -382,12 +382,12 @@ class LettuceReactiveClientTest extends AgentTestRunner {
|
||||||
errored false
|
errored false
|
||||||
childOf span(0)
|
childOf span(0)
|
||||||
attributes {
|
attributes {
|
||||||
"${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP"
|
"${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP"
|
||||||
"${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1"
|
"${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1"
|
||||||
"${SemanticAttributes.NET_PEER_PORT.key()}" port
|
"${SemanticAttributes.NET_PEER_PORT.key}" port
|
||||||
"${SemanticAttributes.DB_CONNECTION_STRING.key()}" "redis://127.0.0.1:$port"
|
"${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port"
|
||||||
"${SemanticAttributes.DB_SYSTEM.key()}" "redis"
|
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
|
||||||
"${SemanticAttributes.DB_STATEMENT.key()}" "GET key<a>"
|
"${SemanticAttributes.DB_STATEMENT.key}" "GET a"
|
||||||
}
|
}
|
||||||
event(0) {
|
event(0) {
|
||||||
eventName "redis.encode.start"
|
eventName "redis.encode.start"
|
||||||
|
@ -424,12 +424,12 @@ class LettuceReactiveClientTest extends AgentTestRunner {
|
||||||
errored false
|
errored false
|
||||||
childOf span(0)
|
childOf span(0)
|
||||||
attributes {
|
attributes {
|
||||||
"${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP"
|
"${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP"
|
||||||
"${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1"
|
"${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1"
|
||||||
"${SemanticAttributes.NET_PEER_PORT.key()}" port
|
"${SemanticAttributes.NET_PEER_PORT.key}" port
|
||||||
"${SemanticAttributes.DB_CONNECTION_STRING.key()}" "redis://127.0.0.1:$port"
|
"${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port"
|
||||||
"${SemanticAttributes.DB_SYSTEM.key()}" "redis"
|
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
|
||||||
"${SemanticAttributes.DB_STATEMENT.key()}" "SET key<a> value<1>"
|
"${SemanticAttributes.DB_STATEMENT.key}" "SET a ?"
|
||||||
}
|
}
|
||||||
event(0) {
|
event(0) {
|
||||||
eventName "redis.encode.start"
|
eventName "redis.encode.start"
|
||||||
|
@ -444,12 +444,12 @@ class LettuceReactiveClientTest extends AgentTestRunner {
|
||||||
errored false
|
errored false
|
||||||
childOf span(0)
|
childOf span(0)
|
||||||
attributes {
|
attributes {
|
||||||
"${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP"
|
"${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP"
|
||||||
"${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1"
|
"${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1"
|
||||||
"${SemanticAttributes.NET_PEER_PORT.key()}" port
|
"${SemanticAttributes.NET_PEER_PORT.key}" port
|
||||||
"${SemanticAttributes.DB_CONNECTION_STRING.key()}" "redis://127.0.0.1:$port"
|
"${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port"
|
||||||
"${SemanticAttributes.DB_SYSTEM.key()}" "redis"
|
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
|
||||||
"${SemanticAttributes.DB_STATEMENT.key()}" "GET key<a>"
|
"${SemanticAttributes.DB_STATEMENT.key}" "GET a"
|
||||||
}
|
}
|
||||||
event(0) {
|
event(0) {
|
||||||
eventName "redis.encode.start"
|
eventName "redis.encode.start"
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
|
|
||||||
package io.opentelemetry.javaagent.instrumentation.lettuce.v5_1
|
package io.opentelemetry.javaagent.instrumentation.lettuce.v5_1
|
||||||
|
|
||||||
|
import static io.opentelemetry.trace.Span.Kind.CLIENT
|
||||||
|
|
||||||
import io.lettuce.core.ClientOptions
|
import io.lettuce.core.ClientOptions
|
||||||
import io.lettuce.core.RedisClient
|
import io.lettuce.core.RedisClient
|
||||||
import io.opentelemetry.instrumentation.test.AgentTestRunner
|
import io.opentelemetry.instrumentation.test.AgentTestRunner
|
||||||
|
@ -13,8 +15,6 @@ import io.opentelemetry.trace.attributes.SemanticAttributes
|
||||||
import redis.embedded.RedisServer
|
import redis.embedded.RedisServer
|
||||||
import spock.lang.Shared
|
import spock.lang.Shared
|
||||||
|
|
||||||
import static io.opentelemetry.trace.Span.Kind.CLIENT
|
|
||||||
|
|
||||||
class LettuceSyncClientAuthTest extends AgentTestRunner {
|
class LettuceSyncClientAuthTest extends AgentTestRunner {
|
||||||
public static final String HOST = "127.0.0.1"
|
public static final String HOST = "127.0.0.1"
|
||||||
public static final int DB_INDEX = 0
|
public static final int DB_INDEX = 0
|
||||||
|
@ -74,12 +74,12 @@ class LettuceSyncClientAuthTest extends AgentTestRunner {
|
||||||
kind CLIENT
|
kind CLIENT
|
||||||
errored false
|
errored false
|
||||||
attributes {
|
attributes {
|
||||||
"${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP"
|
"${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP"
|
||||||
"${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1"
|
"${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1"
|
||||||
"${SemanticAttributes.NET_PEER_PORT.key()}" port
|
"${SemanticAttributes.NET_PEER_PORT.key}" port
|
||||||
"${SemanticAttributes.DB_CONNECTION_STRING.key()}" "redis://127.0.0.1:$port"
|
"${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port"
|
||||||
"${SemanticAttributes.DB_SYSTEM.key()}" "redis"
|
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
|
||||||
"${SemanticAttributes.DB_STATEMENT.key()}" "AUTH"
|
"${SemanticAttributes.DB_STATEMENT.key}" "AUTH ?"
|
||||||
}
|
}
|
||||||
event(0) {
|
event(0) {
|
||||||
eventName "redis.encode.start"
|
eventName "redis.encode.start"
|
||||||
|
|
|
@ -6,10 +6,12 @@
|
||||||
package io.opentelemetry.javaagent.instrumentation.lettuce.v5_1
|
package io.opentelemetry.javaagent.instrumentation.lettuce.v5_1
|
||||||
|
|
||||||
import static io.opentelemetry.trace.Span.Kind.CLIENT
|
import static io.opentelemetry.trace.Span.Kind.CLIENT
|
||||||
|
import static java.nio.charset.StandardCharsets.UTF_8
|
||||||
|
|
||||||
import io.lettuce.core.ClientOptions
|
import io.lettuce.core.ClientOptions
|
||||||
import io.lettuce.core.RedisClient
|
import io.lettuce.core.RedisClient
|
||||||
import io.lettuce.core.RedisConnectionException
|
import io.lettuce.core.RedisConnectionException
|
||||||
|
import io.lettuce.core.ScriptOutputType
|
||||||
import io.lettuce.core.api.StatefulConnection
|
import io.lettuce.core.api.StatefulConnection
|
||||||
import io.lettuce.core.api.sync.RedisCommands
|
import io.lettuce.core.api.sync.RedisCommands
|
||||||
import io.opentelemetry.instrumentation.test.AgentTestRunner
|
import io.opentelemetry.instrumentation.test.AgentTestRunner
|
||||||
|
@ -133,12 +135,12 @@ class LettuceSyncClientTest extends AgentTestRunner {
|
||||||
kind CLIENT
|
kind CLIENT
|
||||||
errored false
|
errored false
|
||||||
attributes {
|
attributes {
|
||||||
"${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP"
|
"${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP"
|
||||||
"${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1"
|
"${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1"
|
||||||
"${SemanticAttributes.NET_PEER_PORT.key()}" port
|
"${SemanticAttributes.NET_PEER_PORT.key}" port
|
||||||
"${SemanticAttributes.DB_CONNECTION_STRING.key()}" "redis://127.0.0.1:$port"
|
"${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port"
|
||||||
"${SemanticAttributes.DB_SYSTEM.key()}" "redis"
|
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
|
||||||
"${SemanticAttributes.DB_STATEMENT.key()}" "SET key<TESTSETKEY> value<TESTSETVAL>"
|
"${SemanticAttributes.DB_STATEMENT.key}" "SET TESTSETKEY ?"
|
||||||
}
|
}
|
||||||
event(0) {
|
event(0) {
|
||||||
eventName "redis.encode.start"
|
eventName "redis.encode.start"
|
||||||
|
@ -167,13 +169,13 @@ class LettuceSyncClientTest extends AgentTestRunner {
|
||||||
kind CLIENT
|
kind CLIENT
|
||||||
errored false
|
errored false
|
||||||
attributes {
|
attributes {
|
||||||
"${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP"
|
"${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP"
|
||||||
"${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1"
|
"${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1"
|
||||||
"net.peer.name" "localhost"
|
"${SemanticAttributes.NET_PEER_NAME.key}" "localhost"
|
||||||
"${SemanticAttributes.NET_PEER_PORT.key()}" port
|
"${SemanticAttributes.NET_PEER_PORT.key}" port
|
||||||
"${SemanticAttributes.DB_CONNECTION_STRING.key()}" "redis://localhost:$port"
|
"${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://localhost:$port"
|
||||||
"${SemanticAttributes.DB_SYSTEM.key()}" "redis"
|
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
|
||||||
"${SemanticAttributes.DB_STATEMENT.key()}" "SET key<TESTSETKEY> value<TESTSETVAL>"
|
"${SemanticAttributes.DB_STATEMENT.key}" "SET TESTSETKEY ?"
|
||||||
}
|
}
|
||||||
event(0) {
|
event(0) {
|
||||||
eventName "redis.encode.start"
|
eventName "redis.encode.start"
|
||||||
|
@ -199,12 +201,12 @@ class LettuceSyncClientTest extends AgentTestRunner {
|
||||||
kind CLIENT
|
kind CLIENT
|
||||||
errored false
|
errored false
|
||||||
attributes {
|
attributes {
|
||||||
"${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP"
|
"${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP"
|
||||||
"${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1"
|
"${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1"
|
||||||
"${SemanticAttributes.NET_PEER_PORT.key()}" port
|
"${SemanticAttributes.NET_PEER_PORT.key}" port
|
||||||
"${SemanticAttributes.DB_CONNECTION_STRING.key()}" "redis://127.0.0.1:$port"
|
"${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port"
|
||||||
"${SemanticAttributes.DB_SYSTEM.key()}" "redis"
|
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
|
||||||
"${SemanticAttributes.DB_STATEMENT.key()}" "GET key<TESTKEY>"
|
"${SemanticAttributes.DB_STATEMENT.key}" "GET TESTKEY"
|
||||||
}
|
}
|
||||||
event(0) {
|
event(0) {
|
||||||
eventName "redis.encode.start"
|
eventName "redis.encode.start"
|
||||||
|
@ -230,12 +232,12 @@ class LettuceSyncClientTest extends AgentTestRunner {
|
||||||
kind CLIENT
|
kind CLIENT
|
||||||
errored false
|
errored false
|
||||||
attributes {
|
attributes {
|
||||||
"${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP"
|
"${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP"
|
||||||
"${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1"
|
"${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1"
|
||||||
"${SemanticAttributes.NET_PEER_PORT.key()}" port
|
"${SemanticAttributes.NET_PEER_PORT.key}" port
|
||||||
"${SemanticAttributes.DB_CONNECTION_STRING.key()}" "redis://127.0.0.1:$port"
|
"${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port"
|
||||||
"${SemanticAttributes.DB_SYSTEM.key()}" "redis"
|
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
|
||||||
"${SemanticAttributes.DB_STATEMENT.key()}" "GET key<NON_EXISTENT_KEY>"
|
"${SemanticAttributes.DB_STATEMENT.key}" "GET NON_EXISTENT_KEY"
|
||||||
}
|
}
|
||||||
event(0) {
|
event(0) {
|
||||||
eventName "redis.encode.start"
|
eventName "redis.encode.start"
|
||||||
|
@ -261,12 +263,12 @@ class LettuceSyncClientTest extends AgentTestRunner {
|
||||||
kind CLIENT
|
kind CLIENT
|
||||||
errored false
|
errored false
|
||||||
attributes {
|
attributes {
|
||||||
"${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP"
|
"${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP"
|
||||||
"${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1"
|
"${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1"
|
||||||
"${SemanticAttributes.NET_PEER_PORT.key()}" port
|
"${SemanticAttributes.NET_PEER_PORT.key}" port
|
||||||
"${SemanticAttributes.DB_CONNECTION_STRING.key()}" "redis://127.0.0.1:$port"
|
"${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port"
|
||||||
"${SemanticAttributes.DB_STATEMENT.key()}" "RANDOMKEY"
|
"${SemanticAttributes.DB_STATEMENT.key}" "RANDOMKEY"
|
||||||
"${SemanticAttributes.DB_SYSTEM.key()}" "redis"
|
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
|
||||||
}
|
}
|
||||||
event(0) {
|
event(0) {
|
||||||
eventName "redis.encode.start"
|
eventName "redis.encode.start"
|
||||||
|
@ -292,12 +294,12 @@ class LettuceSyncClientTest extends AgentTestRunner {
|
||||||
kind CLIENT
|
kind CLIENT
|
||||||
errored false
|
errored false
|
||||||
attributes {
|
attributes {
|
||||||
"${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP"
|
"${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP"
|
||||||
"${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1"
|
"${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1"
|
||||||
"${SemanticAttributes.NET_PEER_PORT.key()}" port
|
"${SemanticAttributes.NET_PEER_PORT.key}" port
|
||||||
"${SemanticAttributes.DB_CONNECTION_STRING.key()}" "redis://127.0.0.1:$port"
|
"${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port"
|
||||||
"${SemanticAttributes.DB_SYSTEM.key()}" "redis"
|
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
|
||||||
"${SemanticAttributes.DB_STATEMENT.key()}" "LPUSH key<TESTLIST> value<TESTLIST ELEMENT>"
|
"${SemanticAttributes.DB_STATEMENT.key}" "LPUSH TESTLIST ?"
|
||||||
}
|
}
|
||||||
event(0) {
|
event(0) {
|
||||||
eventName "redis.encode.start"
|
eventName "redis.encode.start"
|
||||||
|
@ -323,12 +325,12 @@ class LettuceSyncClientTest extends AgentTestRunner {
|
||||||
kind CLIENT
|
kind CLIENT
|
||||||
errored false
|
errored false
|
||||||
attributes {
|
attributes {
|
||||||
"${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP"
|
"${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP"
|
||||||
"${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1"
|
"${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1"
|
||||||
"${SemanticAttributes.NET_PEER_PORT.key()}" port
|
"${SemanticAttributes.NET_PEER_PORT.key}" port
|
||||||
"${SemanticAttributes.DB_CONNECTION_STRING.key()}" "redis://127.0.0.1:$port"
|
"${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port"
|
||||||
"${SemanticAttributes.DB_SYSTEM.key()}" "redis"
|
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
|
||||||
"${SemanticAttributes.DB_STATEMENT.key()}" "HMSET key<user> key<firstname> value<John> key<lastname> value<Doe> key<age> value<53>"
|
"${SemanticAttributes.DB_STATEMENT.key}" "HMSET user firstname ? lastname ? age ?"
|
||||||
}
|
}
|
||||||
event(0) {
|
event(0) {
|
||||||
eventName "redis.encode.start"
|
eventName "redis.encode.start"
|
||||||
|
@ -354,12 +356,83 @@ class LettuceSyncClientTest extends AgentTestRunner {
|
||||||
kind CLIENT
|
kind CLIENT
|
||||||
errored false
|
errored false
|
||||||
attributes {
|
attributes {
|
||||||
"${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP"
|
"${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP"
|
||||||
"${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1"
|
"${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1"
|
||||||
"${SemanticAttributes.NET_PEER_PORT.key()}" port
|
"${SemanticAttributes.NET_PEER_PORT.key}" port
|
||||||
"${SemanticAttributes.DB_CONNECTION_STRING.key()}" "redis://127.0.0.1:$port"
|
"${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port"
|
||||||
"${SemanticAttributes.DB_SYSTEM.key()}" "redis"
|
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
|
||||||
"${SemanticAttributes.DB_STATEMENT.key()}" "HGETALL key<TESTHM>"
|
"${SemanticAttributes.DB_STATEMENT.key}" "HGETALL TESTHM"
|
||||||
|
}
|
||||||
|
event(0) {
|
||||||
|
eventName "redis.encode.start"
|
||||||
|
}
|
||||||
|
event(1) {
|
||||||
|
eventName "redis.encode.end"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def "eval command"() {
|
||||||
|
given:
|
||||||
|
def script = "redis.call('lpush', KEYS[1], ARGV[1], ARGV[2]); return redis.call('llen', KEYS[1])"
|
||||||
|
|
||||||
|
when:
|
||||||
|
def result = syncCommands.eval(script, ScriptOutputType.INTEGER, ["TESTLIST"] as String[], "abc", "def")
|
||||||
|
|
||||||
|
then:
|
||||||
|
result == 2
|
||||||
|
|
||||||
|
def b64Script = Base64.encoder.encodeToString(script.getBytes(UTF_8))
|
||||||
|
assertTraces(1) {
|
||||||
|
trace(0, 1) {
|
||||||
|
span(0) {
|
||||||
|
name "EVAL"
|
||||||
|
kind CLIENT
|
||||||
|
errored false
|
||||||
|
attributes {
|
||||||
|
"${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP"
|
||||||
|
"${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1"
|
||||||
|
"${SemanticAttributes.NET_PEER_PORT.key}" port
|
||||||
|
"${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port"
|
||||||
|
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
|
||||||
|
"${SemanticAttributes.DB_STATEMENT.key}" "EVAL $b64Script 1 TESTLIST ? ?"
|
||||||
|
}
|
||||||
|
event(0) {
|
||||||
|
eventName "redis.encode.start"
|
||||||
|
}
|
||||||
|
event(1) {
|
||||||
|
eventName "redis.encode.end"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def "mset command"() {
|
||||||
|
when:
|
||||||
|
def res = syncCommands.mset([
|
||||||
|
"key1": "value1",
|
||||||
|
"key2": "value2"
|
||||||
|
])
|
||||||
|
|
||||||
|
then:
|
||||||
|
res == "OK"
|
||||||
|
|
||||||
|
assertTraces(1) {
|
||||||
|
trace(0, 1) {
|
||||||
|
span(0) {
|
||||||
|
name "MSET"
|
||||||
|
kind CLIENT
|
||||||
|
errored false
|
||||||
|
attributes {
|
||||||
|
"${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP"
|
||||||
|
"${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1"
|
||||||
|
"${SemanticAttributes.NET_PEER_PORT.key}" port
|
||||||
|
"${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port"
|
||||||
|
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
|
||||||
|
"${SemanticAttributes.DB_STATEMENT.key}" "MSET key1 ? key2 ?"
|
||||||
}
|
}
|
||||||
event(0) {
|
event(0) {
|
||||||
eventName "redis.encode.start"
|
eventName "redis.encode.start"
|
||||||
|
|
|
@ -0,0 +1,148 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.javaagent.instrumentation.lettuce.v5_1
|
||||||
|
|
||||||
|
import spock.lang.Specification
|
||||||
|
import spock.lang.Unroll
|
||||||
|
|
||||||
|
class RedisCommandNormalizerTest extends Specification {
|
||||||
|
@Unroll
|
||||||
|
def "should normalize #expected"() {
|
||||||
|
when:
|
||||||
|
def normalised = RedisCommandNormalizer.normalize(command, args)
|
||||||
|
|
||||||
|
then:
|
||||||
|
normalised == expected
|
||||||
|
|
||||||
|
where:
|
||||||
|
command | args | expected
|
||||||
|
// Connection
|
||||||
|
"AUTH" | ["password"] | "AUTH ?"
|
||||||
|
"HELLO" | ["3", "AUTH", "username", "password"] | "HELLO 3 AUTH ? ?"
|
||||||
|
"HELLO" | ["3"] | "HELLO 3"
|
||||||
|
// Hashes
|
||||||
|
"HMSET" | ["hash", "key1", "value1", "key2", "value2"] | "HMSET hash key1 ? key2 ?"
|
||||||
|
"HSET" | ["hash", "key1", "value1", "key2", "value2"] | "HSET hash key1 ? key2 ?"
|
||||||
|
"HSETNX" | ["hash", "key", "value"] | "HSETNX hash key ?"
|
||||||
|
// HyperLogLog
|
||||||
|
"PFADD" | ["hll", "a", "b", "c"] | "PFADD hll ? ? ?"
|
||||||
|
// Keys
|
||||||
|
"MIGRATE" | ["127.0.0.1", "4242", "key", "0", "5000", "AUTH", "password"] | "MIGRATE 127.0.0.1 4242 key 0 5000 AUTH ?"
|
||||||
|
"RESTORE" | ["key", "42", "value"] | "RESTORE key 42 ?"
|
||||||
|
// Lists
|
||||||
|
"LINSERT" | ["list", "BEFORE", "value1", "value2"] | "LINSERT list BEFORE ? ?"
|
||||||
|
"LPOS" | ["list", "value"] | "LPOS list ?"
|
||||||
|
"LPUSH" | ["list", "value1", "value2"] | "LPUSH list ? ?"
|
||||||
|
"LPUSHX" | ["list", "value1", "value2"] | "LPUSHX list ? ?"
|
||||||
|
"LREM" | ["list", "2", "value"] | "LREM list ? ?"
|
||||||
|
"LSET" | ["list", "2", "value"] | "LSET list ? ?"
|
||||||
|
"RPUSH" | ["list", "value1", "value2"] | "RPUSH list ? ?"
|
||||||
|
"RPUSHX" | ["list", "value1", "value2"] | "RPUSHX list ? ?"
|
||||||
|
// Pub/Sub
|
||||||
|
"PUBLISH" | ["channel", "message"] | "PUBLISH channel ?"
|
||||||
|
// Scripting
|
||||||
|
"EVAL" | ["script", "2", "key1", "key2", "value"] | "EVAL script 2 key1 key2 ?"
|
||||||
|
"EVALSHA" | ["sha1", "0", "value1", "value2"] | "EVALSHA sha1 0 ? ?"
|
||||||
|
// Sets
|
||||||
|
"SADD" | ["set", "value1", "value2"] | "SADD set ? ?"
|
||||||
|
"SISMEMBER" | ["set", "value"] | "SISMEMBER set ?"
|
||||||
|
"SMISMEMBER" | ["set", "value1", "value2"] | "SMISMEMBER set ? ?"
|
||||||
|
"SMOVE" | ["set1", "set2", "value"] | "SMOVE set1 set2 ?"
|
||||||
|
"SREM" | ["set", "value1", "value2"] | "SREM set ? ?"
|
||||||
|
// Server
|
||||||
|
"CONFIG" | ["SET", "masterpassword", "password"] | "CONFIG SET masterpassword ?"
|
||||||
|
// Sorted Sets
|
||||||
|
"ZADD" | ["sset", "1", "value1", "2", "value2"] | "ZADD sset ? ? ? ?"
|
||||||
|
"ZCOUNT" | ["sset", "1", "10"] | "ZCOUNT sset ? ?"
|
||||||
|
"ZINCRBY" | ["sset", "1", "value"] | "ZINCRBY sset ? ?"
|
||||||
|
"ZLEXCOUNT" | ["sset", "1", "10"] | "ZLEXCOUNT sset ? ?"
|
||||||
|
"ZMSCORE" | ["sset", "value1", "value2"] | "ZMSCORE sset ? ?"
|
||||||
|
"ZRANGEBYLEX" | ["sset", "1", "10"] | "ZRANGEBYLEX sset ? ?"
|
||||||
|
"ZRANGEBYSCORE" | ["sset", "1", "10"] | "ZRANGEBYSCORE sset ? ?"
|
||||||
|
"ZRANK" | ["sset", "value"] | "ZRANK sset ?"
|
||||||
|
"ZREM" | ["sset", "value1", "value2"] | "ZREM sset ? ?"
|
||||||
|
"ZREMRANGEBYLEX" | ["sset", "1", "10"] | "ZREMRANGEBYLEX sset ? ?"
|
||||||
|
"ZREMRANGEBYSCORE" | ["sset", "1", "10"] | "ZREMRANGEBYSCORE sset ? ?"
|
||||||
|
"ZREVRANGEBYLEX" | ["sset", "1", "10"] | "ZREVRANGEBYLEX sset ? ?"
|
||||||
|
"ZREVRANGEBYSCORE" | ["sset", "1", "10"] | "ZREVRANGEBYSCORE sset ? ?"
|
||||||
|
"ZREVRANK" | ["sset", "value"] | "ZREVRANK sset ?"
|
||||||
|
"ZSCORE" | ["sset", "value"] | "ZSCORE sset ?"
|
||||||
|
// Streams
|
||||||
|
"XADD" | ["stream", "*", "key1", "value1", "key2", "value2"] | "XADD stream * key1 ? key2 ?"
|
||||||
|
// Strings
|
||||||
|
"APPEND" | ["key", "value"] | "APPEND key ?"
|
||||||
|
"GETSET" | ["key", "value"] | "GETSET key ?"
|
||||||
|
"MSET" | ["key1", "value1", "key2", "value2"] | "MSET key1 ? key2 ?"
|
||||||
|
"MSETNX" | ["key1", "value1", "key2", "value2"] | "MSETNX key1 ? key2 ?"
|
||||||
|
"PSETEX" | ["key", "10000", "value"] | "PSETEX key 10000 ?"
|
||||||
|
"SET" | ["key", "value"] | "SET key ?"
|
||||||
|
"SETEX" | ["key", "10", "value"] | "SETEX key 10 ?"
|
||||||
|
"SETNX" | ["key", "value"] | "SETNX key ?"
|
||||||
|
"SETRANGE" | ["key", "42", "value"] | "SETRANGE key ? ?"
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unroll
|
||||||
|
def "should keep all arguments of #command"() {
|
||||||
|
given:
|
||||||
|
def args = ["arg1", "arg 2"]
|
||||||
|
|
||||||
|
when:
|
||||||
|
def normalised = RedisCommandNormalizer.normalize(command, args)
|
||||||
|
|
||||||
|
then:
|
||||||
|
normalised == command + " " + args.join(" ")
|
||||||
|
|
||||||
|
where:
|
||||||
|
command << [
|
||||||
|
// Cluster
|
||||||
|
"CLUSTER", "READONLY", "READWRITE",
|
||||||
|
// Connection
|
||||||
|
"CLIENT", "ECHO", "PING", "QUIT", "SELECT",
|
||||||
|
// Geo
|
||||||
|
"GEOADD", "GEODIST", "GEOHASH", "GEOPOS", "GEORADIUS", "GEORADIUSBYMEMBER",
|
||||||
|
// Hashes
|
||||||
|
"HDEL", "HEXISTS", "HGET", "HGETALL", "HINCRBY", "HINCRBYFLOAT", "HKEYS", "HLEN", "HMGET",
|
||||||
|
"HSCAN", "HSTRLEN", "HVALS",
|
||||||
|
// HyperLogLog
|
||||||
|
"PFCOUNT", "PFMERGE",
|
||||||
|
// Keys
|
||||||
|
"DEL", "DUMP", "EXISTS", "EXPIRE", "EXPIREAT", "KEYS", "MOVE", "OBJECT", "PERSIST", "PEXPIRE",
|
||||||
|
"PEXPIREAT", "PTTL", "RANDOMKEY", "RENAME", "RENAMENX", "RESTORE", "SCAN", "SORT", "TOUCH",
|
||||||
|
"TTL", "TYPE", "UNLINK", "WAIT",
|
||||||
|
// Lists
|
||||||
|
"BLMOVE", "BLPOP", "BRPOP", "BRPOPLPUSH", "LINDEX", "LLEN", "LMOVE", "LPOP", "LRANGE",
|
||||||
|
"LTRIM", "RPOP", "RPOPLPUSH",
|
||||||
|
// Pub/Sub
|
||||||
|
"PSUBSCRIBE", "PUBSUB", "PUNSUBSCRIBE", "SUBSCRIBE", "UNSUBSCRIBE",
|
||||||
|
// Server
|
||||||
|
"ACL", "BGREWRITEAOF", "BGSAVE", "COMMAND", "DBSIZE", "DEBUG", "FLUSHALL", "FLUSHDB", "INFO",
|
||||||
|
"LASTSAVE", "LATENCY", "LOLWUT", "MEMORY", "MODULE", "MONITOR", "PSYNC", "REPLICAOF", "ROLE",
|
||||||
|
"SAVE", "SHUTDOWN", "SLAVEOF", "SLOWLOG", "SWAPDB", "SYNC", "TIME",
|
||||||
|
// Sets
|
||||||
|
"SCARD", "SDIFF", "SDIFFSTORE", "SINTER", "SINTERSTORE", "SMEMBERS", "SPOP", "SRANDMEMBER",
|
||||||
|
"SSCAN", "SUNION", "SUNIONSTORE",
|
||||||
|
// Sorted Sets
|
||||||
|
"BZPOPMAX", "BZPOPMIN", "ZCARD", "ZINTER", "ZINTERSTORE", "ZPOPMAX", "ZPOPMIN", "ZRANGE",
|
||||||
|
"ZREMRANGEBYRANK", "ZREVRANGE", "ZSCAN", "ZUNION", "ZUNIONSTORE",
|
||||||
|
// Streams
|
||||||
|
"XACK", "XCLAIM", "XDEL", "XGROUP", "XINFO", "XLEN", "XPENDING", "XRANGE", "XREAD",
|
||||||
|
"XREADGROUP", "XREVRANGE", "XTRIM",
|
||||||
|
// Strings
|
||||||
|
"BITCOUNT", "BITFIELD", "BITOP", "BITPOS", "DECR", "DECRBY", "GET", "GETBIT", "GETRANGE",
|
||||||
|
"INCR", "INCRBY", "INCRBYFLOAT", "MGET", "SETBIT", "STRALGO", "STRLEN",
|
||||||
|
// Transactions
|
||||||
|
"DISCARD", "EXEC", "MULTI", "UNWATCH", "WATCH"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
def "should mask all arguments of an unknown command"() {
|
||||||
|
when:
|
||||||
|
def normalised = RedisCommandNormalizer.normalize("NEWAUTH", ["password", "secret"])
|
||||||
|
|
||||||
|
then:
|
||||||
|
normalised == "NEWAUTH ? ?"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue