diff --git a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/tracer/DatabaseClientTracer.java b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/tracer/DatabaseClientTracer.java index 1abec743fb..fc25f8ff30 100644 --- a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/tracer/DatabaseClientTracer.java +++ b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/tracer/DatabaseClientTracer.java @@ -8,16 +8,22 @@ package io.opentelemetry.instrumentation.api.tracer; import static io.opentelemetry.api.trace.SpanKind.CLIENT; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.StatusCode; +import io.opentelemetry.api.trace.SpanBuilder; import io.opentelemetry.context.Context; import io.opentelemetry.instrumentation.api.tracer.utils.NetPeerUtils; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; import java.net.InetSocketAddress; -import java.util.concurrent.ExecutionException; - -public abstract class DatabaseClientTracer extends BaseTracer { +import org.checkerframework.checker.nullness.qual.Nullable; +/** + * Base class for implementing Tracers for database clients. + * + * @param type of the database connection. + * @param type of the database statement being executed. + * @param type of the database statement after sanitization. + */ +public abstract class DatabaseClientTracer + extends BaseTracer { protected static final String DB_QUERY = "DB Query"; public DatabaseClientTracer() {} @@ -30,61 +36,68 @@ public abstract class DatabaseClientTracer extends BaseTracer return shouldStartSpan(CLIENT, parentContext); } - public Context startSpan(Context parentContext, CONNECTION connection, QUERY query) { - String normalizedQuery = normalizeQuery(query); + public Context startSpan(Context parentContext, CONNECTION connection, STATEMENT statement) { + SANITIZEDSTATEMENT sanitizedStatement = sanitizeStatement(statement); - Span span = + SpanBuilder span = tracer - .spanBuilder(spanName(connection, query, normalizedQuery)) + .spanBuilder(spanName(connection, statement, sanitizedStatement)) .setParent(parentContext) .setSpanKind(CLIENT) - .setAttribute(SemanticAttributes.DB_SYSTEM, dbSystem(connection)) - .startSpan(); + .setAttribute(SemanticAttributes.DB_SYSTEM, dbSystem(connection)); if (connection != null) { onConnection(span, connection); setNetSemanticConvention(span, connection); } - onStatement(span, normalizedQuery); + onStatement(span, connection, statement, sanitizedStatement); - return withClientSpan(parentContext, span); + return withClientSpan(parentContext, span.startSpan()); } - public void endExceptionally(Context context, Throwable throwable) { - Span span = Span.fromContext(context); - onError(span, throwable); - end(span); + protected abstract SANITIZEDSTATEMENT sanitizeStatement(STATEMENT statement); + + protected String spanName( + CONNECTION connection, STATEMENT statement, SANITIZEDSTATEMENT sanitizedStatement) { + return conventionSpanName( + dbName(connection), dbOperation(connection, statement, sanitizedStatement), null); } + /** + * A helper method for constructing the span name formatting according to DB semantic conventions: + * {@code }. + */ + public static String conventionSpanName( + @Nullable String dbName, @Nullable String operation, @Nullable String table) { + if (operation == null) { + return dbName == null ? DB_QUERY : dbName; + } + + StringBuilder name = new StringBuilder(operation); + if (dbName != null || table != null) { + name.append(' '); + } + if (dbName != null) { + name.append(dbName); + if (table != null) { + name.append('.'); + } + } + if (table != null) { + name.append(table); + } + return name.toString(); + } + + protected abstract String dbSystem(CONNECTION connection); + /** This should be called when the connection is being used, not when it's created. */ - protected Span onConnection(Span span, CONNECTION connection) { + protected void onConnection(SpanBuilder span, CONNECTION connection) { span.setAttribute(SemanticAttributes.DB_USER, dbUser(connection)); span.setAttribute(SemanticAttributes.DB_NAME, dbName(connection)); span.setAttribute(SemanticAttributes.DB_CONNECTION_STRING, dbConnectionString(connection)); - return span; } - @Override - protected void onError(Span span, Throwable throwable) { - if (throwable != null) { - span.setStatus(StatusCode.ERROR); - addThrowable( - span, throwable instanceof ExecutionException ? throwable.getCause() : throwable); - } - } - - protected void setNetSemanticConvention(Span span, CONNECTION connection) { - NetPeerUtils.INSTANCE.setNetPeer(span, peerAddress(connection)); - } - - protected void onStatement(Span span, String statement) { - span.setAttribute(SemanticAttributes.DB_STATEMENT, statement); - } - - protected abstract String normalizeQuery(QUERY query); - - protected abstract String dbSystem(CONNECTION connection); - protected String dbUser(CONNECTION connection) { return null; } @@ -97,17 +110,30 @@ public abstract class DatabaseClientTracer extends BaseTracer return null; } + protected void setNetSemanticConvention(SpanBuilder span, CONNECTION connection) { + NetPeerUtils.INSTANCE.setNetPeer(span, peerAddress(connection)); + } + protected abstract InetSocketAddress peerAddress(CONNECTION connection); - protected String spanName(CONNECTION connection, QUERY query, String normalizedQuery) { - if (normalizedQuery != null) { - return normalizedQuery; - } + protected void onStatement( + SpanBuilder span, + CONNECTION connection, + STATEMENT statement, + SANITIZEDSTATEMENT sanitizedStatement) { + span.setAttribute( + SemanticAttributes.DB_STATEMENT, dbStatement(connection, statement, sanitizedStatement)); + span.setAttribute( + SemanticAttributes.DB_OPERATION, dbOperation(connection, statement, sanitizedStatement)); + } - String result = null; - if (connection != null) { - result = dbName(connection); - } - return result == null ? DB_QUERY : result; + protected String dbStatement( + CONNECTION connection, STATEMENT statement, SANITIZEDSTATEMENT sanitizedStatement) { + return null; + } + + protected String dbOperation( + CONNECTION connection, STATEMENT statement, SANITIZEDSTATEMENT sanitizedStatement) { + return null; } } diff --git a/instrumentation/cassandra/cassandra-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v3_0/CassandraDatabaseClientTracer.java b/instrumentation/cassandra/cassandra-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v3_0/CassandraDatabaseClientTracer.java index 956eb24bc5..b6cd47dac9 100644 --- a/instrumentation/cassandra/cassandra-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v3_0/CassandraDatabaseClientTracer.java +++ b/instrumentation/cassandra/cassandra-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v3_0/CassandraDatabaseClientTracer.java @@ -9,15 +9,18 @@ import com.datastax.driver.core.ExecutionInfo; import com.datastax.driver.core.Host; import com.datastax.driver.core.Session; import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanBuilder; import io.opentelemetry.context.Context; import io.opentelemetry.instrumentation.api.tracer.DatabaseClientTracer; import io.opentelemetry.instrumentation.api.tracer.utils.NetPeerUtils; +import io.opentelemetry.javaagent.instrumentation.api.db.SqlStatementInfo; import io.opentelemetry.javaagent.instrumentation.api.db.SqlStatementSanitizer; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes.DbSystemValues; import java.net.InetSocketAddress; -public class CassandraDatabaseClientTracer extends DatabaseClientTracer { +public class CassandraDatabaseClientTracer + extends DatabaseClientTracer { private static final CassandraDatabaseClientTracer TRACER = new CassandraDatabaseClientTracer(); public static CassandraDatabaseClientTracer tracer() { @@ -30,8 +33,23 @@ public class CassandraDatabaseClientTracer extends DatabaseClientTracer .
naming scheme + protected String spanName( + Session connection, String statement, SqlStatementInfo sanitizedStatement) { + String fullStatement = sanitizedStatement.getFullStatement(); + if (fullStatement != null) { + return fullStatement; + } + + String result = null; + if (connection != null) { + result = dbName(connection); + } + return result == null ? DB_QUERY : result; } @Override @@ -39,20 +57,26 @@ public class CassandraDatabaseClientTracer extends DatabaseClientTracer { +public class CassandraDatabaseClientTracer + extends DatabaseClientTracer { private static final CassandraDatabaseClientTracer TRACER = new CassandraDatabaseClientTracer(); @@ -37,8 +40,23 @@ public class CassandraDatabaseClientTracer extends DatabaseClientTracer .
naming scheme + protected String spanName( + CqlSession connection, String statement, SqlStatementInfo sanitizedStatement) { + String fullStatement = sanitizedStatement.getFullStatement(); + if (fullStatement != null) { + return fullStatement; + } + + String result = null; + if (connection != null) { + result = dbName(connection); + } + return result == null ? DB_QUERY : result; } @Override @@ -127,9 +145,13 @@ public class CassandraDatabaseClientTracer extends DatabaseClientTracer.
int i = table.indexOf('.'); @@ -139,4 +161,10 @@ public class CassandraDatabaseClientTracer extends DatabaseClientTracer { +public class CouchbaseClientTracer extends DatabaseClientTracer { private static final CouchbaseClientTracer TRACER = new CouchbaseClientTracer(); public static CouchbaseClientTracer tracer() { @@ -18,13 +18,18 @@ public class CouchbaseClientTracer extends DatabaseClientTracer { } @Override - protected String normalizeQuery(Method method) { + protected String spanName(Void connection, Method method, Void sanitizedStatement) { Class declaringClass = method.getDeclaringClass(); String className = declaringClass.getSimpleName().replace("CouchbaseAsync", "").replace("DefaultAsync", ""); return className + "." + method.getName(); } + @Override + protected Void sanitizeStatement(Method method) { + return null; + } + @Override protected String dbSystem(Void connection) { return DbSystemValues.COUCHBASE; diff --git a/instrumentation/elasticsearch/elasticsearch-rest-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/ElasticsearchRestClientTracer.java b/instrumentation/elasticsearch/elasticsearch-rest-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/ElasticsearchRestClientTracer.java index e19bd0fafd..b0ed417558 100644 --- a/instrumentation/elasticsearch/elasticsearch-rest-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/ElasticsearchRestClientTracer.java +++ b/instrumentation/elasticsearch/elasticsearch-rest-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/ElasticsearchRestClientTracer.java @@ -13,7 +13,7 @@ import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; import java.net.InetSocketAddress; import org.elasticsearch.client.Response; -public class ElasticsearchRestClientTracer extends DatabaseClientTracer { +public class ElasticsearchRestClientTracer extends DatabaseClientTracer { private static final ElasticsearchRestClientTracer TRACER = new ElasticsearchRestClientTracer(); public static ElasticsearchRestClientTracer tracer() { @@ -29,13 +29,8 @@ public class ElasticsearchRestClientTracer extends DatabaseClientTracer> { + extends DatabaseClientTracer, String> { private static final ElasticsearchTransportClientTracer TRACER = new ElasticsearchTransportClientTracer(); @@ -21,15 +20,15 @@ public class ElasticsearchTransportClientTracer return TRACER; } - public void onRequest(Context context, Class action, Class request) { + public void onRequest(Context context, Class action, Class request) { Span span = Span.fromContext(context); span.setAttribute("elasticsearch.action", action.getSimpleName()); span.setAttribute("elasticsearch.request", request.getSimpleName()); } @Override - protected String normalizeQuery(Action query) { - return query.getClass().getSimpleName(); + protected String sanitizeStatement(Action action) { + return action.getClass().getSimpleName(); } @Override @@ -43,8 +42,8 @@ public class ElasticsearchTransportClientTracer } @Override - protected void onStatement(Span span, String statement) { - span.setAttribute(SemanticAttributes.DB_OPERATION, statement); + protected String dbOperation(Void connection, Action action, String operation) { + return operation; } @Override diff --git a/instrumentation/geode-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/GeodeTracer.java b/instrumentation/geode-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/GeodeTracer.java index 902671bf64..00cfd95f21 100644 --- a/instrumentation/geode-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/GeodeTracer.java +++ b/instrumentation/geode-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/GeodeTracer.java @@ -8,13 +8,15 @@ package io.opentelemetry.javaagent.instrumentation.geode; import static io.opentelemetry.api.trace.SpanKind.CLIENT; import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanBuilder; import io.opentelemetry.instrumentation.api.tracer.DatabaseClientTracer; +import io.opentelemetry.javaagent.instrumentation.api.db.SqlStatementInfo; import io.opentelemetry.javaagent.instrumentation.api.db.SqlStatementSanitizer; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; import java.net.InetSocketAddress; import org.apache.geode.cache.Region; -public class GeodeTracer extends DatabaseClientTracer, String> { +public class GeodeTracer extends DatabaseClientTracer, String, SqlStatementInfo> { private static final GeodeTracer TRACER = new GeodeTracer(); public static GeodeTracer tracer() { @@ -22,33 +24,30 @@ public class GeodeTracer extends DatabaseClientTracer, String> { } public Span startSpan(String operation, Region connection, String query) { - String normalizedQuery = normalizeQuery(query); + SqlStatementInfo sanitizedStatement = sanitizeStatement(query); - Span span = + SpanBuilder span = tracer .spanBuilder(operation) .setSpanKind(CLIENT) .setAttribute(SemanticAttributes.DB_SYSTEM, dbSystem(connection)) - .setAttribute(SemanticAttributes.DB_OPERATION, operation) - .startSpan(); + .setAttribute(SemanticAttributes.DB_OPERATION, operation); onConnection(span, connection); setNetSemanticConvention(span, connection); - onStatement(span, normalizedQuery); + onStatement(span, connection, query, sanitizedStatement); - return span; + return span.startSpan(); } @Override - protected String normalizeQuery(String query) { - return SqlStatementSanitizer.sanitize(query).getFullStatement(); + protected SqlStatementInfo sanitizeStatement(String statement) { + return SqlStatementSanitizer.sanitize(statement); } @Override protected String dbSystem(Region region) { - // TODO(anuraaga): Replace with semantic attribute - // https://github.com/open-telemetry/opentelemetry-specification/pull/1321 - return "geode"; + return SemanticAttributes.DbSystemValues.GEODE; } @Override @@ -61,6 +60,12 @@ public class GeodeTracer extends DatabaseClientTracer, String> { return null; } + @Override + protected String dbStatement( + Region connection, String statement, SqlStatementInfo sanitizedStatement) { + return sanitizedStatement.getFullStatement(); + } + @Override protected String getInstrumentationName() { return "io.opentelemetry.javaagent.geode"; diff --git a/instrumentation/jdbc/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/ConnectionInstrumentation.java b/instrumentation/jdbc/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/ConnectionInstrumentation.java index 3a3e33fff3..f38d82fe90 100644 --- a/instrumentation/jdbc/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/ConnectionInstrumentation.java +++ b/instrumentation/jdbc/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/ConnectionInstrumentation.java @@ -14,7 +14,6 @@ import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.returns; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; -import io.opentelemetry.javaagent.instrumentation.api.db.SqlStatementSanitizer; import io.opentelemetry.javaagent.tooling.TypeInstrumentation; import java.sql.PreparedStatement; import java.util.Map; @@ -49,7 +48,7 @@ public class ConnectionInstrumentation implements TypeInstrumentation { @Advice.OnMethodExit(suppress = Throwable.class) public static void addDbInfo( @Advice.Argument(0) String sql, @Advice.Return PreparedStatement statement) { - JdbcMaps.preparedStatements.put(statement, SqlStatementSanitizer.sanitize(sql)); + JdbcMaps.preparedStatements.put(statement, sql); } } } diff --git a/instrumentation/jdbc/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/JdbcMaps.java b/instrumentation/jdbc/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/JdbcMaps.java index 7d55428931..5aec943f69 100644 --- a/instrumentation/jdbc/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/JdbcMaps.java +++ b/instrumentation/jdbc/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/JdbcMaps.java @@ -8,7 +8,6 @@ package io.opentelemetry.javaagent.instrumentation.jdbc; import static io.opentelemetry.javaagent.instrumentation.api.WeakMap.Provider.newWeakMap; import io.opentelemetry.javaagent.instrumentation.api.WeakMap; -import io.opentelemetry.javaagent.instrumentation.api.db.SqlStatementInfo; import java.sql.Connection; import java.sql.PreparedStatement; @@ -19,6 +18,5 @@ import java.sql.PreparedStatement; */ public class JdbcMaps { public static final WeakMap connectionInfo = newWeakMap(); - public static final WeakMap preparedStatements = - newWeakMap(); + public static final WeakMap preparedStatements = newWeakMap(); } diff --git a/instrumentation/jdbc/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/JdbcTracer.java b/instrumentation/jdbc/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/JdbcTracer.java index e706a6a42d..aa2de06a07 100644 --- a/instrumentation/jdbc/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/JdbcTracer.java +++ b/instrumentation/jdbc/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/JdbcTracer.java @@ -9,8 +9,6 @@ import static io.opentelemetry.javaagent.instrumentation.jdbc.JdbcUtils.connecti import io.opentelemetry.context.Context; import io.opentelemetry.instrumentation.api.tracer.DatabaseClientTracer; -import io.opentelemetry.javaagent.instrumentation.api.CallDepth; -import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; import io.opentelemetry.javaagent.instrumentation.api.db.SqlStatementInfo; import io.opentelemetry.javaagent.instrumentation.api.db.SqlStatementSanitizer; import java.net.InetSocketAddress; @@ -20,7 +18,7 @@ import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Statement; -public class JdbcTracer extends DatabaseClientTracer { +public class JdbcTracer extends DatabaseClientTracer { private static final JdbcTracer TRACER = new JdbcTracer(); public static JdbcTracer tracer() { @@ -32,6 +30,33 @@ public class JdbcTracer extends DatabaseClientTracer { return "io.opentelemetry.javaagent.jdbc"; } + public Context startSpan(Context parentContext, PreparedStatement statement) { + return startSpan(parentContext, statement, JdbcMaps.preparedStatements.get(statement)); + } + + public Context startSpan(Context parentContext, Statement statement, String query) { + Connection connection = connectionFromStatement(statement); + if (connection == null) { + return null; + } + + DbInfo dbInfo = extractDbInfo(connection); + + return startSpan(parentContext, dbInfo, query); + } + + @Override + protected SqlStatementInfo sanitizeStatement(String statement) { + return SqlStatementSanitizer.sanitize(statement); + } + + @Override + protected String spanName( + DbInfo connection, String statement, SqlStatementInfo sanitizedStatement) { + return conventionSpanName( + dbName(connection), sanitizedStatement.getOperation(), sanitizedStatement.getTable()); + } + @Override protected String dbSystem(DbInfo info) { return info.getSystem(); @@ -51,6 +76,11 @@ public class JdbcTracer extends DatabaseClientTracer { } } + @Override + protected String dbConnectionString(DbInfo info) { + return info.getShortUrl(); + } + // TODO find a way to implement @Override protected InetSocketAddress peerAddress(DbInfo dbInfo) { @@ -58,58 +88,9 @@ public class JdbcTracer extends DatabaseClientTracer { } @Override - protected String dbConnectionString(DbInfo info) { - return info.getShortUrl(); - } - - public CallDepth getCallDepth() { - return CallDepthThreadLocalMap.getCallDepth(Statement.class); - } - - public Context startSpan(Context parentContext, PreparedStatement statement) { - return startSpan(parentContext, statement, JdbcMaps.preparedStatements.get(statement)); - } - - public Context startSpan(Context parentContext, Statement statement, String query) { - return startSpan(parentContext, statement, SqlStatementSanitizer.sanitize(query)); - } - - private Context startSpan( - Context parentContext, Statement statement, SqlStatementInfo queryInfo) { - Connection connection = connectionFromStatement(statement); - if (connection == null) { - return null; - } - - DbInfo dbInfo = extractDbInfo(connection); - - return startSpan(parentContext, dbInfo, queryInfo); - } - - @Override - protected String normalizeQuery(SqlStatementInfo query) { - return query.getFullStatement(); - } - - @Override - protected String spanName(DbInfo connection, SqlStatementInfo query, String normalizedQuery) { - String dbName = dbName(connection); - if (query.getOperation() == null) { - return dbName == null ? DB_QUERY : dbName; - } - - StringBuilder name = new StringBuilder(); - name.append(query.getOperation()).append(' '); - if (dbName != null) { - name.append(dbName); - if (query.getTable() != null) { - name.append('.'); - } - } - if (query.getTable() != null) { - name.append(query.getTable()); - } - return name.toString(); + protected String dbStatement( + DbInfo connection, String statement, SqlStatementInfo sanitizedStatement) { + return sanitizedStatement.getFullStatement(); } private DbInfo extractDbInfo(Connection connection) { diff --git a/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisClientTracer.java b/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisClientTracer.java index 028f051e7f..78c6153ba9 100644 --- a/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisClientTracer.java +++ b/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisClientTracer.java @@ -15,7 +15,7 @@ import java.util.List; import redis.clients.jedis.Connection; import redis.clients.jedis.Protocol.Command; -public class JedisClientTracer extends DatabaseClientTracer { +public class JedisClientTracer extends DatabaseClientTracer { private static final JedisClientTracer TRACER = new JedisClientTracer(); public static JedisClientTracer tracer() { @@ -23,13 +23,14 @@ public class JedisClientTracer extends DatabaseClientTracer { +public class JedisClientTracer extends DatabaseClientTracer { private static final JedisClientTracer TRACER = new JedisClientTracer(); public static JedisClientTracer tracer() { @@ -25,13 +25,14 @@ public class JedisClientTracer extends DatabaseClientTracer - extends DatabaseClientTracer { +public abstract class LettuceAbstractDatabaseClientTracer + extends DatabaseClientTracer { + + @Override + protected String spanName(RedisURI connection, STATEMENT statement, String operation) { + return operation; + } + + @Override + public void onConnection(SpanBuilder span, RedisURI connection) { + if (connection != null && connection.getDatabase() != 0) { + span.setAttribute( + SemanticAttributes.DB_REDIS_DATABASE_INDEX, (long) connection.getDatabase()); + } + super.onConnection(span, connection); + } @Override protected String dbSystem(RedisURI connection) { @@ -26,11 +40,8 @@ public abstract class LettuceAbstractDatabaseClientTracer } @Override - public Span onConnection(Span span, RedisURI connection) { - if (connection != null && connection.getDatabase() != 0) { - span.setAttribute(SemanticAttributes.DB_REDIS_DATABASE_INDEX, connection.getDatabase()); - } - return super.onConnection(span, connection); + protected String dbStatement(RedisURI connection, STATEMENT statement, String operation) { + return operation; } @Override diff --git a/instrumentation/lettuce/lettuce-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceConnectionDatabaseClientTracer.java b/instrumentation/lettuce/lettuce-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceConnectionDatabaseClientTracer.java index 8dd484cb5b..6d169af1d2 100644 --- a/instrumentation/lettuce/lettuce-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceConnectionDatabaseClientTracer.java +++ b/instrumentation/lettuce/lettuce-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceConnectionDatabaseClientTracer.java @@ -16,7 +16,7 @@ public class LettuceConnectionDatabaseClientTracer } @Override - protected String normalizeQuery(String command) { + protected String sanitizeStatement(String command) { return command; } } diff --git a/instrumentation/lettuce/lettuce-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceDatabaseClientTracer.java b/instrumentation/lettuce/lettuce-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceDatabaseClientTracer.java index efee20a04c..524c0ac226 100644 --- a/instrumentation/lettuce/lettuce-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceDatabaseClientTracer.java +++ b/instrumentation/lettuce/lettuce-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceDatabaseClientTracer.java @@ -17,7 +17,7 @@ public class LettuceDatabaseClientTracer } @Override - protected String normalizeQuery(RedisCommand command) { + protected String sanitizeStatement(RedisCommand command) { return command.getType().name(); } } diff --git a/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceAbstractDatabaseClientTracer.java b/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceAbstractDatabaseClientTracer.java index ffe0c3718a..1328589b70 100644 --- a/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceAbstractDatabaseClientTracer.java +++ b/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceAbstractDatabaseClientTracer.java @@ -6,14 +6,14 @@ package io.opentelemetry.javaagent.instrumentation.lettuce.v5_0; import io.lettuce.core.RedisURI; -import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanBuilder; import io.opentelemetry.instrumentation.api.tracer.DatabaseClientTracer; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes.DbSystemValues; import java.net.InetSocketAddress; -public abstract class LettuceAbstractDatabaseClientTracer - extends DatabaseClientTracer { +public abstract class LettuceAbstractDatabaseClientTracer + extends DatabaseClientTracer { @Override protected String getInstrumentationName() { return "io.opentelemetry.javaagent.lettuce"; @@ -30,10 +30,17 @@ public abstract class LettuceAbstractDatabaseClientTracer } @Override - public Span onConnection(Span span, RedisURI connection) { + public void onConnection(SpanBuilder span, RedisURI connection) { if (connection != null && connection.getDatabase() != 0) { - span.setAttribute(SemanticAttributes.DB_REDIS_DATABASE_INDEX, connection.getDatabase()); + span.setAttribute( + SemanticAttributes.DB_REDIS_DATABASE_INDEX, (long) connection.getDatabase()); } - return super.onConnection(span, connection); + super.onConnection(span, connection); + } + + @Override + protected String dbStatement( + RedisURI connection, STATEMENT statement, String sanitizedStatement) { + return sanitizedStatement; } } diff --git a/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceAsyncBiFunction.java b/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceAsyncBiFunction.java index 3edd2f2d85..7e6d5ed75f 100644 --- a/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceAsyncBiFunction.java +++ b/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceAsyncBiFunction.java @@ -37,10 +37,11 @@ public class LettuceAsyncBiFunction @Override public R apply(T t, Throwable throwable) { - if (throwable instanceof CancellationException) { + if (throwable == null) { + tracer().end(context); + } else if (throwable instanceof CancellationException) { if (CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES) { - Span span = Span.fromContext(context); - span.setAttribute("lettuce.command.cancelled", true); + Span.fromContext(context).setAttribute("lettuce.command.cancelled", true); } tracer().end(context); } else { diff --git a/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceConnectionDatabaseClientTracer.java b/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceConnectionDatabaseClientTracer.java index 6bd6ad8d6b..207f21d80a 100644 --- a/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceConnectionDatabaseClientTracer.java +++ b/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceConnectionDatabaseClientTracer.java @@ -5,6 +5,8 @@ package io.opentelemetry.javaagent.instrumentation.lettuce.v5_0; +import io.lettuce.core.RedisURI; + public class LettuceConnectionDatabaseClientTracer extends LettuceAbstractDatabaseClientTracer { private static final LettuceConnectionDatabaseClientTracer TRACER = @@ -15,7 +17,12 @@ public class LettuceConnectionDatabaseClientTracer } @Override - protected String normalizeQuery(String query) { - return query; + protected String sanitizeStatement(String command) { + return command; + } + + @Override + protected String spanName(RedisURI connection, String command, String ignored) { + return command; } } diff --git a/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceDatabaseClientTracer.java b/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceDatabaseClientTracer.java index bd148ba6e4..084d428df1 100644 --- a/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceDatabaseClientTracer.java +++ b/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceDatabaseClientTracer.java @@ -21,13 +21,7 @@ public class LettuceDatabaseClientTracer } @Override - protected String spanName( - RedisURI connection, RedisCommand query, String normalizedQuery) { - return LettuceInstrumentationUtil.getCommandName(query); - } - - @Override - protected String normalizeQuery(RedisCommand redisCommand) { + protected String sanitizeStatement(RedisCommand redisCommand) { String command = LettuceInstrumentationUtil.getCommandName(redisCommand); List args = redisCommand.getArgs() == null @@ -35,4 +29,10 @@ public class LettuceDatabaseClientTracer : LettuceArgSplitter.splitArgs(redisCommand.getArgs().toCommandString()); return RedisCommandSanitizer.sanitize(command, args); } + + @Override + protected String spanName( + RedisURI connection, RedisCommand command, String sanitizedStatement) { + return LettuceInstrumentationUtil.getCommandName(command); + } } diff --git a/instrumentation/mongo/mongo-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/MongoClientTracer.java b/instrumentation/mongo/mongo-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/MongoClientTracer.java index 90d989920a..7c49e0c1c0 100644 --- a/instrumentation/mongo/mongo-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/MongoClientTracer.java +++ b/instrumentation/mongo/mongo-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/MongoClientTracer.java @@ -10,7 +10,7 @@ import static java.util.Arrays.asList; import com.mongodb.ServerAddress; import com.mongodb.connection.ConnectionDescription; import com.mongodb.event.CommandStartedEvent; -import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanBuilder; import io.opentelemetry.instrumentation.api.tracer.DatabaseClientTracer; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes.DbSystemValues; @@ -20,7 +20,6 @@ import java.lang.reflect.Method; import java.net.InetSocketAddress; import java.util.Arrays; import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; @@ -30,7 +29,8 @@ import org.bson.BsonValue; import org.bson.json.JsonWriter; import org.bson.json.JsonWriterSettings; -public class MongoClientTracer extends DatabaseClientTracer { +public class MongoClientTracer + extends DatabaseClientTracer { private static final MongoClientTracer TRACER = new MongoClientTracer(); private final int maxNormalizedQueryLength; @@ -54,19 +54,34 @@ public class MongoClientTracer extends DatabaseClientTracer= 3.7, the substring invocation will be a no-op due to use of + // JsonWriterSettings.Builder.maxLength in the static initializer for JSON_WRITER_SETTINGS + return stringWriter + .getBuffer() + .substring(0, Math.min(maxNormalizedQueryLength, stringWriter.getBuffer().length())); + } + + @Override + public String spanName(CommandStartedEvent event, BsonDocument document, String normalizedQuery) { + return conventionSpanName(dbName(event), event.getCommandName(), collectionName(event)); + } + @Override protected String dbSystem(CommandStartedEvent event) { return DbSystemValues.MONGODB; } @Override - protected Span onConnection(Span span, CommandStartedEvent event) { - span.setAttribute(SemanticAttributes.DB_OPERATION, event.getCommandName()); + protected void onConnection(SpanBuilder span, CommandStartedEvent event) { String collection = collectionName(event); if (collection != null) { span.setAttribute(SemanticAttributes.DB_MONGODB_COLLECTION, collection); } - return super.onConnection(span, event); + super.onConnection(span, event); } @Override @@ -74,41 +89,6 @@ public class MongoClientTracer extends DatabaseClientTracer UNSCRUBBED_FIELDS = - asList("ordered", "insert", "count", "find", "create"); - private JsonWriterSettings createJsonWriterSettings(int maxNormalizedQueryLength) { JsonWriterSettings settings = null; try { @@ -192,17 +187,6 @@ public class MongoClientTracer extends DatabaseClientTracer= 3.7, the substring invocation will be a no-op due to use of - // JsonWriterSettings.Builder.maxLength in the static initializer for JSON_WRITER_SETTINGS - return stringWriter - .getBuffer() - .substring(0, Math.min(maxNormalizedQueryLength, stringWriter.getBuffer().length())); - } - private static final String HIDDEN_CHAR = "?"; private static boolean writeScrubbed(BsonDocument origin, JsonWriter writer, boolean isRoot) { diff --git a/instrumentation/mongo/mongo-common/javaagent/src/test/groovy/MongoClientTracerTest.groovy b/instrumentation/mongo/mongo-common/javaagent/src/test/groovy/MongoClientTracerTest.groovy index 5177479028..9947f9c422 100644 --- a/instrumentation/mongo/mongo-common/javaagent/src/test/groovy/MongoClientTracerTest.groovy +++ b/instrumentation/mongo/mongo-common/javaagent/src/test/groovy/MongoClientTracerTest.groovy @@ -3,10 +3,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -import com.mongodb.event.CommandStartedEvent - import static java.util.Arrays.asList +import com.mongodb.event.CommandStartedEvent import io.opentelemetry.javaagent.instrumentation.mongo.MongoClientTracer import org.bson.BsonArray import org.bson.BsonDocument @@ -15,21 +14,21 @@ import org.bson.BsonString import spock.lang.Specification class MongoClientTracerTest extends Specification { - def 'should normalize queries to json'() { + def 'should sanitize statements to json'() { setup: def tracer = new MongoClientTracer() expect: - normalizeQueryAcrossVersions(tracer, + sanitizeStatementAcrossVersions(tracer, new BsonDocument("cmd", new BsonInt32(1))) == '{"cmd": "?"}' - normalizeQueryAcrossVersions(tracer, + sanitizeStatementAcrossVersions(tracer, new BsonDocument("cmd", new BsonInt32(1)) .append("sub", new BsonDocument("a", new BsonInt32(1)))) == '{"cmd": "?", "sub": {"a": "?"}}' - normalizeQueryAcrossVersions(tracer, + sanitizeStatementAcrossVersions(tracer, new BsonDocument("cmd", new BsonInt32(1)) .append("sub", new BsonArray(asList(new BsonInt32(1))))) == '{"cmd": "?", "sub": ["?"]}' @@ -40,7 +39,7 @@ class MongoClientTracerTest extends Specification { def tracer = new MongoClientTracer() expect: - normalizeQueryAcrossVersions(tracer, + sanitizeStatementAcrossVersions(tracer, new BsonDocument("cmd", new BsonString("c")) .append("f", new BsonString("c")) .append("sub", new BsonString("c"))) == @@ -51,7 +50,7 @@ class MongoClientTracerTest extends Specification { setup: def tracer = new MongoClientTracer(20) - def normalized = normalizeQueryAcrossVersions(tracer, + def normalized = sanitizeStatementAcrossVersions(tracer, new BsonDocument("cmd", new BsonString("c")) .append("f1", new BsonString("c1")) .append("f2", new BsonString("c2"))) @@ -64,7 +63,7 @@ class MongoClientTracerTest extends Specification { setup: def tracer = new MongoClientTracer(27) - def normalized = normalizeQueryAcrossVersions(tracer, + def normalized = sanitizeStatementAcrossVersions(tracer, new BsonDocument("cmd", new BsonString("c")) .append("f1", new BsonArray(Arrays.asList(new BsonString("c1"), new BsonString("c2")))) .append("f2", new BsonString("c3"))) @@ -89,11 +88,11 @@ class MongoClientTracerTest extends Specification { command = "listDatabases" } - def normalizeQueryAcrossVersions(MongoClientTracer tracer, BsonDocument query) { - return normalizeAcrossVersions(tracer.normalizeQuery(query)) + def sanitizeStatementAcrossVersions(MongoClientTracer tracer, BsonDocument query) { + return sanitizeAcrossVersions(tracer.sanitizeStatement(query)) } - def normalizeAcrossVersions(String json) { + def sanitizeAcrossVersions(String json) { json = json.replaceAll('\\{ ', '{') json = json.replaceAll(' }', '}') json = json.replaceAll(' :', ':') diff --git a/instrumentation/rediscala-1.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/RediscalaClientTracer.java b/instrumentation/rediscala-1.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/RediscalaClientTracer.java index 5195fb65a2..3f819d1332 100644 --- a/instrumentation/rediscala-1.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/RediscalaClientTracer.java +++ b/instrumentation/rediscala-1.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/RediscalaClientTracer.java @@ -11,7 +11,7 @@ import java.net.InetSocketAddress; import redis.RedisCommand; public class RediscalaClientTracer - extends DatabaseClientTracer, RedisCommand> { + extends DatabaseClientTracer, RedisCommand, String> { private static final RediscalaClientTracer TRACER = new RediscalaClientTracer(); @@ -20,20 +20,32 @@ public class RediscalaClientTracer } @Override - protected String normalizeQuery(RedisCommand redisCommand) { + protected String sanitizeStatement(RedisCommand redisCommand) { return spanNameForClass(redisCommand.getClass()); } @Override - protected String dbSystem(RedisCommand redisCommand) { + protected String spanName( + RedisCommand connection, RedisCommand statement, String operation) { + return operation; + } + + @Override + protected String dbSystem(RedisCommand redisCommand) { return DbSystemValues.REDIS; } @Override - protected InetSocketAddress peerAddress(RedisCommand redisCommand) { + protected InetSocketAddress peerAddress(RedisCommand redisCommand) { return null; } + @Override + protected String dbStatement( + RedisCommand connection, RedisCommand command, String operation) { + return operation; + } + @Override protected String getInstrumentationName() { return "io.opentelemetry.javaagent.rediscala"; diff --git a/instrumentation/redisson-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/redisson/RedissonClientTracer.java b/instrumentation/redisson-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/redisson/RedissonClientTracer.java index 82d61bc821..43aa1c710d 100644 --- a/instrumentation/redisson-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/redisson/RedissonClientTracer.java +++ b/instrumentation/redisson-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/redisson/RedissonClientTracer.java @@ -5,6 +5,9 @@ package io.opentelemetry.javaagent.instrumentation.redisson; +import static java.util.Collections.emptyList; +import static java.util.Collections.singletonList; + import io.netty.buffer.ByteBuf; import io.netty.channel.Channel; import io.opentelemetry.instrumentation.api.tracer.DatabaseClientTracer; @@ -13,11 +16,13 @@ import io.opentelemetry.semconv.trace.attributes.SemanticAttributes.DbSystemValu import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; import org.redisson.client.RedisConnection; import org.redisson.client.protocol.CommandData; import org.redisson.client.protocol.CommandsData; -public class RedissonClientTracer extends DatabaseClientTracer { +public class RedissonClientTracer + extends DatabaseClientTracer> { private static final String UNKNOWN_COMMAND = "Redis Command"; private static final RedissonClientTracer TRACER = new RedissonClientTracer(); @@ -27,22 +32,24 @@ public class RedissonClientTracer extends DatabaseClientTracer> commands = ((CommandsData) query).getCommands(); - StringBuilder commandStrings = new StringBuilder(); - for (CommandData commandData : commands) { - commandStrings.append(commandData.getCommand().getName()).append(";"); - } - if (commandStrings.length() > 0) { - commandStrings.deleteCharAt(commandStrings.length() - 1); - } - return commandStrings.toString(); - } else if (query instanceof CommandData) { - return ((CommandData) query).getCommand().getName(); + protected String spanName( + RedisConnection connection, Object ignored, List sanitizedStatements) { + switch (sanitizedStatements.size()) { + case 0: + return UNKNOWN_COMMAND; + // optimize for the most common case + case 1: + return getCommandName(sanitizedStatements.get(0)); + default: + return sanitizedStatements.stream() + .map(this::getCommandName) + .collect(Collectors.joining(";")); } + } - return UNKNOWN_COMMAND; + private String getCommandName(String statement) { + int spacePos = statement.indexOf(' '); + return spacePos == -1 ? statement : statement.substring(0, spacePos); } @Override @@ -51,22 +58,15 @@ public class RedissonClientTracer extends DatabaseClientTracer sanitizeStatement(Object command) { // get command if (command instanceof CommandsData) { List> commands = ((CommandsData) command).getCommands(); - StringBuilder commandStrings = new StringBuilder(); - for (CommandData commandData : commands) { - commandStrings.append(normalizeSingleCommand(commandData)).append(";"); - } - if (commandStrings.length() > 0) { - commandStrings.deleteCharAt(commandStrings.length() - 1); - } - return commandStrings.toString(); + return commands.stream().map(this::normalizeSingleCommand).collect(Collectors.toList()); } else if (command instanceof CommandData) { - return normalizeSingleCommand((CommandData) command); + return singletonList(normalizeSingleCommand((CommandData) command)); } - return UNKNOWN_COMMAND; + return emptyList(); } private String normalizeSingleCommand(CommandData command) { @@ -110,4 +110,18 @@ public class RedissonClientTracer extends DatabaseClientTracer sanitizedStatements) { + switch (sanitizedStatements.size()) { + case 0: + return UNKNOWN_COMMAND; + // optimize for the most common case + case 1: + return sanitizedStatements.get(0); + default: + return String.join(";", sanitizedStatements); + } + } } diff --git a/instrumentation/spymemcached-2.12/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spymemcached/CompletionListener.java b/instrumentation/spymemcached-2.12/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spymemcached/CompletionListener.java index 789975ed3f..97cbc6daf5 100644 --- a/instrumentation/spymemcached-2.12/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spymemcached/CompletionListener.java +++ b/instrumentation/spymemcached-2.12/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spymemcached/CompletionListener.java @@ -64,7 +64,11 @@ public abstract class CompletionListener { } protected void closeSyncSpan(Throwable thrown) { - tracer().endExceptionally(context, thrown); + if (thrown == null) { + tracer().end(context); + } else { + tracer().endExceptionally(context, thrown); + } } protected abstract void processResult(Span span, T future) diff --git a/instrumentation/spymemcached-2.12/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spymemcached/MemcacheClientTracer.java b/instrumentation/spymemcached-2.12/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spymemcached/MemcacheClientTracer.java index a660152a82..35dd6862a0 100644 --- a/instrumentation/spymemcached-2.12/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spymemcached/MemcacheClientTracer.java +++ b/instrumentation/spymemcached-2.12/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spymemcached/MemcacheClientTracer.java @@ -5,19 +5,33 @@ package io.opentelemetry.javaagent.instrumentation.spymemcached; -import io.opentelemetry.api.trace.Span; import io.opentelemetry.instrumentation.api.tracer.DatabaseClientTracer; -import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; import java.net.InetSocketAddress; import net.spy.memcached.MemcachedConnection; -public class MemcacheClientTracer extends DatabaseClientTracer { +public class MemcacheClientTracer + extends DatabaseClientTracer { private static final MemcacheClientTracer TRACER = new MemcacheClientTracer(); public static MemcacheClientTracer tracer() { return TRACER; } + @Override + protected String sanitizeStatement(String methodName) { + char[] chars = + methodName + .replaceFirst("^async", "") + // 'CAS' name is special, we have to lowercase whole name + .replaceFirst("^CAS", "cas") + .toCharArray(); + + // Lowercase first letter + chars[0] = Character.toLowerCase(chars[0]); + + return new String(chars); + } + @Override protected String dbSystem(MemcachedConnection memcachedConnection) { return "memcached"; @@ -29,23 +43,9 @@ public class MemcacheClientTracer extends DatabaseClientTracer