diff --git a/dd-java-agent/instrumentation/aws-java/aws-java-eventbridge-2.0/src/main/java/datadog/trace/instrumentation/aws/v2/eventbridge/EventBridgeInterceptor.java b/dd-java-agent/instrumentation/aws-java/aws-java-eventbridge-2.0/src/main/java/datadog/trace/instrumentation/aws/v2/eventbridge/EventBridgeInterceptor.java index 7e7cd81b053..6b566886938 100644 --- a/dd-java-agent/instrumentation/aws-java/aws-java-eventbridge-2.0/src/main/java/datadog/trace/instrumentation/aws/v2/eventbridge/EventBridgeInterceptor.java +++ b/dd-java-agent/instrumentation/aws-java/aws-java-eventbridge-2.0/src/main/java/datadog/trace/instrumentation/aws/v2/eventbridge/EventBridgeInterceptor.java @@ -6,6 +6,7 @@ import static datadog.trace.instrumentation.aws.v2.eventbridge.TextMapInjectAdapter.SETTER; import datadog.context.Context; +import datadog.trace.api.Config; import datadog.trace.api.datastreams.DataStreamsContext; import datadog.trace.api.datastreams.DataStreamsTags; import datadog.trace.api.datastreams.PathwayContext; @@ -34,7 +35,8 @@ public class EventBridgeInterceptor implements ExecutionInterceptor { @Override public SdkRequest modifyRequest(ModifyRequest context, ExecutionAttributes executionAttributes) { - if (!(context.request() instanceof PutEventsRequest)) { + if (!(context.request() instanceof PutEventsRequest) + || !Config.get().isEventbridgeInjectDatadogAttributeEnabled()) { return context.request(); } diff --git a/dd-java-agent/instrumentation/aws-java/aws-java-eventbridge-2.0/src/test/groovy/EventBridgeClientTest.groovy b/dd-java-agent/instrumentation/aws-java/aws-java-eventbridge-2.0/src/test/groovy/EventBridgeClientTest.groovy index ce531ae50ca..3362d3f4b97 100644 --- a/dd-java-agent/instrumentation/aws-java/aws-java-eventbridge-2.0/src/test/groovy/EventBridgeClientTest.groovy +++ b/dd-java-agent/instrumentation/aws-java/aws-java-eventbridge-2.0/src/test/groovy/EventBridgeClientTest.groovy @@ -2,6 +2,8 @@ import datadog.trace.agent.test.InstrumentationSpecification import datadog.trace.api.DDSpanTypes import datadog.trace.api.config.GeneralConfig import groovy.json.JsonSlurper +import java.time.Duration +import java.util.concurrent.CompletableFuture import org.testcontainers.containers.GenericContainer import org.testcontainers.utility.DockerImageName import software.amazon.awssdk.auth.credentials.AwsBasicCredentials @@ -17,9 +19,6 @@ import software.amazon.awssdk.services.sqs.SqsClient import software.amazon.awssdk.services.sqs.model.QueueAttributeName import spock.lang.Shared -import java.time.Duration -import java.util.concurrent.CompletableFuture - class EventBridgeClientTest extends InstrumentationSpecification { static final LOCALSTACK = new GenericContainer(DockerImageName.parse("localstack/localstack:4.2.0")) .withExposedPorts(4566) @@ -495,4 +494,31 @@ class EventBridgeClientTest extends InstrumentationSpecification { 'tracestate' ] } + + def "datadog context is not injected when eventbridgeInjectDatadogAttribute is disabled"() { + setup: + injectSysConfig("eventbridge.inject.datadog.attribute.enabled", "false") + + when: + TEST_WRITER.clear() + eventBridgeClient.putEvents { req -> + req.entries( + PutEventsRequestEntry.builder() + .source("com.example") + .detailType("test-no-inject") + .detail('{"message":"no-inject"}') + .eventBusName(testBusARN) + .build() + ) + } + + def message = sqsClient.receiveMessage { it.queueUrl(testQueueURL).waitTimeSeconds(3) }.messages().get(0) + def messageBody = new JsonSlurper().parseText(message.body()) + + then: + def detail = messageBody["detail"] + assert detail instanceof Map + assert detail["message"] == "no-inject" + assert detail["_datadog"] == null + } } diff --git a/dd-java-agent/instrumentation/aws-java/aws-java-sfn-2.0/src/main/java/datadog/trace/instrumentation/aws/v2/sfn/SfnInterceptor.java b/dd-java-agent/instrumentation/aws-java/aws-java-sfn-2.0/src/main/java/datadog/trace/instrumentation/aws/v2/sfn/SfnInterceptor.java index abc6b72e15b..5ab99ecae96 100644 --- a/dd-java-agent/instrumentation/aws-java/aws-java-sfn-2.0/src/main/java/datadog/trace/instrumentation/aws/v2/sfn/SfnInterceptor.java +++ b/dd-java-agent/instrumentation/aws-java/aws-java-sfn-2.0/src/main/java/datadog/trace/instrumentation/aws/v2/sfn/SfnInterceptor.java @@ -3,6 +3,7 @@ import static datadog.trace.bootstrap.instrumentation.api.AgentSpan.fromContext; import datadog.context.Context; +import datadog.trace.api.Config; import datadog.trace.bootstrap.InstanceStore; import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import software.amazon.awssdk.core.SdkRequest; @@ -23,10 +24,14 @@ public SfnInterceptor() {} @Override public SdkRequest modifyRequest(ModifyRequest context, ExecutionAttributes executionAttributes) { + SdkRequest request = context.request(); + if (!Config.get().isSfnInjectDatadogAttributeEnabled()) { + return request; + } try { return modifyRequestImpl(context, executionAttributes); } catch (Exception e) { - return context.request(); + return request; } } diff --git a/dd-java-agent/instrumentation/aws-java/aws-java-sfn-2.0/src/test/groovy/SfnClientTest.groovy b/dd-java-agent/instrumentation/aws-java/aws-java-sfn-2.0/src/test/groovy/SfnClientTest.groovy index b90c4b4b131..d921d09e17a 100644 --- a/dd-java-agent/instrumentation/aws-java/aws-java-sfn-2.0/src/test/groovy/SfnClientTest.groovy +++ b/dd-java-agent/instrumentation/aws-java/aws-java-sfn-2.0/src/test/groovy/SfnClientTest.groovy @@ -1,23 +1,21 @@ +import static datadog.trace.agent.test.utils.TraceUtils.basicSpan + import datadog.trace.agent.test.naming.VersionedNamingTestBase import datadog.trace.agent.test.utils.TraceUtils import datadog.trace.api.DDSpanTypes import datadog.trace.bootstrap.instrumentation.api.Tags import groovy.json.JsonSlurper +import java.time.Duration import org.testcontainers.containers.GenericContainer import org.testcontainers.utility.DockerImageName +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider +import software.amazon.awssdk.regions.Region import software.amazon.awssdk.services.sfn.SfnClient import software.amazon.awssdk.services.sfn.model.SfnException import software.amazon.awssdk.services.sfn.model.StartExecutionResponse -import software.amazon.awssdk.regions.Region -import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider -import software.amazon.awssdk.auth.credentials.AwsBasicCredentials import spock.lang.Shared -import java.time.Duration - -import static datadog.trace.agent.test.utils.TraceUtils.basicSpan - - abstract class SfnClientTest extends VersionedNamingTestBase { @Shared GenericContainer localStack @Shared SfnClient sfnClient @@ -117,6 +115,28 @@ abstract class SfnClientTest extends VersionedNamingTestBase { input["_datadog"]["x-datadog-tags"] != null } + def "datadog context is not injected when SfnInjectDatadogAttribute is disabled"() { + setup: + injectSysConfig("sfn.inject.datadog.attribute.enabled", "false") + + when: + StartExecutionResponse response = sfnClient.startExecution { builder -> + builder.stateMachineArn(testStateMachineARN) + .input("{\"key\": \"value\"}") + .build() + } + + then: + def execution = sfnClient.describeExecution { builder -> + builder.executionArn(response.executionArn()) + .build() + } + + def input = new JsonSlurper().parseText(execution.input()) + assert input["key"] == "value" + assert input["_datadog"] == null + } + def "AWS rejects invalid JSON but instrumentation does not error"() { when: sfnClient.startExecution { b -> diff --git a/dd-java-agent/instrumentation/aws-java/aws-java-sns-1.0/src/main/java/datadog/trace/instrumentation/aws/v1/sns/SnsInterceptor.java b/dd-java-agent/instrumentation/aws-java/aws-java-sns-1.0/src/main/java/datadog/trace/instrumentation/aws/v1/sns/SnsInterceptor.java index 63855b1455c..4a09ad3292c 100644 --- a/dd-java-agent/instrumentation/aws-java/aws-java-sns-1.0/src/main/java/datadog/trace/instrumentation/aws/v1/sns/SnsInterceptor.java +++ b/dd-java-agent/instrumentation/aws-java/aws-java-sns-1.0/src/main/java/datadog/trace/instrumentation/aws/v1/sns/SnsInterceptor.java @@ -13,6 +13,7 @@ import com.amazonaws.services.sns.model.PublishBatchRequestEntry; import com.amazonaws.services.sns.model.PublishRequest; import datadog.context.Context; +import datadog.trace.api.Config; import datadog.trace.api.datastreams.DataStreamsContext; import datadog.trace.api.datastreams.DataStreamsTags; import datadog.trace.bootstrap.ContextStore; @@ -49,6 +50,9 @@ private ByteBuffer getMessageAttributeValueToInject( @Override public AmazonWebServiceRequest beforeMarshalling(AmazonWebServiceRequest request) { + if (!Config.get().isSnsInjectDatadogAttributeEnabled()) { + return request; + } // Injecting the trace context into SNS messageAttributes. if (request instanceof PublishRequest) { PublishRequest pRequest = (PublishRequest) request; diff --git a/dd-java-agent/instrumentation/aws-java/aws-java-sns-1.0/src/test/groovy/SnsClientTest.groovy b/dd-java-agent/instrumentation/aws-java/aws-java-sns-1.0/src/test/groovy/SnsClientTest.groovy index efa7dfe4c8c..4aa1e6e2ddc 100644 --- a/dd-java-agent/instrumentation/aws-java/aws-java-sns-1.0/src/test/groovy/SnsClientTest.groovy +++ b/dd-java-agent/instrumentation/aws-java/aws-java-sns-1.0/src/test/groovy/SnsClientTest.groovy @@ -13,6 +13,7 @@ import datadog.trace.api.config.GeneralConfig import datadog.trace.bootstrap.instrumentation.api.Tags import datadog.trace.core.datastreams.StatsGroup import groovy.json.JsonSlurper +import java.time.Duration import org.testcontainers.containers.GenericContainer import org.testcontainers.utility.DockerImageName import software.amazon.awssdk.auth.credentials.AwsBasicCredentials @@ -22,9 +23,6 @@ import software.amazon.awssdk.services.sqs.SqsClient import software.amazon.awssdk.services.sqs.model.QueueAttributeName import spock.lang.Shared -import java.time.Duration - - abstract class SnsClientTest extends VersionedNamingTestBase { static final LOCALSTACK = new GenericContainer(DockerImageName.parse("localstack/localstack:4.2.0")) @@ -210,6 +208,26 @@ abstract class SnsClientTest extends VersionedNamingTestBase { !traceContextInJson['dd-pathway-ctx-base64'].toString().isBlank() } + + def "datadog context is not injected when SnsInjectDatadogAttribute is disabled"() { + setup: + TEST_WRITER.clear() + injectSysConfig("sns.inject.datadog.attribute.enabled", "false") + + when: + snsClient.publish(testTopicARN, 'sometext') + + def message = sqsClient.receiveMessage { it.queueUrl(testQueueURL).waitTimeSeconds(3) }.messages().get(0) + def jsonSlurper = new JsonSlurper() + def messageBody = jsonSlurper.parseText(message.body()) + if (isDataStreamsEnabled()) { + TEST_DATA_STREAMS_WRITER.waitForGroups(1) + } + then: + assert messageBody["Message"] == "sometext" + assert messageBody["MessageAttributes"] == null + } + def "SNS message to phone number doesn't leak exception"() { when: snsClient.publish(new PublishRequest().withPhoneNumber("+19995550123").withMessage('sometext')) diff --git a/dd-java-agent/instrumentation/aws-java/aws-java-sns-2.0/src/main/java/datadog/trace/instrumentation/aws/v2/sns/SnsInterceptor.java b/dd-java-agent/instrumentation/aws-java/aws-java-sns-2.0/src/main/java/datadog/trace/instrumentation/aws/v2/sns/SnsInterceptor.java index 4090a46c0c6..fb9ca4b1495 100644 --- a/dd-java-agent/instrumentation/aws-java/aws-java-sns-2.0/src/main/java/datadog/trace/instrumentation/aws/v2/sns/SnsInterceptor.java +++ b/dd-java-agent/instrumentation/aws-java/aws-java-sns-2.0/src/main/java/datadog/trace/instrumentation/aws/v2/sns/SnsInterceptor.java @@ -7,6 +7,7 @@ import static datadog.trace.instrumentation.aws.v2.sns.TextMapInjectAdapter.SETTER; import datadog.context.Context; +import datadog.trace.api.Config; import datadog.trace.api.datastreams.DataStreamsContext; import datadog.trace.api.datastreams.DataStreamsTags; import datadog.trace.bootstrap.InstanceStore; @@ -50,6 +51,9 @@ public SnsInterceptor() {} @Override public SdkRequest modifyRequest(ModifyRequest context, ExecutionAttributes executionAttributes) { + if (!Config.get().isSnsInjectDatadogAttributeEnabled()) { + return context.request(); + } // Injecting the trace context into SNS messageAttributes. if (context.request() instanceof PublishRequest) { PublishRequest request = (PublishRequest) context.request(); diff --git a/dd-java-agent/instrumentation/aws-java/aws-java-sns-2.0/src/test/groovy/SnsClientTest.groovy b/dd-java-agent/instrumentation/aws-java/aws-java-sns-2.0/src/test/groovy/SnsClientTest.groovy index 1a52006e07f..5c3eb59c295 100644 --- a/dd-java-agent/instrumentation/aws-java/aws-java-sns-2.0/src/test/groovy/SnsClientTest.groovy +++ b/dd-java-agent/instrumentation/aws-java/aws-java-sns-2.0/src/test/groovy/SnsClientTest.groovy @@ -180,6 +180,25 @@ abstract class SnsClientTest extends VersionedNamingTestBase { !traceContextInJson['dd-pathway-ctx-base64'].toString().isBlank() } + def "datadog context is not injected when SnsInjectDatadogAttribute is disabled"() { + setup: + TEST_WRITER.clear() + injectSysConfig("sns.inject.datadog.attribute.enabled", "false") + + when: + snsClient.publish { it.message("sometext").topicArn(testTopicARN)} + + def message = sqsClient.receiveMessage { it.queueUrl(testQueueURL).waitTimeSeconds(3) }.messages().get(0) + def jsonSlurper = new JsonSlurper() + def messageBody = jsonSlurper.parseText(message.body()) + if (isDataStreamsEnabled()) { + TEST_DATA_STREAMS_WRITER.waitForGroups(1) + } + then: + assert messageBody["Message"] == "sometext" + assert messageBody["MessageAttributes"] == null + } + def "SNS message to phone number doesn't leak exception"() { when: snsClient.publish { it.message("sometext").phoneNumber("+19995550123") } diff --git a/dd-java-agent/instrumentation/aws-java/aws-java-sqs-1.0/src/main/java/datadog/trace/instrumentation/aws/v1/sqs/MessageAttributeInjector.java b/dd-java-agent/instrumentation/aws-java/aws-java-sqs-1.0/src/main/java/datadog/trace/instrumentation/aws/v1/sqs/MessageAttributeInjector.java index 02a81e8278e..f3302307aca 100644 --- a/dd-java-agent/instrumentation/aws-java/aws-java-sqs-1.0/src/main/java/datadog/trace/instrumentation/aws/v1/sqs/MessageAttributeInjector.java +++ b/dd-java-agent/instrumentation/aws-java/aws-java-sqs-1.0/src/main/java/datadog/trace/instrumentation/aws/v1/sqs/MessageAttributeInjector.java @@ -4,6 +4,7 @@ import com.amazonaws.services.sqs.model.MessageAttributeValue; import datadog.context.propagation.CarrierSetter; +import datadog.trace.api.Config; import java.util.Map; public class MessageAttributeInjector implements CarrierSetter> { @@ -13,7 +14,9 @@ public class MessageAttributeInjector implements CarrierSetter carrier, final String key, final String value) { - if (carrier.size() < 10 && !carrier.containsKey(DATADOG_KEY)) { + if (carrier.size() < 10 + && !carrier.containsKey(DATADOG_KEY) + && Config.get().isSqsInjectDatadogAttributeEnabled()) { String jsonPathway = String.format("{\"%s\": \"%s\"}", key, value); carrier.put( DATADOG_KEY, diff --git a/dd-java-agent/instrumentation/aws-java/aws-java-sqs-1.0/src/main/java/datadog/trace/instrumentation/aws/v1/sqs/SqsInterceptor.java b/dd-java-agent/instrumentation/aws-java/aws-java-sqs-1.0/src/main/java/datadog/trace/instrumentation/aws/v1/sqs/SqsInterceptor.java index 3a7fa98632f..3534e1ed9e2 100644 --- a/dd-java-agent/instrumentation/aws-java/aws-java-sqs-1.0/src/main/java/datadog/trace/instrumentation/aws/v1/sqs/SqsInterceptor.java +++ b/dd-java-agent/instrumentation/aws-java/aws-java-sqs-1.0/src/main/java/datadog/trace/instrumentation/aws/v1/sqs/SqsInterceptor.java @@ -18,6 +18,7 @@ import datadog.context.Context; import datadog.context.propagation.Propagator; import datadog.context.propagation.Propagators; +import datadog.trace.api.Config; import datadog.trace.api.datastreams.DataStreamsContext; import datadog.trace.api.datastreams.DataStreamsTags; import datadog.trace.bootstrap.ContextStore; @@ -69,7 +70,8 @@ public AmazonWebServiceRequest beforeMarshalling(AmazonWebServiceRequest request } } else if (request instanceof ReceiveMessageRequest) { ReceiveMessageRequest rmRequest = (ReceiveMessageRequest) request; - if (rmRequest.getMessageAttributeNames().size() < 10 + if (Config.get().isSqsInjectDatadogAttributeEnabled() + && rmRequest.getMessageAttributeNames().size() < 10 && !rmRequest.getMessageAttributeNames().contains(DATADOG_KEY)) { List attributeNames = new ArrayList<>(rmRequest.getMessageAttributeNames()); attributeNames.add(DATADOG_KEY); diff --git a/dd-java-agent/instrumentation/aws-java/aws-java-sqs-1.0/src/test/groovy/SqsClientTest.groovy b/dd-java-agent/instrumentation/aws-java/aws-java-sqs-1.0/src/test/groovy/SqsClientTest.groovy index 927fcfd110d..1ae7b65c8fc 100644 --- a/dd-java-agent/instrumentation/aws-java/aws-java-sqs-1.0/src/test/groovy/SqsClientTest.groovy +++ b/dd-java-agent/instrumentation/aws-java/aws-java-sqs-1.0/src/test/groovy/SqsClientTest.groovy @@ -1,3 +1,6 @@ +import static datadog.trace.agent.test.utils.TraceUtils.basicSpan +import static java.nio.charset.StandardCharsets.UTF_8 + import com.amazon.sqs.javamessaging.ProviderConfiguration import com.amazon.sqs.javamessaging.SQSConnectionFactory import com.amazonaws.SDKGlobalConfiguration @@ -23,17 +26,13 @@ import datadog.trace.bootstrap.instrumentation.api.InstrumentationTags import datadog.trace.bootstrap.instrumentation.api.Tags import datadog.trace.core.datastreams.StatsGroup import datadog.trace.instrumentation.aws.v1.sqs.TracingList +import java.nio.ByteBuffer +import java.nio.charset.Charset +import javax.jms.Session import org.elasticmq.rest.sqs.SQSRestServerBuilder import spock.lang.IgnoreIf import spock.lang.Shared -import javax.jms.Session -import java.nio.ByteBuffer -import java.nio.charset.Charset - -import static datadog.trace.agent.test.utils.TraceUtils.basicSpan -import static java.nio.charset.StandardCharsets.UTF_8 - abstract class SqsClientTest extends VersionedNamingTestBase { def setup() { @@ -189,6 +188,31 @@ abstract class SqsClientTest extends VersionedNamingTestBase { client.shutdown() } + def "dadatog context is not injected if SqsInjectDatadogAttribute is disabled"() { + setup: + injectSysConfig("sqs.inject.datadog.attribute.enabled", "false") + def client = AmazonSQSClientBuilder.standard() + .withEndpointConfiguration(endpoint) + .withCredentials(credentialsProvider) + .build() + def queueUrl = client.createQueue('somequeue').queueUrl + TEST_WRITER.clear() + + when: + client.sendMessage(queueUrl, 'sometext') + def messages = client.receiveMessage(queueUrl).messages + + if (isDataStreamsEnabled()) { + TEST_DATA_STREAMS_WRITER.waitForGroups(1) + } + + then: + assert !messages[0].messageAttributes.containsKey("_datadog") + + cleanup: + client.shutdown() + } + @IgnoreIf({ !instance.isDataStreamsEnabled() }) def "propagation even when message attributes are readonly"() { setup: diff --git a/dd-java-agent/instrumentation/aws-java/aws-java-sqs-2.0/src/main/java/datadog/trace/instrumentation/aws/v2/sqs/MessageAttributeInjector.java b/dd-java-agent/instrumentation/aws-java/aws-java-sqs-2.0/src/main/java/datadog/trace/instrumentation/aws/v2/sqs/MessageAttributeInjector.java index e39e3ac42db..889ff8e94c6 100644 --- a/dd-java-agent/instrumentation/aws-java/aws-java-sqs-2.0/src/main/java/datadog/trace/instrumentation/aws/v2/sqs/MessageAttributeInjector.java +++ b/dd-java-agent/instrumentation/aws-java/aws-java-sqs-2.0/src/main/java/datadog/trace/instrumentation/aws/v2/sqs/MessageAttributeInjector.java @@ -3,6 +3,7 @@ import static datadog.trace.api.datastreams.PathwayContext.DATADOG_KEY; import datadog.context.propagation.CarrierSetter; +import datadog.trace.api.Config; import java.util.Map; import javax.annotation.ParametersAreNonnullByDefault; import software.amazon.awssdk.services.sqs.model.MessageAttributeValue; @@ -15,7 +16,10 @@ public class MessageAttributeInjector implements CarrierSetter carrier, final String key, final String value) { - if (carrier.size() < 10 && !carrier.containsKey(DATADOG_KEY)) { + if (carrier.size() < 10 + && !carrier.containsKey(DATADOG_KEY) + && Config.get().isSqsInjectDatadogAttributeEnabled()) { + String jsonPathway = String.format("{\"%s\": \"%s\"}", key, value); carrier.put( DATADOG_KEY, diff --git a/dd-java-agent/instrumentation/aws-java/aws-java-sqs-2.0/src/main/java/datadog/trace/instrumentation/aws/v2/sqs/SqsInterceptor.java b/dd-java-agent/instrumentation/aws-java/aws-java-sqs-2.0/src/main/java/datadog/trace/instrumentation/aws/v2/sqs/SqsInterceptor.java index c78e041fa7e..14bf6591938 100644 --- a/dd-java-agent/instrumentation/aws-java/aws-java-sqs-2.0/src/main/java/datadog/trace/instrumentation/aws/v2/sqs/SqsInterceptor.java +++ b/dd-java-agent/instrumentation/aws-java/aws-java-sqs-2.0/src/main/java/datadog/trace/instrumentation/aws/v2/sqs/SqsInterceptor.java @@ -10,6 +10,7 @@ import datadog.context.Context; import datadog.context.propagation.Propagator; import datadog.context.propagation.Propagators; +import datadog.trace.api.Config; import datadog.trace.api.datastreams.DataStreamsContext; import datadog.trace.api.datastreams.DataStreamsTags; import datadog.trace.bootstrap.InstanceStore; @@ -77,7 +78,8 @@ public SdkRequest modifyRequest(ModifyRequest context, ExecutionAttributes execu } else if (context.request() instanceof ReceiveMessageRequest) { ReceiveMessageRequest request = (ReceiveMessageRequest) context.request(); if (request.messageAttributeNames().size() < 10 - && !request.messageAttributeNames().contains(DATADOG_KEY)) { + && !request.messageAttributeNames().contains(DATADOG_KEY) + && Config.get().isSqsInjectDatadogAttributeEnabled()) { List messageAttributeNames = new ArrayList<>(request.messageAttributeNames()); messageAttributeNames.add(DATADOG_KEY); return request.toBuilder().messageAttributeNames(messageAttributeNames).build(); diff --git a/dd-java-agent/instrumentation/aws-java/aws-java-sqs-2.0/src/test/groovy/SqsClientTest.groovy b/dd-java-agent/instrumentation/aws-java/aws-java-sqs-2.0/src/test/groovy/SqsClientTest.groovy index fe196f12a6f..c5919e2349a 100644 --- a/dd-java-agent/instrumentation/aws-java/aws-java-sqs-2.0/src/test/groovy/SqsClientTest.groovy +++ b/dd-java-agent/instrumentation/aws-java/aws-java-sqs-2.0/src/test/groovy/SqsClientTest.groovy @@ -1,3 +1,6 @@ +import static datadog.trace.agent.test.utils.TraceUtils.basicSpan +import static java.nio.charset.StandardCharsets.UTF_8 + import com.amazon.sqs.javamessaging.ProviderConfiguration import com.amazon.sqs.javamessaging.SQSConnectionFactory import datadog.trace.agent.test.naming.VersionedNamingTestBase @@ -11,8 +14,9 @@ import datadog.trace.api.naming.SpanNaming import datadog.trace.bootstrap.instrumentation.api.InstrumentationTags import datadog.trace.bootstrap.instrumentation.api.Tags import datadog.trace.core.datastreams.StatsGroup -import datadog.trace.instrumentation.aws.v2.sqs.TracingList import datadog.trace.instrumentation.aws.ExpectedQueryParams +import datadog.trace.instrumentation.aws.v2.sqs.TracingList +import javax.jms.Session import org.elasticmq.rest.sqs.SQSRestServerBuilder import software.amazon.awssdk.auth.credentials.AnonymousCredentialsProvider import software.amazon.awssdk.core.SdkBytes @@ -27,11 +31,6 @@ import software.amazon.awssdk.services.sqs.model.SendMessageRequest import spock.lang.IgnoreIf import spock.lang.Shared -import javax.jms.Session - -import static datadog.trace.agent.test.utils.TraceUtils.basicSpan -import static java.nio.charset.StandardCharsets.UTF_8 - abstract class SqsClientTest extends VersionedNamingTestBase { def setup() { @@ -189,6 +188,31 @@ abstract class SqsClientTest extends VersionedNamingTestBase { client.close() } + def "dadatog context is not injected if SqsInjectDatadogAttribute is disabled"() { + setup: + injectSysConfig("sqs.inject.datadog.attribute.enabled", "false") + def client = SqsClient.builder() + .region(Region.EU_CENTRAL_1) + .endpointOverride(endpoint) + .credentialsProvider(credentialsProvider) + .build() + def queueUrl = client.createQueue(CreateQueueRequest.builder().queueName('somequeue').build()).queueUrl() + TEST_WRITER.clear() + + when: + client.sendMessage(SendMessageRequest.builder().queueUrl(queueUrl).messageBody('sometext').build()) + def messages = client.receiveMessage(ReceiveMessageRequest.builder().queueUrl(queueUrl).build()).messages() + + if (isDataStreamsEnabled()) { + TEST_DATA_STREAMS_WRITER.waitForGroups(1) + } + + then: + assert !messages[0].messageAttributes().containsKey("_datadog") + + cleanup: + client.close() + } @IgnoreIf({instance.isDataStreamsEnabled()}) def "trace details propagated via embedded SQS message attribute (string)"() { setup: diff --git a/dd-trace-api/src/main/java/datadog/trace/api/ConfigDefaults.java b/dd-trace-api/src/main/java/datadog/trace/api/ConfigDefaults.java index 8ac6de1cf0b..c00c327139f 100644 --- a/dd-trace-api/src/main/java/datadog/trace/api/ConfigDefaults.java +++ b/dd-trace-api/src/main/java/datadog/trace/api/ConfigDefaults.java @@ -46,6 +46,7 @@ public final class ConfigDefaults { public static final String DEFAULT_AGENT_WRITER_TYPE = "DDAgentWriter"; public static final boolean DEFAULT_STARTUP_LOGS_ENABLED = true; + static final boolean DEFAULT_INJECT_DATADOG_ATTRIBUTE = true; static final boolean DEFAULT_WRITER_BAGGAGE_INJECT = true; static final String DEFAULT_SITE = "datadoghq.com"; diff --git a/internal-api/src/main/java/datadog/trace/api/Config.java b/internal-api/src/main/java/datadog/trace/api/Config.java index 4455a97403a..c4f6e4efa03 100644 --- a/internal-api/src/main/java/datadog/trace/api/Config.java +++ b/internal-api/src/main/java/datadog/trace/api/Config.java @@ -107,6 +107,7 @@ import static datadog.trace.api.ConfigDefaults.DEFAULT_IAST_TRUNCATION_MAX_VALUE_LENGTH; import static datadog.trace.api.ConfigDefaults.DEFAULT_IAST_WEAK_CIPHER_ALGORITHMS; import static datadog.trace.api.ConfigDefaults.DEFAULT_IAST_WEAK_HASH_ALGORITHMS; +import static datadog.trace.api.ConfigDefaults.DEFAULT_INJECT_DATADOG_ATTRIBUTE; import static datadog.trace.api.ConfigDefaults.DEFAULT_INSTRUMENTATION_SOURCE; import static datadog.trace.api.ConfigDefaults.DEFAULT_JAX_RS_EXCEPTION_AS_ERROR_ENABLED; import static datadog.trace.api.ConfigDefaults.DEFAULT_JMX_FETCH_ENABLED; @@ -1309,6 +1310,11 @@ public static String getHostName() { private final int tagValueUtf8CacheSize; private final int stackTraceLengthLimit; + private final boolean sfnInjectDatadogAttributeEnabled; + private final boolean sqsInjectDatadogAttributeEnabled; + private final boolean snsInjectDatadogAttributeEnabled; + private final boolean eventbridgeInjectDatadogAttributeEnabled; + private final RumInjectorConfig rumInjectorConfig; private final boolean aiGuardEnabled; @@ -1591,6 +1597,15 @@ private Config(final ConfigProvider configProvider, final InstrumenterConfig ins awsServerless = getEnv("AWS_LAMBDA_FUNCTION_NAME") != null && !getEnv("AWS_LAMBDA_FUNCTION_NAME").isEmpty(); + sfnInjectDatadogAttributeEnabled = + isInjectDatadogAttributeEnabled(DEFAULT_INJECT_DATADOG_ATTRIBUTE, "sfn"); + eventbridgeInjectDatadogAttributeEnabled = + isInjectDatadogAttributeEnabled(DEFAULT_INJECT_DATADOG_ATTRIBUTE, "eventbridge"); + snsInjectDatadogAttributeEnabled = + isInjectDatadogAttributeEnabled(DEFAULT_INJECT_DATADOG_ATTRIBUTE, "sns"); + sqsInjectDatadogAttributeEnabled = + isInjectDatadogAttributeEnabled(DEFAULT_INJECT_DATADOG_ATTRIBUTE, "sqs"); + spanAttributeSchemaVersion = schemaVersionFromConfig(); peerHostNameEnabled = configProvider.getBoolean(TRACE_PEER_HOSTNAME_ENABLED, true); @@ -4734,6 +4749,22 @@ public int getStackTraceLengthLimit() { return stackTraceLengthLimit; } + public boolean isSqsInjectDatadogAttributeEnabled() { + return sqsInjectDatadogAttributeEnabled; + } + + public boolean isSnsInjectDatadogAttributeEnabled() { + return snsInjectDatadogAttributeEnabled; + } + + public boolean isEventbridgeInjectDatadogAttributeEnabled() { + return eventbridgeInjectDatadogAttributeEnabled; + } + + public boolean isSfnInjectDatadogAttributeEnabled() { + return sfnInjectDatadogAttributeEnabled; + } + /** @return A map of tags to be applied only to the local application root span. */ public TagMap getLocalRootSpanTags() { final Map runtimeTags = getRuntimeTags(); @@ -5181,6 +5212,12 @@ public boolean isPropagationEnabled( Arrays.asList(integrationNames), "", ".propagation.enabled", defaultEnabled); } + public boolean isInjectDatadogAttributeEnabled( + final boolean defaultEnabled, final String... integrationNames) { + return configProvider.isEnabled( + Arrays.asList(integrationNames), "", ".inject.datadog.attribute.enabled", defaultEnabled); + } + public boolean isLegacyTracingEnabled( final boolean defaultEnabled, final String... integrationNames) { return configProvider.isEnabled( diff --git a/internal-api/src/test/groovy/datadog/trace/api/ConfigTest.groovy b/internal-api/src/test/groovy/datadog/trace/api/ConfigTest.groovy index 028e5f0e29b..f82b9d2f874 100644 --- a/internal-api/src/test/groovy/datadog/trace/api/ConfigTest.groovy +++ b/internal-api/src/test/groovy/datadog/trace/api/ConfigTest.groovy @@ -189,6 +189,16 @@ class ConfigTest extends DDSpecification { private static final DD_TRACE_CLOUD_REQUEST_PAYLOAD_TAGGING_ENV = "DD_TRACE_CLOUD_REQUEST_PAYLOAD_TAGGING" private static final DD_TRACE_CLOUD_RESPONSE_PAYLOAD_TAGGING_ENV = "DD_TRACE_CLOUD_RESPONSE_PAYLOAD_TAGGING" + private static final DD_SFN_INJECT_DATADOG_ATTRIBUTE_ENABLED_ENV = "DD_SFN_INJECT_DATADOG_ATTRIBUTE_ENABLED" + private static final DD_SNS_INJECT_DATADOG_ATTRIBUTE_ENABLED_ENV = "DD_SNS_INJECT_DATADOG_ATTRIBUTE_ENABLED" + private static final DD_SQS_INJECT_DATADOG_ATTRIBUTE_ENABLED_ENV = "DD_SQS_INJECT_DATADOG_ATTRIBUTE_ENABLED" + private static final DD_EVENTBRIDGE_INJECT_DATADOG_ATTRIBUTE_ENABLED_ENV = "DD_EVENTBRIDGE_INJECT_DATADOG_ATTRIBUTE_ENABLED" + + private static final EVENTBRIDGE_INJECT_DATADOG_ATTRIBUTE_ENABLED = "eventbridge.inject.datadog.attribute.enabled" + private static final SFN_INJECT_DATADOG_ATTRIBUTE_ENABLED = "sfn.inject.datadog.attribute.enabled" + private static final SNS_INJECT_DATADOG_ATTRIBUTE_ENABLED = "sns.inject.datadog.attribute.enabled" + private static final SQS_INJECT_DATADOG_ATTRIBUTE_ENABLED = "sqs.inject.datadog.attribute.enabled" + private static final DD_TRACE_OTEL_ENABLED_ENV = "DD_TRACE_OTEL_ENABLED" private static final DD_TRACE_OTEL_ENABLED_PROP = "dd.trace.otel.enabled" @@ -320,6 +330,11 @@ class ConfigTest extends DDSpecification { prop.setProperty(TRACE_CLOUD_REQUEST_PAYLOAD_TAGGING, "all") prop.setProperty(TRACE_CLOUD_RESPONSE_PAYLOAD_TAGGING, "all") + prop.setProperty(SFN_INJECT_DATADOG_ATTRIBUTE_ENABLED, "false") + prop.setProperty(EVENTBRIDGE_INJECT_DATADOG_ATTRIBUTE_ENABLED, "false") + prop.setProperty(SNS_INJECT_DATADOG_ATTRIBUTE_ENABLED, "false") + prop.setProperty(SQS_INJECT_DATADOG_ATTRIBUTE_ENABLED, "false") + prop.setProperty(METRICS_OTEL_ENABLED, "True") prop.setProperty(METRICS_OTEL_INTERVAL, "11000") prop.setProperty(METRICS_OTEL_TIMEOUT, "9000") @@ -428,6 +443,11 @@ class ConfigTest extends DDSpecification { config.cloudRequestPayloadTagging == [] config.cloudResponsePayloadTagging == [] + !config.isSfnInjectDatadogAttributeEnabled() + !config.isSqsInjectDatadogAttributeEnabled() + !config.isSnsInjectDatadogAttributeEnabled() + !config.isEventbridgeInjectDatadogAttributeEnabled() + config.xDatadogTagsMaxLength == 128 config.metricsOtelEnabled config.metricsOtelInterval == 11000 @@ -722,6 +742,11 @@ class ConfigTest extends DDSpecification { System.setProperty(PREFIX + TRACE_CLOUD_REQUEST_PAYLOAD_TAGGING, "all") System.setProperty(PREFIX + TRACE_CLOUD_RESPONSE_PAYLOAD_TAGGING, "all") + System.setProperty(PREFIX + SFN_INJECT_DATADOG_ATTRIBUTE_ENABLED, "false") + System.setProperty(PREFIX + EVENTBRIDGE_INJECT_DATADOG_ATTRIBUTE_ENABLED, "false") + System.setProperty(PREFIX + SNS_INJECT_DATADOG_ATTRIBUTE_ENABLED, "false") + System.setProperty(PREFIX + SQS_INJECT_DATADOG_ATTRIBUTE_ENABLED, "false") + System.setProperty(DD_METRICS_OTEL_ENABLED_PROP, "True") System.setProperty(OTEL_METRIC_EXPORT_INTERVAL_PROP, "11000") System.setProperty(OTEL_METRIC_EXPORT_TIMEOUT_PROP, "9000") @@ -826,6 +851,11 @@ class ConfigTest extends DDSpecification { config.cloudRequestPayloadTagging == [] config.cloudResponsePayloadTagging == [] + !config.isSfnInjectDatadogAttributeEnabled() + !config.isSqsInjectDatadogAttributeEnabled() + !config.isSnsInjectDatadogAttributeEnabled() + !config.isEventbridgeInjectDatadogAttributeEnabled() + config.xDatadogTagsMaxLength == 128 config.metricsOtelEnabled @@ -859,6 +889,10 @@ class ConfigTest extends DDSpecification { environmentVariables.set(DD_TRACE_HEADER_TAGS, "*") environmentVariables.set(DD_TRACE_CLOUD_REQUEST_PAYLOAD_TAGGING_ENV, "all") environmentVariables.set(DD_TRACE_CLOUD_RESPONSE_PAYLOAD_TAGGING_ENV, "all") + environmentVariables.set(DD_SFN_INJECT_DATADOG_ATTRIBUTE_ENABLED_ENV, "false") + environmentVariables.set(DD_SQS_INJECT_DATADOG_ATTRIBUTE_ENABLED_ENV, "false") + environmentVariables.set(DD_SNS_INJECT_DATADOG_ATTRIBUTE_ENABLED_ENV, "false") + environmentVariables.set(DD_EVENTBRIDGE_INJECT_DATADOG_ATTRIBUTE_ENABLED_ENV, "false") environmentVariables.set(DD_METRICS_OTEL_ENABLED_ENV, "True") environmentVariables.set(OTEL_RESOURCE_ATTRIBUTES_ENV, "service.name=my=app,service.version=1.0.0,deployment.environment=production") @@ -890,6 +924,10 @@ class ConfigTest extends DDSpecification { config.getLongRunningTraceFlushInterval() == 81 config.cloudRequestPayloadTagging == [] config.cloudResponsePayloadTagging == [] + !config.isSfnInjectDatadogAttributeEnabled() + !config.isSqsInjectDatadogAttributeEnabled() + !config.isSnsInjectDatadogAttributeEnabled() + !config.isEventbridgeInjectDatadogAttributeEnabled() config.requestHeaderTags == ["*": "http.request.headers."] config.responseHeaderTags == ["*": "http.response.headers."] diff --git a/metadata/supported-configurations.json b/metadata/supported-configurations.json index 29a68a26cd8..556024a384d 100644 --- a/metadata/supported-configurations.json +++ b/metadata/supported-configurations.json @@ -668,6 +668,7 @@ "DD_TRACE_EMR_AWS_SDK_ENABLED": ["A"], "DD_TRACE_ENABLED": ["A"], "DD_TRACE_EVENTBRIDGE_ENABLED": ["A"], + "DD_TRACE_EVENTBRIDGE_INJECT_DATADOG_ATTRIBUTE_ENABLED": ["A"], "DD_TRACE_EXECUTORS": ["A"], "DD_TRACE_EXECUTORS_ALL": ["A"], "DD_TRACE_EXPERIMENTAL_FEATURES_ENABLED": ["A"], @@ -1190,10 +1191,12 @@ "DD_TRACE_SERVLET_SESSION_ENABLED": ["A"], "DD_TRACE_SETUP_TEARDOWN_ENABLED": ["A"], "DD_TRACE_SFN_ENABLED": ["A"], + "DD_TRACE_SFN_INJECT_DATADOG_ATTRIBUTE_ENABLED": ["A"], "DD_TRACE_SHUTDOWN_ENABLED": ["A"], "DD_TRACE_SLICK_ENABLED": ["A"], "DD_TRACE_SNAKEYAML_ENABLED": ["A"], "DD_TRACE_SNS_ENABLED": ["A"], + "DD_TRACE_SNS_INJECT_DATADOG_ATTRIBUTE_ENABLED": ["A"], "DD_TRACE_SOCKET_ENABLED": ["A"], "DD_TRACE_SPAN_ATTRIBUTE_SCHEMA": ["A"], "DD_TRACE_SPAN_TAGS": ["A"], @@ -1250,6 +1253,7 @@ "DD_TRACE_SPYMEMCACHED_ENABLED": ["A"], "DD_TRACE_SQS_BODY_PROPAGATION_ENABLED": ["A"], "DD_TRACE_SQS_ENABLED": ["A"], + "DD_TRACE_SQS_INJECT_DATADOG_ATTRIBUTE_ENABLED": ["A"], "DD_TRACE_SQS_LEGACY_TRACING_ENABLED": ["A"], "DD_TRACE_SQS_PROPAGATION_ENABLED": ["A"], "DD_TRACE_SQS_TIME_IN_QUEUE_ENABLED": ["A"], @@ -1499,6 +1503,7 @@ "DD_TRACE_ELASTICSEARCH_TRANSPORT_ENABLED": ["DD_TRACE_INTEGRATION_ELASTICSEARCH_TRANSPORT_ENABLED","DD_INTEGRATION_ELASTICSEARCH_TRANSPORT_ENABLED"], "DD_TRACE_EMR_AWS_SDK_ENABLED": ["DD_TRACE_INTEGRATION_EMR_AWS_SDK_ENABLED","DD_INTEGRATION_EMR_AWS_SDK_ENABLED"], "DD_TRACE_EVENTBRIDGE_ENABLED": ["DD_TRACE_INTEGRATION_EVENTBRIDGE_ENABLED","DD_INTEGRATION_EVENTBRIDGE_ENABLED"], + "DD_TRACE_EVENTBRIDGE_INJECT_DATADOG_ATTRIBUTE_ENABLED": ["DD_EVENTBRIDGE_INJECT_DATADOG_ATTRIBUTE_ENABLED"], "DD_TRACE_FILEITEMITERATOR_ENABLED": ["DD_TRACE_INTEGRATION_FILEITEMITERATOR_ENABLED","DD_INTEGRATION_FILEITEMITERATOR_ENABLED"], "DD_TRACE_FILEITEMSTREAM_ENABLED": ["DD_TRACE_INTEGRATION_FILEITEMSTREAM_ENABLED","DD_INTEGRATION_FILEITEMSTREAM_ENABLED"], "DD_TRACE_FILEITEM_ENABLED": ["DD_TRACE_INTEGRATION_FILEITEM_ENABLED","DD_INTEGRATION_FILEITEM_ENABLED"], @@ -1881,10 +1886,12 @@ "DD_TRACE_SERVLET_SESSION_ENABLED": ["DD_TRACE_INTEGRATION_SERVLET_SESSION_ENABLED","DD_INTEGRATION_SERVLET_SESSION_ENABLED"], "DD_TRACE_SETUP_TEARDOWN_ENABLED": ["DD_TRACE_INTEGRATION_SETUP_TEARDOWN_ENABLED","DD_INTEGRATION_SETUP_TEARDOWN_ENABLED"], "DD_TRACE_SFN_ENABLED": ["DD_TRACE_INTEGRATION_SFN_ENABLED","DD_INTEGRATION_SFN_ENABLED"], + "DD_TRACE_SFN_INJECT_DATADOG_ATTRIBUTE_ENABLED": ["DD_SFN_INJECT_DATADOG_ATTRIBUTE_ENABLED"], "DD_TRACE_SHUTDOWN_ENABLED": ["DD_TRACE_INTEGRATION_SHUTDOWN_ENABLED","DD_INTEGRATION_SHUTDOWN_ENABLED"], "DD_TRACE_SLICK_ENABLED": ["DD_TRACE_INTEGRATION_SLICK_ENABLED","DD_INTEGRATION_SLICK_ENABLED"], "DD_TRACE_SNAKEYAML_ENABLED": ["DD_TRACE_INTEGRATION_SNAKEYAML_ENABLED","DD_INTEGRATION_SNAKEYAML_ENABLED"], "DD_TRACE_SNS_ENABLED": ["DD_TRACE_INTEGRATION_SNS_ENABLED","DD_INTEGRATION_SNS_ENABLED"], + "DD_TRACE_SNS_INJECT_DATADOG_ATTRIBUTE_ENABLED": ["DD_SNS_INJECT_DATADOG_ATTRIBUTE_ENABLED"], "DD_TRACE_SOCKET_ENABLED": ["DD_TRACE_INTEGRATION_SOCKET_ENABLED","DD_INTEGRATION_SOCKET_ENABLED"], "DD_TRACE_SPARKJAVA_2_4_ENABLED": ["DD_TRACE_INTEGRATION_SPARKJAVA_2_4_ENABLED","DD_INTEGRATION_SPARKJAVA_2_4_ENABLED"], "DD_TRACE_SPARKJAVA_ENABLED": ["DD_TRACE_INTEGRATION_SPARKJAVA_ENABLED","DD_INTEGRATION_SPARKJAVA_ENABLED"], @@ -1933,6 +1940,7 @@ "DD_TRACE_SPYMEMCACHED_ANALYTICS_SAMPLE_RATE": ["DD_SPYMEMCACHED_ANALYTICS_SAMPLE_RATE"], "DD_TRACE_SPYMEMCACHED_ENABLED": ["DD_TRACE_INTEGRATION_SPYMEMCACHED_ENABLED","DD_INTEGRATION_SPYMEMCACHED_ENABLED"], "DD_TRACE_SQS_ENABLED": ["DD_TRACE_INTEGRATION_SQS_ENABLED","DD_INTEGRATION_SQS_ENABLED"], + "DD_TRACE_SQS_INJECT_DATADOG_ATTRIBUTE_ENABLED": ["DD_SQS_INJECT_DATADOG_ATTRIBUTE_ENABLED"], "DD_TRACE_SQS_LEGACY_TRACING_ENABLED": ["DD_SQS_LEGACY_TRACING_ENABLED"], "DD_TRACE_SQS_PROPAGATION_ENABLED": ["DD_TRACE_INTEGRATION_SQS_PROPAGATION_ENABLED","DD_INTEGRATION_SQS_PROPAGATION_ENABLED"], "DD_TRACE_SSLSOCKET_ENABLED": ["DD_TRACE_INTEGRATION_SSLSOCKET_ENABLED","DD_INTEGRATION_SSLSOCKET_ENABLED"],