InstrumentationConfig part 4: DB sanitization (#6317)
* InstrumentationConfig part 4: DB sanitization * fix couchbase unit tests * code review comments Co-authored-by: Trask Stalnaker <trask.stalnaker@gmail.com>
This commit is contained in:
parent
3af56e7d22
commit
8d1ba17d29
|
@ -38,22 +38,4 @@ tasks {
|
||||||
sourcesJar {
|
sourcesJar {
|
||||||
dependsOn("generateJflex")
|
dependsOn("generateJflex")
|
||||||
}
|
}
|
||||||
|
|
||||||
val testStatementSanitizerConfig by registering(Test::class) {
|
|
||||||
filter {
|
|
||||||
includeTestsMatching("StatementSanitizationConfigTest")
|
|
||||||
}
|
|
||||||
include("**/StatementSanitizationConfigTest.*")
|
|
||||||
jvmArgs("-Dotel.instrumentation.common.db-statement-sanitizer.enabled=false")
|
|
||||||
}
|
|
||||||
|
|
||||||
test {
|
|
||||||
filter {
|
|
||||||
excludeTestsMatching("StatementSanitizationConfigTest")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
check {
|
|
||||||
dependsOn(testStatementSanitizerConfig)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,10 +8,6 @@ package io.opentelemetry.instrumentation.api.db;
|
||||||
import static java.util.Arrays.asList;
|
import static java.util.Arrays.asList;
|
||||||
import static java.util.Collections.unmodifiableMap;
|
import static java.util.Collections.unmodifiableMap;
|
||||||
|
|
||||||
import io.opentelemetry.instrumentation.api.db.RedisCommandSanitizer.CommandSanitizer.CommandAndNumArgs;
|
|
||||||
import io.opentelemetry.instrumentation.api.db.RedisCommandSanitizer.CommandSanitizer.Eval;
|
|
||||||
import io.opentelemetry.instrumentation.api.db.RedisCommandSanitizer.CommandSanitizer.KeepAllArgs;
|
|
||||||
import io.opentelemetry.instrumentation.api.db.RedisCommandSanitizer.CommandSanitizer.MultiKeyValue;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -353,8 +349,18 @@ public final class RedisCommandSanitizer {
|
||||||
SANITIZERS = unmodifiableMap(sanitizers);
|
SANITIZERS = unmodifiableMap(sanitizers);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String sanitize(String command, List<?> args) {
|
public static RedisCommandSanitizer create(boolean statementSanitizationEnabled) {
|
||||||
if (!StatementSanitizationConfig.isStatementSanitizationEnabled()) {
|
return new RedisCommandSanitizer(statementSanitizationEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final boolean statementSanitizationEnabled;
|
||||||
|
|
||||||
|
private RedisCommandSanitizer(boolean statementSanitizationEnabled) {
|
||||||
|
this.statementSanitizationEnabled = statementSanitizationEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String sanitize(String command, List<?> args) {
|
||||||
|
if (!statementSanitizationEnabled) {
|
||||||
return KeepAllArgs.INSTANCE.sanitize(command, args);
|
return KeepAllArgs.INSTANCE.sanitize(command, args);
|
||||||
}
|
}
|
||||||
return SANITIZERS
|
return SANITIZERS
|
||||||
|
@ -362,107 +368,105 @@ public final class RedisCommandSanitizer {
|
||||||
.sanitize(command, args);
|
.sanitize(command, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface CommandSanitizer {
|
interface CommandSanitizer {
|
||||||
String sanitize(String command, List<?> args);
|
String sanitize(String command, List<?> args);
|
||||||
|
}
|
||||||
|
|
||||||
static String argToString(Object arg) {
|
enum KeepAllArgs implements CommandSanitizer {
|
||||||
if (arg instanceof byte[]) {
|
INSTANCE;
|
||||||
return new String((byte[]) arg, StandardCharsets.UTF_8);
|
|
||||||
} else {
|
@Override
|
||||||
return String.valueOf(arg);
|
public String sanitize(String command, List<?> args) {
|
||||||
}
|
StringBuilder sanitized = new StringBuilder(command);
|
||||||
}
|
for (Object arg : args) {
|
||||||
|
sanitized.append(" ").append(argToString(arg));
|
||||||
enum KeepAllArgs implements CommandSanitizer {
|
|
||||||
INSTANCE;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String sanitize(String command, List<?> args) {
|
|
||||||
StringBuilder sanitized = new StringBuilder(command);
|
|
||||||
for (Object arg : args) {
|
|
||||||
sanitized.append(" ").append(argToString(arg));
|
|
||||||
}
|
|
||||||
return sanitized.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// keeps only a chosen number of arguments
|
|
||||||
// example for num=2: CMD arg1 arg2 ? ?
|
|
||||||
class CommandAndNumArgs implements CommandSanitizer {
|
|
||||||
private final int numOfArgsToKeep;
|
|
||||||
|
|
||||||
public CommandAndNumArgs(int numOfArgsToKeep) {
|
|
||||||
this.numOfArgsToKeep = numOfArgsToKeep;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String sanitize(String command, List<?> args) {
|
|
||||||
StringBuilder sanitized = new StringBuilder(command);
|
|
||||||
for (int i = 0; i < numOfArgsToKeep && i < args.size(); ++i) {
|
|
||||||
sanitized.append(" ").append(argToString(args.get(i)));
|
|
||||||
}
|
|
||||||
for (int i = numOfArgsToKeep; i < args.size(); ++i) {
|
|
||||||
sanitized.append(" ?");
|
|
||||||
}
|
|
||||||
return sanitized.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// keeps only chosen number of arguments and then every second one
|
|
||||||
// example for num=2: CMD arg1 arg2 key1 ? key2 ?
|
|
||||||
class MultiKeyValue implements CommandSanitizer {
|
|
||||||
private final int numOfArgsBeforeKeyValue;
|
|
||||||
|
|
||||||
public MultiKeyValue(int numOfArgsBeforeKeyValue) {
|
|
||||||
this.numOfArgsBeforeKeyValue = numOfArgsBeforeKeyValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String sanitize(String command, List<?> args) {
|
|
||||||
StringBuilder sanitized = new StringBuilder(command);
|
|
||||||
// append all "initial" arguments before key-value pairs start
|
|
||||||
for (int i = 0; i < numOfArgsBeforeKeyValue && i < args.size(); ++i) {
|
|
||||||
sanitized.append(" ").append(argToString(args.get(i)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// loop over keys only
|
|
||||||
for (int i = numOfArgsBeforeKeyValue; i < args.size(); i += 2) {
|
|
||||||
sanitized.append(" ").append(argToString(args.get(i))).append(" ?");
|
|
||||||
}
|
|
||||||
return sanitized.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Eval implements CommandSanitizer {
|
|
||||||
INSTANCE;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String sanitize(String command, List<?> args) {
|
|
||||||
StringBuilder sanitized = 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(argToString(args.get(1)));
|
|
||||||
} catch (NumberFormatException ignored) {
|
|
||||||
// Ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
// log the script, number of keys and all keys
|
|
||||||
for (; i < (numberOfKeys + 2) && i < args.size(); ++i) {
|
|
||||||
sanitized.append(" ").append(argToString(args.get(i)));
|
|
||||||
}
|
|
||||||
// mask the rest
|
|
||||||
for (; i < args.size(); ++i) {
|
|
||||||
sanitized.append(" ?");
|
|
||||||
}
|
|
||||||
return sanitized.toString();
|
|
||||||
}
|
}
|
||||||
|
return sanitized.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private RedisCommandSanitizer() {}
|
// keeps only a chosen number of arguments
|
||||||
|
// example for num=2: CMD arg1 arg2 ? ?
|
||||||
|
static final class CommandAndNumArgs implements CommandSanitizer {
|
||||||
|
private final int numOfArgsToKeep;
|
||||||
|
|
||||||
|
CommandAndNumArgs(int numOfArgsToKeep) {
|
||||||
|
this.numOfArgsToKeep = numOfArgsToKeep;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String sanitize(String command, List<?> args) {
|
||||||
|
StringBuilder sanitized = new StringBuilder(command);
|
||||||
|
for (int i = 0; i < numOfArgsToKeep && i < args.size(); ++i) {
|
||||||
|
sanitized.append(" ").append(argToString(args.get(i)));
|
||||||
|
}
|
||||||
|
for (int i = numOfArgsToKeep; i < args.size(); ++i) {
|
||||||
|
sanitized.append(" ?");
|
||||||
|
}
|
||||||
|
return sanitized.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// keeps only chosen number of arguments and then every second one
|
||||||
|
// example for num=2: CMD arg1 arg2 key1 ? key2 ?
|
||||||
|
static final class MultiKeyValue implements CommandSanitizer {
|
||||||
|
private final int numOfArgsBeforeKeyValue;
|
||||||
|
|
||||||
|
MultiKeyValue(int numOfArgsBeforeKeyValue) {
|
||||||
|
this.numOfArgsBeforeKeyValue = numOfArgsBeforeKeyValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String sanitize(String command, List<?> args) {
|
||||||
|
StringBuilder sanitized = new StringBuilder(command);
|
||||||
|
// append all "initial" arguments before key-value pairs start
|
||||||
|
for (int i = 0; i < numOfArgsBeforeKeyValue && i < args.size(); ++i) {
|
||||||
|
sanitized.append(" ").append(argToString(args.get(i)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// loop over keys only
|
||||||
|
for (int i = numOfArgsBeforeKeyValue; i < args.size(); i += 2) {
|
||||||
|
sanitized.append(" ").append(argToString(args.get(i))).append(" ?");
|
||||||
|
}
|
||||||
|
return sanitized.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Eval implements CommandSanitizer {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String sanitize(String command, List<?> args) {
|
||||||
|
StringBuilder sanitized = 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(argToString(args.get(1)));
|
||||||
|
} catch (NumberFormatException ignored) {
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
// log the script, number of keys and all keys
|
||||||
|
for (; i < (numberOfKeys + 2) && i < args.size(); ++i) {
|
||||||
|
sanitized.append(" ").append(argToString(args.get(i)));
|
||||||
|
}
|
||||||
|
// mask the rest
|
||||||
|
for (; i < args.size(); ++i) {
|
||||||
|
sanitized.append(" ?");
|
||||||
|
}
|
||||||
|
return sanitized.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static String argToString(Object arg) {
|
||||||
|
if (arg instanceof byte[]) {
|
||||||
|
return new String((byte[]) arg, StandardCharsets.UTF_8);
|
||||||
|
} else {
|
||||||
|
return String.valueOf(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
|
|
||||||
package io.opentelemetry.instrumentation.api.db;
|
package io.opentelemetry.instrumentation.api.db;
|
||||||
|
|
||||||
import static io.opentelemetry.instrumentation.api.db.StatementSanitizationConfig.isStatementSanitizationEnabled;
|
|
||||||
import static io.opentelemetry.instrumentation.api.internal.SupportabilityMetrics.CounterNames.SQL_STATEMENT_SANITIZER_CACHE_MISS;
|
import static io.opentelemetry.instrumentation.api.internal.SupportabilityMetrics.CounterNames.SQL_STATEMENT_SANITIZER_CACHE_MISS;
|
||||||
|
|
||||||
import com.google.auto.value.AutoValue;
|
import com.google.auto.value.AutoValue;
|
||||||
|
@ -23,12 +22,22 @@ public final class SqlStatementSanitizer {
|
||||||
private static final Cache<CacheKey, SqlStatementInfo> sqlToStatementInfoCache =
|
private static final Cache<CacheKey, SqlStatementInfo> sqlToStatementInfoCache =
|
||||||
Cache.bounded(1000);
|
Cache.bounded(1000);
|
||||||
|
|
||||||
public static SqlStatementInfo sanitize(@Nullable String statement) {
|
public static SqlStatementSanitizer create(boolean statementSanitizationEnabled) {
|
||||||
|
return new SqlStatementSanitizer(statementSanitizationEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final boolean statementSanitizationEnabled;
|
||||||
|
|
||||||
|
private SqlStatementSanitizer(boolean statementSanitizationEnabled) {
|
||||||
|
this.statementSanitizationEnabled = statementSanitizationEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SqlStatementInfo sanitize(@Nullable String statement) {
|
||||||
return sanitize(statement, SqlDialect.DEFAULT);
|
return sanitize(statement, SqlDialect.DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SqlStatementInfo sanitize(@Nullable String statement, SqlDialect dialect) {
|
public SqlStatementInfo sanitize(@Nullable String statement, SqlDialect dialect) {
|
||||||
if (!isStatementSanitizationEnabled() || statement == null) {
|
if (!statementSanitizationEnabled || statement == null) {
|
||||||
return SqlStatementInfo.create(statement, null, null);
|
return SqlStatementInfo.create(statement, null, null);
|
||||||
}
|
}
|
||||||
return sqlToStatementInfoCache.computeIfAbsent(
|
return sqlToStatementInfoCache.computeIfAbsent(
|
||||||
|
@ -50,6 +59,4 @@ public final class SqlStatementSanitizer {
|
||||||
|
|
||||||
abstract SqlDialect getDialect();
|
abstract SqlDialect getDialect();
|
||||||
}
|
}
|
||||||
|
|
||||||
private SqlStatementSanitizer() {}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright The OpenTelemetry Authors
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.opentelemetry.instrumentation.api.db;
|
|
||||||
|
|
||||||
import io.opentelemetry.instrumentation.api.config.Config;
|
|
||||||
|
|
||||||
/** DB statement sanitization is always enabled by default, you have to manually disable it. */
|
|
||||||
final class StatementSanitizationConfig {
|
|
||||||
|
|
||||||
private static final boolean STATEMENT_SANITIZATION_ENABLED =
|
|
||||||
Config.get().getBoolean("otel.instrumentation.common.db-statement-sanitizer.enabled", true);
|
|
||||||
|
|
||||||
static boolean isStatementSanitizationEnabled() {
|
|
||||||
return STATEMENT_SANITIZATION_ENABLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
private StatementSanitizationConfig() {}
|
|
||||||
}
|
|
|
@ -82,6 +82,9 @@ public abstract class DbClientSpanNameExtractor<REQUEST> implements SpanNameExtr
|
||||||
private static final class SqlClientSpanNameExtractor<REQUEST>
|
private static final class SqlClientSpanNameExtractor<REQUEST>
|
||||||
extends DbClientSpanNameExtractor<REQUEST> {
|
extends DbClientSpanNameExtractor<REQUEST> {
|
||||||
|
|
||||||
|
// a dedicated sanitizer just for extracting the operation and table name
|
||||||
|
private static final SqlStatementSanitizer sanitizer = SqlStatementSanitizer.create(true);
|
||||||
|
|
||||||
private final SqlClientAttributesGetter<REQUEST> getter;
|
private final SqlClientAttributesGetter<REQUEST> getter;
|
||||||
|
|
||||||
private SqlClientSpanNameExtractor(SqlClientAttributesGetter<REQUEST> getter) {
|
private SqlClientSpanNameExtractor(SqlClientAttributesGetter<REQUEST> getter) {
|
||||||
|
@ -91,8 +94,7 @@ public abstract class DbClientSpanNameExtractor<REQUEST> implements SpanNameExtr
|
||||||
@Override
|
@Override
|
||||||
public String extract(REQUEST request) {
|
public String extract(REQUEST request) {
|
||||||
String dbName = getter.name(request);
|
String dbName = getter.name(request);
|
||||||
SqlStatementInfo sanitizedStatement =
|
SqlStatementInfo sanitizedStatement = sanitizer.sanitize(getter.rawStatement(request));
|
||||||
SqlStatementSanitizer.sanitize(getter.rawStatement(request));
|
|
||||||
return computeSpanName(
|
return computeSpanName(
|
||||||
dbName, sanitizedStatement.getOperation(), sanitizedStatement.getTable());
|
dbName, sanitizedStatement.getOperation(), sanitizedStatement.getTable());
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,19 +44,22 @@ public final class SqlClientAttributesExtractor<REQUEST, RESPONSE>
|
||||||
}
|
}
|
||||||
|
|
||||||
private final AttributeKey<String> dbTableAttribute;
|
private final AttributeKey<String> dbTableAttribute;
|
||||||
|
private final SqlStatementSanitizer sanitizer;
|
||||||
|
|
||||||
SqlClientAttributesExtractor(
|
SqlClientAttributesExtractor(
|
||||||
SqlClientAttributesGetter<REQUEST> getter, AttributeKey<String> dbTableAttribute) {
|
SqlClientAttributesGetter<REQUEST> getter,
|
||||||
|
AttributeKey<String> dbTableAttribute,
|
||||||
|
SqlStatementSanitizer sanitizer) {
|
||||||
super(getter);
|
super(getter);
|
||||||
this.dbTableAttribute = dbTableAttribute;
|
this.dbTableAttribute = dbTableAttribute;
|
||||||
|
this.sanitizer = sanitizer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStart(AttributesBuilder attributes, Context parentContext, REQUEST request) {
|
public void onStart(AttributesBuilder attributes, Context parentContext, REQUEST request) {
|
||||||
super.onStart(attributes, parentContext, request);
|
super.onStart(attributes, parentContext, request);
|
||||||
|
|
||||||
SqlStatementInfo sanitizedStatement =
|
SqlStatementInfo sanitizedStatement = sanitizer.sanitize(getter.rawStatement(request));
|
||||||
SqlStatementSanitizer.sanitize(getter.rawStatement(request));
|
|
||||||
internalSet(attributes, SemanticAttributes.DB_STATEMENT, sanitizedStatement.getFullStatement());
|
internalSet(attributes, SemanticAttributes.DB_STATEMENT, sanitizedStatement.getFullStatement());
|
||||||
internalSet(attributes, SemanticAttributes.DB_OPERATION, sanitizedStatement.getOperation());
|
internalSet(attributes, SemanticAttributes.DB_OPERATION, sanitizedStatement.getOperation());
|
||||||
internalSet(attributes, dbTableAttribute, sanitizedStatement.getTable());
|
internalSet(attributes, dbTableAttribute, sanitizedStatement.getTable());
|
||||||
|
|
|
@ -8,6 +8,7 @@ package io.opentelemetry.instrumentation.api.instrumenter.db;
|
||||||
import static java.util.Objects.requireNonNull;
|
import static java.util.Objects.requireNonNull;
|
||||||
|
|
||||||
import io.opentelemetry.api.common.AttributeKey;
|
import io.opentelemetry.api.common.AttributeKey;
|
||||||
|
import io.opentelemetry.instrumentation.api.db.SqlStatementSanitizer;
|
||||||
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
|
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
|
||||||
|
|
||||||
/** A builder of {@link SqlClientAttributesExtractor}. */
|
/** A builder of {@link SqlClientAttributesExtractor}. */
|
||||||
|
@ -15,6 +16,7 @@ public final class SqlClientAttributesExtractorBuilder<REQUEST, RESPONSE> {
|
||||||
|
|
||||||
final SqlClientAttributesGetter<REQUEST> getter;
|
final SqlClientAttributesGetter<REQUEST> getter;
|
||||||
AttributeKey<String> dbTableAttribute = SemanticAttributes.DB_SQL_TABLE;
|
AttributeKey<String> dbTableAttribute = SemanticAttributes.DB_SQL_TABLE;
|
||||||
|
boolean statementSanitizationEnabled = true;
|
||||||
|
|
||||||
SqlClientAttributesExtractorBuilder(SqlClientAttributesGetter<REQUEST> getter) {
|
SqlClientAttributesExtractorBuilder(SqlClientAttributesGetter<REQUEST> getter) {
|
||||||
this.getter = getter;
|
this.getter = getter;
|
||||||
|
@ -34,11 +36,23 @@ public final class SqlClientAttributesExtractorBuilder<REQUEST, RESPONSE> {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the {@code db.statement} attribute extracted by the constructed {@link
|
||||||
|
* SqlClientAttributesExtractor} should be sanitized. If set to {@code true}, all parameters that
|
||||||
|
* can potentially contain sensitive information will be masked. Enabled by default.
|
||||||
|
*/
|
||||||
|
public SqlClientAttributesExtractorBuilder<REQUEST, RESPONSE> setStatementSanitizationEnabled(
|
||||||
|
boolean statementSanitizationEnabled) {
|
||||||
|
this.statementSanitizationEnabled = statementSanitizationEnabled;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new {@link SqlClientAttributesExtractor} with the settings of this {@link
|
* Returns a new {@link SqlClientAttributesExtractor} with the settings of this {@link
|
||||||
* SqlClientAttributesExtractorBuilder}.
|
* SqlClientAttributesExtractorBuilder}.
|
||||||
*/
|
*/
|
||||||
public SqlClientAttributesExtractor<REQUEST, RESPONSE> build() {
|
public SqlClientAttributesExtractor<REQUEST, RESPONSE> build() {
|
||||||
return new SqlClientAttributesExtractor<>(getter, dbTableAttribute);
|
return new SqlClientAttributesExtractor<>(
|
||||||
|
getter, dbTableAttribute, SqlStatementSanitizer.create(statementSanitizationEnabled));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ class RedisCommandSanitizerTest extends Specification {
|
||||||
@Unroll
|
@Unroll
|
||||||
def "should sanitize #expected"() {
|
def "should sanitize #expected"() {
|
||||||
when:
|
when:
|
||||||
def sanitized = RedisCommandSanitizer.sanitize(command, args)
|
def sanitized = RedisCommandSanitizer.create(true).sanitize(command, args)
|
||||||
|
|
||||||
then:
|
then:
|
||||||
sanitized == expected
|
sanitized == expected
|
||||||
|
@ -90,7 +90,7 @@ class RedisCommandSanitizerTest extends Specification {
|
||||||
def args = ["arg1", "arg 2"]
|
def args = ["arg1", "arg 2"]
|
||||||
|
|
||||||
when:
|
when:
|
||||||
def sanitized = RedisCommandSanitizer.sanitize(command, args)
|
def sanitized = RedisCommandSanitizer.create(true).sanitize(command, args)
|
||||||
|
|
||||||
then:
|
then:
|
||||||
sanitized == command + " " + args.join(" ")
|
sanitized == command + " " + args.join(" ")
|
||||||
|
@ -140,7 +140,7 @@ class RedisCommandSanitizerTest extends Specification {
|
||||||
|
|
||||||
def "should mask all arguments of an unknown command"() {
|
def "should mask all arguments of an unknown command"() {
|
||||||
when:
|
when:
|
||||||
def sanitized = RedisCommandSanitizer.sanitize("NEWAUTH", ["password", "secret"])
|
def sanitized = RedisCommandSanitizer.create(true).sanitize("NEWAUTH", ["password", "secret"])
|
||||||
|
|
||||||
then:
|
then:
|
||||||
sanitized == "NEWAUTH ? ?"
|
sanitized == "NEWAUTH ? ?"
|
||||||
|
|
|
@ -12,7 +12,7 @@ class SqlStatementSanitizerTest extends Specification {
|
||||||
|
|
||||||
def "normalize #originalSql"() {
|
def "normalize #originalSql"() {
|
||||||
setup:
|
setup:
|
||||||
def actualSanitized = SqlStatementSanitizer.sanitize(originalSql)
|
def actualSanitized = SqlStatementSanitizer.create(true).sanitize(originalSql)
|
||||||
|
|
||||||
expect:
|
expect:
|
||||||
actualSanitized.getFullStatement() == sanitizedSql
|
actualSanitized.getFullStatement() == sanitizedSql
|
||||||
|
@ -79,7 +79,7 @@ class SqlStatementSanitizerTest extends Specification {
|
||||||
|
|
||||||
def "normalize couchbase #originalSql"() {
|
def "normalize couchbase #originalSql"() {
|
||||||
setup:
|
setup:
|
||||||
def actualSanitized = SqlStatementSanitizer.sanitize(originalSql, SqlDialect.COUCHBASE)
|
def actualSanitized = SqlStatementSanitizer.create(true).sanitize(originalSql, SqlDialect.COUCHBASE)
|
||||||
|
|
||||||
expect:
|
expect:
|
||||||
actualSanitized.getFullStatement() == sanitizedSql
|
actualSanitized.getFullStatement() == sanitizedSql
|
||||||
|
@ -99,7 +99,7 @@ class SqlStatementSanitizerTest extends Specification {
|
||||||
@Unroll
|
@Unroll
|
||||||
def "should simplify #sql"() {
|
def "should simplify #sql"() {
|
||||||
expect:
|
expect:
|
||||||
SqlStatementSanitizer.sanitize(sql) == expected
|
SqlStatementSanitizer.create(true).sanitize(sql) == expected
|
||||||
|
|
||||||
where:
|
where:
|
||||||
sql | expected
|
sql | expected
|
||||||
|
@ -169,14 +169,14 @@ class SqlStatementSanitizerTest extends Specification {
|
||||||
|
|
||||||
expect:
|
expect:
|
||||||
def sanitizedQuery = query.replace('=123', '=?').substring(0, AutoSqlSanitizer.LIMIT)
|
def sanitizedQuery = query.replace('=123', '=?').substring(0, AutoSqlSanitizer.LIMIT)
|
||||||
SqlStatementSanitizer.sanitize(query) == SqlStatementInfo.create(sanitizedQuery, "SELECT", "table")
|
SqlStatementSanitizer.create(true).sanitize(query) == SqlStatementInfo.create(sanitizedQuery, "SELECT", "table")
|
||||||
}
|
}
|
||||||
|
|
||||||
def "lots and lots of ticks don't cause stack overflow or long runtimes"() {
|
def "lots and lots of ticks don't cause stack overflow or long runtimes"() {
|
||||||
setup:
|
setup:
|
||||||
String s = "'"
|
String s = "'"
|
||||||
for (int i = 0; i < 10000; i++) {
|
for (int i = 0; i < 10000; i++) {
|
||||||
assert SqlStatementSanitizer.sanitize(s) != null
|
assert SqlStatementSanitizer.create(true).sanitize(s) != null
|
||||||
s += "'"
|
s += "'"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -187,7 +187,7 @@ class SqlStatementSanitizerTest extends Specification {
|
||||||
for (int i = 0; i < 10000; i++) {
|
for (int i = 0; i < 10000; i++) {
|
||||||
s += String.valueOf(i)
|
s += String.valueOf(i)
|
||||||
}
|
}
|
||||||
assert "?" == SqlStatementSanitizer.sanitize(s).getFullStatement()
|
assert "?" == SqlStatementSanitizer.create(true).sanitize(s).getFullStatement()
|
||||||
}
|
}
|
||||||
|
|
||||||
def "very long numbers at end of table name don't cause problem"() {
|
def "very long numbers at end of table name don't cause problem"() {
|
||||||
|
@ -196,7 +196,7 @@ class SqlStatementSanitizerTest extends Specification {
|
||||||
for (int i = 0; i < 10000; i++) {
|
for (int i = 0; i < 10000; i++) {
|
||||||
s += String.valueOf(i)
|
s += String.valueOf(i)
|
||||||
}
|
}
|
||||||
assert s.substring(0, AutoSqlSanitizer.LIMIT) == SqlStatementSanitizer.sanitize(s).getFullStatement()
|
assert s.substring(0, AutoSqlSanitizer.LIMIT) == SqlStatementSanitizer.create(true).sanitize(s).getFullStatement()
|
||||||
}
|
}
|
||||||
|
|
||||||
def "test 32k truncation"() {
|
def "test 32k truncation"() {
|
||||||
|
@ -205,7 +205,7 @@ class SqlStatementSanitizerTest extends Specification {
|
||||||
for (int i = 0; i < 10000; i++) {
|
for (int i = 0; i < 10000; i++) {
|
||||||
s.append("SELECT * FROM TABLE WHERE FIELD = 1234 AND ")
|
s.append("SELECT * FROM TABLE WHERE FIELD = 1234 AND ")
|
||||||
}
|
}
|
||||||
String sanitized = SqlStatementSanitizer.sanitize(s.toString()).getFullStatement()
|
String sanitized = SqlStatementSanitizer.create(true).sanitize(s.toString()).getFullStatement()
|
||||||
System.out.println(sanitized.length())
|
System.out.println(sanitized.length())
|
||||||
assert sanitized.length() <= AutoSqlSanitizer.LIMIT
|
assert sanitized.length() <= AutoSqlSanitizer.LIMIT
|
||||||
assert !sanitized.contains("1234")
|
assert !sanitized.contains("1234")
|
||||||
|
@ -219,7 +219,7 @@ class SqlStatementSanitizerTest extends Specification {
|
||||||
for (int c = 0; c < 1000; c++) {
|
for (int c = 0; c < 1000; c++) {
|
||||||
sb.append((char) r.nextInt((int) Character.MAX_VALUE))
|
sb.append((char) r.nextInt((int) Character.MAX_VALUE))
|
||||||
}
|
}
|
||||||
SqlStatementSanitizer.sanitize(sb.toString())
|
SqlStatementSanitizer.create(true).sanitize(sb.toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright The OpenTelemetry Authors
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.opentelemetry.instrumentation.api.db;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
public class StatementSanitizationConfigTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void shouldGetFalse() {
|
|
||||||
assertFalse(StatementSanitizationConfig.isStatementSanitizationEnabled());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -25,6 +25,7 @@ package io.opentelemetry.javaagent.instrumentation.apachecamel.decorators;
|
||||||
|
|
||||||
import io.opentelemetry.api.common.AttributesBuilder;
|
import io.opentelemetry.api.common.AttributesBuilder;
|
||||||
import io.opentelemetry.instrumentation.api.db.SqlStatementSanitizer;
|
import io.opentelemetry.instrumentation.api.db.SqlStatementSanitizer;
|
||||||
|
import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig;
|
||||||
import io.opentelemetry.javaagent.instrumentation.apachecamel.CamelDirection;
|
import io.opentelemetry.javaagent.instrumentation.apachecamel.CamelDirection;
|
||||||
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
|
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
@ -34,6 +35,9 @@ import org.apache.camel.Exchange;
|
||||||
|
|
||||||
class DbSpanDecorator extends BaseSpanDecorator {
|
class DbSpanDecorator extends BaseSpanDecorator {
|
||||||
|
|
||||||
|
private static final SqlStatementSanitizer sanitizer =
|
||||||
|
SqlStatementSanitizer.create(CommonConfig.get().isStatementSanitizationEnabled());
|
||||||
|
|
||||||
private final String component;
|
private final String component;
|
||||||
private final String system;
|
private final String system;
|
||||||
|
|
||||||
|
@ -65,19 +69,19 @@ class DbSpanDecorator extends BaseSpanDecorator {
|
||||||
case "cql":
|
case "cql":
|
||||||
Object cqlObj = exchange.getIn().getHeader("CamelCqlQuery");
|
Object cqlObj = exchange.getIn().getHeader("CamelCqlQuery");
|
||||||
if (cqlObj != null) {
|
if (cqlObj != null) {
|
||||||
return SqlStatementSanitizer.sanitize(cqlObj.toString()).getFullStatement();
|
return sanitizer.sanitize(cqlObj.toString()).getFullStatement();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
case "jdbc":
|
case "jdbc":
|
||||||
Object body = exchange.getIn().getBody();
|
Object body = exchange.getIn().getBody();
|
||||||
if (body instanceof String) {
|
if (body instanceof String) {
|
||||||
return SqlStatementSanitizer.sanitize((String) body).getFullStatement();
|
return sanitizer.sanitize((String) body).getFullStatement();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
case "sql":
|
case "sql":
|
||||||
Object sqlquery = exchange.getIn().getHeader("CamelSqlQuery");
|
Object sqlquery = exchange.getIn().getHeader("CamelSqlQuery");
|
||||||
if (sqlquery instanceof String) {
|
if (sqlquery instanceof String) {
|
||||||
return SqlStatementSanitizer.sanitize((String) sqlquery).getFullStatement();
|
return sanitizer.sanitize((String) sqlquery).getFullStatement();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -12,6 +12,7 @@ import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor;
|
||||||
import io.opentelemetry.instrumentation.api.instrumenter.db.DbClientSpanNameExtractor;
|
import io.opentelemetry.instrumentation.api.instrumenter.db.DbClientSpanNameExtractor;
|
||||||
import io.opentelemetry.instrumentation.api.instrumenter.db.SqlClientAttributesExtractor;
|
import io.opentelemetry.instrumentation.api.instrumenter.db.SqlClientAttributesExtractor;
|
||||||
import io.opentelemetry.instrumentation.api.instrumenter.net.NetClientAttributesExtractor;
|
import io.opentelemetry.instrumentation.api.instrumenter.net.NetClientAttributesExtractor;
|
||||||
|
import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig;
|
||||||
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
|
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
|
||||||
|
|
||||||
public final class CassandraSingletons {
|
public final class CassandraSingletons {
|
||||||
|
@ -32,6 +33,8 @@ public final class CassandraSingletons {
|
||||||
.addAttributesExtractor(
|
.addAttributesExtractor(
|
||||||
SqlClientAttributesExtractor.builder(attributesGetter)
|
SqlClientAttributesExtractor.builder(attributesGetter)
|
||||||
.setTableAttribute(SemanticAttributes.DB_CASSANDRA_TABLE)
|
.setTableAttribute(SemanticAttributes.DB_CASSANDRA_TABLE)
|
||||||
|
.setStatementSanitizationEnabled(
|
||||||
|
CommonConfig.get().isStatementSanitizationEnabled())
|
||||||
.build())
|
.build())
|
||||||
.addAttributesExtractor(
|
.addAttributesExtractor(
|
||||||
NetClientAttributesExtractor.create(new CassandraNetAttributesGetter()))
|
NetClientAttributesExtractor.create(new CassandraNetAttributesGetter()))
|
||||||
|
|
|
@ -12,6 +12,7 @@ import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor;
|
||||||
import io.opentelemetry.instrumentation.api.instrumenter.db.DbClientSpanNameExtractor;
|
import io.opentelemetry.instrumentation.api.instrumenter.db.DbClientSpanNameExtractor;
|
||||||
import io.opentelemetry.instrumentation.api.instrumenter.db.SqlClientAttributesExtractor;
|
import io.opentelemetry.instrumentation.api.instrumenter.db.SqlClientAttributesExtractor;
|
||||||
import io.opentelemetry.instrumentation.api.instrumenter.net.NetClientAttributesExtractor;
|
import io.opentelemetry.instrumentation.api.instrumenter.net.NetClientAttributesExtractor;
|
||||||
|
import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig;
|
||||||
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
|
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
|
||||||
|
|
||||||
public final class CassandraSingletons {
|
public final class CassandraSingletons {
|
||||||
|
@ -31,6 +32,8 @@ public final class CassandraSingletons {
|
||||||
.addAttributesExtractor(
|
.addAttributesExtractor(
|
||||||
SqlClientAttributesExtractor.builder(attributesGetter)
|
SqlClientAttributesExtractor.builder(attributesGetter)
|
||||||
.setTableAttribute(SemanticAttributes.DB_CASSANDRA_TABLE)
|
.setTableAttribute(SemanticAttributes.DB_CASSANDRA_TABLE)
|
||||||
|
.setStatementSanitizationEnabled(
|
||||||
|
CommonConfig.get().isStatementSanitizationEnabled())
|
||||||
.build())
|
.build())
|
||||||
.addAttributesExtractor(
|
.addAttributesExtractor(
|
||||||
NetClientAttributesExtractor.create(new CassandraNetAttributesGetter()))
|
NetClientAttributesExtractor.create(new CassandraNetAttributesGetter()))
|
||||||
|
|
|
@ -7,6 +7,7 @@ dependencies {
|
||||||
testImplementation("org.spockframework:spock-core")
|
testImplementation("org.spockframework:spock-core")
|
||||||
|
|
||||||
testImplementation(project(":instrumentation-api-semconv"))
|
testImplementation(project(":instrumentation-api-semconv"))
|
||||||
|
testImplementation(project(":javaagent-extension-api"))
|
||||||
testImplementation(project(":instrumentation:couchbase:couchbase-2-common:javaagent"))
|
testImplementation(project(":instrumentation:couchbase:couchbase-2-common:javaagent"))
|
||||||
testImplementation("com.couchbase.client:java-client:2.5.0")
|
testImplementation("com.couchbase.client:java-client:2.5.0")
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,12 +8,17 @@ package io.opentelemetry.javaagent.instrumentation.couchbase.v2_0;
|
||||||
import io.opentelemetry.instrumentation.api.db.SqlDialect;
|
import io.opentelemetry.instrumentation.api.db.SqlDialect;
|
||||||
import io.opentelemetry.instrumentation.api.db.SqlStatementInfo;
|
import io.opentelemetry.instrumentation.api.db.SqlStatementInfo;
|
||||||
import io.opentelemetry.instrumentation.api.db.SqlStatementSanitizer;
|
import io.opentelemetry.instrumentation.api.db.SqlStatementSanitizer;
|
||||||
|
import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig;
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
import java.lang.invoke.MethodType;
|
import java.lang.invoke.MethodType;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
public final class CouchbaseQuerySanitizer {
|
public final class CouchbaseQuerySanitizer {
|
||||||
|
|
||||||
|
private static final SqlStatementSanitizer sanitizer =
|
||||||
|
SqlStatementSanitizer.create(CommonConfig.get().isStatementSanitizationEnabled());
|
||||||
|
|
||||||
@Nullable private static final Class<?> QUERY_CLASS;
|
@Nullable private static final Class<?> QUERY_CLASS;
|
||||||
@Nullable private static final Class<?> STATEMENT_CLASS;
|
@Nullable private static final Class<?> STATEMENT_CLASS;
|
||||||
@Nullable private static final Class<?> N1QL_QUERY_CLASS;
|
@Nullable private static final Class<?> N1QL_QUERY_CLASS;
|
||||||
|
@ -116,7 +121,7 @@ public final class CouchbaseQuerySanitizer {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SqlStatementInfo sanitizeString(String query) {
|
private static SqlStatementInfo sanitizeString(String query) {
|
||||||
return SqlStatementSanitizer.sanitize(query, SqlDialect.COUCHBASE);
|
return sanitizer.sanitize(query, SqlDialect.COUCHBASE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private CouchbaseQuerySanitizer() {}
|
private CouchbaseQuerySanitizer() {}
|
||||||
|
|
|
@ -7,11 +7,15 @@ package io.opentelemetry.javaagent.instrumentation.geode;
|
||||||
|
|
||||||
import io.opentelemetry.instrumentation.api.db.SqlStatementSanitizer;
|
import io.opentelemetry.instrumentation.api.db.SqlStatementSanitizer;
|
||||||
import io.opentelemetry.instrumentation.api.instrumenter.db.DbClientAttributesGetter;
|
import io.opentelemetry.instrumentation.api.instrumenter.db.DbClientAttributesGetter;
|
||||||
|
import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig;
|
||||||
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
|
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
final class GeodeDbAttributesGetter implements DbClientAttributesGetter<GeodeRequest> {
|
final class GeodeDbAttributesGetter implements DbClientAttributesGetter<GeodeRequest> {
|
||||||
|
|
||||||
|
private static final SqlStatementSanitizer sanitizer =
|
||||||
|
SqlStatementSanitizer.create(CommonConfig.get().isStatementSanitizationEnabled());
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String system(GeodeRequest request) {
|
public String system(GeodeRequest request) {
|
||||||
return SemanticAttributes.DbSystemValues.GEODE;
|
return SemanticAttributes.DbSystemValues.GEODE;
|
||||||
|
@ -38,7 +42,7 @@ final class GeodeDbAttributesGetter implements DbClientAttributesGetter<GeodeReq
|
||||||
@Nullable
|
@Nullable
|
||||||
public String statement(GeodeRequest request) {
|
public String statement(GeodeRequest request) {
|
||||||
// sanitized statement is cached
|
// sanitized statement is cached
|
||||||
return SqlStatementSanitizer.sanitize(request.getQuery()).getFullStatement();
|
return sanitizer.sanitize(request.getQuery()).getFullStatement();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -7,15 +7,19 @@ package io.opentelemetry.javaagent.instrumentation.hibernate;
|
||||||
|
|
||||||
import io.opentelemetry.instrumentation.api.db.SqlStatementInfo;
|
import io.opentelemetry.instrumentation.api.db.SqlStatementInfo;
|
||||||
import io.opentelemetry.instrumentation.api.db.SqlStatementSanitizer;
|
import io.opentelemetry.instrumentation.api.db.SqlStatementSanitizer;
|
||||||
|
import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
public final class OperationNameUtil {
|
public final class OperationNameUtil {
|
||||||
|
|
||||||
|
private static final SqlStatementSanitizer sanitizer =
|
||||||
|
SqlStatementSanitizer.create(CommonConfig.get().isStatementSanitizationEnabled());
|
||||||
|
|
||||||
public static String getOperationNameForQuery(String query) {
|
public static String getOperationNameForQuery(String query) {
|
||||||
// set operation to default value that is used when sql sanitizer fails to extract
|
// set operation to default value that is used when sql sanitizer fails to extract
|
||||||
// operation name
|
// operation name
|
||||||
String operation = "Hibernate Query";
|
String operation = "Hibernate Query";
|
||||||
SqlStatementInfo info = SqlStatementSanitizer.sanitize(query);
|
SqlStatementInfo info = sanitizer.sanitize(query);
|
||||||
if (info.getOperation() != null) {
|
if (info.getOperation() != null) {
|
||||||
operation = info.getOperation();
|
operation = info.getOperation();
|
||||||
if (info.getTable() != null) {
|
if (info.getTable() != null) {
|
||||||
|
|
|
@ -31,7 +31,11 @@ public final class JdbcSingletons {
|
||||||
GlobalOpenTelemetry.get(),
|
GlobalOpenTelemetry.get(),
|
||||||
INSTRUMENTATION_NAME,
|
INSTRUMENTATION_NAME,
|
||||||
DbClientSpanNameExtractor.create(dbAttributesGetter))
|
DbClientSpanNameExtractor.create(dbAttributesGetter))
|
||||||
.addAttributesExtractor(SqlClientAttributesExtractor.create(dbAttributesGetter))
|
.addAttributesExtractor(
|
||||||
|
SqlClientAttributesExtractor.builder(dbAttributesGetter)
|
||||||
|
.setStatementSanitizationEnabled(
|
||||||
|
CommonConfig.get().isStatementSanitizationEnabled())
|
||||||
|
.build())
|
||||||
.addAttributesExtractor(NetClientAttributesExtractor.create(netAttributesGetter))
|
.addAttributesExtractor(NetClientAttributesExtractor.create(netAttributesGetter))
|
||||||
.addAttributesExtractor(
|
.addAttributesExtractor(
|
||||||
PeerServiceAttributesExtractor.create(
|
PeerServiceAttributesExtractor.create(
|
||||||
|
|
|
@ -11,6 +11,7 @@ import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor;
|
||||||
import io.opentelemetry.instrumentation.api.instrumenter.db.DbClientSpanNameExtractor;
|
import io.opentelemetry.instrumentation.api.instrumenter.db.DbClientSpanNameExtractor;
|
||||||
import io.opentelemetry.instrumentation.api.instrumenter.db.SqlClientAttributesExtractor;
|
import io.opentelemetry.instrumentation.api.instrumenter.db.SqlClientAttributesExtractor;
|
||||||
import io.opentelemetry.instrumentation.api.instrumenter.net.NetClientAttributesExtractor;
|
import io.opentelemetry.instrumentation.api.instrumenter.net.NetClientAttributesExtractor;
|
||||||
|
import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
|
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
|
||||||
|
@ -30,7 +31,12 @@ public final class JdbcSingletons {
|
||||||
GlobalOpenTelemetry.get(),
|
GlobalOpenTelemetry.get(),
|
||||||
INSTRUMENTATION_NAME,
|
INSTRUMENTATION_NAME,
|
||||||
DbClientSpanNameExtractor.create(dbAttributesGetter))
|
DbClientSpanNameExtractor.create(dbAttributesGetter))
|
||||||
.addAttributesExtractor(SqlClientAttributesExtractor.create(dbAttributesGetter))
|
.addAttributesExtractor(
|
||||||
|
SqlClientAttributesExtractor.builder(dbAttributesGetter)
|
||||||
|
.setStatementSanitizationEnabled(
|
||||||
|
ConfigPropertiesUtil.getBoolean(
|
||||||
|
"otel.instrumentation.common.db-statement-sanitizer.enabled", true))
|
||||||
|
.build())
|
||||||
.addAttributesExtractor(NetClientAttributesExtractor.create(netAttributesGetter))
|
.addAttributesExtractor(NetClientAttributesExtractor.create(netAttributesGetter))
|
||||||
.newInstrumenter(SpanKindExtractor.alwaysClient());
|
.newInstrumenter(SpanKindExtractor.alwaysClient());
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,11 +7,15 @@ package io.opentelemetry.javaagent.instrumentation.jedis.v1_4;
|
||||||
|
|
||||||
import io.opentelemetry.instrumentation.api.db.RedisCommandSanitizer;
|
import io.opentelemetry.instrumentation.api.db.RedisCommandSanitizer;
|
||||||
import io.opentelemetry.instrumentation.api.instrumenter.db.DbClientAttributesGetter;
|
import io.opentelemetry.instrumentation.api.instrumenter.db.DbClientAttributesGetter;
|
||||||
|
import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig;
|
||||||
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
|
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
final class JedisDbAttributesGetter implements DbClientAttributesGetter<JedisRequest> {
|
final class JedisDbAttributesGetter implements DbClientAttributesGetter<JedisRequest> {
|
||||||
|
|
||||||
|
private static final RedisCommandSanitizer sanitizer =
|
||||||
|
RedisCommandSanitizer.create(CommonConfig.get().isStatementSanitizationEnabled());
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String system(JedisRequest request) {
|
public String system(JedisRequest request) {
|
||||||
return SemanticAttributes.DbSystemValues.REDIS;
|
return SemanticAttributes.DbSystemValues.REDIS;
|
||||||
|
@ -35,7 +39,7 @@ final class JedisDbAttributesGetter implements DbClientAttributesGetter<JedisReq
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String statement(JedisRequest request) {
|
public String statement(JedisRequest request) {
|
||||||
return RedisCommandSanitizer.sanitize(request.getCommand().name(), request.getArgs());
|
return sanitizer.sanitize(request.getCommand().name(), request.getArgs());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -7,6 +7,7 @@ package io.opentelemetry.javaagent.instrumentation.jedis.v3_0;
|
||||||
|
|
||||||
import com.google.auto.value.AutoValue;
|
import com.google.auto.value.AutoValue;
|
||||||
import io.opentelemetry.instrumentation.api.db.RedisCommandSanitizer;
|
import io.opentelemetry.instrumentation.api.db.RedisCommandSanitizer;
|
||||||
|
import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import redis.clients.jedis.Connection;
|
import redis.clients.jedis.Connection;
|
||||||
|
@ -16,6 +17,9 @@ import redis.clients.jedis.commands.ProtocolCommand;
|
||||||
@AutoValue
|
@AutoValue
|
||||||
public abstract class JedisRequest {
|
public abstract class JedisRequest {
|
||||||
|
|
||||||
|
private static final RedisCommandSanitizer sanitizer =
|
||||||
|
RedisCommandSanitizer.create(CommonConfig.get().isStatementSanitizationEnabled());
|
||||||
|
|
||||||
public static JedisRequest create(
|
public static JedisRequest create(
|
||||||
Connection connection, ProtocolCommand command, List<byte[]> args) {
|
Connection connection, ProtocolCommand command, List<byte[]> args) {
|
||||||
return new AutoValue_JedisRequest(connection, command, args);
|
return new AutoValue_JedisRequest(connection, command, args);
|
||||||
|
@ -39,6 +43,6 @@ public abstract class JedisRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getStatement() {
|
public String getStatement() {
|
||||||
return RedisCommandSanitizer.sanitize(getOperation(), getArgs());
|
return sanitizer.sanitize(getOperation(), getArgs());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ package io.opentelemetry.javaagent.instrumentation.jedis.v4_0;
|
||||||
|
|
||||||
import com.google.auto.value.AutoValue;
|
import com.google.auto.value.AutoValue;
|
||||||
import io.opentelemetry.instrumentation.api.db.RedisCommandSanitizer;
|
import io.opentelemetry.instrumentation.api.db.RedisCommandSanitizer;
|
||||||
|
import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
@ -20,6 +21,9 @@ import redis.clients.jedis.commands.ProtocolCommand;
|
||||||
@AutoValue
|
@AutoValue
|
||||||
public abstract class JedisRequest {
|
public abstract class JedisRequest {
|
||||||
|
|
||||||
|
private static final RedisCommandSanitizer sanitizer =
|
||||||
|
RedisCommandSanitizer.create(CommonConfig.get().isStatementSanitizationEnabled());
|
||||||
|
|
||||||
public static JedisRequest create(ProtocolCommand command, List<byte[]> args) {
|
public static JedisRequest create(ProtocolCommand command, List<byte[]> args) {
|
||||||
return new AutoValue_JedisRequest(command, args);
|
return new AutoValue_JedisRequest(command, args);
|
||||||
}
|
}
|
||||||
|
@ -54,7 +58,7 @@ public abstract class JedisRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getStatement() {
|
public String getStatement() {
|
||||||
return RedisCommandSanitizer.sanitize(getOperation(), getArgs());
|
return sanitizer.sanitize(getOperation(), getArgs());
|
||||||
}
|
}
|
||||||
|
|
||||||
private SocketAddress remoteSocketAddress;
|
private SocketAddress remoteSocketAddress;
|
||||||
|
|
|
@ -9,6 +9,7 @@ import io.lettuce.core.protocol.RedisCommand;
|
||||||
import io.opentelemetry.instrumentation.api.db.RedisCommandSanitizer;
|
import io.opentelemetry.instrumentation.api.db.RedisCommandSanitizer;
|
||||||
import io.opentelemetry.instrumentation.api.instrumenter.db.DbClientAttributesGetter;
|
import io.opentelemetry.instrumentation.api.instrumenter.db.DbClientAttributesGetter;
|
||||||
import io.opentelemetry.instrumentation.lettuce.common.LettuceArgSplitter;
|
import io.opentelemetry.instrumentation.lettuce.common.LettuceArgSplitter;
|
||||||
|
import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig;
|
||||||
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
|
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -16,6 +17,9 @@ import javax.annotation.Nullable;
|
||||||
|
|
||||||
final class LettuceDbAttributesGetter implements DbClientAttributesGetter<RedisCommand<?, ?, ?>> {
|
final class LettuceDbAttributesGetter implements DbClientAttributesGetter<RedisCommand<?, ?, ?>> {
|
||||||
|
|
||||||
|
private static final RedisCommandSanitizer sanitizer =
|
||||||
|
RedisCommandSanitizer.create(CommonConfig.get().isStatementSanitizationEnabled());
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String system(RedisCommand<?, ?, ?> request) {
|
public String system(RedisCommand<?, ?, ?> request) {
|
||||||
return SemanticAttributes.DbSystemValues.REDIS;
|
return SemanticAttributes.DbSystemValues.REDIS;
|
||||||
|
@ -46,7 +50,7 @@ final class LettuceDbAttributesGetter implements DbClientAttributesGetter<RedisC
|
||||||
request.getArgs() == null
|
request.getArgs() == null
|
||||||
? Collections.emptyList()
|
? Collections.emptyList()
|
||||||
: LettuceArgSplitter.splitArgs(request.getArgs().toCommandString());
|
: LettuceArgSplitter.splitArgs(request.getArgs().toCommandString());
|
||||||
return RedisCommandSanitizer.sanitize(command, args);
|
return sanitizer.sanitize(command, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -9,6 +9,7 @@ import io.lettuce.core.tracing.Tracing;
|
||||||
import io.opentelemetry.api.OpenTelemetry;
|
import io.opentelemetry.api.OpenTelemetry;
|
||||||
import io.opentelemetry.api.trace.Tracer;
|
import io.opentelemetry.api.trace.Tracer;
|
||||||
import io.opentelemetry.api.trace.TracerBuilder;
|
import io.opentelemetry.api.trace.TracerBuilder;
|
||||||
|
import io.opentelemetry.instrumentation.api.db.RedisCommandSanitizer;
|
||||||
import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties;
|
import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties;
|
||||||
|
|
||||||
/** Entrypoint for instrumenting Lettuce or clients. */
|
/** Entrypoint for instrumenting Lettuce or clients. */
|
||||||
|
@ -18,18 +19,27 @@ public final class LettuceTelemetry {
|
||||||
|
|
||||||
/** Returns a new {@link LettuceTelemetry} configured with the given {@link OpenTelemetry}. */
|
/** Returns a new {@link LettuceTelemetry} configured with the given {@link OpenTelemetry}. */
|
||||||
public static LettuceTelemetry create(OpenTelemetry openTelemetry) {
|
public static LettuceTelemetry create(OpenTelemetry openTelemetry) {
|
||||||
return new LettuceTelemetry(openTelemetry);
|
return builder(openTelemetry).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new {@link LettuceTelemetryBuilder} configured with the given {@link OpenTelemetry}.
|
||||||
|
*/
|
||||||
|
public static LettuceTelemetryBuilder builder(OpenTelemetry openTelemetry) {
|
||||||
|
return new LettuceTelemetryBuilder(openTelemetry);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Tracer tracer;
|
private final Tracer tracer;
|
||||||
|
private final RedisCommandSanitizer sanitizer;
|
||||||
|
|
||||||
private LettuceTelemetry(OpenTelemetry openTelemetry) {
|
LettuceTelemetry(OpenTelemetry openTelemetry, boolean statementSanitizationEnabled) {
|
||||||
TracerBuilder tracerBuilder = openTelemetry.tracerBuilder(INSTRUMENTATION_NAME);
|
TracerBuilder tracerBuilder = openTelemetry.tracerBuilder(INSTRUMENTATION_NAME);
|
||||||
String version = EmbeddedInstrumentationProperties.findVersion(INSTRUMENTATION_NAME);
|
String version = EmbeddedInstrumentationProperties.findVersion(INSTRUMENTATION_NAME);
|
||||||
if (version != null) {
|
if (version != null) {
|
||||||
tracerBuilder.setInstrumentationVersion(version);
|
tracerBuilder.setInstrumentationVersion(version);
|
||||||
}
|
}
|
||||||
tracer = tracerBuilder.build();
|
tracer = tracerBuilder.build();
|
||||||
|
sanitizer = RedisCommandSanitizer.create(statementSanitizationEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,6 +47,6 @@ public final class LettuceTelemetry {
|
||||||
* io.lettuce.core.resource.ClientResources.Builder#tracing(Tracing)}.
|
* io.lettuce.core.resource.ClientResources.Builder#tracing(Tracing)}.
|
||||||
*/
|
*/
|
||||||
public Tracing newTracing() {
|
public Tracing newTracing() {
|
||||||
return new OpenTelemetryTracing(tracer);
|
return new OpenTelemetryTracing(tracer, sanitizer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.instrumentation.lettuce.v5_1;
|
||||||
|
|
||||||
|
import io.opentelemetry.api.OpenTelemetry;
|
||||||
|
|
||||||
|
/** A builder of {@link LettuceTelemetry}. */
|
||||||
|
public final class LettuceTelemetryBuilder {
|
||||||
|
|
||||||
|
private final OpenTelemetry openTelemetry;
|
||||||
|
|
||||||
|
private boolean statementSanitizationEnabled = true;
|
||||||
|
|
||||||
|
LettuceTelemetryBuilder(OpenTelemetry openTelemetry) {
|
||||||
|
this.openTelemetry = openTelemetry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the {@code db.statement} attribute on the spans emitted by the constructed {@link
|
||||||
|
* LettuceTelemetry} should be sanitized. If set to {@code true}, all parameters that can
|
||||||
|
* potentially contain sensitive information will be masked. Enabled by default.
|
||||||
|
*/
|
||||||
|
public LettuceTelemetryBuilder setStatementSanitizationEnabled(
|
||||||
|
boolean statementSanitizationEnabled) {
|
||||||
|
this.statementSanitizationEnabled = statementSanitizationEnabled;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new {@link LettuceTelemetry} with the settings of this {@link
|
||||||
|
* LettuceTelemetryBuilder}.
|
||||||
|
*/
|
||||||
|
public LettuceTelemetry build() {
|
||||||
|
return new LettuceTelemetry(openTelemetry, statementSanitizationEnabled);
|
||||||
|
}
|
||||||
|
}
|
|
@ -40,8 +40,8 @@ final class OpenTelemetryTracing implements Tracing {
|
||||||
NetClientAttributesExtractor.create(new LettuceNetAttributesGetter());
|
NetClientAttributesExtractor.create(new LettuceNetAttributesGetter());
|
||||||
private final TracerProvider tracerProvider;
|
private final TracerProvider tracerProvider;
|
||||||
|
|
||||||
OpenTelemetryTracing(io.opentelemetry.api.trace.Tracer tracer) {
|
OpenTelemetryTracing(io.opentelemetry.api.trace.Tracer tracer, RedisCommandSanitizer sanitizer) {
|
||||||
this.tracerProvider = new OpenTelemetryTracerProvider(tracer);
|
this.tracerProvider = new OpenTelemetryTracerProvider(tracer, sanitizer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -81,8 +81,9 @@ final class OpenTelemetryTracing implements Tracing {
|
||||||
|
|
||||||
private final Tracer openTelemetryTracer;
|
private final Tracer openTelemetryTracer;
|
||||||
|
|
||||||
OpenTelemetryTracerProvider(io.opentelemetry.api.trace.Tracer tracer) {
|
OpenTelemetryTracerProvider(
|
||||||
openTelemetryTracer = new OpenTelemetryTracer(tracer);
|
io.opentelemetry.api.trace.Tracer tracer, RedisCommandSanitizer sanitizer) {
|
||||||
|
openTelemetryTracer = new OpenTelemetryTracer(tracer, sanitizer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -126,9 +127,11 @@ final class OpenTelemetryTracing implements Tracing {
|
||||||
private static class OpenTelemetryTracer extends Tracer {
|
private static class OpenTelemetryTracer extends Tracer {
|
||||||
|
|
||||||
private final io.opentelemetry.api.trace.Tracer tracer;
|
private final io.opentelemetry.api.trace.Tracer tracer;
|
||||||
|
private final RedisCommandSanitizer sanitizer;
|
||||||
|
|
||||||
OpenTelemetryTracer(io.opentelemetry.api.trace.Tracer tracer) {
|
OpenTelemetryTracer(io.opentelemetry.api.trace.Tracer tracer, RedisCommandSanitizer sanitizer) {
|
||||||
this.tracer = tracer;
|
this.tracer = tracer;
|
||||||
|
this.sanitizer = sanitizer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -155,7 +158,7 @@ final class OpenTelemetryTracing implements Tracing {
|
||||||
.setSpanKind(SpanKind.CLIENT)
|
.setSpanKind(SpanKind.CLIENT)
|
||||||
.setParent(context)
|
.setParent(context)
|
||||||
.setAttribute(SemanticAttributes.DB_SYSTEM, DbSystemValues.REDIS);
|
.setAttribute(SemanticAttributes.DB_SYSTEM, DbSystemValues.REDIS);
|
||||||
return new OpenTelemetrySpan(context, spanBuilder);
|
return new OpenTelemetrySpan(context, spanBuilder, sanitizer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,6 +170,7 @@ final class OpenTelemetryTracing implements Tracing {
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private final SpanBuilder spanBuilder;
|
private final SpanBuilder spanBuilder;
|
||||||
|
private final RedisCommandSanitizer sanitizer;
|
||||||
|
|
||||||
@Nullable private String name;
|
@Nullable private String name;
|
||||||
@Nullable private List<Object> events;
|
@Nullable private List<Object> events;
|
||||||
|
@ -174,9 +178,10 @@ final class OpenTelemetryTracing implements Tracing {
|
||||||
@Nullable private Span span;
|
@Nullable private Span span;
|
||||||
@Nullable private String args;
|
@Nullable private String args;
|
||||||
|
|
||||||
OpenTelemetrySpan(Context context, SpanBuilder spanBuilder) {
|
OpenTelemetrySpan(Context context, SpanBuilder spanBuilder, RedisCommandSanitizer sanitizer) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.spanBuilder = spanBuilder;
|
this.spanBuilder = spanBuilder;
|
||||||
|
this.sanitizer = sanitizer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -319,7 +324,7 @@ final class OpenTelemetryTracing implements Tracing {
|
||||||
|
|
||||||
private void finish(Span span) {
|
private void finish(Span span) {
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
String statement = RedisCommandSanitizer.sanitize(name, splitArgs(args));
|
String statement = sanitizer.sanitize(name, splitArgs(args));
|
||||||
span.setAttribute(SemanticAttributes.DB_STATEMENT, statement);
|
span.setAttribute(SemanticAttributes.DB_STATEMENT, statement);
|
||||||
}
|
}
|
||||||
span.end();
|
span.end();
|
||||||
|
|
|
@ -11,6 +11,7 @@ import static java.util.Collections.singletonList;
|
||||||
import com.google.auto.value.AutoValue;
|
import com.google.auto.value.AutoValue;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.opentelemetry.instrumentation.api.db.RedisCommandSanitizer;
|
import io.opentelemetry.instrumentation.api.db.RedisCommandSanitizer;
|
||||||
|
import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig;
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
import java.lang.invoke.MethodType;
|
import java.lang.invoke.MethodType;
|
||||||
|
@ -27,6 +28,9 @@ import org.redisson.client.protocol.CommandsData;
|
||||||
@AutoValue
|
@AutoValue
|
||||||
public abstract class RedissonRequest {
|
public abstract class RedissonRequest {
|
||||||
|
|
||||||
|
private static final RedisCommandSanitizer sanitizer =
|
||||||
|
RedisCommandSanitizer.create(CommonConfig.get().isStatementSanitizationEnabled());
|
||||||
|
|
||||||
public static RedissonRequest create(InetSocketAddress address, Object command) {
|
public static RedissonRequest create(InetSocketAddress address, Object command) {
|
||||||
return new AutoValue_RedissonRequest(address, command);
|
return new AutoValue_RedissonRequest(address, command);
|
||||||
}
|
}
|
||||||
|
@ -98,7 +102,7 @@ public abstract class RedissonRequest {
|
||||||
args.add(param);
|
args.add(param);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return RedisCommandSanitizer.sanitize(command.getCommand().getName(), args);
|
return sanitizer.sanitize(command.getCommand().getName(), args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|
|
@ -28,6 +28,7 @@ public final class CommonConfig {
|
||||||
private final List<String> clientResponseHeaders;
|
private final List<String> clientResponseHeaders;
|
||||||
private final List<String> serverRequestHeaders;
|
private final List<String> serverRequestHeaders;
|
||||||
private final List<String> serverResponseHeaders;
|
private final List<String> serverResponseHeaders;
|
||||||
|
private final boolean statementSanitizationEnabled;
|
||||||
|
|
||||||
CommonConfig(InstrumentationConfig config) {
|
CommonConfig(InstrumentationConfig config) {
|
||||||
peerServiceMapping =
|
peerServiceMapping =
|
||||||
|
@ -40,6 +41,8 @@ public final class CommonConfig {
|
||||||
config.getList("otel.instrumentation.http.capture-headers.server.request", emptyList());
|
config.getList("otel.instrumentation.http.capture-headers.server.request", emptyList());
|
||||||
serverResponseHeaders =
|
serverResponseHeaders =
|
||||||
config.getList("otel.instrumentation.http.capture-headers.server.response", emptyList());
|
config.getList("otel.instrumentation.http.capture-headers.server.response", emptyList());
|
||||||
|
statementSanitizationEnabled =
|
||||||
|
config.getBoolean("otel.instrumentation.common.db-statement-sanitizer.enabled", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, String> getPeerServiceMapping() {
|
public Map<String, String> getPeerServiceMapping() {
|
||||||
|
@ -61,4 +64,8 @@ public final class CommonConfig {
|
||||||
public List<String> getServerResponseHeaders() {
|
public List<String> getServerResponseHeaders() {
|
||||||
return serverResponseHeaders;
|
return serverResponseHeaders;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isStatementSanitizationEnabled() {
|
||||||
|
return statementSanitizationEnabled;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue