Standardize DB query normalizer property names
* Standardize DB query normalizer property names
And add normalizer configuration for Redis, Couchbase, Cassandra and Geode
* apply code review comments
MODIFY
instrumentation/cassandra/cassandra-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v3_0/CassandraQueryNormalizer.java
instrumentation/cassandra/cassandra-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v3_0/CassandraQueryNormalizer.java
package io.opentelemetry.javaagent.instrumentation.cassandra.v3_0;
+import static io.opentelemetry.javaagent.instrumentation.api.db.QueryNormalizationConfig.isQueryNormalizationEnabled;
+
import io.opentelemetry.javaagent.instrumentation.api.db.normalizer.ParseException;
import io.opentelemetry.javaagent.instrumentation.api.db.normalizer.SqlNormalizer;
import org.slf4j.Logger;
@@ -12,8 +14,12 @@ import org.slf4j.LoggerFactory;
public final class CassandraQueryNormalizer {
private static final Logger log = LoggerFactory.getLogger(CassandraQueryNormalizer.class);
+ private static final boolean NORMALIZATION_ENABLED = isQueryNormalizationEnabled("cassandra");
public static String normalize(String query) {
+ if (!NORMALIZATION_ENABLED) {
+ return query;
+ }
try {
return SqlNormalizer.normalize(query);
} catch (ParseException e) {

MODIFY
instrumentation/cassandra/cassandra-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/CassandraQueryNormalizer.java
instrumentation/cassandra/cassandra-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/CassandraQueryNormalizer.java
package io.opentelemetry.javaagent.instrumentation.cassandra.v4_0;
+import static io.opentelemetry.javaagent.instrumentation.api.db.QueryNormalizationConfig.isQueryNormalizationEnabled;
+
import io.opentelemetry.javaagent.instrumentation.api.db.normalizer.ParseException;
import io.opentelemetry.javaagent.instrumentation.api.db.normalizer.SqlNormalizer;
import org.slf4j.Logger;
@@ -12,8 +14,12 @@ import org.slf4j.LoggerFactory;
public final class CassandraQueryNormalizer {
private static final Logger log = LoggerFactory.getLogger(CassandraQueryNormalizer.class);
+ private static final boolean NORMALIZATION_ENABLED = isQueryNormalizationEnabled("cassandra");
public static String normalize(String query) {
+ if (!NORMALIZATION_ENABLED) {
+ return query;
+ }
try {
return SqlNormalizer.normalize(query);
} catch (ParseException e) {

MODIFY
instrumentation/couchbase/couchbase-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseQueryNormalizer.java
instrumentation/couchbase/couchbase-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseQueryNormalizer.java
package io.opentelemetry.javaagent.instrumentation.couchbase.v2_0;
+import static io.opentelemetry.javaagent.instrumentation.api.db.QueryNormalizationConfig.isQueryNormalizationEnabled;
+
import io.opentelemetry.javaagent.instrumentation.api.db.normalizer.ParseException;
import io.opentelemetry.javaagent.instrumentation.api.db.normalizer.SqlNormalizer;
import java.lang.invoke.MethodHandle;
@@ -15,6 +17,7 @@ import org.slf4j.LoggerFactory;
public final class CouchbaseQueryNormalizer {
private static final Logger log = LoggerFactory.getLogger(CouchbaseQueryNormalizer.class);
+ private static final boolean NORMALIZATION_ENABLED = isQueryNormalizationEnabled("couchbase");
private static final Class<?> QUERY_CLASS;
private static final Class<?> STATEMENT_CLASS;
@@ -118,6 +121,9 @@ public final class CouchbaseQueryNormalizer {
}
private static String normalizeString(String query) {
+ if (!NORMALIZATION_ENABLED || query == null) {
+ return query;
+ }
try {
return SqlNormalizer.normalize(query);
} catch (ParseException e) {

MODIFY
instrumentation/geode-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/GeodeQueryNormalizer.java
instrumentation/geode-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/GeodeQueryNormalizer.java
package io.opentelemetry.javaagent.instrumentation.geode;
+import static io.opentelemetry.javaagent.instrumentation.api.db.QueryNormalizationConfig.isQueryNormalizationEnabled;
+
import io.opentelemetry.javaagent.instrumentation.api.db.normalizer.ParseException;
import io.opentelemetry.javaagent.instrumentation.api.db.normalizer.SqlNormalizer;
import org.slf4j.Logger;
@@ -12,10 +14,12 @@ import org.slf4j.LoggerFactory;
public final class GeodeQueryNormalizer {
private static final Logger log = LoggerFactory.getLogger(GeodeQueryNormalizer.class);
+ private static final boolean NORMALIZATION_ENABLED =
+ isQueryNormalizationEnabled("geode", "geode-client");
public static String normalize(String query) {
- if (query == null) {
- return null;
+ if (!NORMALIZATION_ENABLED || query == null) {
+ return query;
}
try {
return SqlNormalizer.normalize(query);

MODIFY
instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/JDBCUtils.java
instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/JDBCUtils.java
package io.opentelemetry.javaagent.instrumentation.jdbc;
-import io.opentelemetry.instrumentation.api.config.Config;
+import static io.opentelemetry.javaagent.instrumentation.api.db.QueryNormalizationConfig.isQueryNormalizationEnabled;
+
import io.opentelemetry.javaagent.instrumentation.api.db.normalizer.SqlNormalizer;
import java.lang.reflect.Field;
import java.sql.Connection;
@@ -17,8 +18,7 @@ public abstract class JDBCUtils {
private static final Logger log = LoggerFactory.getLogger(JDBCUtils.class);
- private static final boolean SQL_NORMALIZER_ENABLED =
- Config.get().getBooleanProperty("sql.normalizer.enabled", true);
+ private static final boolean NORMALIZATION_ENABLED = isQueryNormalizationEnabled("jdbc");
private static Field c3poField = null;
@@ -71,7 +71,7 @@ public abstract class JDBCUtils {
/** @return null if the sql could not be normalized for any reason */
public static String normalizeSql(String sql) {
- if (!SQL_NORMALIZER_ENABLED) {
+ if (!NORMALIZATION_ENABLED) {
return sql;
}
try {

MODIFY
instrumentation/jedis/jedis-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisClientTracer.java
instrumentation/jedis/jedis-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisClientTracer.java
@@ -18,6 +18,9 @@ import redis.clients.jedis.Protocol.Command;
public class JedisClientTracer extends DatabaseClientTracer<Connection, CommandWithArgs> {
public static final JedisClientTracer TRACER = new JedisClientTracer();
+ private final RedisCommandNormalizer commandNormalizer =
+ new RedisCommandNormalizer("jedis", "redis");
+
@Override
protected String spanName(Connection connection, CommandWithArgs query, String normalizedQuery) {
return query.getStringCommand();
@@ -25,7 +28,7 @@ public class JedisClientTracer extends DatabaseClientTracer<Connection, CommandW
@Override
protected String normalizeQuery(CommandWithArgs command) {
- return RedisCommandNormalizer.normalize(command.getStringCommand(), command.getArgs());
+ return commandNormalizer.normalize(command.getStringCommand(), command.getArgs());
}
@Override

MODIFY
instrumentation/jedis/jedis-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v3_0/JedisClientTracer.java
instrumentation/jedis/jedis-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v3_0/JedisClientTracer.java
@@ -20,6 +20,9 @@ import redis.clients.jedis.commands.ProtocolCommand;
public class JedisClientTracer extends DatabaseClientTracer<Connection, CommandWithArgs> {
public static final JedisClientTracer TRACER = new JedisClientTracer();
+ private final RedisCommandNormalizer commandNormalizer =
+ new RedisCommandNormalizer("jedis", "redis");
+
@Override
protected String spanName(Connection connection, CommandWithArgs query, String normalizedQuery) {
return query.getStringCommand();
@@ -27,7 +30,7 @@ public class JedisClientTracer extends DatabaseClientTracer<Connection, CommandW
@Override
protected String normalizeQuery(CommandWithArgs command) {
- return RedisCommandNormalizer.normalize(command.getStringCommand(), command.getArgs());
+ return commandNormalizer.normalize(command.getStringCommand(), command.getArgs());
}
@Override

MODIFY
instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceDatabaseClientTracer.java
instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceDatabaseClientTracer.java
@@ -16,6 +16,9 @@ public class LettuceDatabaseClientTracer
extends LettuceAbstractDatabaseClientTracer<RedisCommand<?, ?, ?>> {
public static final LettuceDatabaseClientTracer TRACER = new LettuceDatabaseClientTracer();
+ private final RedisCommandNormalizer commandNormalizer =
+ new RedisCommandNormalizer("lettuce", "lettuce-5");
+
@Override
protected String spanName(
RedisURI connection, RedisCommand<?, ?, ?> query, String normalizedQuery) {
@@ -29,6 +32,6 @@ public class LettuceDatabaseClientTracer
redisCommand.getArgs() == null
? Collections.emptyList()
: LettuceArgSplitter.splitArgs(redisCommand.getArgs().toCommandString());
- return RedisCommandNormalizer.normalize(command, args);
+ return commandNormalizer.normalize(command, args);
}
}

MODIFY
instrumentation/lettuce/lettuce-5.1/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/OpenTelemetryTracing.java
instrumentation/lettuce/lettuce-5.1/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/OpenTelemetryTracing.java
@@ -36,6 +36,9 @@ public enum OpenTelemetryTracing implements Tracing {
public static final io.opentelemetry.trace.Tracer TRACER =
OpenTelemetry.getGlobalTracer("io.opentelemetry.auto.lettuce-5.1");
+ private static final RedisCommandNormalizer commandNormalizer =
+ new RedisCommandNormalizer("lettuce", "lettuce-5", "lettuce-5.1");
+
@Override
public TracerProvider getTracerProvider() {
return OpenTelemetryTracerProvider.INSTANCE;
@@ -250,7 +253,7 @@ public enum OpenTelemetryTracing implements Tracing {
public synchronized void finish() {
if (span != null) {
if (name != null) {
- String statement = RedisCommandNormalizer.normalize(name, splitArgs(args));
+ String statement = commandNormalizer.normalize(name, splitArgs(args));
span.setAttribute(SemanticAttributes.DB_STATEMENT, statement);
}
span.end();

MODIFY
instrumentation/redisson-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/redisson/RedissonClientTracer.java
instrumentation/redisson-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/redisson/RedissonClientTracer.java
@@ -22,6 +22,9 @@ public class RedissonClientTracer extends DatabaseClientTracer<RedisConnection,
public static final RedissonClientTracer TRACER = new RedissonClientTracer();
+ private final RedisCommandNormalizer commandNormalizer =
+ new RedisCommandNormalizer("redisson", "redis");
+
@Override
protected String spanName(RedisConnection connection, Object query, String normalizedQuery) {
if (query instanceof CommandsData) {
@@ -65,7 +68,7 @@ public class RedissonClientTracer extends DatabaseClientTracer<RedisConnection,
return UNKNOWN_COMMAND;
}
- private static String normalizeSingleCommand(CommandData<?, ?> command) {
+ private String normalizeSingleCommand(CommandData<?, ?> command) {
Object[] commandParams = command.getParams();
List<Object> args = new ArrayList<>(commandParams.length + 1);
if (command.getCommand().getSubName() != null) {
@@ -86,7 +89,7 @@ public class RedissonClientTracer extends DatabaseClientTracer<RedisConnection,
args.add(param);
}
}
- return RedisCommandNormalizer.normalize(command.getCommand().getName(), args);
+ return commandNormalizer.normalize(command.getCommand().getName(), args);
}
@Override

ADD
javaagent-api/src/main/java/io/opentelemetry/javaagent/instrumentation/api/db/QueryNormalizationConfig.java
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.api.db;
+
+import io.opentelemetry.instrumentation.api.config.Config;
+
+/**
+ * This class encapsulates query normalization property naming convention. Query normalization is
+ * always enabled by default, you have to manually disable it.
+ */
+public final class QueryNormalizationConfig {
+
+ public static boolean isQueryNormalizationEnabled(String... instrumentationNames) {
+ for (String instrumentationName : instrumentationNames) {
+ if (!Config.get().getBooleanProperty(propertyName(instrumentationName), true)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static String propertyName(String instrumentationName) {
+ return "otel.instrumentation." + instrumentationName + ".query.normalizer.enabled";
+ }
+
+ private QueryNormalizationConfig() {}
+}

MODIFY
javaagent-api/src/main/java/io/opentelemetry/javaagent/instrumentation/api/db/RedisCommandNormalizer.java
javaagent-api/src/main/java/io/opentelemetry/javaagent/instrumentation/api/db/RedisCommandNormalizer.java
package io.opentelemetry.javaagent.instrumentation.api.db;
+import static io.opentelemetry.javaagent.instrumentation.api.db.QueryNormalizationConfig.isQueryNormalizationEnabled;
import static java.util.Arrays.asList;
import static java.util.Collections.unmodifiableMap;
@@ -312,7 +313,16 @@ public final class RedisCommandNormalizer {
NORMALIZERS = unmodifiableMap(normalizers);
}
- public static String normalize(String command, List<?> args) {
+ private final boolean normalizationEnabled;
+
+ public RedisCommandNormalizer(String... instrumentationNames) {
+ this.normalizationEnabled = isQueryNormalizationEnabled(instrumentationNames);
+ }
+
+ public String normalize(String command, List<?> args) {
+ if (!normalizationEnabled) {
+ return KeepAllArgs.INSTANCE.normalize(command, args);
+ }
return NORMALIZERS.getOrDefault(command.toUpperCase(), DEFAULT).normalize(command, args);
}
@@ -416,6 +426,4 @@ public final class RedisCommandNormalizer {
}
}
}
-
- private RedisCommandNormalizer() {}
}

MODIFY
javaagent-api/src/test/groovy/io/opentelemetry/javaagent/instrumentation/api/db/RedisCommandNormalizerTest.groovy
javaagent-api/src/test/groovy/io/opentelemetry/javaagent/instrumentation/api/db/RedisCommandNormalizerTest.groovy
package io.opentelemetry.javaagent.instrumentation.api.db
+import io.opentelemetry.instrumentation.test.utils.ConfigUtils
import spock.lang.Specification
import spock.lang.Unroll
class RedisCommandNormalizerTest extends Specification {
+ def normalizer = new RedisCommandNormalizer("redis")
+
+ def "should not normalize anything when turned off"() {
+ given:
+ def previousConfig = ConfigUtils.updateConfig({
+ it.setProperty("otel.instrumentation.redis.query.normalizer.enabled", "false")
+ })
+
+ def normalizer = new RedisCommandNormalizer("redis-instrumentation", "redis")
+
+ when:
+ def result = normalizer.normalize("AUTH", ["user", "password"])
+
+ then:
+ result == "AUTH user password"
+
+ cleanup:
+ ConfigUtils.setConfig(previousConfig)
+ }
+
@Unroll
def "should normalize #expected"() {
when:
- def normalised = RedisCommandNormalizer.normalize(command, args)
+ def normalised = normalizer.normalize(command, args)
then:
normalised == expected
@@ -90,7 +111,7 @@ class RedisCommandNormalizerTest extends Specification {
def args = ["arg1", "arg 2"]
when:
- def normalised = RedisCommandNormalizer.normalize(command, args)
+ def normalised = normalizer.normalize(command, args)
then:
normalised == command + " " + args.join(" ")
@@ -140,7 +161,7 @@ class RedisCommandNormalizerTest extends Specification {
def "should mask all arguments of an unknown command"() {
when:
- def normalised = RedisCommandNormalizer.normalize("NEWAUTH", ["password", "secret"])
+ def normalised = normalizer.normalize("NEWAUTH", ["password", "secret"])
then:
normalised == "NEWAUTH ? ?"

Standardize DB query normalizer property names (#1509)

* Standardize DB query normalizer property names

And add normalizer configuration for Redis, Couchbase, Cassandra and Geode

* apply code review comments