Lettuce 5.1 instrumentation should log normalised commands as db.statement (#1405)

This commit is contained in:
Mateusz Rzeszutek 2020-10-20 23:57:23 +02:00 committed by GitHub
parent a5475b23a4
commit f077b23c9f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 904 additions and 211 deletions

View File

@ -5,6 +5,7 @@
package io.opentelemetry.instrumentation.api.tracer.utils;
import io.opentelemetry.common.AttributeKey;
import io.opentelemetry.instrumentation.api.config.Config;
import io.opentelemetry.trace.Span;
import io.opentelemetry.trace.attributes.SemanticAttributes;
@ -30,13 +31,15 @@ public final class NetPeerUtils {
setNetPeer(span, remoteAddress, remoteConnection.getPort());
} else {
// 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) {
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) {
@ -45,16 +48,20 @@ public final class NetPeerUtils {
setNetPeer(span, address);
} catch (IllegalArgumentException iae) {
// 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) {
setNetPeer(span, peerName, peerIp, -1);
setNetPeer(span::setAttribute, peerName, peerIp, -1);
}
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)) {
span.setAttribute(SemanticAttributes.NET_PEER_NAME, peerName);
}
@ -81,4 +88,12 @@ public final class NetPeerUtils {
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);
}
}

View File

@ -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() {}
}

View File

@ -41,6 +41,13 @@ public class LettuceClientResourcesInstrumentation extends Instrumenter.Default
@Override
public String[] helperClassNames() {
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$OpenTelemetryTracerProvider",
packageName + ".OpenTelemetryTracing$OpenTelemetryTraceContextProvider",

View File

@ -5,6 +5,8 @@
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.lettuce.core.tracing.TraceContext;
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.Tracing;
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.trace.Span;
import io.opentelemetry.trace.Span.Kind;
@ -23,7 +27,7 @@ import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import reactor.util.annotation.Nullable;
import org.checkerframework.checker.nullness.qual.Nullable;
public enum OpenTelemetryTracing implements Tracing {
INSTANCE;
@ -57,8 +61,8 @@ public enum OpenTelemetryTracing implements Tracing {
if (socketAddress instanceof InetSocketAddress) {
InetSocketAddress address = (InetSocketAddress) socketAddress;
return new OpenTelemetryEndpoint(
address.getAddress().getHostAddress(), address.getPort(), address.getHostString());
String ip = address.getAddress() == null ? null : address.getAddress().getHostAddress();
return new OpenTelemetryEndpoint(ip, address.getPort(), address.getHostString());
}
return null;
}
@ -96,18 +100,14 @@ public enum OpenTelemetryTracing implements Tracing {
}
private static class OpenTelemetryEndpoint implements Endpoint {
final String ip;
@Nullable final String ip;
final int port;
@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.port = port;
if (!ip.equals(name)) {
this.name = name;
} else {
this.name = null;
}
this.name = name;
}
}
@ -175,9 +175,9 @@ public enum OpenTelemetryTracing implements Tracing {
public synchronized Tracer.Span remoteEndpoint(Endpoint endpoint) {
if (endpoint instanceof OpenTelemetryEndpoint) {
if (span != null) {
fillEndpoint(span, (OpenTelemetryEndpoint) endpoint);
fillEndpoint(span::setAttribute, (OpenTelemetryEndpoint) endpoint);
} else {
fillEndpoint(spanBuilder, (OpenTelemetryEndpoint) endpoint);
fillEndpoint(spanBuilder::setAttribute, (OpenTelemetryEndpoint) endpoint);
}
}
return this;
@ -249,50 +249,20 @@ public enum OpenTelemetryTracing implements Tracing {
public synchronized void finish() {
if (span != null) {
if (name != null) {
String statement =
(args != null && !args.isEmpty()) && !name.equals("AUTH") ? name + " " + args : name;
String statement = RedisCommandNormalizer.normalize(name, splitArgs(args));
span.setAttribute(SemanticAttributes.DB_STATEMENT, statement);
}
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_PEER_IP, endpoint.ip);
NetPeerUtils.setNetPeer(span, endpoint.name, endpoint.ip, endpoint.port);
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);
}
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);
StringBuilder redisUrl =
new StringBuilder("redis://").append(endpoint.name != null ? endpoint.name : endpoint.ip);
if (endpoint.port > 0) {
redisUrl.append(":").append(endpoint.port);
}

View File

@ -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() {}
}

View File

@ -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"]
}
}

View File

@ -152,12 +152,12 @@ class LettuceAsyncClientTest extends AgentTestRunner {
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()}" "SET key<TESTSETKEY> value<TESTSETVAL>"
"${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}" "SET TESTSETKEY ?"
}
event(0) {
eventName "redis.encode.start"
@ -195,12 +195,12 @@ class LettuceAsyncClientTest extends AgentTestRunner {
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()}" "GET key<TESTKEY>"
"${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}" "GET TESTKEY"
}
event(0) {
eventName "redis.encode.start"
@ -252,12 +252,12 @@ class LettuceAsyncClientTest extends AgentTestRunner {
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()}" "GET key<NON_EXISTENT_KEY>"
"${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}" "GET NON_EXISTENT_KEY"
}
event(0) {
eventName "redis.encode.start"
@ -295,12 +295,12 @@ class LettuceAsyncClientTest extends AgentTestRunner {
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_STATEMENT.key()}" "RANDOMKEY"
"${SemanticAttributes.DB_SYSTEM.key()}" "redis"
"${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_STATEMENT.key}" "RANDOMKEY"
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
}
event(0) {
eventName "redis.encode.start"
@ -356,12 +356,12 @@ class LettuceAsyncClientTest extends AgentTestRunner {
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()}" "HMSET key<TESTHM> key<firstname> value<John> key<lastname> value<Doe> key<age> value<53>"
"${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}" "HMSET TESTHM firstname ? lastname ? age ?"
}
event(0) {
eventName "redis.encode.start"
@ -377,12 +377,12 @@ class LettuceAsyncClientTest extends AgentTestRunner {
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()}" "HGETALL key<TESTHM>"
"${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}" "HGETALL TESTHM"
}
event(0) {
eventName "redis.encode.start"

View File

@ -102,12 +102,12 @@ class LettuceReactiveClientTest extends AgentTestRunner {
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()}" "SET key<TESTSETKEY> value<TESTSETVAL>"
"${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}" "SET TESTSETKEY ?"
}
event(0) {
eventName "redis.encode.start"
@ -136,12 +136,12 @@ class LettuceReactiveClientTest extends AgentTestRunner {
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()}" "GET key<TESTKEY>"
"${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}" "GET TESTKEY"
}
event(0) {
eventName "redis.encode.start"
@ -178,12 +178,12 @@ class LettuceReactiveClientTest extends AgentTestRunner {
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()}" "GET key<NON_EXISTENT_KEY>"
"${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}" "GET NON_EXISTENT_KEY"
}
event(0) {
eventName "redis.encode.start"
@ -218,12 +218,12 @@ class LettuceReactiveClientTest extends AgentTestRunner {
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_STATEMENT.key()}" "RANDOMKEY"
"${SemanticAttributes.DB_SYSTEM.key()}" "redis"
"${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_STATEMENT.key}" "RANDOMKEY"
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
}
event(0) {
eventName "redis.encode.start"
@ -248,12 +248,12 @@ class LettuceReactiveClientTest extends AgentTestRunner {
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_STATEMENT.key()}" "COMMAND"
"${SemanticAttributes.DB_SYSTEM.key()}" "redis"
"${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_STATEMENT.key}" "COMMAND"
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
}
event(0) {
eventName "redis.encode.start"
@ -301,12 +301,12 @@ class LettuceReactiveClientTest extends AgentTestRunner {
errored false
childOf span(0)
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()}" "SET key<a> value<1>"
"${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}" "SET a ?"
}
event(0) {
eventName "redis.encode.start"
@ -321,12 +321,12 @@ class LettuceReactiveClientTest extends AgentTestRunner {
errored false
childOf span(0)
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()}" "GET key<a>"
"${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}" "GET a"
}
event(0) {
eventName "redis.encode.start"
@ -362,12 +362,12 @@ class LettuceReactiveClientTest extends AgentTestRunner {
errored false
childOf span(0)
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()}" "SET key<a> value<1>"
"${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}" "SET a ?"
}
event(0) {
eventName "redis.encode.start"
@ -382,12 +382,12 @@ class LettuceReactiveClientTest extends AgentTestRunner {
errored false
childOf span(0)
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()}" "GET key<a>"
"${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}" "GET a"
}
event(0) {
eventName "redis.encode.start"
@ -424,12 +424,12 @@ class LettuceReactiveClientTest extends AgentTestRunner {
errored false
childOf span(0)
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()}" "SET key<a> value<1>"
"${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}" "SET a ?"
}
event(0) {
eventName "redis.encode.start"
@ -444,12 +444,12 @@ class LettuceReactiveClientTest extends AgentTestRunner {
errored false
childOf span(0)
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()}" "GET key<a>"
"${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}" "GET a"
}
event(0) {
eventName "redis.encode.start"

View File

@ -5,6 +5,8 @@
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.RedisClient
import io.opentelemetry.instrumentation.test.AgentTestRunner
@ -13,8 +15,6 @@ import io.opentelemetry.trace.attributes.SemanticAttributes
import redis.embedded.RedisServer
import spock.lang.Shared
import static io.opentelemetry.trace.Span.Kind.CLIENT
class LettuceSyncClientAuthTest extends AgentTestRunner {
public static final String HOST = "127.0.0.1"
public static final int DB_INDEX = 0
@ -74,12 +74,12 @@ class LettuceSyncClientAuthTest extends AgentTestRunner {
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()}" "AUTH"
"${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}" "AUTH ?"
}
event(0) {
eventName "redis.encode.start"

View File

@ -6,10 +6,12 @@
package io.opentelemetry.javaagent.instrumentation.lettuce.v5_1
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.RedisClient
import io.lettuce.core.RedisConnectionException
import io.lettuce.core.ScriptOutputType
import io.lettuce.core.api.StatefulConnection
import io.lettuce.core.api.sync.RedisCommands
import io.opentelemetry.instrumentation.test.AgentTestRunner
@ -133,12 +135,12 @@ class LettuceSyncClientTest extends AgentTestRunner {
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()}" "SET key<TESTSETKEY> value<TESTSETVAL>"
"${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}" "SET TESTSETKEY ?"
}
event(0) {
eventName "redis.encode.start"
@ -167,13 +169,13 @@ class LettuceSyncClientTest extends AgentTestRunner {
kind CLIENT
errored false
attributes {
"${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP"
"${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1"
"net.peer.name" "localhost"
"${SemanticAttributes.NET_PEER_PORT.key()}" port
"${SemanticAttributes.DB_CONNECTION_STRING.key()}" "redis://localhost:$port"
"${SemanticAttributes.DB_SYSTEM.key()}" "redis"
"${SemanticAttributes.DB_STATEMENT.key()}" "SET key<TESTSETKEY> value<TESTSETVAL>"
"${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP"
"${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1"
"${SemanticAttributes.NET_PEER_NAME.key}" "localhost"
"${SemanticAttributes.NET_PEER_PORT.key}" port
"${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://localhost:$port"
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
"${SemanticAttributes.DB_STATEMENT.key}" "SET TESTSETKEY ?"
}
event(0) {
eventName "redis.encode.start"
@ -199,12 +201,12 @@ class LettuceSyncClientTest extends AgentTestRunner {
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()}" "GET key<TESTKEY>"
"${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}" "GET TESTKEY"
}
event(0) {
eventName "redis.encode.start"
@ -230,12 +232,12 @@ class LettuceSyncClientTest extends AgentTestRunner {
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()}" "GET key<NON_EXISTENT_KEY>"
"${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}" "GET NON_EXISTENT_KEY"
}
event(0) {
eventName "redis.encode.start"
@ -261,12 +263,12 @@ class LettuceSyncClientTest extends AgentTestRunner {
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_STATEMENT.key()}" "RANDOMKEY"
"${SemanticAttributes.DB_SYSTEM.key()}" "redis"
"${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_STATEMENT.key}" "RANDOMKEY"
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
}
event(0) {
eventName "redis.encode.start"
@ -292,12 +294,12 @@ class LettuceSyncClientTest extends AgentTestRunner {
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()}" "LPUSH key<TESTLIST> value<TESTLIST ELEMENT>"
"${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}" "LPUSH TESTLIST ?"
}
event(0) {
eventName "redis.encode.start"
@ -323,12 +325,12 @@ class LettuceSyncClientTest extends AgentTestRunner {
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()}" "HMSET key<user> key<firstname> value<John> key<lastname> value<Doe> key<age> value<53>"
"${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}" "HMSET user firstname ? lastname ? age ?"
}
event(0) {
eventName "redis.encode.start"
@ -354,12 +356,83 @@ class LettuceSyncClientTest extends AgentTestRunner {
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()}" "HGETALL key<TESTHM>"
"${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}" "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) {
eventName "redis.encode.start"

View File

@ -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 ? ?"
}
}