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
This commit is contained in:
Mateusz Rzeszutek 2020-10-29 15:20:33 +01:00 committed by GitHub
parent af5fb0c944
commit e89942d430
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 114 additions and 18 deletions

View File

@ -5,6 +5,8 @@
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) {

View File

@ -5,6 +5,8 @@
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) {

View File

@ -5,6 +5,8 @@
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) {

View File

@ -5,6 +5,8 @@
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);

View File

@ -5,7 +5,8 @@
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 {

View File

@ -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

View File

@ -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

View File

@ -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);
}
}

View File

@ -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();

View File

@ -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

View File

@ -0,0 +1,30 @@
/*
* 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() {}
}

View File

@ -5,6 +5,7 @@
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() {}
}

View File

@ -5,14 +5,35 @@
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 ? ?"