diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/testSqsNoReceiveTelemetry/groovy/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/SqsSuppressReceiveSpansTest.groovy b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/testSqsNoReceiveTelemetry/groovy/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/SqsSuppressReceiveSpansTest.groovy deleted file mode 100644 index 05c3db6ca7d9..000000000000 --- a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/testSqsNoReceiveTelemetry/groovy/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/SqsSuppressReceiveSpansTest.groovy +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.awssdk.v1_11 - -import com.amazonaws.services.sqs.AmazonSQSAsyncClientBuilder -import io.opentelemetry.instrumentation.awssdk.v1_11.AbstractSqsSuppressReceiveSpansTest -import io.opentelemetry.instrumentation.test.AgentTestTrait - -class SqsSuppressReceiveSpansTest extends AbstractSqsSuppressReceiveSpansTest implements AgentTestTrait { - @Override - AmazonSQSAsyncClientBuilder configureClient(AmazonSQSAsyncClientBuilder client) { - return client - } -} diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/testSqsNoReceiveTelemetry/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/SqsSuppressReceiveSpansTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/testSqsNoReceiveTelemetry/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/SqsSuppressReceiveSpansTest.java new file mode 100644 index 000000000000..16fce32ac1e3 --- /dev/null +++ b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/testSqsNoReceiveTelemetry/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/SqsSuppressReceiveSpansTest.java @@ -0,0 +1,28 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.awssdk.v1_11; + +import com.amazonaws.services.sqs.AmazonSQSAsyncClientBuilder; +import io.opentelemetry.instrumentation.awssdk.v1_11.AbstractSqsSuppressReceiveSpansTest; +import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import org.junit.jupiter.api.extension.RegisterExtension; + +class SqsSuppressReceiveSpansTest extends AbstractSqsSuppressReceiveSpansTest { + + @RegisterExtension + private static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); + + @Override + protected InstrumentationExtension testing() { + return testing; + } + + @Override + public AmazonSQSAsyncClientBuilder configureClient(AmazonSQSAsyncClientBuilder client) { + return client; + } +} diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/test/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/instrumentor/SqsSuppressReceiveSpansTest.groovy b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/test/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/instrumentor/SqsSuppressReceiveSpansTest.groovy deleted file mode 100644 index 9a33658390b2..000000000000 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/test/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/instrumentor/SqsSuppressReceiveSpansTest.groovy +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.awssdk.v1_11.instrumentor - -import com.amazonaws.services.sqs.AmazonSQSAsyncClientBuilder -import io.opentelemetry.instrumentation.awssdk.v1_11.AbstractSqsSuppressReceiveSpansTest -import io.opentelemetry.instrumentation.test.LibraryTestTrait - -class SqsSuppressReceiveSpansTest extends AbstractSqsSuppressReceiveSpansTest implements LibraryTestTrait { - @Override - AmazonSQSAsyncClientBuilder configureClient(AmazonSQSAsyncClientBuilder client) { - return client - } -} diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/instrumentor/SqsSuppressReceiveSpansTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/instrumentor/SqsSuppressReceiveSpansTest.java new file mode 100644 index 000000000000..f676cf2c2703 --- /dev/null +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/instrumentor/SqsSuppressReceiveSpansTest.java @@ -0,0 +1,28 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.awssdk.v1_11.instrumentor; + +import com.amazonaws.services.sqs.AmazonSQSAsyncClientBuilder; +import io.opentelemetry.instrumentation.awssdk.v1_11.AbstractSqsSuppressReceiveSpansTest; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension; +import org.junit.jupiter.api.extension.RegisterExtension; + +public class SqsSuppressReceiveSpansTest extends AbstractSqsSuppressReceiveSpansTest { + + @RegisterExtension + private static final InstrumentationExtension testing = LibraryInstrumentationExtension.create(); + + @Override + protected InstrumentationExtension testing() { + return testing; + } + + @Override + public AmazonSQSAsyncClientBuilder configureClient(AmazonSQSAsyncClientBuilder client) { + return client; + } +} diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/SqsSuppressReceiveSpansTest.groovy b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/SqsSuppressReceiveSpansTest.groovy deleted file mode 100644 index 471ffb571408..000000000000 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/SqsSuppressReceiveSpansTest.groovy +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.awssdk.v1_11 - -import com.amazonaws.services.sqs.AmazonSQSAsyncClientBuilder -import io.opentelemetry.instrumentation.test.LibraryTestTrait - -class SqsSuppressReceiveSpansTest extends AbstractSqsSuppressReceiveSpansTest implements LibraryTestTrait { - @Override - AmazonSQSAsyncClientBuilder configureClient(AmazonSQSAsyncClientBuilder client) { - return client.withRequestHandlers( - AwsSdkTelemetry.builder(getOpenTelemetry()) - .setCaptureExperimentalSpanAttributes(true) - .build() - .newRequestHandler()) - } -} diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsSuppressReceiveSpansTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsSuppressReceiveSpansTest.java new file mode 100644 index 000000000000..d87d8f0af1a1 --- /dev/null +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsSuppressReceiveSpansTest.java @@ -0,0 +1,31 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.awssdk.v1_11; + +import com.amazonaws.services.sqs.AmazonSQSAsyncClientBuilder; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension; +import org.junit.jupiter.api.extension.RegisterExtension; + +public class SqsSuppressReceiveSpansTest extends AbstractSqsSuppressReceiveSpansTest { + + @RegisterExtension + private static final InstrumentationExtension testing = LibraryInstrumentationExtension.create(); + + @Override + protected InstrumentationExtension testing() { + return testing; + } + + @Override + public AmazonSQSAsyncClientBuilder configureClient(AmazonSQSAsyncClientBuilder client) { + return client.withRequestHandlers( + AwsSdkTelemetry.builder(testing().getOpenTelemetry()) + .setCaptureExperimentalSpanAttributes(true) + .build() + .newRequestHandler()); + } +} diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractSqsSuppressReceiveSpansTest.groovy b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractSqsSuppressReceiveSpansTest.groovy deleted file mode 100644 index 66aebca87807..000000000000 --- a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractSqsSuppressReceiveSpansTest.groovy +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.awssdk.v1_11 - -import com.amazonaws.auth.AWSStaticCredentialsProvider -import com.amazonaws.auth.BasicAWSCredentials -import com.amazonaws.client.builder.AwsClientBuilder -import com.amazonaws.services.sqs.AmazonSQSAsyncClient -import com.amazonaws.services.sqs.AmazonSQSAsyncClientBuilder -import com.amazonaws.services.sqs.model.ReceiveMessageRequest -import com.amazonaws.services.sqs.model.SendMessageRequest -import io.opentelemetry.instrumentation.test.InstrumentationSpecification -import io.opentelemetry.instrumentation.test.utils.PortUtils -import io.opentelemetry.semconv.SemanticAttributes -import org.elasticmq.rest.sqs.SQSRestServerBuilder -import spock.lang.Shared - -import static io.opentelemetry.api.trace.SpanKind.CLIENT -import static io.opentelemetry.api.trace.SpanKind.CONSUMER -import static io.opentelemetry.api.trace.SpanKind.PRODUCER - -abstract class AbstractSqsSuppressReceiveSpansTest extends InstrumentationSpecification { - - abstract AmazonSQSAsyncClientBuilder configureClient(AmazonSQSAsyncClientBuilder client) - - @Shared - def sqs - @Shared - AmazonSQSAsyncClient client - @Shared - int sqsPort - - def setupSpec() { - - sqsPort = PortUtils.findOpenPort() - sqs = SQSRestServerBuilder.withPort(sqsPort).withInterface("localhost").start() - println getClass().name + " SQS server started at: localhost:$sqsPort/" - - def credentials = new AWSStaticCredentialsProvider(new BasicAWSCredentials("x", "x")) - def endpointConfiguration = new AwsClientBuilder.EndpointConfiguration("http://localhost:" + sqsPort, "elasticmq") - client = configureClient(AmazonSQSAsyncClient.asyncBuilder()).withCredentials(credentials).withEndpointConfiguration(endpointConfiguration).build() - } - - def cleanupSpec() { - if (sqs != null) { - sqs.stopAndWait() - } - } - - def "simple sqs producer-consumer services"() { - setup: - client.createQueue("testSdkSqs") - - when: - SendMessageRequest send = new SendMessageRequest("http://localhost:$sqsPort/000000000000/testSdkSqs", "{\"type\": \"hello\"}") - client.sendMessage(send) - def receiveMessageResult = client.receiveMessage("http://localhost:$sqsPort/000000000000/testSdkSqs") - receiveMessageResult.messages.each {message -> runWithSpan("process child") {}} - - then: - assertTraces(2) { - trace(0, 1) { - - span(0) { - name "SQS.CreateQueue" - kind CLIENT - hasNoParent() - attributes { - "aws.agent" "java-aws-sdk" - "aws.endpoint" "http://localhost:$sqsPort" - "aws.queue.name" "testSdkSqs" - "rpc.system" "aws-api" - "rpc.service" "AmazonSQS" - "rpc.method" "CreateQueue" - "$SemanticAttributes.HTTP_REQUEST_METHOD" "POST" - "$SemanticAttributes.HTTP_RESPONSE_STATUS_CODE" 200 - "$SemanticAttributes.URL_FULL" "http://localhost:$sqsPort" - "$SemanticAttributes.SERVER_ADDRESS" "localhost" - "$SemanticAttributes.SERVER_PORT" sqsPort - "$SemanticAttributes.NETWORK_PROTOCOL_VERSION" "1.1" - } - } - } - trace(1, 3) { - span(0) { - name "testSdkSqs publish" - kind PRODUCER - hasNoParent() - attributes { - "aws.agent" "java-aws-sdk" - "aws.endpoint" "http://localhost:$sqsPort" - "aws.queue.url" "http://localhost:$sqsPort/000000000000/testSdkSqs" - "rpc.system" "aws-api" - "rpc.method" "SendMessage" - "rpc.service" "AmazonSQS" - "$SemanticAttributes.HTTP_REQUEST_METHOD" "POST" - "$SemanticAttributes.HTTP_RESPONSE_STATUS_CODE" 200 - "$SemanticAttributes.URL_FULL" "http://localhost:$sqsPort" - "$SemanticAttributes.SERVER_ADDRESS" "localhost" - "$SemanticAttributes.SERVER_PORT" sqsPort - "$SemanticAttributes.MESSAGING_SYSTEM" "AmazonSQS" - "$SemanticAttributes.MESSAGING_DESTINATION_NAME" "testSdkSqs" - "$SemanticAttributes.MESSAGING_OPERATION" "publish" - "$SemanticAttributes.MESSAGING_MESSAGE_ID" String - "$SemanticAttributes.NETWORK_PROTOCOL_VERSION" "1.1" - } - } - span(1) { - name "testSdkSqs process" - kind CONSUMER - childOf span(0) - attributes { - "aws.agent" "java-aws-sdk" - "aws.endpoint" "http://localhost:$sqsPort" - "rpc.method" "ReceiveMessage" - "aws.queue.url" "http://localhost:$sqsPort/000000000000/testSdkSqs" - "rpc.system" "aws-api" - "rpc.service" "AmazonSQS" - "$SemanticAttributes.HTTP_REQUEST_METHOD" "POST" - "$SemanticAttributes.HTTP_RESPONSE_STATUS_CODE" 200 - "$SemanticAttributes.URL_FULL" "http://localhost:$sqsPort" - "$SemanticAttributes.SERVER_ADDRESS" "localhost" - "$SemanticAttributes.SERVER_PORT" sqsPort - "$SemanticAttributes.MESSAGING_SYSTEM" "AmazonSQS" - "$SemanticAttributes.MESSAGING_DESTINATION_NAME" "testSdkSqs" - "$SemanticAttributes.MESSAGING_OPERATION" "process" - "$SemanticAttributes.MESSAGING_MESSAGE_ID" String - "$SemanticAttributes.NETWORK_PROTOCOL_VERSION" "1.1" - } - } - span(2) { - name "process child" - childOf span(1) - attributes { - } - } - } - } - } - - def "simple sqs producer-consumer services with parent span"() { - setup: - client.createQueue("testSdkSqs") - - when: - SendMessageRequest send = new SendMessageRequest("http://localhost:$sqsPort/000000000000/testSdkSqs", "{\"type\": \"hello\"}") - client.sendMessage(send) - runWithSpan("parent") { - def receiveMessageResult = client.receiveMessage("http://localhost:$sqsPort/000000000000/testSdkSqs") - receiveMessageResult.messages.each {message -> runWithSpan("process child") {}} - } - - then: - assertTraces(3) { - trace(0, 1) { - - span(0) { - name "SQS.CreateQueue" - kind CLIENT - hasNoParent() - attributes { - "aws.agent" "java-aws-sdk" - "aws.endpoint" "http://localhost:$sqsPort" - "aws.queue.name" "testSdkSqs" - "rpc.system" "aws-api" - "rpc.service" "AmazonSQS" - "rpc.method" "CreateQueue" - "$SemanticAttributes.HTTP_REQUEST_METHOD" "POST" - "$SemanticAttributes.HTTP_RESPONSE_STATUS_CODE" 200 - "$SemanticAttributes.URL_FULL" "http://localhost:$sqsPort" - "$SemanticAttributes.SERVER_ADDRESS" "localhost" - "$SemanticAttributes.SERVER_PORT" sqsPort - "$SemanticAttributes.NETWORK_PROTOCOL_VERSION" "1.1" - } - } - } - trace(1, 3) { - span(0) { - name "testSdkSqs publish" - kind PRODUCER - hasNoParent() - attributes { - "aws.agent" "java-aws-sdk" - "aws.endpoint" "http://localhost:$sqsPort" - "aws.queue.url" "http://localhost:$sqsPort/000000000000/testSdkSqs" - "rpc.system" "aws-api" - "rpc.method" "SendMessage" - "rpc.service" "AmazonSQS" - "$SemanticAttributes.HTTP_REQUEST_METHOD" "POST" - "$SemanticAttributes.HTTP_RESPONSE_STATUS_CODE" 200 - "$SemanticAttributes.URL_FULL" "http://localhost:$sqsPort" - "$SemanticAttributes.SERVER_ADDRESS" "localhost" - "$SemanticAttributes.SERVER_PORT" sqsPort - "$SemanticAttributes.MESSAGING_SYSTEM" "AmazonSQS" - "$SemanticAttributes.MESSAGING_DESTINATION_NAME" "testSdkSqs" - "$SemanticAttributes.MESSAGING_OPERATION" "publish" - "$SemanticAttributes.MESSAGING_MESSAGE_ID" String - "$SemanticAttributes.NETWORK_PROTOCOL_VERSION" "1.1" - } - } - span(1) { - name "testSdkSqs process" - kind CONSUMER - childOf span(0) - attributes { - "aws.agent" "java-aws-sdk" - "aws.endpoint" "http://localhost:$sqsPort" - "rpc.method" "ReceiveMessage" - "aws.queue.url" "http://localhost:$sqsPort/000000000000/testSdkSqs" - "rpc.system" "aws-api" - "rpc.service" "AmazonSQS" - "$SemanticAttributes.HTTP_REQUEST_METHOD" "POST" - "$SemanticAttributes.HTTP_RESPONSE_STATUS_CODE" 200 - "$SemanticAttributes.URL_FULL" "http://localhost:$sqsPort" - "$SemanticAttributes.SERVER_ADDRESS" "localhost" - "$SemanticAttributes.SERVER_PORT" sqsPort - "$SemanticAttributes.MESSAGING_SYSTEM" "AmazonSQS" - "$SemanticAttributes.MESSAGING_DESTINATION_NAME" "testSdkSqs" - "$SemanticAttributes.MESSAGING_OPERATION" "process" - "$SemanticAttributes.MESSAGING_MESSAGE_ID" String - "$SemanticAttributes.NETWORK_PROTOCOL_VERSION" "1.1" - } - } - span(2) { - name "process child" - childOf span(1) - attributes { - } - } - } - /** - * This span represents HTTP "sending of receive message" operation. It's always single, while there can be multiple CONSUMER spans (one per consumed message). - * This one could be suppressed (by IF in TracingRequestHandler#beforeRequest but then HTTP instrumentation span would appear - */ - trace(2, 2) { - span(0) { - name "parent" - hasNoParent() - } - span(1) { - name "SQS.ReceiveMessage" - kind CLIENT - childOf span(0) - attributes { - "aws.agent" "java-aws-sdk" - "aws.endpoint" "http://localhost:$sqsPort" - "rpc.method" "ReceiveMessage" - "aws.queue.url" "http://localhost:$sqsPort/000000000000/testSdkSqs" - "rpc.system" "aws-api" - "rpc.service" "AmazonSQS" - "$SemanticAttributes.HTTP_REQUEST_METHOD" "POST" - "$SemanticAttributes.HTTP_RESPONSE_STATUS_CODE" 200 - "$SemanticAttributes.URL_FULL" "http://localhost:$sqsPort" - "$SemanticAttributes.SERVER_ADDRESS" "localhost" - "$SemanticAttributes.SERVER_PORT" sqsPort - "$SemanticAttributes.NETWORK_PROTOCOL_VERSION" "1.1" - } - } - } - } - } - - def "only adds attribute name once when request reused"() { - setup: - client.createQueue("testSdkSqs2") - - when: - SendMessageRequest send = new SendMessageRequest("http://localhost:$sqsPort/000000000000/testSdkSqs2", "{\"type\": \"hello\"}") - client.sendMessage(send) - ReceiveMessageRequest receive = new ReceiveMessageRequest("http://localhost:$sqsPort/000000000000/testSdkSqs2") - client.receiveMessage(receive) - client.sendMessage(send) - client.receiveMessage(receive) - - then: - receive.getAttributeNames() == ["AWSTraceHeader"] - } -} diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractSqsSuppressReceiveSpansTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractSqsSuppressReceiveSpansTest.java new file mode 100644 index 000000000000..dbfde22fa6f7 --- /dev/null +++ b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractSqsSuppressReceiveSpansTest.java @@ -0,0 +1,305 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.awssdk.v1_11; + +import static io.opentelemetry.api.common.AttributeKey.stringKey; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies; +import static org.assertj.core.api.Assertions.assertThat; + +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.client.builder.AwsClientBuilder; +import com.amazonaws.services.sqs.AmazonSQSAsync; +import com.amazonaws.services.sqs.AmazonSQSAsyncClient; +import com.amazonaws.services.sqs.AmazonSQSAsyncClientBuilder; +import com.amazonaws.services.sqs.model.ReceiveMessageRequest; +import com.amazonaws.services.sqs.model.ReceiveMessageResult; +import com.amazonaws.services.sqs.model.SendMessageRequest; +import com.google.common.collect.ImmutableList; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.instrumentation.test.utils.PortUtils; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.semconv.SemanticAttributes; +import org.elasticmq.rest.sqs.SQSRestServer; +import org.elasticmq.rest.sqs.SQSRestServerBuilder; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public abstract class AbstractSqsSuppressReceiveSpansTest { + + protected abstract InstrumentationExtension testing(); + + protected abstract AmazonSQSAsyncClientBuilder configureClient( + AmazonSQSAsyncClientBuilder client); + + private static int sqsPort; + private static SQSRestServer sqsRestServer; + private static AmazonSQSAsync sqsClient; + + @BeforeEach + void setUp() { + sqsPort = PortUtils.findOpenPort(); + sqsRestServer = SQSRestServerBuilder.withPort(sqsPort).withInterface("localhost").start(); + + AWSStaticCredentialsProvider credentials = + new AWSStaticCredentialsProvider(new BasicAWSCredentials("x", "x")); + AwsClientBuilder.EndpointConfiguration endpointConfiguration = + new AwsClientBuilder.EndpointConfiguration("http://localhost:" + sqsPort, "elasticmq"); + + sqsClient = + configureClient(AmazonSQSAsyncClient.asyncBuilder()) + .withCredentials(credentials) + .withEndpointConfiguration(endpointConfiguration) + .build(); + } + + @AfterEach + void cleanUp() { + if (sqsRestServer != null) { + sqsRestServer.stopAndWait(); + } + } + + @Test + void testSimpleSqsProducerConsumerServices() { + sqsClient.createQueue("testSdkSqs"); + + SendMessageRequest send = + new SendMessageRequest( + "http://localhost:" + sqsPort + "/000000000000/testSdkSqs", "{\"type\": \"hello\"}"); + sqsClient.sendMessage(send); + ReceiveMessageResult receiveMessageResult = + sqsClient.receiveMessage("http://localhost:" + sqsPort + "/000000000000/testSdkSqs"); + receiveMessageResult + .getMessages() + .forEach(message -> testing().runWithSpan("process child", () -> {})); + + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("SQS.CreateQueue") + .hasKind(SpanKind.CLIENT) + .hasNoParent() + .hasAttributesSatisfyingExactly( + equalTo(stringKey("aws.agent"), "java-aws-sdk"), + equalTo(stringKey("aws.endpoint"), "http://localhost:" + sqsPort), + equalTo(stringKey("aws.queue.name"), "testSdkSqs"), + equalTo(SemanticAttributes.RPC_SYSTEM, "aws-api"), + equalTo(SemanticAttributes.RPC_SERVICE, "AmazonSQS"), + equalTo(SemanticAttributes.RPC_METHOD, "CreateQueue"), + equalTo(SemanticAttributes.HTTP_REQUEST_METHOD, "POST"), + equalTo(SemanticAttributes.HTTP_RESPONSE_STATUS_CODE, 200), + equalTo(SemanticAttributes.URL_FULL, "http://localhost:" + sqsPort), + equalTo(SemanticAttributes.SERVER_ADDRESS, "localhost"), + equalTo(SemanticAttributes.SERVER_PORT, sqsPort), + equalTo(SemanticAttributes.NETWORK_PROTOCOL_VERSION, "1.1"))), + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("testSdkSqs publish") + .hasKind(SpanKind.PRODUCER) + .hasNoParent() + .hasAttributesSatisfyingExactly( + equalTo(stringKey("aws.agent"), "java-aws-sdk"), + equalTo(stringKey("aws.endpoint"), "http://localhost:" + sqsPort), + equalTo( + stringKey("aws.queue.url"), + "http://localhost:" + sqsPort + "/000000000000/testSdkSqs"), + equalTo(SemanticAttributes.RPC_SYSTEM, "aws-api"), + equalTo(SemanticAttributes.RPC_SERVICE, "AmazonSQS"), + equalTo(SemanticAttributes.RPC_METHOD, "SendMessage"), + equalTo(SemanticAttributes.HTTP_REQUEST_METHOD, "POST"), + equalTo(SemanticAttributes.HTTP_RESPONSE_STATUS_CODE, 200), + equalTo(SemanticAttributes.URL_FULL, "http://localhost:" + sqsPort), + equalTo(SemanticAttributes.SERVER_ADDRESS, "localhost"), + equalTo(SemanticAttributes.SERVER_PORT, sqsPort), + equalTo(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS"), + equalTo( + SemanticAttributes.MESSAGING_DESTINATION_NAME, "testSdkSqs"), + equalTo(SemanticAttributes.MESSAGING_OPERATION, "publish"), + satisfies( + SemanticAttributes.MESSAGING_MESSAGE_ID, + val -> val.isInstanceOf(String.class)), + equalTo(SemanticAttributes.NETWORK_PROTOCOL_VERSION, "1.1")), + span -> + span.hasName("testSdkSqs process") + .hasKind(SpanKind.CONSUMER) + .hasParent(trace.getSpan(0)) + .hasAttributesSatisfyingExactly( + equalTo(stringKey("aws.agent"), "java-aws-sdk"), + equalTo(stringKey("aws.endpoint"), "http://localhost:" + sqsPort), + equalTo( + stringKey("aws.queue.url"), + "http://localhost:" + sqsPort + "/000000000000/testSdkSqs"), + equalTo(SemanticAttributes.RPC_SYSTEM, "aws-api"), + equalTo(SemanticAttributes.RPC_SERVICE, "AmazonSQS"), + equalTo(SemanticAttributes.RPC_METHOD, "ReceiveMessage"), + equalTo(SemanticAttributes.HTTP_REQUEST_METHOD, "POST"), + equalTo(SemanticAttributes.HTTP_RESPONSE_STATUS_CODE, 200), + equalTo(SemanticAttributes.URL_FULL, "http://localhost:" + sqsPort), + equalTo(SemanticAttributes.SERVER_ADDRESS, "localhost"), + equalTo(SemanticAttributes.SERVER_PORT, sqsPort), + equalTo(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS"), + equalTo( + SemanticAttributes.MESSAGING_DESTINATION_NAME, "testSdkSqs"), + equalTo(SemanticAttributes.MESSAGING_OPERATION, "process"), + satisfies( + SemanticAttributes.MESSAGING_MESSAGE_ID, + val -> val.isInstanceOf(String.class)), + equalTo(SemanticAttributes.NETWORK_PROTOCOL_VERSION, "1.1")), + span -> + span.hasName("process child") + .hasParent(trace.getSpan(1)) + .hasAttributes(Attributes.empty()))); + } + + @Test + void testSimpleSqsProducerConsumerServicesWithParentSpan() { + sqsClient.createQueue("testSdkSqs"); + SendMessageRequest sendMessageRequest = + new SendMessageRequest( + "http://localhost:" + sqsPort + "/000000000000/testSdkSqs", "{\"type\": \"hello\"}"); + sqsClient.sendMessage(sendMessageRequest); + + testing() + .runWithSpan( + "parent", + () -> { + ReceiveMessageResult receiveMessageResult = + sqsClient.receiveMessage( + "http://localhost:" + sqsPort + "/000000000000/testSdkSqs"); + receiveMessageResult + .getMessages() + .forEach(message -> testing().runWithSpan("process child", () -> {})); + }); + + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("SQS.CreateQueue") + .hasKind(SpanKind.CLIENT) + .hasNoParent() + .hasAttributesSatisfyingExactly( + equalTo(stringKey("aws.agent"), "java-aws-sdk"), + equalTo(stringKey("aws.endpoint"), "http://localhost:" + sqsPort), + equalTo(stringKey("aws.queue.name"), "testSdkSqs"), + equalTo(SemanticAttributes.RPC_SYSTEM, "aws-api"), + equalTo(SemanticAttributes.RPC_SERVICE, "AmazonSQS"), + equalTo(SemanticAttributes.RPC_METHOD, "CreateQueue"), + equalTo(SemanticAttributes.HTTP_REQUEST_METHOD, "POST"), + equalTo(SemanticAttributes.HTTP_RESPONSE_STATUS_CODE, 200), + equalTo(SemanticAttributes.URL_FULL, "http://localhost:" + sqsPort), + equalTo(SemanticAttributes.SERVER_ADDRESS, "localhost"), + equalTo(SemanticAttributes.SERVER_PORT, sqsPort), + equalTo(SemanticAttributes.NETWORK_PROTOCOL_VERSION, "1.1"))), + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("testSdkSqs publish") + .hasKind(SpanKind.PRODUCER) + .hasNoParent() + .hasAttributesSatisfyingExactly( + equalTo(stringKey("aws.agent"), "java-aws-sdk"), + equalTo(stringKey("aws.endpoint"), "http://localhost:" + sqsPort), + equalTo( + stringKey("aws.queue.url"), + "http://localhost:" + sqsPort + "/000000000000/testSdkSqs"), + equalTo(SemanticAttributes.RPC_SYSTEM, "aws-api"), + equalTo(SemanticAttributes.RPC_SERVICE, "AmazonSQS"), + equalTo(SemanticAttributes.RPC_METHOD, "SendMessage"), + equalTo(SemanticAttributes.HTTP_REQUEST_METHOD, "POST"), + equalTo(SemanticAttributes.HTTP_RESPONSE_STATUS_CODE, 200), + equalTo(SemanticAttributes.URL_FULL, "http://localhost:" + sqsPort), + equalTo(SemanticAttributes.SERVER_ADDRESS, "localhost"), + equalTo(SemanticAttributes.SERVER_PORT, sqsPort), + equalTo(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS"), + equalTo( + SemanticAttributes.MESSAGING_DESTINATION_NAME, "testSdkSqs"), + equalTo(SemanticAttributes.MESSAGING_OPERATION, "publish"), + satisfies( + SemanticAttributes.MESSAGING_MESSAGE_ID, + val -> val.isInstanceOf(String.class)), + equalTo(SemanticAttributes.NETWORK_PROTOCOL_VERSION, "1.1")), + span -> + span.hasName("testSdkSqs process") + .hasKind(SpanKind.CONSUMER) + .hasParent(trace.getSpan(0)) + .hasAttributesSatisfyingExactly( + equalTo(stringKey("aws.agent"), "java-aws-sdk"), + equalTo(stringKey("aws.endpoint"), "http://localhost:" + sqsPort), + equalTo( + stringKey("aws.queue.url"), + "http://localhost:" + sqsPort + "/000000000000/testSdkSqs"), + equalTo(SemanticAttributes.RPC_SYSTEM, "aws-api"), + equalTo(SemanticAttributes.RPC_SERVICE, "AmazonSQS"), + equalTo(SemanticAttributes.RPC_METHOD, "ReceiveMessage"), + equalTo(SemanticAttributes.HTTP_REQUEST_METHOD, "POST"), + equalTo(SemanticAttributes.HTTP_RESPONSE_STATUS_CODE, 200), + equalTo(SemanticAttributes.URL_FULL, "http://localhost:" + sqsPort), + equalTo(SemanticAttributes.SERVER_ADDRESS, "localhost"), + equalTo(SemanticAttributes.SERVER_PORT, sqsPort), + equalTo(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS"), + equalTo( + SemanticAttributes.MESSAGING_DESTINATION_NAME, "testSdkSqs"), + equalTo(SemanticAttributes.MESSAGING_OPERATION, "process"), + satisfies( + SemanticAttributes.MESSAGING_MESSAGE_ID, + val -> val.isInstanceOf(String.class)), + equalTo(SemanticAttributes.NETWORK_PROTOCOL_VERSION, "1.1")), + span -> + span.hasName("process child") + .hasParent(trace.getSpan(1)) + .hasAttributes(Attributes.empty())), + /* + * This span represents HTTP "sending of receive message" operation. It's always single, while there can be multiple CONSUMER spans (one per consumed message). + * This one could be suppressed (by IF in TracingRequestHandler#beforeRequest but then HTTP instrumentation span would appear + */ + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("parent").hasNoParent(), + span -> + span.hasName("SQS.ReceiveMessage") + .hasKind(SpanKind.CLIENT) + .hasParent(trace.getSpan(0)) + .hasAttributesSatisfyingExactly( + equalTo(stringKey("aws.agent"), "java-aws-sdk"), + equalTo(stringKey("aws.endpoint"), "http://localhost:" + sqsPort), + equalTo( + stringKey("aws.queue.url"), + "http://localhost:" + sqsPort + "/000000000000/testSdkSqs"), + equalTo(SemanticAttributes.RPC_SYSTEM, "aws-api"), + equalTo(SemanticAttributes.RPC_SERVICE, "AmazonSQS"), + equalTo(SemanticAttributes.RPC_METHOD, "ReceiveMessage"), + equalTo(SemanticAttributes.HTTP_REQUEST_METHOD, "POST"), + equalTo(SemanticAttributes.HTTP_RESPONSE_STATUS_CODE, 200), + equalTo(SemanticAttributes.URL_FULL, "http://localhost:" + sqsPort), + equalTo(SemanticAttributes.SERVER_ADDRESS, "localhost"), + equalTo(SemanticAttributes.SERVER_PORT, sqsPort), + equalTo(SemanticAttributes.NETWORK_PROTOCOL_VERSION, "1.1")))); + } + + @Test + void testOnlyAddsAttributeNameOnceWhenRequestReused() { + sqsClient.createQueue("testSdkSqs2"); + SendMessageRequest send = + new SendMessageRequest( + "http://localhost:" + sqsPort + "/000000000000/testSdkSqs2", "{\"type\": \"hello\"}"); + sqsClient.sendMessage(send); + ReceiveMessageRequest receive = + new ReceiveMessageRequest("http://localhost:" + sqsPort + "/000000000000/testSdkSqs2"); + sqsClient.receiveMessage(receive); + sqsClient.sendMessage(send); + sqsClient.receiveMessage(receive); + assertThat(receive.getAttributeNames()).isEqualTo(ImmutableList.of("AWSTraceHeader")); + } +}