From a19f73a5ea4bef8936a6931530a40a99fb1b7261 Mon Sep 17 00:00:00 2001 From: Andrea Marziali Date: Wed, 18 Dec 2024 11:29:53 +0100 Subject: [PATCH] Dynamically evaluate service name for message consumers (#8088) * Dynamically evaluate service name for message consumers * Do complex logic only when the FF is enabled --- .../aws/v1/sqs/SqsDecorator.java | 9 +- .../src/test/groovy/SqsClientTest.groovy | 2 +- .../aws/v2/sqs/SqsDecorator.java | 10 +- .../src/test/groovy/SqsClientTest.groovy | 2 +- .../googlepubsub/PubSubDecorator.java | 10 +- .../jakarta/jms/JMSDecorator.java | 12 ++- .../instrumentation/jms/JMSDecorator.java | 12 ++- .../kafka_clients/KafkaDecorator.java | 10 +- .../kafka_clients38/KafkaDecorator.java | 10 +- .../kafka_streams/KafkaStreamsDecorator.java | 10 +- .../rabbitmq/amqp/RabbitDecorator.java | 10 +- .../api/naming/MessagingNamingBenchmark.java | 96 +++++++++++++++++++ .../trace/api/naming/NamingSchema.java | 11 ++- .../api/naming/v0/MessagingNamingV0.java | 47 ++++++--- .../api/naming/v1/MessagingNamingV1.java | 16 ++-- .../api/naming/NamingV0ForkedTest.groovy | 4 +- 16 files changed, 206 insertions(+), 65 deletions(-) create mode 100644 dd-trace-core/src/jmh/java/datadog/trace/api/naming/MessagingNamingBenchmark.java diff --git a/dd-java-agent/instrumentation/aws-java-sqs-1.0/src/main/java/datadog/trace/instrumentation/aws/v1/sqs/SqsDecorator.java b/dd-java-agent/instrumentation/aws-java-sqs-1.0/src/main/java/datadog/trace/instrumentation/aws/v1/sqs/SqsDecorator.java index 560e05fe5de..a306525a91e 100644 --- a/dd-java-agent/instrumentation/aws-java-sqs-1.0/src/main/java/datadog/trace/instrumentation/aws/v1/sqs/SqsDecorator.java +++ b/dd-java-agent/instrumentation/aws-java-sqs-1.0/src/main/java/datadog/trace/instrumentation/aws/v1/sqs/SqsDecorator.java @@ -10,6 +10,7 @@ import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; import datadog.trace.bootstrap.instrumentation.decorator.MessagingClientDecorator; +import java.util.function.Supplier; public class SqsDecorator extends MessagingClientDecorator { static final CharSequence COMPONENT_NAME = UTF8BytesString.create("java-aws-sdk"); @@ -25,7 +26,7 @@ public class SqsDecorator extends MessagingClientDecorator { Config.get().isTimeInQueueEnabled(!SQS_LEGACY_TRACING, "sqs"); private final String spanKind; private final CharSequence spanType; - private final String serviceName; + private final Supplier serviceNameSupplier; public static final SqsDecorator CONSUMER_DECORATE = new SqsDecorator( @@ -42,10 +43,10 @@ public class SqsDecorator extends MessagingClientDecorator { MESSAGE_BROKER, SpanNaming.instance().namingSchema().messaging().timeInQueueService("sqs")); - protected SqsDecorator(String spanKind, CharSequence spanType, String serviceName) { + protected SqsDecorator(String spanKind, CharSequence spanType, Supplier serviceName) { this.spanKind = spanKind; this.spanType = spanType; - this.serviceName = serviceName; + this.serviceNameSupplier = serviceName; } @Override @@ -60,7 +61,7 @@ protected String[] instrumentationNames() { @Override protected String service() { - return serviceName; + return serviceNameSupplier.get(); } @Override diff --git a/dd-java-agent/instrumentation/aws-java-sqs-1.0/src/test/groovy/SqsClientTest.groovy b/dd-java-agent/instrumentation/aws-java-sqs-1.0/src/test/groovy/SqsClientTest.groovy index 64fa37fab99..e2d3961f79e 100644 --- a/dd-java-agent/instrumentation/aws-java-sqs-1.0/src/test/groovy/SqsClientTest.groovy +++ b/dd-java-agent/instrumentation/aws-java-sqs-1.0/src/test/groovy/SqsClientTest.groovy @@ -407,7 +407,7 @@ abstract class SqsClientTest extends VersionedNamingTestBase { } trace(1) { span { - serviceName SpanNaming.instance().namingSchema().messaging().inboundService("jms", Config.get().isJmsLegacyTracingEnabled()) ?: Config.get().getServiceName() + serviceName SpanNaming.instance().namingSchema().messaging().inboundService("jms", Config.get().isJmsLegacyTracingEnabled()).get() ?: Config.get().getServiceName() operationName SpanNaming.instance().namingSchema().messaging().inboundOperation("jms") resourceName "Consumed from Queue somequeue" spanType DDSpanTypes.MESSAGE_CONSUMER diff --git a/dd-java-agent/instrumentation/aws-java-sqs-2.0/src/main/java/datadog/trace/instrumentation/aws/v2/sqs/SqsDecorator.java b/dd-java-agent/instrumentation/aws-java-sqs-2.0/src/main/java/datadog/trace/instrumentation/aws/v2/sqs/SqsDecorator.java index e3daf13584d..661a7fdccdd 100644 --- a/dd-java-agent/instrumentation/aws-java-sqs-2.0/src/main/java/datadog/trace/instrumentation/aws/v2/sqs/SqsDecorator.java +++ b/dd-java-agent/instrumentation/aws-java-sqs-2.0/src/main/java/datadog/trace/instrumentation/aws/v2/sqs/SqsDecorator.java @@ -10,6 +10,7 @@ import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; import datadog.trace.bootstrap.instrumentation.decorator.MessagingClientDecorator; +import java.util.function.Supplier; public class SqsDecorator extends MessagingClientDecorator { static final CharSequence COMPONENT_NAME = UTF8BytesString.create("java-aws-sdk"); @@ -26,7 +27,7 @@ public class SqsDecorator extends MessagingClientDecorator { Config.get().isTimeInQueueEnabled(!SQS_LEGACY_TRACING, "sqs"); private final String spanKind; private final CharSequence spanType; - private final String serviceName; + private final Supplier serviceNameSupplier; public static final SqsDecorator CONSUMER_DECORATE = new SqsDecorator( @@ -43,10 +44,11 @@ public class SqsDecorator extends MessagingClientDecorator { MESSAGE_BROKER, SpanNaming.instance().namingSchema().messaging().timeInQueueService("sqs")); - protected SqsDecorator(String spanKind, CharSequence spanType, String serviceName) { + protected SqsDecorator( + String spanKind, CharSequence spanType, Supplier serviceNameSupplier) { this.spanKind = spanKind; this.spanType = spanType; - this.serviceName = serviceName; + this.serviceNameSupplier = serviceNameSupplier; } @Override @@ -61,7 +63,7 @@ protected String[] instrumentationNames() { @Override protected String service() { - return serviceName; + return serviceNameSupplier.get(); } @Override diff --git a/dd-java-agent/instrumentation/aws-java-sqs-2.0/src/test/groovy/SqsClientTest.groovy b/dd-java-agent/instrumentation/aws-java-sqs-2.0/src/test/groovy/SqsClientTest.groovy index c62e653901b..c0a1085d6ad 100644 --- a/dd-java-agent/instrumentation/aws-java-sqs-2.0/src/test/groovy/SqsClientTest.groovy +++ b/dd-java-agent/instrumentation/aws-java-sqs-2.0/src/test/groovy/SqsClientTest.groovy @@ -419,7 +419,7 @@ abstract class SqsClientTest extends VersionedNamingTestBase { } trace(1) { span { - serviceName SpanNaming.instance().namingSchema().messaging().inboundService("jms", Config.get().isJmsLegacyTracingEnabled()) ?: Config.get().getServiceName() + serviceName SpanNaming.instance().namingSchema().messaging().inboundService("jms", Config.get().isJmsLegacyTracingEnabled()).get() ?: Config.get().getServiceName() operationName SpanNaming.instance().namingSchema().messaging().inboundOperation("jms") resourceName "Consumed from Queue somequeue" spanType DDSpanTypes.MESSAGE_CONSUMER diff --git a/dd-java-agent/instrumentation/google-pubsub/src/main/java/datadog/trace/instrumentation/googlepubsub/PubSubDecorator.java b/dd-java-agent/instrumentation/google-pubsub/src/main/java/datadog/trace/instrumentation/googlepubsub/PubSubDecorator.java index 24ba0778893..75d8608e1cf 100644 --- a/dd-java-agent/instrumentation/google-pubsub/src/main/java/datadog/trace/instrumentation/googlepubsub/PubSubDecorator.java +++ b/dd-java-agent/instrumentation/google-pubsub/src/main/java/datadog/trace/instrumentation/googlepubsub/PubSubDecorator.java @@ -22,6 +22,7 @@ import datadog.trace.bootstrap.instrumentation.decorator.MessagingClientDecorator; import java.util.LinkedHashMap; import java.util.function.Function; +import java.util.function.Supplier; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -91,12 +92,13 @@ public CharSequence apply(CharSequence input) { .inboundService(PUBSUB, Config.get().isGooglePubSubLegacyTracingEnabled())); private final String spanKind; private final CharSequence spanType; - private final String serviceName; + private final Supplier serviceNameSupplier; - protected PubSubDecorator(String spanKind, CharSequence spanType, String serviceName) { + protected PubSubDecorator( + String spanKind, CharSequence spanType, Supplier serviceNameSupplier) { this.spanKind = spanKind; this.spanType = spanType; - this.serviceName = serviceName; + this.serviceNameSupplier = serviceNameSupplier; } @Override @@ -111,7 +113,7 @@ protected String[] instrumentationNames() { @Override protected String service() { - return serviceName; + return serviceNameSupplier.get(); } @Override diff --git a/dd-java-agent/instrumentation/jakarta-jms/src/main/java/datadog/trace/instrumentation/jakarta/jms/JMSDecorator.java b/dd-java-agent/instrumentation/jakarta-jms/src/main/java/datadog/trace/instrumentation/jakarta/jms/JMSDecorator.java index d8825b1e7a2..7d4b7530de9 100644 --- a/dd-java-agent/instrumentation/jakarta-jms/src/main/java/datadog/trace/instrumentation/jakarta/jms/JMSDecorator.java +++ b/dd-java-agent/instrumentation/jakarta-jms/src/main/java/datadog/trace/instrumentation/jakarta/jms/JMSDecorator.java @@ -22,6 +22,7 @@ import jakarta.jms.Topic; import java.util.concurrent.TimeUnit; import java.util.function.Function; +import java.util.function.Supplier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -60,7 +61,7 @@ public final class JMSDecorator extends MessagingClientDecorator { private final String spanKind; private final CharSequence spanType; - private final String serviceName; + private final Supplier serviceNameSupplier; public static final JMSDecorator PRODUCER_DECORATE = new JMSDecorator( @@ -89,7 +90,10 @@ public final class JMSDecorator extends MessagingClientDecorator { SpanNaming.instance().namingSchema().messaging().timeInQueueService(JMS.toString())); public JMSDecorator( - String resourcePrefix, String spanKind, CharSequence spanType, String serviceName) { + String resourcePrefix, + String spanKind, + CharSequence spanType, + Supplier serviceNameSupplier) { this.resourcePrefix = resourcePrefix; this.queueTempResourceName = UTF8BytesString.create(resourcePrefix + "Temporary Queue"); @@ -100,7 +104,7 @@ public JMSDecorator( this.spanKind = spanKind; this.spanType = spanType; - this.serviceName = serviceName; + this.serviceNameSupplier = serviceNameSupplier; } @Override @@ -115,7 +119,7 @@ protected CharSequence spanType() { @Override protected String service() { - return serviceName; + return serviceNameSupplier.get(); } @Override diff --git a/dd-java-agent/instrumentation/jms/src/main/java/datadog/trace/instrumentation/jms/JMSDecorator.java b/dd-java-agent/instrumentation/jms/src/main/java/datadog/trace/instrumentation/jms/JMSDecorator.java index f07fca0ee6b..9cc12dff9ee 100644 --- a/dd-java-agent/instrumentation/jms/src/main/java/datadog/trace/instrumentation/jms/JMSDecorator.java +++ b/dd-java-agent/instrumentation/jms/src/main/java/datadog/trace/instrumentation/jms/JMSDecorator.java @@ -15,6 +15,7 @@ import datadog.trace.bootstrap.instrumentation.decorator.MessagingClientDecorator; import java.util.concurrent.TimeUnit; import java.util.function.Function; +import java.util.function.Supplier; import javax.jms.Destination; import javax.jms.JMSException; import javax.jms.Message; @@ -60,7 +61,7 @@ public final class JMSDecorator extends MessagingClientDecorator { private final String spanKind; private final CharSequence spanType; - private final String serviceName; + private final Supplier serviceNameSupplier; public static final JMSDecorator PRODUCER_DECORATE = new JMSDecorator( @@ -90,7 +91,10 @@ public final class JMSDecorator extends MessagingClientDecorator { SpanNaming.instance().namingSchema().messaging().timeInQueueService(JMS.toString())); public JMSDecorator( - String resourcePrefix, String spanKind, CharSequence spanType, String serviceName) { + String resourcePrefix, + String spanKind, + CharSequence spanType, + Supplier serviceNameSupplier) { this.resourcePrefix = resourcePrefix; this.queueTempResourceName = UTF8BytesString.create(resourcePrefix + "Temporary Queue"); @@ -101,7 +105,7 @@ public JMSDecorator( this.spanKind = spanKind; this.spanType = spanType; - this.serviceName = serviceName; + this.serviceNameSupplier = serviceNameSupplier; } public static void logJMSException(JMSException ex) { @@ -122,7 +126,7 @@ protected CharSequence spanType() { @Override protected String service() { - return serviceName; + return serviceNameSupplier.get(); } @Override diff --git a/dd-java-agent/instrumentation/kafka-clients-0.11/src/main/java/datadog/trace/instrumentation/kafka_clients/KafkaDecorator.java b/dd-java-agent/instrumentation/kafka-clients-0.11/src/main/java/datadog/trace/instrumentation/kafka_clients/KafkaDecorator.java index b1ca0958116..fcdd3943f8f 100644 --- a/dd-java-agent/instrumentation/kafka-clients-0.11/src/main/java/datadog/trace/instrumentation/kafka_clients/KafkaDecorator.java +++ b/dd-java-agent/instrumentation/kafka-clients-0.11/src/main/java/datadog/trace/instrumentation/kafka_clients/KafkaDecorator.java @@ -18,6 +18,7 @@ import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; import datadog.trace.bootstrap.instrumentation.decorator.MessagingClientDecorator; import java.util.function.Function; +import java.util.function.Supplier; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.clients.producer.ProducerConfig; import org.apache.kafka.clients.producer.ProducerRecord; @@ -41,7 +42,7 @@ public class KafkaDecorator extends MessagingClientDecorator { public static final String KAFKA_PRODUCED_KEY = "x_datadog_kafka_produced"; private final String spanKind; private final CharSequence spanType; - private final String serviceName; + private final Supplier serviceNameSupplier; private static final DDCache PRODUCER_RESOURCE_NAME_CACHE = DDCaches.newFixedSizeCache(32); @@ -78,10 +79,11 @@ public class KafkaDecorator extends MessagingClientDecorator { InternalSpanTypes.MESSAGE_BROKER, SpanNaming.instance().namingSchema().messaging().timeInQueueService(KAFKA)); - protected KafkaDecorator(String spanKind, CharSequence spanType, String serviceName) { + protected KafkaDecorator( + String spanKind, CharSequence spanType, Supplier serviceNameSupplier) { this.spanKind = spanKind; this.spanType = spanType; - this.serviceName = serviceName; + this.serviceNameSupplier = serviceNameSupplier; } @Override @@ -96,7 +98,7 @@ protected String[] instrumentationNames() { @Override protected String service() { - return serviceName; + return serviceNameSupplier.get(); } @Override diff --git a/dd-java-agent/instrumentation/kafka-clients-3.8/src/main/java17/datadog/trace/instrumentation/kafka_clients38/KafkaDecorator.java b/dd-java-agent/instrumentation/kafka-clients-3.8/src/main/java17/datadog/trace/instrumentation/kafka_clients38/KafkaDecorator.java index 16ff81ab572..2361a441e50 100644 --- a/dd-java-agent/instrumentation/kafka-clients-3.8/src/main/java17/datadog/trace/instrumentation/kafka_clients38/KafkaDecorator.java +++ b/dd-java-agent/instrumentation/kafka-clients-3.8/src/main/java17/datadog/trace/instrumentation/kafka_clients38/KafkaDecorator.java @@ -18,6 +18,7 @@ import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; import datadog.trace.bootstrap.instrumentation.decorator.MessagingClientDecorator; import java.util.function.Function; +import java.util.function.Supplier; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.clients.producer.ProducerConfig; import org.apache.kafka.clients.producer.ProducerRecord; @@ -41,7 +42,7 @@ public class KafkaDecorator extends MessagingClientDecorator { public static final String KAFKA_PRODUCED_KEY = "x_datadog_kafka_produced"; private final String spanKind; private final CharSequence spanType; - private final String serviceName; + private final Supplier serviceNameSupplier; private static final DDCache PRODUCER_RESOURCE_NAME_CACHE = DDCaches.newFixedSizeCache(32); @@ -78,10 +79,11 @@ public class KafkaDecorator extends MessagingClientDecorator { InternalSpanTypes.MESSAGE_BROKER, SpanNaming.instance().namingSchema().messaging().timeInQueueService(KAFKA)); - protected KafkaDecorator(String spanKind, CharSequence spanType, String serviceName) { + protected KafkaDecorator( + String spanKind, CharSequence spanType, Supplier serviceNameSupplier) { this.spanKind = spanKind; this.spanType = spanType; - this.serviceName = serviceName; + this.serviceNameSupplier = serviceNameSupplier; } @Override @@ -96,7 +98,7 @@ protected String[] instrumentationNames() { @Override protected String service() { - return serviceName; + return serviceNameSupplier.get(); } @Override diff --git a/dd-java-agent/instrumentation/kafka-streams-0.11/src/main/java/datadog/trace/instrumentation/kafka_streams/KafkaStreamsDecorator.java b/dd-java-agent/instrumentation/kafka-streams-0.11/src/main/java/datadog/trace/instrumentation/kafka_streams/KafkaStreamsDecorator.java index 1868c359790..91b018367b0 100644 --- a/dd-java-agent/instrumentation/kafka-streams-0.11/src/main/java/datadog/trace/instrumentation/kafka_streams/KafkaStreamsDecorator.java +++ b/dd-java-agent/instrumentation/kafka-streams-0.11/src/main/java/datadog/trace/instrumentation/kafka_streams/KafkaStreamsDecorator.java @@ -14,6 +14,7 @@ import datadog.trace.bootstrap.instrumentation.api.Tags; import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; import datadog.trace.bootstrap.instrumentation.decorator.MessagingClientDecorator; +import java.util.function.Supplier; import org.apache.kafka.streams.processor.internals.ProcessorNode; import org.apache.kafka.streams.processor.internals.ProcessorRecordContext; import org.apache.kafka.streams.processor.internals.StampedRecord; @@ -33,7 +34,7 @@ public class KafkaStreamsDecorator extends MessagingClientDecorator { private final String spanKind; private final CharSequence spanType; - private final String serviceName; + private final Supplier serviceNameSupplier; private static final DDCache RESOURCE_NAME_CACHE = DDCaches.newFixedSizeCache(32); @@ -54,10 +55,11 @@ public class KafkaStreamsDecorator extends MessagingClientDecorator { InternalSpanTypes.MESSAGE_BROKER, SpanNaming.instance().namingSchema().messaging().timeInQueueService(KAFKA)); - protected KafkaStreamsDecorator(String spanKind, CharSequence spanType, String serviceName) { + protected KafkaStreamsDecorator( + String spanKind, CharSequence spanType, Supplier serviceNameSupplier) { this.spanKind = spanKind; this.spanType = spanType; - this.serviceName = serviceName; + this.serviceNameSupplier = serviceNameSupplier; } @Override @@ -67,7 +69,7 @@ protected String[] instrumentationNames() { @Override protected String service() { - return serviceName; + return serviceNameSupplier.get(); } @Override diff --git a/dd-java-agent/instrumentation/rabbitmq-amqp-2.7/src/main/java/datadog/trace/instrumentation/rabbitmq/amqp/RabbitDecorator.java b/dd-java-agent/instrumentation/rabbitmq-amqp-2.7/src/main/java/datadog/trace/instrumentation/rabbitmq/amqp/RabbitDecorator.java index 6ba59b6734a..051b9348983 100644 --- a/dd-java-agent/instrumentation/rabbitmq-amqp-2.7/src/main/java/datadog/trace/instrumentation/rabbitmq/amqp/RabbitDecorator.java +++ b/dd-java-agent/instrumentation/rabbitmq-amqp-2.7/src/main/java/datadog/trace/instrumentation/rabbitmq/amqp/RabbitDecorator.java @@ -30,6 +30,7 @@ import java.util.LinkedHashMap; import java.util.Map; import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; public class RabbitDecorator extends MessagingClientDecorator { @@ -84,12 +85,13 @@ public class RabbitDecorator extends MessagingClientDecorator { private final String spanKind; private final CharSequence spanType; - private final String serviceName; + private final Supplier serviceNameSupplier; - public RabbitDecorator(String spanKind, CharSequence spanType, String serviceName) { + public RabbitDecorator( + String spanKind, CharSequence spanType, Supplier serviceNameSupplier) { this.spanKind = spanKind; this.spanType = spanType; - this.serviceName = serviceName; + this.serviceNameSupplier = serviceNameSupplier; } @Override @@ -99,7 +101,7 @@ protected String[] instrumentationNames() { @Override protected String service() { - return serviceName; + return serviceNameSupplier.get(); } @Override diff --git a/dd-trace-core/src/jmh/java/datadog/trace/api/naming/MessagingNamingBenchmark.java b/dd-trace-core/src/jmh/java/datadog/trace/api/naming/MessagingNamingBenchmark.java new file mode 100644 index 00000000000..36de260f215 --- /dev/null +++ b/dd-trace-core/src/jmh/java/datadog/trace/api/naming/MessagingNamingBenchmark.java @@ -0,0 +1,96 @@ +package datadog.trace.api.naming; + +import static java.util.concurrent.TimeUnit.MICROSECONDS; +import static java.util.concurrent.TimeUnit.SECONDS; + +import datadog.trace.api.Config; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import datadog.trace.core.BlackholeWriter; +import datadog.trace.core.CoreTracer; +import datadog.trace.core.TraceCounters; +import java.util.WeakHashMap; +import java.util.function.Supplier; +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.Warmup; +import org.openjdk.jmh.infra.Blackhole; + +/** + * Benchmark (pinThreadServiceName) Mode Cnt Score Error Units + * MessagingNamingBenchmark.complexSupplierServiceName false avgt 3 0.710 ± 0.040 us/op + * MessagingNamingBenchmark.complexSupplierServiceName true avgt 3 0.718 ± 0.105 us/op + * MessagingNamingBenchmark.constantServiceName false avgt 3 0.668 ± 0.024 us/op + * MessagingNamingBenchmark.constantSupplierServiceName false avgt 3 0.666 ± 0.044 us/op + */ +@State(Scope.Benchmark) +@Warmup(iterations = 1, time = 15, timeUnit = SECONDS) +@Measurement(iterations = 3, time = 30, timeUnit = SECONDS) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(MICROSECONDS) +@Fork(value = 1) +public class MessagingNamingBenchmark { + + CoreTracer tracer; + + WeakHashMap weakCache; + + private static final Supplier constantSupplier = () -> "constant"; + + private final Supplier complexSupplier = + () -> { + String ret = weakCache.get(Thread.currentThread().getContextClassLoader()); + if (ret == null) { + ret = Config.get().getServiceName(); + } + return ret; + }; + + @Param({"false", "true"}) + boolean pinThreadServiceName; + + @Setup(Level.Iteration) + public void init(Blackhole blackhole) { + tracer = + CoreTracer.builder() + .writer(new BlackholeWriter(blackhole, new TraceCounters(), 0)) + .strictTraceWrites(false) + .build(); + weakCache = new WeakHashMap<>(); + if (pinThreadServiceName) { + weakCache.put(Thread.currentThread().getContextClassLoader(), constantSupplier.get()); + } + } + + @Benchmark + public void constantServiceName(Blackhole blackhole) { + final AgentSpan span = tracer.startSpan("", ""); + span.setServiceName("constant"); + span.finish(); + blackhole.consume(span); + } + + @Benchmark + public void constantSupplierServiceName(Blackhole blackhole) { + final AgentSpan span = tracer.startSpan("", ""); + span.setServiceName(constantSupplier.get()); + span.finish(); + blackhole.consume(span); + } + + @Benchmark + public void complexSupplierServiceName(Blackhole blackhole) { + final AgentSpan span = tracer.startSpan("", ""); + span.setServiceName(complexSupplier.get()); + span.finish(); + blackhole.consume(span); + } +} diff --git a/internal-api/src/main/java/datadog/trace/api/naming/NamingSchema.java b/internal-api/src/main/java/datadog/trace/api/naming/NamingSchema.java index ce91d05b2b1..63cd5afd2c9 100644 --- a/internal-api/src/main/java/datadog/trace/api/naming/NamingSchema.java +++ b/internal-api/src/main/java/datadog/trace/api/naming/NamingSchema.java @@ -1,6 +1,7 @@ package datadog.trace.api.naming; import java.util.Map; +import java.util.function.Supplier; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -176,9 +177,9 @@ interface ForMessaging { * * @param messagingSystem the messaging system (e.g. jms, kafka, amqp,..) * @param useLegacyTracing if true legacy tracing service naming will be applied if compatible - * @return the service name + * @return the supplier for the service name */ - String inboundService(@Nonnull String messagingSystem, boolean useLegacyTracing); + Supplier inboundService(@Nonnull String messagingSystem, boolean useLegacyTracing); /** * Calculate the operation name for a messaging producer span. @@ -196,16 +197,16 @@ interface ForMessaging { * @param useLegacyTracing if true legacy tracing service naming will be applied if compatible * @return the service name */ - String outboundService(@Nonnull String messagingSystem, boolean useLegacyTracing); + Supplier outboundService(@Nonnull String messagingSystem, boolean useLegacyTracing); /** * Calculate the service name for a messaging time in queue synthetic span. * * @param messagingSystem the messaging system (e.g. jms, kafka, amqp,..) - * @return the service name + * @return the service name supplier */ @Nonnull - String timeInQueueService(@Nonnull String messagingSystem); + Supplier timeInQueueService(@Nonnull String messagingSystem); /** * Calculate the operation name for a messaging time in queue synthetic span. diff --git a/internal-api/src/main/java/datadog/trace/api/naming/v0/MessagingNamingV0.java b/internal-api/src/main/java/datadog/trace/api/naming/v0/MessagingNamingV0.java index 89be91e3d7e..e7e227fbeb0 100644 --- a/internal-api/src/main/java/datadog/trace/api/naming/v0/MessagingNamingV0.java +++ b/internal-api/src/main/java/datadog/trace/api/naming/v0/MessagingNamingV0.java @@ -4,9 +4,29 @@ import datadog.trace.api.naming.ClassloaderServiceNames; import datadog.trace.api.naming.NamingSchema; import datadog.trace.api.remoteconfig.ServiceNameCollector; +import java.util.function.Supplier; import javax.annotation.Nonnull; class MessagingNamingV0 implements NamingSchema.ForMessaging { + + private static class ClassloaderDependentNamingSupplier implements Supplier { + private static final ClassloaderDependentNamingSupplier INSTANCE = + new ClassloaderDependentNamingSupplier(); + private final String configServiceName = Config.get().getServiceName(); + + @Override + public String get() { + final String contextual = ClassloaderServiceNames.maybeGetForCurrentThread(); + if (contextual != null) { + ServiceNameCollector.get().addService(contextual); + return contextual; + } + return configServiceName; + } + } + + private static final Supplier NULL_SUPPLIER = () -> null; + private final boolean allowInferredServices; public MessagingNamingV0(final boolean allowInferredServices) { @@ -23,7 +43,8 @@ public String outboundOperation(@Nonnull final String messagingSystem) { } @Override - public String outboundService(@Nonnull final String messagingSystem, boolean useLegacyTracing) { + public Supplier outboundService( + @Nonnull final String messagingSystem, boolean useLegacyTracing) { return inboundService(messagingSystem, useLegacyTracing); } @@ -41,29 +62,27 @@ public String inboundOperation(@Nonnull final String messagingSystem) { } @Override - public String inboundService(@Nonnull final String messagingSystem, boolean useLegacyTracing) { + public Supplier inboundService( + @Nonnull final String messagingSystem, boolean useLegacyTracing) { if (allowInferredServices) { if (useLegacyTracing) { ServiceNameCollector.get().addService(messagingSystem); - return messagingSystem; - } else { - final String contextual = ClassloaderServiceNames.maybeGetForCurrentThread(); - if (contextual != null) { - ServiceNameCollector.get().addService(contextual); - return contextual; - } - return Config.get().getServiceName(); + return messagingSystem::toString; + } else if (Config.get().isJeeSplitByDeployment()) { + // in this particular case we're narrowing the service name from the context classloader. + // this is more expensive so we're doing only if that feature is enabled. + return ClassloaderDependentNamingSupplier.INSTANCE; } - } else { - return null; + return Config.get()::getServiceName; } + return NULL_SUPPLIER; } @Override @Nonnull - public String timeInQueueService(@Nonnull final String messagingSystem) { + public Supplier timeInQueueService(@Nonnull final String messagingSystem) { ServiceNameCollector.get().addService(messagingSystem); - return messagingSystem; + return () -> messagingSystem; } @Nonnull diff --git a/internal-api/src/main/java/datadog/trace/api/naming/v1/MessagingNamingV1.java b/internal-api/src/main/java/datadog/trace/api/naming/v1/MessagingNamingV1.java index e086d9e91fe..298d724a83e 100644 --- a/internal-api/src/main/java/datadog/trace/api/naming/v1/MessagingNamingV1.java +++ b/internal-api/src/main/java/datadog/trace/api/naming/v1/MessagingNamingV1.java @@ -1,9 +1,11 @@ package datadog.trace.api.naming.v1; import datadog.trace.api.naming.NamingSchema; +import java.util.function.Supplier; import javax.annotation.Nonnull; public class MessagingNamingV1 implements NamingSchema.ForMessaging { + private static final Supplier NULL_SUPPLIER = () -> null; private String normalizeForCloud(@Nonnull final String messagingSystem) { switch (messagingSystem) { @@ -24,8 +26,9 @@ public String outboundOperation(@Nonnull String messagingSystem) { } @Override - public String outboundService(@Nonnull String messagingSystem, boolean useLegacyTracing) { - return null; + public Supplier outboundService( + @Nonnull String messagingSystem, boolean useLegacyTracing) { + return NULL_SUPPLIER; } @Nonnull @@ -35,14 +38,15 @@ public String inboundOperation(@Nonnull String messagingSystem) { } @Override - public String inboundService(@Nonnull String messagingSystem, boolean useLegacyTracing) { - return null; + public Supplier inboundService( + @Nonnull String messagingSystem, boolean useLegacyTracing) { + return NULL_SUPPLIER; } @Override @Nonnull - public String timeInQueueService(@Nonnull String messagingSystem) { - return messagingSystem + "-queue"; + public Supplier timeInQueueService(@Nonnull String messagingSystem) { + return () -> messagingSystem + "-queue"; } @Nonnull diff --git a/internal-api/src/test/groovy/datadog/trace/api/naming/NamingV0ForkedTest.groovy b/internal-api/src/test/groovy/datadog/trace/api/naming/NamingV0ForkedTest.groovy index 28111086f03..f2a0dd68b3b 100644 --- a/internal-api/src/test/groovy/datadog/trace/api/naming/NamingV0ForkedTest.groovy +++ b/internal-api/src/test/groovy/datadog/trace/api/naming/NamingV0ForkedTest.groovy @@ -17,8 +17,8 @@ class NamingV0ForkedTest extends DDSpecification { then: assert SpanNaming.instance().version() == 0 assert !schema.allowInferredServices() - assert schema.messaging().inboundService("anything", true) == null - assert schema.messaging().outboundService("anything", true) == null + assert schema.messaging().inboundService("anything", true) .get()== null + assert schema.messaging().outboundService("anything", true).get() == null assert schema.database().service("anything") == null assert schema.cache().service("anything") == null assert schema.cloud().serviceForRequest("any", "anything") == null