diff --git a/dd-java-agent/agent-bootstrap/src/jmh/java/datadog/trace/bootstrap/instrumentation/decorator/DatabaseClientConnectionBenchmark.java b/dd-java-agent/agent-bootstrap/src/jmh/java/datadog/trace/bootstrap/instrumentation/decorator/DatabaseClientConnectionBenchmark.java new file mode 100644 index 00000000000..ff70c1f147c --- /dev/null +++ b/dd-java-agent/agent-bootstrap/src/jmh/java/datadog/trace/bootstrap/instrumentation/decorator/DatabaseClientConnectionBenchmark.java @@ -0,0 +1,209 @@ +package datadog.trace.bootstrap.instrumentation.decorator; + +import static datadog.trace.bootstrap.instrumentation.api.Tags.DB_USER; +import static java.util.concurrent.TimeUnit.SECONDS; + +import datadog.trace.api.GlobalTracer; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import datadog.trace.bootstrap.instrumentation.api.TagExtractor; +import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; +import datadog.trace.common.writer.Writer; +import datadog.trace.core.CoreTracer; +import datadog.trace.core.DDSpan; +import java.util.List; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Threads; +import org.openjdk.jmh.annotations.Warmup; + +/** + * Acceptance test for the {@code dbUser} peel: measures the param-injected connection-tags {@link + * TagExtractor} form of {@link DatabaseClientDecorator#onConnection(AgentSpan, Object, + * TagExtractor)} — the shape that replaced the sparsely-overridden {@code dbUser} template method. + * + *

One decorator type is used throughout (so the receiver and the {@code dbInstance}/{@code + * dbHostname} template calls stay monomorphic); only the injected extractor varies, to isolate the + * question raised in review: does passing the extractor as a caller-side constant devirtualize and + * inline? + * + *

{@code mode}: + * + *

+ * + *

Run with {@code -XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining} to confirm the mechanism + * (the tree, not just the number) — look for {@code DatabaseClientDecorator::onConnection} and the + * extractor {@code extract} bodies. + */ +@State(Scope.Thread) +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(SECONDS) +@Warmup(iterations = 5, time = 2) +@Measurement(iterations = 5, time = 2) +@Fork(3) +@Threads(8) +public class DatabaseClientConnectionBenchmark { + + private static final int TYPES = 8; + private static final String CONN = "bench-user"; + + /** The mono call site: a single static-final constant extractor. */ + private static final TagExtractor MONO = new E0(); + + @Param({"mono", "mega"}) + String mode; + + private boolean mega; + private BenchDbDecorator decorator; + private AgentSpan span; + private TagExtractor[] extractors; + private int idx; + + @SuppressWarnings("unchecked") + @Setup(Level.Trial) + public void setUp() { + CoreTracer tracer = + CoreTracer.builder().strictTraceWrites(true).writer(new NoOpWriter()).build(); + GlobalTracer.forceRegister(tracer); + decorator = new BenchDbDecorator(); + span = tracer.startSpan("benchmark", "db.query"); + extractors = + new TagExtractor[] { + new E0(), new E1(), new E2(), new E3(), new E4(), new E5(), new E6(), new E7() + }; + mega = "mega".equals(mode); + } + + @Benchmark + public AgentSpan onConnection() { + if (mega) { + int i = idx; + idx = (i + 1 == TYPES) ? 0 : i + 1; + return decorator.onConnection(span, CONN, extractors[i]); + } + return decorator.onConnection(span, CONN, MONO); + } + + // Eight structurally-identical but distinct extractor types (so the mega site sees a rotating + // type). + static final class E0 implements TagExtractor { + public void extract(String c, AgentSpan s) { + s.setTag(DB_USER, c); + } + } + + static final class E1 implements TagExtractor { + public void extract(String c, AgentSpan s) { + s.setTag(DB_USER, c); + } + } + + static final class E2 implements TagExtractor { + public void extract(String c, AgentSpan s) { + s.setTag(DB_USER, c); + } + } + + static final class E3 implements TagExtractor { + public void extract(String c, AgentSpan s) { + s.setTag(DB_USER, c); + } + } + + static final class E4 implements TagExtractor { + public void extract(String c, AgentSpan s) { + s.setTag(DB_USER, c); + } + } + + static final class E5 implements TagExtractor { + public void extract(String c, AgentSpan s) { + s.setTag(DB_USER, c); + } + } + + static final class E6 implements TagExtractor { + public void extract(String c, AgentSpan s) { + s.setTag(DB_USER, c); + } + } + + static final class E7 implements TagExtractor { + public void extract(String c, AgentSpan s) { + s.setTag(DB_USER, c); + } + } + + static final class BenchDbDecorator extends DatabaseClientDecorator { + private static final CharSequence COMPONENT = UTF8BytesString.create("benchmark"); + + @Override + protected String[] instrumentationNames() { + return new String[] {"benchmark"}; + } + + @Override + protected String service() { + return "benchmark-db"; + } + + @Override + protected CharSequence component() { + return COMPONENT; + } + + @Override + protected CharSequence spanType() { + return "sql"; + } + + @Override + protected String dbType() { + return "benchdb"; + } + + @Override + protected String dbInstance(String connection) { + return connection; + } + + @Override + protected CharSequence dbHostname(String connection) { + return null; + } + } + + private static class NoOpWriter implements Writer { + @Override + public void write(final List trace) {} + + @Override + public void start() {} + + @Override + public boolean flush() { + return false; + } + + @Override + public void close() {} + + @Override + public void incrementDropCounts(final int spanCount) {} + } +} diff --git a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/decorator/DatabaseClientDecorator.java b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/decorator/DatabaseClientDecorator.java index 7336a059bdc..7c108758e24 100644 --- a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/decorator/DatabaseClientDecorator.java +++ b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/decorator/DatabaseClientDecorator.java @@ -16,6 +16,7 @@ import datadog.trace.api.naming.SpanNaming; import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.bootstrap.instrumentation.api.AgentTracer; +import datadog.trace.bootstrap.instrumentation.api.TagExtractor; import datadog.trace.bootstrap.instrumentation.api.Tags; import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; import java.util.function.BiConsumer; @@ -55,12 +56,15 @@ public String getDbType() { protected abstract String dbType(); - protected abstract String dbUser(CONNECTION connection); - protected abstract String dbInstance(CONNECTION connection); protected abstract CharSequence dbHostname(CONNECTION connection); + /** + * No-op connection-tag extractor: the default for stores that contribute no pure connection tags. + */ + private static final TagExtractor NO_CONNECTION_TAGS = (connection, span) -> {}; + /** * This should be called when the connection is being used, not when it's created. * @@ -69,8 +73,26 @@ public String getDbType() { * @return */ public AgentSpan onConnection(final AgentSpan span, final CONNECTION connection) { + return onConnection(span, connection, noConnectionTags()); + } + + /** + * As {@link #onConnection(AgentSpan, Object)}, but with a {@link TagExtractor} for the store's + * pure connection tags (e.g. {@code db.user} for SQL) injected as a parameter. + * + *

Passing the extractor as a caller-side argument — rather than fetching it from a virtual + * method — is what preserves inlining: at a monomorphic advice site the extractor is a {@code + * static final} constant, so when this (small) method inlines, {@code extractor.extract(...)} + * devirtualizes and inlines too. It replaces the previous per-store template methods (the + * sparsely overridden {@code dbUser}, which most NoSQL stores could only answer with {@code + * null}) and is the seam for disentangling pure tag extraction from the derivation below. + */ + public AgentSpan onConnection( + final AgentSpan span, + final CONNECTION connection, + final TagExtractor connectionTags) { if (connection != null) { - span.setTag(Tags.DB_USER, dbUser(connection)); + connectionTags.extract(connection, span); onInstance(span, dbInstance(connection)); CharSequence hostName = dbHostname(connection); if (hostName != null) { @@ -84,6 +106,11 @@ public AgentSpan onConnection(final AgentSpan span, final CONNECTION connection) return span; } + @SuppressWarnings("unchecked") + protected static TagExtractor noConnectionTags() { + return (TagExtractor) NO_CONNECTION_TAGS; + } + protected AgentSpan onInstance(final AgentSpan span, final String dbInstance) { if (dbInstance != null) { span.setTag(Tags.DB_INSTANCE, dbInstance); diff --git a/dd-java-agent/agent-bootstrap/src/test/groovy/datadog/trace/bootstrap/instrumentation/decorator/DBTypeProcessingDatabaseClientDecoratorTest.groovy b/dd-java-agent/agent-bootstrap/src/test/groovy/datadog/trace/bootstrap/instrumentation/decorator/DBTypeProcessingDatabaseClientDecoratorTest.groovy index 624100fcc50..c7794fcda1f 100644 --- a/dd-java-agent/agent-bootstrap/src/test/groovy/datadog/trace/bootstrap/instrumentation/decorator/DBTypeProcessingDatabaseClientDecoratorTest.groovy +++ b/dd-java-agent/agent-bootstrap/src/test/groovy/datadog/trace/bootstrap/instrumentation/decorator/DBTypeProcessingDatabaseClientDecoratorTest.groovy @@ -67,11 +67,6 @@ class DBTypeProcessingDatabaseClientDecoratorTest extends ClientDecoratorTest { return "test-db" } - @Override - protected String dbUser(Map map) { - return map.user - } - @Override protected String dbInstance(Map map) { return map.instance diff --git a/dd-java-agent/agent-bootstrap/src/test/groovy/datadog/trace/bootstrap/instrumentation/decorator/DatabaseClientDecoratorTest.groovy b/dd-java-agent/agent-bootstrap/src/test/groovy/datadog/trace/bootstrap/instrumentation/decorator/DatabaseClientDecoratorTest.groovy index 93852ccc88c..6f6bab2e8fa 100644 --- a/dd-java-agent/agent-bootstrap/src/test/groovy/datadog/trace/bootstrap/instrumentation/decorator/DatabaseClientDecoratorTest.groovy +++ b/dd-java-agent/agent-bootstrap/src/test/groovy/datadog/trace/bootstrap/instrumentation/decorator/DatabaseClientDecoratorTest.groovy @@ -51,7 +51,8 @@ class DatabaseClientDecoratorTest extends ClientDecoratorTest { then: if (session) { - 1 * span.setTag(Tags.DB_USER, session.user) + // db.user is no longer set by the 2-arg onConnection (it used to come from the dbUser template + // method); it now arrives via the connection-tags extractor of the 3-arg form (see below). if (session.instance != null) { 1 * span.setTag(Tags.DB_INSTANCE, session.instance) } @@ -88,6 +89,32 @@ class DatabaseClientDecoratorTest extends ClientDecoratorTest { true | true | true | [user: "test-user", instance: "test-instance"] } + def "test onConnection applies the connection-tags extractor"() { + setup: + def decorator = newDecorator() + def session = [user: "test-user"] + + when: + decorator.onConnection(span, session, { Map m, AgentSpan s -> s.setTag(Tags.DB_USER, m.user) }) + + then: + 1 * span.setTag(Tags.DB_USER, "test-user") + 0 * _ + } + + def "test onConnection with a null connection skips the extractor"() { + setup: + def decorator = newDecorator() + def extractor = Mock(datadog.trace.bootstrap.instrumentation.api.TagExtractor) + + when: + decorator.onConnection(span, null, extractor) + + then: + 0 * extractor.extract(_, _) + 0 * _ + } + def "test onStatement"() { setup: def decorator = newDecorator() @@ -134,11 +161,6 @@ class DatabaseClientDecoratorTest extends ClientDecoratorTest { return "test-db" } - @Override - protected String dbUser(Map map) { - return map.user - } - @Override protected String dbInstance(Map map) { return map.instance diff --git a/dd-java-agent/agent-bootstrap/src/test/groovy/datadog/trace/bootstrap/instrumentation/decorator/OrmClientDecoratorTest.groovy b/dd-java-agent/agent-bootstrap/src/test/groovy/datadog/trace/bootstrap/instrumentation/decorator/OrmClientDecoratorTest.groovy index f5c2995ccaa..8778ca6be09 100644 --- a/dd-java-agent/agent-bootstrap/src/test/groovy/datadog/trace/bootstrap/instrumentation/decorator/OrmClientDecoratorTest.groovy +++ b/dd-java-agent/agent-bootstrap/src/test/groovy/datadog/trace/bootstrap/instrumentation/decorator/OrmClientDecoratorTest.groovy @@ -35,11 +35,6 @@ class OrmClientDecoratorTest extends DatabaseClientDecoratorTest { return "test-db" } - @Override - protected String dbUser(Object o) { - return "test-user" - } - @Override protected String dbInstance(Object o) { return "test-user" diff --git a/dd-java-agent/instrumentation/aerospike-4.0/src/main/java/datadog/trace/instrumentation/aerospike4/AerospikeClientDecorator.java b/dd-java-agent/instrumentation/aerospike-4.0/src/main/java/datadog/trace/instrumentation/aerospike4/AerospikeClientDecorator.java index e00683755c9..4b403f37809 100644 --- a/dd-java-agent/instrumentation/aerospike-4.0/src/main/java/datadog/trace/instrumentation/aerospike4/AerospikeClientDecorator.java +++ b/dd-java-agent/instrumentation/aerospike-4.0/src/main/java/datadog/trace/instrumentation/aerospike4/AerospikeClientDecorator.java @@ -50,11 +50,6 @@ protected String dbType() { return DB_TYPE; } - @Override - protected String dbUser(final Node node) { - return null; - } - @Override protected String dbInstance(final Node node) { return null; diff --git a/dd-java-agent/instrumentation/couchbase/couchbase-2.0/src/main/java/datadog/trace/instrumentation/couchbase/client/CouchbaseClientDecorator.java b/dd-java-agent/instrumentation/couchbase/couchbase-2.0/src/main/java/datadog/trace/instrumentation/couchbase/client/CouchbaseClientDecorator.java index cd592761951..0b8e57673f3 100644 --- a/dd-java-agent/instrumentation/couchbase/couchbase-2.0/src/main/java/datadog/trace/instrumentation/couchbase/client/CouchbaseClientDecorator.java +++ b/dd-java-agent/instrumentation/couchbase/couchbase-2.0/src/main/java/datadog/trace/instrumentation/couchbase/client/CouchbaseClientDecorator.java @@ -42,11 +42,6 @@ protected String dbType() { return "couchbase"; } - @Override - protected String dbUser(final Object o) { - return null; - } - @Override protected String dbInstance(final Object o) { return null; diff --git a/dd-java-agent/instrumentation/couchbase/couchbase-3.1/src/main/java/datadog/trace/instrumentation/couchbase_31/client/CouchbaseClientDecorator.java b/dd-java-agent/instrumentation/couchbase/couchbase-3.1/src/main/java/datadog/trace/instrumentation/couchbase_31/client/CouchbaseClientDecorator.java index 803b53e7e49..de988fa86ee 100644 --- a/dd-java-agent/instrumentation/couchbase/couchbase-3.1/src/main/java/datadog/trace/instrumentation/couchbase_31/client/CouchbaseClientDecorator.java +++ b/dd-java-agent/instrumentation/couchbase/couchbase-3.1/src/main/java/datadog/trace/instrumentation/couchbase_31/client/CouchbaseClientDecorator.java @@ -51,11 +51,6 @@ protected String dbType() { return DB_TYPE; } - @Override - protected String dbUser(final Object o) { - return null; - } - @Override protected String dbInstance(final Object o) { return null; diff --git a/dd-java-agent/instrumentation/couchbase/couchbase-3.2/src/main/java/datadog/trace/instrumentation/couchbase_32/client/CouchbaseClientDecorator.java b/dd-java-agent/instrumentation/couchbase/couchbase-3.2/src/main/java/datadog/trace/instrumentation/couchbase_32/client/CouchbaseClientDecorator.java index 642f88eb739..985cf901f6d 100644 --- a/dd-java-agent/instrumentation/couchbase/couchbase-3.2/src/main/java/datadog/trace/instrumentation/couchbase_32/client/CouchbaseClientDecorator.java +++ b/dd-java-agent/instrumentation/couchbase/couchbase-3.2/src/main/java/datadog/trace/instrumentation/couchbase_32/client/CouchbaseClientDecorator.java @@ -51,11 +51,6 @@ protected String dbType() { return DB_TYPE; } - @Override - protected String dbUser(final Object o) { - return null; - } - @Override protected String dbInstance(final Object o) { return null; diff --git a/dd-java-agent/instrumentation/datanucleus-4.0.5/src/main/java/datadog/trace/instrumentation/datanucleus/DatanucleusDecorator.java b/dd-java-agent/instrumentation/datanucleus-4.0.5/src/main/java/datadog/trace/instrumentation/datanucleus/DatanucleusDecorator.java index bbd970de659..1de3ea5b480 100644 --- a/dd-java-agent/instrumentation/datanucleus-4.0.5/src/main/java/datadog/trace/instrumentation/datanucleus/DatanucleusDecorator.java +++ b/dd-java-agent/instrumentation/datanucleus-4.0.5/src/main/java/datadog/trace/instrumentation/datanucleus/DatanucleusDecorator.java @@ -68,11 +68,6 @@ protected String dbType() { return null; } - @Override - protected String dbUser(final Object o) { - return null; - } - @Override protected String dbInstance(final Object o) { return null; diff --git a/dd-java-agent/instrumentation/datastax-cassandra/datastax-cassandra-3.0/src/main/java/datadog/trace/instrumentation/datastax/cassandra/CassandraClientDecorator.java b/dd-java-agent/instrumentation/datastax-cassandra/datastax-cassandra-3.0/src/main/java/datadog/trace/instrumentation/datastax/cassandra/CassandraClientDecorator.java index 09f83cd84fa..a3967b4c4d2 100644 --- a/dd-java-agent/instrumentation/datastax-cassandra/datastax-cassandra-3.0/src/main/java/datadog/trace/instrumentation/datastax/cassandra/CassandraClientDecorator.java +++ b/dd-java-agent/instrumentation/datastax-cassandra/datastax-cassandra-3.0/src/main/java/datadog/trace/instrumentation/datastax/cassandra/CassandraClientDecorator.java @@ -62,11 +62,6 @@ protected String dbType() { return DB_TYPE; } - @Override - protected String dbUser(final Session session) { - return null; - } - @Override protected String dbInstance(final Session session) { return session.getLoggedKeyspace(); diff --git a/dd-java-agent/instrumentation/datastax-cassandra/datastax-cassandra-4.0/src/main/java/datadog/trace/instrumentation/datastax/cassandra4/CassandraClientDecorator.java b/dd-java-agent/instrumentation/datastax-cassandra/datastax-cassandra-4.0/src/main/java/datadog/trace/instrumentation/datastax/cassandra4/CassandraClientDecorator.java index 73badd7fbd2..a4356c6f74c 100644 --- a/dd-java-agent/instrumentation/datastax-cassandra/datastax-cassandra-4.0/src/main/java/datadog/trace/instrumentation/datastax/cassandra4/CassandraClientDecorator.java +++ b/dd-java-agent/instrumentation/datastax-cassandra/datastax-cassandra-4.0/src/main/java/datadog/trace/instrumentation/datastax/cassandra4/CassandraClientDecorator.java @@ -67,11 +67,6 @@ protected String dbType() { return DB_TYPE; } - @Override - protected String dbUser(final Session session) { - return null; - } - @Override protected String dbInstance(final Session session) { return session.getKeyspace().map(Objects::toString).orElse(null); diff --git a/dd-java-agent/instrumentation/elasticsearch/elasticsearch-common/src/main/java/datadog/trace/instrumentation/elasticsearch/ElasticsearchRestClientDecorator.java b/dd-java-agent/instrumentation/elasticsearch/elasticsearch-common/src/main/java/datadog/trace/instrumentation/elasticsearch/ElasticsearchRestClientDecorator.java index 0741e14a39e..ea133164520 100644 --- a/dd-java-agent/instrumentation/elasticsearch/elasticsearch-common/src/main/java/datadog/trace/instrumentation/elasticsearch/ElasticsearchRestClientDecorator.java +++ b/dd-java-agent/instrumentation/elasticsearch/elasticsearch-common/src/main/java/datadog/trace/instrumentation/elasticsearch/ElasticsearchRestClientDecorator.java @@ -57,11 +57,6 @@ protected String dbType() { return "elasticsearch"; } - @Override - protected String dbUser(final Object o) { - return null; - } - @Override protected String dbInstance(final Object o) { return null; diff --git a/dd-java-agent/instrumentation/elasticsearch/elasticsearch-common/src/main/java/datadog/trace/instrumentation/elasticsearch/ElasticsearchTransportClientDecorator.java b/dd-java-agent/instrumentation/elasticsearch/elasticsearch-common/src/main/java/datadog/trace/instrumentation/elasticsearch/ElasticsearchTransportClientDecorator.java index 172a7a56ef8..0ceb11c5bfd 100644 --- a/dd-java-agent/instrumentation/elasticsearch/elasticsearch-common/src/main/java/datadog/trace/instrumentation/elasticsearch/ElasticsearchTransportClientDecorator.java +++ b/dd-java-agent/instrumentation/elasticsearch/elasticsearch-common/src/main/java/datadog/trace/instrumentation/elasticsearch/ElasticsearchTransportClientDecorator.java @@ -45,11 +45,6 @@ protected String dbType() { return DB_TYPE; } - @Override - protected String dbUser(final Object o) { - return null; - } - @Override protected String dbInstance(final Object o) { return null; diff --git a/dd-java-agent/instrumentation/hibernate/hibernate-common/src/main/java/datadog/trace/instrumentation/hibernate/HibernateDecorator.java b/dd-java-agent/instrumentation/hibernate/hibernate-common/src/main/java/datadog/trace/instrumentation/hibernate/HibernateDecorator.java index 6c7aa6b9798..e7f4136e139 100644 --- a/dd-java-agent/instrumentation/hibernate/hibernate-common/src/main/java/datadog/trace/instrumentation/hibernate/HibernateDecorator.java +++ b/dd-java-agent/instrumentation/hibernate/hibernate-common/src/main/java/datadog/trace/instrumentation/hibernate/HibernateDecorator.java @@ -40,11 +40,6 @@ protected String dbType() { return null; } - @Override - protected String dbUser(final Object o) { - return null; - } - @Override protected String dbInstance(final Object o) { return null; diff --git a/dd-java-agent/instrumentation/ignite-2.0/src/main/java/datadog/trace/instrumentation/ignite/v2/cache/IgniteCacheDecorator.java b/dd-java-agent/instrumentation/ignite-2.0/src/main/java/datadog/trace/instrumentation/ignite/v2/cache/IgniteCacheDecorator.java index ef372f24a06..64b2649f7b8 100644 --- a/dd-java-agent/instrumentation/ignite-2.0/src/main/java/datadog/trace/instrumentation/ignite/v2/cache/IgniteCacheDecorator.java +++ b/dd-java-agent/instrumentation/ignite-2.0/src/main/java/datadog/trace/instrumentation/ignite/v2/cache/IgniteCacheDecorator.java @@ -56,11 +56,6 @@ protected String dbType() { return DB_TYPE; } - @Override - protected String dbUser(IgniteCache igniteCache) { - return null; - } - @Override protected String dbInstance(IgniteCache igniteCache) { return null; diff --git a/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/ConnectionInfoExtractor.java b/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/ConnectionInfoExtractor.java index 4f001e3c73f..db1d0b4c14d 100644 --- a/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/ConnectionInfoExtractor.java +++ b/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/ConnectionInfoExtractor.java @@ -2,6 +2,7 @@ import static datadog.trace.bootstrap.instrumentation.api.Tags.DB_POOL_NAME; import static datadog.trace.bootstrap.instrumentation.api.Tags.DB_SCHEMA; +import static datadog.trace.bootstrap.instrumentation.api.Tags.DB_USER; import static datadog.trace.bootstrap.instrumentation.api.Tags.DB_WAREHOUSE; import datadog.trace.bootstrap.instrumentation.api.AgentSpan; @@ -27,6 +28,9 @@ private ConnectionInfoExtractor() {} @Override public void extract(final DBInfo info, final AgentSpan span) { + // DB_USER is set unconditionally to preserve the prior DatabaseClientDecorator behavior (it set + // db.user from dbUser(info) without a present-check); the rest skip null/empty. + span.setTag(DB_USER, info.getUser()); setTagIfPresent(span, DB_WAREHOUSE, info.getWarehouse()); setTagIfPresent(span, DB_SCHEMA, info.getSchema()); setTagIfPresent(span, DB_POOL_NAME, info.getPoolName()); diff --git a/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/JDBCDecorator.java b/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/JDBCDecorator.java index 32b59beafbc..d3799172c20 100644 --- a/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/JDBCDecorator.java +++ b/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/JDBCDecorator.java @@ -128,11 +128,6 @@ protected String dbType() { return "jdbc"; } - @Override - protected String dbUser(final DBInfo info) { - return info.getUser(); - } - @Override protected String dbInstance(final DBInfo info) { if (info.getInstance() != null) { @@ -150,10 +145,10 @@ protected String dbHostname(final DBInfo info) { public AgentSpan onConnection(final AgentSpan span, DBInfo dbInfo) { if (dbInfo != null) { processDatabaseType(span, dbInfo.getType()); - - span.setTags(dbInfo, ConnectionInfoExtractor.INSTANCE); } - return super.onConnection(span, dbInfo); + // Pure connection tags (db.user / warehouse / schema / pool) are injected via the param form; + // the base applies them under its own null-check alongside instance/hostname derivation. + return super.onConnection(span, dbInfo, ConnectionInfoExtractor.INSTANCE); } public static DBInfo parseDBInfo( diff --git a/dd-java-agent/instrumentation/jedis/jedis-1.4/src/main/java/datadog/trace/instrumentation/jedis/JedisClientDecorator.java b/dd-java-agent/instrumentation/jedis/jedis-1.4/src/main/java/datadog/trace/instrumentation/jedis/JedisClientDecorator.java index f85167f6ba2..012880d4a5b 100644 --- a/dd-java-agent/instrumentation/jedis/jedis-1.4/src/main/java/datadog/trace/instrumentation/jedis/JedisClientDecorator.java +++ b/dd-java-agent/instrumentation/jedis/jedis-1.4/src/main/java/datadog/trace/instrumentation/jedis/JedisClientDecorator.java @@ -40,11 +40,6 @@ protected String dbType() { return REDIS; } - @Override - protected String dbUser(final Connection connection) { - return null; - } - @Override protected String dbInstance(final Connection connection) { return null; diff --git a/dd-java-agent/instrumentation/jedis/jedis-3.0/src/main/java/datadog/trace/instrumentation/jedis30/JedisClientDecorator.java b/dd-java-agent/instrumentation/jedis/jedis-3.0/src/main/java/datadog/trace/instrumentation/jedis30/JedisClientDecorator.java index edaaa9278b3..e0bd1c94911 100644 --- a/dd-java-agent/instrumentation/jedis/jedis-3.0/src/main/java/datadog/trace/instrumentation/jedis30/JedisClientDecorator.java +++ b/dd-java-agent/instrumentation/jedis/jedis-3.0/src/main/java/datadog/trace/instrumentation/jedis30/JedisClientDecorator.java @@ -41,11 +41,6 @@ protected String dbType() { return REDIS; } - @Override - protected String dbUser(final Connection connection) { - return null; - } - @Override protected String dbInstance(final Connection connection) { return null; diff --git a/dd-java-agent/instrumentation/jedis/jedis-4.0/src/main/java/redis/clients/jedis/JedisClientDecorator.java b/dd-java-agent/instrumentation/jedis/jedis-4.0/src/main/java/redis/clients/jedis/JedisClientDecorator.java index ccbfc3d3418..8e8e51027dd 100644 --- a/dd-java-agent/instrumentation/jedis/jedis-4.0/src/main/java/redis/clients/jedis/JedisClientDecorator.java +++ b/dd-java-agent/instrumentation/jedis/jedis-4.0/src/main/java/redis/clients/jedis/JedisClientDecorator.java @@ -40,11 +40,6 @@ protected String dbType() { return REDIS; } - @Override - protected String dbUser(final Connection connection) { - return null; - } - @Override protected String dbInstance(final Connection connection) { return null; diff --git a/dd-java-agent/instrumentation/lettuce/lettuce-4.0/src/main/java/datadog/trace/instrumentation/lettuce4/LettuceClientDecorator.java b/dd-java-agent/instrumentation/lettuce/lettuce-4.0/src/main/java/datadog/trace/instrumentation/lettuce4/LettuceClientDecorator.java index 31b8c2e67e2..034fbd8fb28 100644 --- a/dd-java-agent/instrumentation/lettuce/lettuce-4.0/src/main/java/datadog/trace/instrumentation/lettuce4/LettuceClientDecorator.java +++ b/dd-java-agent/instrumentation/lettuce/lettuce-4.0/src/main/java/datadog/trace/instrumentation/lettuce4/LettuceClientDecorator.java @@ -45,11 +45,6 @@ protected String dbType() { return "redis"; } - @Override - protected String dbUser(final RedisURI connection) { - return null; - } - @Override protected String dbInstance(final RedisURI connection) { return null; diff --git a/dd-java-agent/instrumentation/lettuce/lettuce-5.0/src/main/java/datadog/trace/instrumentation/lettuce5/LettuceClientDecorator.java b/dd-java-agent/instrumentation/lettuce/lettuce-5.0/src/main/java/datadog/trace/instrumentation/lettuce5/LettuceClientDecorator.java index a8442a1f320..00b2582295d 100644 --- a/dd-java-agent/instrumentation/lettuce/lettuce-5.0/src/main/java/datadog/trace/instrumentation/lettuce5/LettuceClientDecorator.java +++ b/dd-java-agent/instrumentation/lettuce/lettuce-5.0/src/main/java/datadog/trace/instrumentation/lettuce5/LettuceClientDecorator.java @@ -41,11 +41,6 @@ protected String dbType() { return "redis"; } - @Override - protected String dbUser(final RedisURI connection) { - return null; - } - @Override protected String dbInstance(final RedisURI connection) { return null; diff --git a/dd-java-agent/instrumentation/mongo/mongo-common/src/main/java/datadog/trace/instrumentation/mongo/MongoDecorator.java b/dd-java-agent/instrumentation/mongo/mongo-common/src/main/java/datadog/trace/instrumentation/mongo/MongoDecorator.java index bb6c0f7d8bd..030586fdf53 100644 --- a/dd-java-agent/instrumentation/mongo/mongo-common/src/main/java/datadog/trace/instrumentation/mongo/MongoDecorator.java +++ b/dd-java-agent/instrumentation/mongo/mongo-common/src/main/java/datadog/trace/instrumentation/mongo/MongoDecorator.java @@ -52,11 +52,6 @@ protected final String dbType() { return DB_TYPE; } - @Override - protected final String dbUser(final CommandStartedEvent event) { - return null; - } - @Override protected final String dbHostname(CommandStartedEvent event) { final ConnectionDescription connectionDescription = event.getConnectionDescription(); diff --git a/dd-java-agent/instrumentation/opensearch/opensearch-common/src/main/java/datadog/trace/instrumentation/opensearch/OpensearchRestClientDecorator.java b/dd-java-agent/instrumentation/opensearch/opensearch-common/src/main/java/datadog/trace/instrumentation/opensearch/OpensearchRestClientDecorator.java index ec07a1c8e55..0d98fe70401 100644 --- a/dd-java-agent/instrumentation/opensearch/opensearch-common/src/main/java/datadog/trace/instrumentation/opensearch/OpensearchRestClientDecorator.java +++ b/dd-java-agent/instrumentation/opensearch/opensearch-common/src/main/java/datadog/trace/instrumentation/opensearch/OpensearchRestClientDecorator.java @@ -55,11 +55,6 @@ protected String dbType() { return "opensearch"; } - @Override - protected String dbUser(final Object o) { - return null; - } - @Override protected String dbInstance(final Object o) { return null; diff --git a/dd-java-agent/instrumentation/opensearch/opensearch-common/src/main/java/datadog/trace/instrumentation/opensearch/OpensearchTransportClientDecorator.java b/dd-java-agent/instrumentation/opensearch/opensearch-common/src/main/java/datadog/trace/instrumentation/opensearch/OpensearchTransportClientDecorator.java index a91b3dffcbc..b36fe4ac655 100644 --- a/dd-java-agent/instrumentation/opensearch/opensearch-common/src/main/java/datadog/trace/instrumentation/opensearch/OpensearchTransportClientDecorator.java +++ b/dd-java-agent/instrumentation/opensearch/opensearch-common/src/main/java/datadog/trace/instrumentation/opensearch/OpensearchTransportClientDecorator.java @@ -44,11 +44,6 @@ protected String dbType() { return DB_TYPE; } - @Override - protected String dbUser(final Object o) { - return null; - } - @Override protected String dbInstance(final Object o) { return null; diff --git a/dd-java-agent/instrumentation/rediscala-1.8/src/main/java/datadog/trace/instrumentation/rediscala/RediscalaClientDecorator.java b/dd-java-agent/instrumentation/rediscala-1.8/src/main/java/datadog/trace/instrumentation/rediscala/RediscalaClientDecorator.java index 3205409a63e..303bbc8e71c 100644 --- a/dd-java-agent/instrumentation/rediscala-1.8/src/main/java/datadog/trace/instrumentation/rediscala/RediscalaClientDecorator.java +++ b/dd-java-agent/instrumentation/rediscala-1.8/src/main/java/datadog/trace/instrumentation/rediscala/RediscalaClientDecorator.java @@ -43,11 +43,6 @@ protected String dbType() { return "redis"; } - @Override - protected String dbUser(final RedisConnectionInfo redisConnectionInfo) { - return null; - } - @Override protected String dbInstance(final RedisConnectionInfo redisConnectionInfo) { return null; diff --git a/dd-java-agent/instrumentation/redisson/redisson-2.0.0/src/main/java/datadog/trace/instrumentation/redisson/RedissonClientDecorator.java b/dd-java-agent/instrumentation/redisson/redisson-2.0.0/src/main/java/datadog/trace/instrumentation/redisson/RedissonClientDecorator.java index 481fd745e3b..d115e6883bb 100644 --- a/dd-java-agent/instrumentation/redisson/redisson-2.0.0/src/main/java/datadog/trace/instrumentation/redisson/RedissonClientDecorator.java +++ b/dd-java-agent/instrumentation/redisson/redisson-2.0.0/src/main/java/datadog/trace/instrumentation/redisson/RedissonClientDecorator.java @@ -42,11 +42,6 @@ protected String dbType() { return "redis"; } - @Override - protected String dbUser(CommandData commandData) { - return null; - } - @Override protected String dbInstance(CommandData commandData) { return null; diff --git a/dd-java-agent/instrumentation/redisson/redisson-2.3.0/src/main/java/datadog/trace/instrumentation/redisson23/RedissonClientDecorator.java b/dd-java-agent/instrumentation/redisson/redisson-2.3.0/src/main/java/datadog/trace/instrumentation/redisson23/RedissonClientDecorator.java index 19e452b3f14..cfc96c62da5 100644 --- a/dd-java-agent/instrumentation/redisson/redisson-2.3.0/src/main/java/datadog/trace/instrumentation/redisson23/RedissonClientDecorator.java +++ b/dd-java-agent/instrumentation/redisson/redisson-2.3.0/src/main/java/datadog/trace/instrumentation/redisson23/RedissonClientDecorator.java @@ -42,11 +42,6 @@ protected String dbType() { return "redis"; } - @Override - protected String dbUser(CommandData commandData) { - return null; - } - @Override protected String dbInstance(CommandData commandData) { return null; diff --git a/dd-java-agent/instrumentation/redisson/redisson-3.10.3/src/main/java/datadog/trace/instrumentation/redisson30/RedissonClientDecorator.java b/dd-java-agent/instrumentation/redisson/redisson-3.10.3/src/main/java/datadog/trace/instrumentation/redisson30/RedissonClientDecorator.java index 4d157fb8f06..3fe22fddc6d 100644 --- a/dd-java-agent/instrumentation/redisson/redisson-3.10.3/src/main/java/datadog/trace/instrumentation/redisson30/RedissonClientDecorator.java +++ b/dd-java-agent/instrumentation/redisson/redisson-3.10.3/src/main/java/datadog/trace/instrumentation/redisson30/RedissonClientDecorator.java @@ -42,11 +42,6 @@ protected String dbType() { return "redis"; } - @Override - protected String dbUser(CommandData commandData) { - return null; - } - @Override protected String dbInstance(CommandData commandData) { return null; diff --git a/dd-java-agent/instrumentation/spymemcached-2.10/src/main/java/datadog/trace/instrumentation/spymemcached/MemcacheClientDecorator.java b/dd-java-agent/instrumentation/spymemcached-2.10/src/main/java/datadog/trace/instrumentation/spymemcached/MemcacheClientDecorator.java index bcfc58674d5..ea01cf282b5 100644 --- a/dd-java-agent/instrumentation/spymemcached-2.10/src/main/java/datadog/trace/instrumentation/spymemcached/MemcacheClientDecorator.java +++ b/dd-java-agent/instrumentation/spymemcached-2.10/src/main/java/datadog/trace/instrumentation/spymemcached/MemcacheClientDecorator.java @@ -44,11 +44,6 @@ protected String dbType() { return DB_TYPE; } - @Override - protected String dbUser(final MemcachedConnection session) { - return null; - } - @Override protected String dbInstance(final MemcachedConnection connection) { return null; diff --git a/dd-java-agent/instrumentation/valkey-java-5.3/src/main/java/io/valkey/ValkeyClientDecorator.java b/dd-java-agent/instrumentation/valkey-java-5.3/src/main/java/io/valkey/ValkeyClientDecorator.java index 0e0e6cf43bf..ebb8ef0bc6c 100644 --- a/dd-java-agent/instrumentation/valkey-java-5.3/src/main/java/io/valkey/ValkeyClientDecorator.java +++ b/dd-java-agent/instrumentation/valkey-java-5.3/src/main/java/io/valkey/ValkeyClientDecorator.java @@ -40,11 +40,6 @@ protected String dbType() { return VALKEY; } - @Override - protected String dbUser(final Connection connection) { - return null; - } - @Override protected String dbInstance(final Connection connection) { return null; diff --git a/dd-java-agent/instrumentation/vertx/vertx-redis-client/vertx-redis-client-3.9/src/main/java/datadog/trace/instrumentation/vertx_redis_client/VertxRedisClientDecorator.java b/dd-java-agent/instrumentation/vertx/vertx-redis-client/vertx-redis-client-3.9/src/main/java/datadog/trace/instrumentation/vertx_redis_client/VertxRedisClientDecorator.java index dec7fe39d02..f04c3498365 100644 --- a/dd-java-agent/instrumentation/vertx/vertx-redis-client/vertx-redis-client-3.9/src/main/java/datadog/trace/instrumentation/vertx_redis_client/VertxRedisClientDecorator.java +++ b/dd-java-agent/instrumentation/vertx/vertx-redis-client/vertx-redis-client-3.9/src/main/java/datadog/trace/instrumentation/vertx_redis_client/VertxRedisClientDecorator.java @@ -54,11 +54,6 @@ protected String dbType() { return "redis"; } - @Override - protected String dbUser(final SocketAddress socketAddress) { - return null; - } - @Override protected String dbInstance(final SocketAddress socketAddress) { return null; diff --git a/dd-java-agent/instrumentation/vertx/vertx-sql-client-3.9/src/main/java/datadog/trace/instrumentation/vertx_sql_client_39/VertxSqlClientDecorator.java b/dd-java-agent/instrumentation/vertx/vertx-sql-client-3.9/src/main/java/datadog/trace/instrumentation/vertx_sql_client_39/VertxSqlClientDecorator.java index d95a6c65137..43fcb7f268e 100644 --- a/dd-java-agent/instrumentation/vertx/vertx-sql-client-3.9/src/main/java/datadog/trace/instrumentation/vertx_sql_client_39/VertxSqlClientDecorator.java +++ b/dd-java-agent/instrumentation/vertx/vertx-sql-client-3.9/src/main/java/datadog/trace/instrumentation/vertx_sql_client_39/VertxSqlClientDecorator.java @@ -53,11 +53,6 @@ protected String dbType() { return "vertx-sql"; } - @Override - protected String dbUser(final DBInfo info) { - return info.getUser(); - } - @Override protected String dbInstance(final DBInfo info) { if (info.getInstance() != null) { @@ -92,7 +87,7 @@ public AgentSpan startAndDecorateSpanForStatement( if (dbInfo != null) { processDatabaseType(span, dbInfo.getType()); } - super.onConnection(span, dbInfo); + super.onConnection(span, dbInfo, VertxSqlConnectionExtractor.INSTANCE); if (null != dbQueryInfo) { span.setResourceName(dbQueryInfo.getSql()); span.setTag(DB_OPERATION, dbQueryInfo.getOperation()); diff --git a/dd-java-agent/instrumentation/vertx/vertx-sql-client-3.9/src/main/java/datadog/trace/instrumentation/vertx_sql_client_39/VertxSqlConnectionExtractor.java b/dd-java-agent/instrumentation/vertx/vertx-sql-client-3.9/src/main/java/datadog/trace/instrumentation/vertx_sql_client_39/VertxSqlConnectionExtractor.java new file mode 100644 index 00000000000..880188e2826 --- /dev/null +++ b/dd-java-agent/instrumentation/vertx/vertx-sql-client-3.9/src/main/java/datadog/trace/instrumentation/vertx_sql_client_39/VertxSqlConnectionExtractor.java @@ -0,0 +1,26 @@ +package datadog.trace.instrumentation.vertx_sql_client_39; + +import static datadog.trace.bootstrap.instrumentation.api.Tags.DB_USER; + +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import datadog.trace.bootstrap.instrumentation.api.TagExtractor; +import datadog.trace.bootstrap.instrumentation.jdbc.DBInfo; + +/** + * Named singleton {@link TagExtractor} for Vertx-SQL's pure connection tags ({@code db.user}). The + * SQL-family counterpart to the NoSQL stores that contribute none — injected via the param form of + * {@code DatabaseClientDecorator.onConnection} rather than the removed {@code dbUser} template + * method. + */ +public final class VertxSqlConnectionExtractor implements TagExtractor { + public static final VertxSqlConnectionExtractor INSTANCE = new VertxSqlConnectionExtractor(); + + private VertxSqlConnectionExtractor() {} + + @Override + public void extract(final DBInfo info, final AgentSpan span) { + // Unconditional to preserve the prior DatabaseClientDecorator behavior (db.user was set from + // dbUser(info) with no present-check). + span.setTag(DB_USER, info.getUser()); + } +}