From 4889f262d1543addc43a250d60660418f40e8acc Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Thu, 20 Apr 2023 01:01:55 -0700 Subject: [PATCH 01/47] BatchMessageHandler --- .../message-handler/library/README.md | 54 +++++++ .../message-handler/library/build.gradle.kts | 16 ++ .../messagehandler/BatchMessageHandler.java | 66 ++++++++ .../SQSBatchMessageHandler.java | 70 +++++++++ .../SQSBatchMessageHandlerTest.java | 142 ++++++++++++++++++ settings.gradle.kts | 1 + 6 files changed, 349 insertions(+) create mode 100644 instrumentation/message-handler/library/README.md create mode 100644 instrumentation/message-handler/library/build.gradle.kts create mode 100644 instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java create mode 100644 instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SQSBatchMessageHandler.java create mode 100644 instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SQSBatchMessageHandlerTest.java diff --git a/instrumentation/message-handler/library/README.md b/instrumentation/message-handler/library/README.md new file mode 100644 index 000000000000..c413e1b87c03 --- /dev/null +++ b/instrumentation/message-handler/library/README.md @@ -0,0 +1,54 @@ +# Library Instrumentation for Java HTTP Client + +Provides OpenTelemetry instrumentation for [Java HTTP Client](https://openjdk.org/groups/net/httpclient/intro.html). + +## Quickstart + +### Add these dependencies to your project + +Replace `OPENTELEMETRY_VERSION` with the [latest +release](https://search.maven.org/search?q=g:io.opentelemetry.instrumentation%20AND%20a:opentelemetry-java-http-client). + +For Maven, add to your `pom.xml` dependencies: + +```xml + + + io.opentelemetry.instrumentation + opentelemetry-java-http-client + OPENTELEMETRY_VERSION + + +``` + +For Gradle, add to your dependencies: + +```groovy +implementation("io.opentelemetry.instrumentation:opentelemetry-java-http-client:OPENTELEMETRY_VERSION") +``` + +### Usage + +The instrumentation library contains an `HttpClient` wrapper that provides OpenTelemetry-based spans +and context propagation. + +```java +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.httpclient.JavaHttpClientTelemetry; +import java.net.http.HttpClient; + +import java.util.concurrent.ExecutorService; + +public class JavaHttpClientConfiguration { + + //Use this HttpClient implementation for making standard http client calls. + public HttpClient createTracedClient(OpenTelemetry openTelemetry) { + return JavaHttpClientTelemetry.builder(openTelemetry).build().newHttpClient(createClient()); + } + + //your configuration of the Java HTTP Client goes here: + private HttpClient createClient() { + return HttpClient.newBuilder().build(); + } +} +``` diff --git a/instrumentation/message-handler/library/build.gradle.kts b/instrumentation/message-handler/library/build.gradle.kts new file mode 100644 index 000000000000..3f3b01fc6194 --- /dev/null +++ b/instrumentation/message-handler/library/build.gradle.kts @@ -0,0 +1,16 @@ +plugins { + id("otel.library-instrumentation") +} + +dependencies { + api(project(":instrumentation:aws-lambda:aws-lambda-core-1.0:library")) + + compileOnly("io.opentelemetry:opentelemetry-sdk") + + library("com.amazonaws:aws-lambda-java-core:1.0.0") + library("com.amazonaws:aws-lambda-java-events:2.2.1") + + implementation("io.opentelemetry.contrib:opentelemetry-aws-xray-propagator") + + testImplementation("io.opentelemetry:opentelemetry-extension-trace-propagators") +} diff --git a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java new file mode 100644 index 000000000000..dad307a36af7 --- /dev/null +++ b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java @@ -0,0 +1,66 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.messagehandler; + +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanBuilder; +import io.opentelemetry.api.trace.SpanContext; +import io.opentelemetry.api.trace.TracerBuilder; +import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessageOperation; +import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; +import java.util.Collection; + +public abstract class BatchMessageHandler { + protected String messagingOperation; + protected OpenTelemetry openTelemetry; + protected String spanName; + + public BatchMessageHandler(OpenTelemetry openTelemetry) { + this.openTelemetry = openTelemetry; + spanName = "Batch Message Handler"; + messagingOperation = MessageOperation.RECEIVE.name(); + } + + public void setMessagingOperation(String messagingOperation) { + this.messagingOperation = messagingOperation; + } + + public void setSpanName(String spanName) { + this.spanName = spanName; + } + + public abstract SpanContext getParentSpanContext(T t); + + protected abstract void doHandleMessages(Collection messages); + + protected void addMessagingAttributes(SpanBuilder spanBuilder) { + spanBuilder.setAttribute(SemanticAttributes.MESSAGING_OPERATION, messagingOperation); + } + + public void handleMessages(Collection messages) { + TracerBuilder tracerBuilder = openTelemetry.tracerBuilder("io.opentelemetry.message.handler"); + tracerBuilder.setInstrumentationVersion("1.0"); + + SpanBuilder spanBuilder = tracerBuilder.build().spanBuilder(spanName); + + for (T t: messages) { + SpanContext spanContext = getParentSpanContext(t); + + if (spanContext != null) { + spanBuilder.addLink(spanContext); + } + } + + addMessagingAttributes(spanBuilder); + + Span span = spanBuilder.startSpan(); + + doHandleMessages(messages); + + span.end(); + } +} diff --git a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SQSBatchMessageHandler.java b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SQSBatchMessageHandler.java new file mode 100644 index 000000000000..29f2a480c6f1 --- /dev/null +++ b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SQSBatchMessageHandler.java @@ -0,0 +1,70 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.messagehandler; + +import com.amazonaws.services.lambda.runtime.events.SQSEvent; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanBuilder; +import io.opentelemetry.api.trace.SpanContext; +import io.opentelemetry.context.Context; +import io.opentelemetry.context.propagation.TextMapGetter; +import io.opentelemetry.contrib.awsxray.propagator.AwsXrayPropagator; +import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; +import java.util.Collections; +import java.util.Locale; +import java.util.Map; + +public abstract class SQSBatchMessageHandler extends BatchMessageHandler { + private static final String AWS_TRACE_HEADER_SQS_ATTRIBUTE_KEY = "AWSTraceHeader"; + private static final String AWS_TRACE_HEADER_PROPAGATOR_KEY = "x-amzn-trace-id"; + + public SQSBatchMessageHandler(OpenTelemetry openTelemetry) { + super(openTelemetry); + } + + @Override + protected void addMessagingAttributes(SpanBuilder spanBuilder) { + super.addMessagingAttributes(spanBuilder); + spanBuilder.setAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS"); + } + + @Override + public SpanContext getParentSpanContext(SQSEvent.SQSMessage message) { + String parentHeader = message.getAttributes().get(AWS_TRACE_HEADER_SQS_ATTRIBUTE_KEY); + + if (parentHeader != null) { + Context xrayContext = + AwsXrayPropagator.getInstance() + .extract( + Context.root(), + Collections.singletonMap(AWS_TRACE_HEADER_PROPAGATOR_KEY, parentHeader), + MapGetter.INSTANCE); + + SpanContext messageSpanCtx = Span.fromContext(xrayContext).getSpanContext(); + + if (messageSpanCtx.isValid()) { + return messageSpanCtx; + } + } + + return null; + } + + private enum MapGetter implements TextMapGetter> { + INSTANCE; + + @Override + public Iterable keys(Map map) { + return map.keySet(); + } + + @Override + public String get(Map map, String s) { + return map.get(s.toLowerCase(Locale.ROOT)); + } + } +} diff --git a/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SQSBatchMessageHandlerTest.java b/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SQSBatchMessageHandlerTest.java new file mode 100644 index 000000000000..76e978fc2892 --- /dev/null +++ b/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SQSBatchMessageHandlerTest.java @@ -0,0 +1,142 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.messagehandler; + +import com.amazonaws.services.lambda.runtime.events.SQSEvent; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanContext; +import io.opentelemetry.api.trace.TraceFlags; +import io.opentelemetry.api.trace.TraceState; +import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessageOperation; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension; +import io.opentelemetry.sdk.trace.data.LinkData; +import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; +import org.junit.Assert; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import java.lang.reflect.Constructor; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +public class SQSBatchMessageHandlerTest { + + @RegisterExtension + public static final InstrumentationExtension testing = LibraryInstrumentationExtension.create(); + + @Test + public void simple() { + SQSEvent.SQSMessage sqsMessage = newMessage(); + SpanContext messageSpanContext = SpanContext.createFromRemoteParent( + "55555555123456789012345678901234", + "1234567890123456", + TraceFlags.getSampled(), + TraceState.getDefault()); + sqsMessage.setAttributes(Collections.singletonMap("AWSTraceHeader", "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")); + + AtomicInteger counter = new AtomicInteger(0); + + SQSBatchMessageHandler messageHandler = new SQSBatchMessageHandler(testing.getOpenTelemetrySdk()) { + @Override + protected void doHandleMessages(Collection messages) { + counter.getAndIncrement(); + } + }; + + Span parentSpan = testing.getOpenTelemetrySdk().getTracer("test").spanBuilder("test").startSpan(); + + messageHandler.handleMessages(Collections.singletonList(sqsMessage)); + + parentSpan.end(); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("test")), + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("Batch Message Handler") + .hasLinks(LinkData.create(messageSpanContext)) + .hasTotalRecordedLinks(1) + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, MessageOperation.RECEIVE.name()) + .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") + .hasTotalAttributeCount(2) + )); + + Assert.assertEquals(1, counter.get()); + } + + @Test + public void multipleMessages() { + List sqsMessages = new LinkedList<>(); + + SQSEvent.SQSMessage sqsMessage1 = newMessage(); + sqsMessage1.setAttributes(Collections.singletonMap("AWSTraceHeader", "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")); + sqsMessages.add(sqsMessage1); + + SQSEvent.SQSMessage sqsMessage2 = newMessage(); + sqsMessage2.setAttributes(Collections.singletonMap("AWSTraceHeader", "Root=1-44444444-123456789012345678901234;Parent=2481624816248161;Sampled=0")); + sqsMessages.add(sqsMessage2); + + AtomicInteger counter = new AtomicInteger(0); + + SQSBatchMessageHandler messageHandler = new SQSBatchMessageHandler(testing.getOpenTelemetrySdk()) { + @Override + protected void doHandleMessages(Collection messages) { + counter.getAndIncrement(); + } + }; + + Span parentSpan = testing.getOpenTelemetrySdk().getTracer("test").spanBuilder("test").startSpan(); + + messageHandler.handleMessages(sqsMessages); + + parentSpan.end(); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("test")), + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("Batch Message Handler") + .hasLinks( + LinkData.create(SpanContext.createFromRemoteParent( + "55555555123456789012345678901234", + "1234567890123456", + TraceFlags.getSampled(), + TraceState.getDefault())), + LinkData.create(SpanContext.createFromRemoteParent( + "44444444123456789012345678901234", + "2481624816248161", + TraceFlags.getDefault(), + TraceState.getDefault()))) + .hasTotalRecordedLinks(2) + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, MessageOperation.RECEIVE.name()) + .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") + .hasTotalAttributeCount(2) + )); + + Assert.assertEquals(1, counter.get()); + } + + private static SQSEvent.SQSMessage newMessage() { + try { + Constructor ctor = SQSEvent.SQSMessage.class.getDeclaredConstructor(); + ctor.setAccessible(true); + return ctor.newInstance(); + } catch (Throwable t) { + throw new AssertionError(t); + } + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index ee126c69c843..35c77675bf08 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -356,6 +356,7 @@ hideFromDependabot(":instrumentation:logback:logback-mdc-1.0:javaagent") hideFromDependabot(":instrumentation:logback:logback-mdc-1.0:library") hideFromDependabot(":instrumentation:logback:logback-mdc-1.0:testing") hideFromDependabot(":instrumentation:methods:javaagent") +hideFromDependabot(":instrumentation:message-handler:library") hideFromDependabot(":instrumentation:micrometer:micrometer-1.5:javaagent") hideFromDependabot(":instrumentation:micrometer:micrometer-1.5:library") hideFromDependabot(":instrumentation:micrometer:micrometer-1.5:testing") From 0131ff2960d97da16b941b627102237f384cc01a Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Thu, 20 Apr 2023 23:39:11 -0700 Subject: [PATCH 02/47] Fixing parent bug --- .../messagehandler/BatchMessageHandler.java | 31 ++- .../SQSBatchMessageHandler.java | 8 + .../SQSBatchMessageHandlerTest.java | 201 ++++++++++++++++-- 3 files changed, 215 insertions(+), 25 deletions(-) diff --git a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java index dad307a36af7..8f3d07e22fad 100644 --- a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java +++ b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java @@ -9,7 +9,10 @@ import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.SpanBuilder; import io.opentelemetry.api.trace.SpanContext; +import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.api.trace.TracerBuilder; +import io.opentelemetry.context.Context; +import io.opentelemetry.context.Scope; import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessageOperation; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; import java.util.Collection; @@ -20,17 +23,17 @@ public abstract class BatchMessageHandler { protected String spanName; public BatchMessageHandler(OpenTelemetry openTelemetry) { - this.openTelemetry = openTelemetry; - spanName = "Batch Message Handler"; - messagingOperation = MessageOperation.RECEIVE.name(); + this(openTelemetry, MessageOperation.RECEIVE.name()); } - public void setMessagingOperation(String messagingOperation) { - this.messagingOperation = messagingOperation; + public BatchMessageHandler(OpenTelemetry openTelemetry, String messageOperation) { + this(openTelemetry, messageOperation, "Batch Message Handler"); } - public void setSpanName(String spanName) { + public BatchMessageHandler(OpenTelemetry openTelemetry, String messageOperation, String spanName) { + this.openTelemetry = openTelemetry; this.spanName = spanName; + this.messagingOperation = messageOperation; } public abstract SpanContext getParentSpanContext(T t); @@ -42,10 +45,16 @@ protected void addMessagingAttributes(SpanBuilder spanBuilder) { } public void handleMessages(Collection messages) { - TracerBuilder tracerBuilder = openTelemetry.tracerBuilder("io.opentelemetry.message.handler"); - tracerBuilder.setInstrumentationVersion("1.0"); + TracerBuilder tracerBuilder = + openTelemetry.tracerBuilder("io.opentelemetry.message.handler") + .setInstrumentationVersion("1.0"); - SpanBuilder spanBuilder = tracerBuilder.build().spanBuilder(spanName); + Span parentSpan = Span.current(); + + SpanBuilder spanBuilder = tracerBuilder.build() + .spanBuilder(spanName) + .setParent(Context.current().with(parentSpan)) + .setSpanKind(SpanKind.INTERNAL); for (T t: messages) { SpanContext spanContext = getParentSpanContext(t); @@ -59,7 +68,9 @@ public void handleMessages(Collection messages) { Span span = spanBuilder.startSpan(); - doHandleMessages(messages); + try (Scope scope = span.makeCurrent()) { + doHandleMessages(messages); + } span.end(); } diff --git a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SQSBatchMessageHandler.java b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SQSBatchMessageHandler.java index 29f2a480c6f1..e5738c274d3f 100644 --- a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SQSBatchMessageHandler.java +++ b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SQSBatchMessageHandler.java @@ -26,6 +26,14 @@ public SQSBatchMessageHandler(OpenTelemetry openTelemetry) { super(openTelemetry); } + public SQSBatchMessageHandler(OpenTelemetry openTelemetry, String messageOperation) { + super(openTelemetry, messageOperation); + } + + public SQSBatchMessageHandler(OpenTelemetry openTelemetry, String messageOperation, String spanName) { + super(openTelemetry, messageOperation, spanName); + } + @Override protected void addMessagingAttributes(SpanBuilder spanBuilder) { super.addMessagingAttributes(spanBuilder); diff --git a/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SQSBatchMessageHandlerTest.java b/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SQSBatchMessageHandlerTest.java index 76e978fc2892..9f437b97c414 100644 --- a/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SQSBatchMessageHandlerTest.java +++ b/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SQSBatchMessageHandlerTest.java @@ -10,6 +10,7 @@ import io.opentelemetry.api.trace.SpanContext; import io.opentelemetry.api.trace.TraceFlags; import io.opentelemetry.api.trace.TraceState; +import io.opentelemetry.context.Scope; import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessageOperation; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension; @@ -33,12 +34,11 @@ public class SQSBatchMessageHandlerTest { @Test public void simple() { SQSEvent.SQSMessage sqsMessage = newMessage(); - SpanContext messageSpanContext = SpanContext.createFromRemoteParent( - "55555555123456789012345678901234", - "1234567890123456", - TraceFlags.getSampled(), - TraceState.getDefault()); - sqsMessage.setAttributes(Collections.singletonMap("AWSTraceHeader", "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")); + + sqsMessage.setAttributes(Collections.singletonMap( + "AWSTraceHeader", + "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1" + )); AtomicInteger counter = new AtomicInteger(0); @@ -51,7 +51,9 @@ protected void doHandleMessages(Collection messages) { Span parentSpan = testing.getOpenTelemetrySdk().getTracer("test").spanBuilder("test").startSpan(); - messageHandler.handleMessages(Collections.singletonList(sqsMessage)); + try (Scope scope = parentSpan.makeCurrent()) { + messageHandler.handleMessages(Collections.singletonList(sqsMessage)); + } parentSpan.end(); @@ -59,16 +61,22 @@ protected void doHandleMessages(Collection messages) { trace -> trace.hasSpansSatisfyingExactly( span -> - span.hasName("test")), - trace -> - trace.hasSpansSatisfyingExactly( + span.hasName("test") + .hasTotalAttributeCount(0) + .hasTotalRecordedLinks(0), span -> span.hasName("Batch Message Handler") - .hasLinks(LinkData.create(messageSpanContext)) + .hasLinks(LinkData.create(SpanContext.createFromRemoteParent( + "55555555123456789012345678901234", + "1234567890123456", + TraceFlags.getSampled(), + TraceState.getDefault()))) .hasTotalRecordedLinks(1) .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, MessageOperation.RECEIVE.name()) .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") .hasTotalAttributeCount(2) + .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) + .hasTraceId(parentSpan.getSpanContext().getTraceId()) )); Assert.assertEquals(1, counter.get()); @@ -97,7 +105,9 @@ protected void doHandleMessages(Collection messages) { Span parentSpan = testing.getOpenTelemetrySdk().getTracer("test").spanBuilder("test").startSpan(); - messageHandler.handleMessages(sqsMessages); + try (Scope scope = parentSpan.makeCurrent()) { + messageHandler.handleMessages(sqsMessages); + } parentSpan.end(); @@ -105,9 +115,9 @@ protected void doHandleMessages(Collection messages) { trace -> trace.hasSpansSatisfyingExactly( span -> - span.hasName("test")), - trace -> - trace.hasSpansSatisfyingExactly( + span.hasName("test") + .hasTotalAttributeCount(0) + .hasTotalRecordedLinks(0), span -> span.hasName("Batch Message Handler") .hasLinks( @@ -125,6 +135,167 @@ protected void doHandleMessages(Collection messages) { .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, MessageOperation.RECEIVE.name()) .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") .hasTotalAttributeCount(2) + .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) + .hasTraceId(parentSpan.getSpanContext().getTraceId()) + )); + + Assert.assertEquals(1, counter.get()); + } + + @Test + public void multipleRunsOfTheHandler() { + SQSEvent.SQSMessage sqsMessage1 = newMessage(); + sqsMessage1.setAttributes(Collections.singletonMap("AWSTraceHeader", "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")); + + SQSEvent.SQSMessage sqsMessage2 = newMessage(); + sqsMessage2.setAttributes(Collections.singletonMap("AWSTraceHeader", "Root=1-44444444-123456789012345678901234;Parent=2481624816248161;Sampled=0")); + + AtomicInteger counter = new AtomicInteger(0); + + SQSBatchMessageHandler messageHandler = new SQSBatchMessageHandler(testing.getOpenTelemetrySdk(), MessageOperation.PROCESS.name()) { + @Override + protected void doHandleMessages(Collection messages) { + counter.getAndIncrement(); + } + }; + + Span parentSpan = testing.getOpenTelemetrySdk().getTracer("test").spanBuilder("test").startSpan(); + + try (Scope scope = parentSpan.makeCurrent()) { + messageHandler.handleMessages(Collections.singletonList(sqsMessage1)); + messageHandler.handleMessages(Collections.singletonList(sqsMessage2)); + } + + parentSpan.end(); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("test") + .hasTotalAttributeCount(0) + .hasTotalRecordedLinks(0), + span -> + span.hasName("Batch Message Handler") + .hasLinks( + LinkData.create(SpanContext.createFromRemoteParent( + "55555555123456789012345678901234", + "1234567890123456", + TraceFlags.getSampled(), + TraceState.getDefault()))) + .hasTotalRecordedLinks(1) + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, MessageOperation.PROCESS.name()) + .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") + .hasTotalAttributeCount(2) + .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) + .hasTraceId(parentSpan.getSpanContext().getTraceId()), + span -> + span.hasName("Batch Message Handler") + .hasLinks( + LinkData.create(SpanContext.createFromRemoteParent( + "44444444123456789012345678901234", + "2481624816248161", + TraceFlags.getDefault(), + TraceState.getDefault()))) + .hasTotalRecordedLinks(1) + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, MessageOperation.PROCESS.name()) + .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") + .hasTotalAttributeCount(2) + .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) + .hasTraceId(parentSpan.getSpanContext().getTraceId()) + )); + + Assert.assertEquals(2, counter.get()); + } + + @Test + public void noMessages() { + AtomicInteger counter = new AtomicInteger(0); + + SQSBatchMessageHandler messageHandler = new SQSBatchMessageHandler(testing.getOpenTelemetrySdk()) { + @Override + protected void doHandleMessages(Collection messages) { + counter.getAndIncrement(); + } + }; + + Span parentSpan = testing.getOpenTelemetrySdk().getTracer("test").spanBuilder("test").startSpan(); + + try (Scope scope = parentSpan.makeCurrent()) { + messageHandler.handleMessages(Collections.emptyList()); + } + + parentSpan.end(); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("test") + .hasTotalAttributeCount(0) + .hasTotalRecordedLinks(0), + span -> + span.hasName("Batch Message Handler") + .hasTotalRecordedLinks(0) + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, MessageOperation.RECEIVE.name()) + .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") + .hasTotalAttributeCount(2) + .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) + .hasTraceId(parentSpan.getSpanContext().getTraceId()) + )); + + Assert.assertEquals(1, counter.get()); + } + + @Test + public void changeDefaults() { + SQSEvent.SQSMessage sqsMessage = newMessage(); + + sqsMessage.setAttributes(Collections.singletonMap( + "AWSTraceHeader", + "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1" + )); + + AtomicInteger counter = new AtomicInteger(0); + + SQSBatchMessageHandler messageHandler = new SQSBatchMessageHandler( + testing.getOpenTelemetrySdk(), + MessageOperation.PROCESS.name(), + "New Name") { + @Override + protected void doHandleMessages(Collection messages) { + counter.getAndIncrement(); + } + }; + + Span parentSpan = testing.getOpenTelemetrySdk().getTracer("test").spanBuilder("test").startSpan(); + + try (Scope scope = parentSpan.makeCurrent()) { + messageHandler.handleMessages(Collections.singletonList(sqsMessage)); + } + + parentSpan.end(); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("test") + .hasTotalAttributeCount(0) + .hasTotalRecordedLinks(0), + span -> + span.hasName("New Name") + .hasLinks(LinkData.create(SpanContext.createFromRemoteParent( + "55555555123456789012345678901234", + "1234567890123456", + TraceFlags.getSampled(), + TraceState.getDefault()))) + .hasTotalRecordedLinks(1) + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, MessageOperation.PROCESS.name()) + .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") + .hasTotalAttributeCount(2) + .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) + .hasTraceId(parentSpan.getSpanContext().getTraceId()) )); Assert.assertEquals(1, counter.get()); From 5934f864ced6895e2c86f8f7d76bb075418909ef Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Fri, 21 Apr 2023 00:01:23 -0700 Subject: [PATCH 03/47] Fixing readme --- .../message-handler/library/README.md | 60 ++++++------------- .../message-handler/library/build.gradle.kts | 2 - 2 files changed, 18 insertions(+), 44 deletions(-) diff --git a/instrumentation/message-handler/library/README.md b/instrumentation/message-handler/library/README.md index c413e1b87c03..332925c8c0f9 100644 --- a/instrumentation/message-handler/library/README.md +++ b/instrumentation/message-handler/library/README.md @@ -1,54 +1,30 @@ -# Library Instrumentation for Java HTTP Client +# Message Handler -Provides OpenTelemetry instrumentation for [Java HTTP Client](https://openjdk.org/groups/net/httpclient/intro.html). +This package contains handlers to instrument message system spans. -## Quickstart +The handler will create a new messaging span, add span links to it, and set the messaging attributes behind the scene. These values are based off of the messages passed in. -### Add these dependencies to your project +The handler provides constructors to change the messaging operation and span name of the newly created messaging span. -Replace `OPENTELEMETRY_VERSION` with the [latest -release](https://search.maven.org/search?q=g:io.opentelemetry.instrumentation%20AND%20a:opentelemetry-java-http-client). +## Available Handlers +- `SQSBatchMessageHandlerTest` - processes messages from Amazon's SQS. -For Maven, add to your `pom.xml` dependencies: +## Using SQSBatchMessageHandlerTest -```xml - - - io.opentelemetry.instrumentation - opentelemetry-java-http-client - OPENTELEMETRY_VERSION - - -``` - -For Gradle, add to your dependencies: - -```groovy -implementation("io.opentelemetry.instrumentation:opentelemetry-java-http-client:OPENTELEMETRY_VERSION") -``` - -### Usage - -The instrumentation library contains an `HttpClient` wrapper that provides OpenTelemetry-based spans -and context propagation. +1. Retrieve a collection of messages to process. +2. Create a SQSBatchMessageHandler and provide the business logic on what to do with the messages. +3. Call the handleMessages function and pass in your messages. +4. It will call the doHandleMessages function you provided wrapped in the messaging span. ```java -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.instrumentation.httpclient.JavaHttpClientTelemetry; -import java.net.http.HttpClient; - -import java.util.concurrent.ExecutorService; +Collection sqsMessages; -public class JavaHttpClientConfiguration { - - //Use this HttpClient implementation for making standard http client calls. - public HttpClient createTracedClient(OpenTelemetry openTelemetry) { - return JavaHttpClientTelemetry.builder(openTelemetry).build().newHttpClient(createClient()); +SQSBatchMessageHandler messageHandler = new SQSBatchMessageHandler(GlobalOpenTelemetry.get()) { + @Override + protected void doHandleMessages(Collection messages) { + // Do my business logic } +}; - //your configuration of the Java HTTP Client goes here: - private HttpClient createClient() { - return HttpClient.newBuilder().build(); - } -} +messageHandler.handleMessages(sqsMessages); ``` diff --git a/instrumentation/message-handler/library/build.gradle.kts b/instrumentation/message-handler/library/build.gradle.kts index 3f3b01fc6194..919c0427719b 100644 --- a/instrumentation/message-handler/library/build.gradle.kts +++ b/instrumentation/message-handler/library/build.gradle.kts @@ -11,6 +11,4 @@ dependencies { library("com.amazonaws:aws-lambda-java-events:2.2.1") implementation("io.opentelemetry.contrib:opentelemetry-aws-xray-propagator") - - testImplementation("io.opentelemetry:opentelemetry-extension-trace-propagators") } From 0ce11c5860afa56b2a609b819dd1dc74e45d01df Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Fri, 21 Apr 2023 10:02:46 -0700 Subject: [PATCH 04/47] Applying spot check --- .../messagehandler/BatchMessageHandler.java | 18 +- .../SQSBatchMessageHandler.java | 3 +- .../SQSBatchMessageHandlerTest.java | 252 +++++++++--------- 3 files changed, 146 insertions(+), 127 deletions(-) diff --git a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java index 8f3d07e22fad..c36f195bba71 100644 --- a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java +++ b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java @@ -30,7 +30,8 @@ public BatchMessageHandler(OpenTelemetry openTelemetry, String messageOperation) this(openTelemetry, messageOperation, "Batch Message Handler"); } - public BatchMessageHandler(OpenTelemetry openTelemetry, String messageOperation, String spanName) { + public BatchMessageHandler( + OpenTelemetry openTelemetry, String messageOperation, String spanName) { this.openTelemetry = openTelemetry; this.spanName = spanName; this.messagingOperation = messageOperation; @@ -46,17 +47,20 @@ protected void addMessagingAttributes(SpanBuilder spanBuilder) { public void handleMessages(Collection messages) { TracerBuilder tracerBuilder = - openTelemetry.tracerBuilder("io.opentelemetry.message.handler") + openTelemetry + .tracerBuilder("io.opentelemetry.message.handler") .setInstrumentationVersion("1.0"); Span parentSpan = Span.current(); - SpanBuilder spanBuilder = tracerBuilder.build() - .spanBuilder(spanName) - .setParent(Context.current().with(parentSpan)) - .setSpanKind(SpanKind.INTERNAL); + SpanBuilder spanBuilder = + tracerBuilder + .build() + .spanBuilder(spanName) + .setParent(Context.current().with(parentSpan)) + .setSpanKind(SpanKind.INTERNAL); - for (T t: messages) { + for (T t : messages) { SpanContext spanContext = getParentSpanContext(t); if (spanContext != null) { diff --git a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SQSBatchMessageHandler.java b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SQSBatchMessageHandler.java index e5738c274d3f..7035d9419ca6 100644 --- a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SQSBatchMessageHandler.java +++ b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SQSBatchMessageHandler.java @@ -30,7 +30,8 @@ public SQSBatchMessageHandler(OpenTelemetry openTelemetry, String messageOperati super(openTelemetry, messageOperation); } - public SQSBatchMessageHandler(OpenTelemetry openTelemetry, String messageOperation, String spanName) { + public SQSBatchMessageHandler( + OpenTelemetry openTelemetry, String messageOperation, String spanName) { super(openTelemetry, messageOperation, spanName); } diff --git a/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SQSBatchMessageHandlerTest.java b/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SQSBatchMessageHandlerTest.java index 9f437b97c414..084b38c6acdb 100644 --- a/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SQSBatchMessageHandlerTest.java +++ b/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SQSBatchMessageHandlerTest.java @@ -16,15 +16,15 @@ import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension; import io.opentelemetry.sdk.trace.data.LinkData; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; -import org.junit.Assert; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; import java.lang.reflect.Constructor; import java.util.Collection; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; +import org.junit.Assert; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; public class SQSBatchMessageHandlerTest { @@ -35,21 +35,23 @@ public class SQSBatchMessageHandlerTest { public void simple() { SQSEvent.SQSMessage sqsMessage = newMessage(); - sqsMessage.setAttributes(Collections.singletonMap( - "AWSTraceHeader", - "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1" - )); + sqsMessage.setAttributes( + Collections.singletonMap( + "AWSTraceHeader", + "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")); AtomicInteger counter = new AtomicInteger(0); - SQSBatchMessageHandler messageHandler = new SQSBatchMessageHandler(testing.getOpenTelemetrySdk()) { - @Override - protected void doHandleMessages(Collection messages) { - counter.getAndIncrement(); - } - }; + SQSBatchMessageHandler messageHandler = + new SQSBatchMessageHandler(testing.getOpenTelemetrySdk()) { + @Override + protected void doHandleMessages(Collection messages) { + counter.getAndIncrement(); + } + }; - Span parentSpan = testing.getOpenTelemetrySdk().getTracer("test").spanBuilder("test").startSpan(); + Span parentSpan = + testing.getOpenTelemetrySdk().getTracer("test").spanBuilder("test").startSpan(); try (Scope scope = parentSpan.makeCurrent()) { messageHandler.handleMessages(Collections.singletonList(sqsMessage)); @@ -60,24 +62,23 @@ protected void doHandleMessages(Collection messages) { testing.waitAndAssertTraces( trace -> trace.hasSpansSatisfyingExactly( - span -> - span.hasName("test") - .hasTotalAttributeCount(0) - .hasTotalRecordedLinks(0), + span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> span.hasName("Batch Message Handler") - .hasLinks(LinkData.create(SpanContext.createFromRemoteParent( - "55555555123456789012345678901234", - "1234567890123456", - TraceFlags.getSampled(), - TraceState.getDefault()))) + .hasLinks( + LinkData.create( + SpanContext.createFromRemoteParent( + "55555555123456789012345678901234", + "1234567890123456", + TraceFlags.getSampled(), + TraceState.getDefault()))) .hasTotalRecordedLinks(1) - .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, MessageOperation.RECEIVE.name()) + .hasAttribute( + SemanticAttributes.MESSAGING_OPERATION, MessageOperation.RECEIVE.name()) .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") .hasTotalAttributeCount(2) .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) - .hasTraceId(parentSpan.getSpanContext().getTraceId()) - )); + .hasTraceId(parentSpan.getSpanContext().getTraceId()))); Assert.assertEquals(1, counter.get()); } @@ -87,23 +88,31 @@ public void multipleMessages() { List sqsMessages = new LinkedList<>(); SQSEvent.SQSMessage sqsMessage1 = newMessage(); - sqsMessage1.setAttributes(Collections.singletonMap("AWSTraceHeader", "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")); + sqsMessage1.setAttributes( + Collections.singletonMap( + "AWSTraceHeader", + "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")); sqsMessages.add(sqsMessage1); SQSEvent.SQSMessage sqsMessage2 = newMessage(); - sqsMessage2.setAttributes(Collections.singletonMap("AWSTraceHeader", "Root=1-44444444-123456789012345678901234;Parent=2481624816248161;Sampled=0")); + sqsMessage2.setAttributes( + Collections.singletonMap( + "AWSTraceHeader", + "Root=1-44444444-123456789012345678901234;Parent=2481624816248161;Sampled=0")); sqsMessages.add(sqsMessage2); AtomicInteger counter = new AtomicInteger(0); - SQSBatchMessageHandler messageHandler = new SQSBatchMessageHandler(testing.getOpenTelemetrySdk()) { - @Override - protected void doHandleMessages(Collection messages) { - counter.getAndIncrement(); - } - }; + SQSBatchMessageHandler messageHandler = + new SQSBatchMessageHandler(testing.getOpenTelemetrySdk()) { + @Override + protected void doHandleMessages(Collection messages) { + counter.getAndIncrement(); + } + }; - Span parentSpan = testing.getOpenTelemetrySdk().getTracer("test").spanBuilder("test").startSpan(); + Span parentSpan = + testing.getOpenTelemetrySdk().getTracer("test").spanBuilder("test").startSpan(); try (Scope scope = parentSpan.makeCurrent()) { messageHandler.handleMessages(sqsMessages); @@ -114,30 +123,29 @@ protected void doHandleMessages(Collection messages) { testing.waitAndAssertTraces( trace -> trace.hasSpansSatisfyingExactly( - span -> - span.hasName("test") - .hasTotalAttributeCount(0) - .hasTotalRecordedLinks(0), + span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> span.hasName("Batch Message Handler") .hasLinks( - LinkData.create(SpanContext.createFromRemoteParent( - "55555555123456789012345678901234", - "1234567890123456", - TraceFlags.getSampled(), - TraceState.getDefault())), - LinkData.create(SpanContext.createFromRemoteParent( - "44444444123456789012345678901234", - "2481624816248161", - TraceFlags.getDefault(), - TraceState.getDefault()))) + LinkData.create( + SpanContext.createFromRemoteParent( + "55555555123456789012345678901234", + "1234567890123456", + TraceFlags.getSampled(), + TraceState.getDefault())), + LinkData.create( + SpanContext.createFromRemoteParent( + "44444444123456789012345678901234", + "2481624816248161", + TraceFlags.getDefault(), + TraceState.getDefault()))) .hasTotalRecordedLinks(2) - .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, MessageOperation.RECEIVE.name()) + .hasAttribute( + SemanticAttributes.MESSAGING_OPERATION, MessageOperation.RECEIVE.name()) .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") .hasTotalAttributeCount(2) .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) - .hasTraceId(parentSpan.getSpanContext().getTraceId()) - )); + .hasTraceId(parentSpan.getSpanContext().getTraceId()))); Assert.assertEquals(1, counter.get()); } @@ -145,21 +153,29 @@ protected void doHandleMessages(Collection messages) { @Test public void multipleRunsOfTheHandler() { SQSEvent.SQSMessage sqsMessage1 = newMessage(); - sqsMessage1.setAttributes(Collections.singletonMap("AWSTraceHeader", "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")); + sqsMessage1.setAttributes( + Collections.singletonMap( + "AWSTraceHeader", + "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")); SQSEvent.SQSMessage sqsMessage2 = newMessage(); - sqsMessage2.setAttributes(Collections.singletonMap("AWSTraceHeader", "Root=1-44444444-123456789012345678901234;Parent=2481624816248161;Sampled=0")); + sqsMessage2.setAttributes( + Collections.singletonMap( + "AWSTraceHeader", + "Root=1-44444444-123456789012345678901234;Parent=2481624816248161;Sampled=0")); AtomicInteger counter = new AtomicInteger(0); - SQSBatchMessageHandler messageHandler = new SQSBatchMessageHandler(testing.getOpenTelemetrySdk(), MessageOperation.PROCESS.name()) { - @Override - protected void doHandleMessages(Collection messages) { - counter.getAndIncrement(); - } - }; + SQSBatchMessageHandler messageHandler = + new SQSBatchMessageHandler(testing.getOpenTelemetrySdk(), MessageOperation.PROCESS.name()) { + @Override + protected void doHandleMessages(Collection messages) { + counter.getAndIncrement(); + } + }; - Span parentSpan = testing.getOpenTelemetrySdk().getTracer("test").spanBuilder("test").startSpan(); + Span parentSpan = + testing.getOpenTelemetrySdk().getTracer("test").spanBuilder("test").startSpan(); try (Scope scope = parentSpan.makeCurrent()) { messageHandler.handleMessages(Collections.singletonList(sqsMessage1)); @@ -171,20 +187,19 @@ protected void doHandleMessages(Collection messages) { testing.waitAndAssertTraces( trace -> trace.hasSpansSatisfyingExactly( - span -> - span.hasName("test") - .hasTotalAttributeCount(0) - .hasTotalRecordedLinks(0), + span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> span.hasName("Batch Message Handler") .hasLinks( - LinkData.create(SpanContext.createFromRemoteParent( - "55555555123456789012345678901234", - "1234567890123456", - TraceFlags.getSampled(), - TraceState.getDefault()))) + LinkData.create( + SpanContext.createFromRemoteParent( + "55555555123456789012345678901234", + "1234567890123456", + TraceFlags.getSampled(), + TraceState.getDefault()))) .hasTotalRecordedLinks(1) - .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, MessageOperation.PROCESS.name()) + .hasAttribute( + SemanticAttributes.MESSAGING_OPERATION, MessageOperation.PROCESS.name()) .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") .hasTotalAttributeCount(2) .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) @@ -192,18 +207,19 @@ protected void doHandleMessages(Collection messages) { span -> span.hasName("Batch Message Handler") .hasLinks( - LinkData.create(SpanContext.createFromRemoteParent( - "44444444123456789012345678901234", - "2481624816248161", - TraceFlags.getDefault(), - TraceState.getDefault()))) + LinkData.create( + SpanContext.createFromRemoteParent( + "44444444123456789012345678901234", + "2481624816248161", + TraceFlags.getDefault(), + TraceState.getDefault()))) .hasTotalRecordedLinks(1) - .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, MessageOperation.PROCESS.name()) + .hasAttribute( + SemanticAttributes.MESSAGING_OPERATION, MessageOperation.PROCESS.name()) .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") .hasTotalAttributeCount(2) .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) - .hasTraceId(parentSpan.getSpanContext().getTraceId()) - )); + .hasTraceId(parentSpan.getSpanContext().getTraceId()))); Assert.assertEquals(2, counter.get()); } @@ -212,14 +228,16 @@ protected void doHandleMessages(Collection messages) { public void noMessages() { AtomicInteger counter = new AtomicInteger(0); - SQSBatchMessageHandler messageHandler = new SQSBatchMessageHandler(testing.getOpenTelemetrySdk()) { - @Override - protected void doHandleMessages(Collection messages) { - counter.getAndIncrement(); - } - }; + SQSBatchMessageHandler messageHandler = + new SQSBatchMessageHandler(testing.getOpenTelemetrySdk()) { + @Override + protected void doHandleMessages(Collection messages) { + counter.getAndIncrement(); + } + }; - Span parentSpan = testing.getOpenTelemetrySdk().getTracer("test").spanBuilder("test").startSpan(); + Span parentSpan = + testing.getOpenTelemetrySdk().getTracer("test").spanBuilder("test").startSpan(); try (Scope scope = parentSpan.makeCurrent()) { messageHandler.handleMessages(Collections.emptyList()); @@ -230,19 +248,16 @@ protected void doHandleMessages(Collection messages) { testing.waitAndAssertTraces( trace -> trace.hasSpansSatisfyingExactly( - span -> - span.hasName("test") - .hasTotalAttributeCount(0) - .hasTotalRecordedLinks(0), + span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> span.hasName("Batch Message Handler") .hasTotalRecordedLinks(0) - .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, MessageOperation.RECEIVE.name()) + .hasAttribute( + SemanticAttributes.MESSAGING_OPERATION, MessageOperation.RECEIVE.name()) .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") .hasTotalAttributeCount(2) .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) - .hasTraceId(parentSpan.getSpanContext().getTraceId()) - )); + .hasTraceId(parentSpan.getSpanContext().getTraceId()))); Assert.assertEquals(1, counter.get()); } @@ -251,24 +266,24 @@ protected void doHandleMessages(Collection messages) { public void changeDefaults() { SQSEvent.SQSMessage sqsMessage = newMessage(); - sqsMessage.setAttributes(Collections.singletonMap( - "AWSTraceHeader", - "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1" - )); + sqsMessage.setAttributes( + Collections.singletonMap( + "AWSTraceHeader", + "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")); AtomicInteger counter = new AtomicInteger(0); - SQSBatchMessageHandler messageHandler = new SQSBatchMessageHandler( - testing.getOpenTelemetrySdk(), - MessageOperation.PROCESS.name(), - "New Name") { - @Override - protected void doHandleMessages(Collection messages) { - counter.getAndIncrement(); - } - }; + SQSBatchMessageHandler messageHandler = + new SQSBatchMessageHandler( + testing.getOpenTelemetrySdk(), MessageOperation.PROCESS.name(), "New Name") { + @Override + protected void doHandleMessages(Collection messages) { + counter.getAndIncrement(); + } + }; - Span parentSpan = testing.getOpenTelemetrySdk().getTracer("test").spanBuilder("test").startSpan(); + Span parentSpan = + testing.getOpenTelemetrySdk().getTracer("test").spanBuilder("test").startSpan(); try (Scope scope = parentSpan.makeCurrent()) { messageHandler.handleMessages(Collections.singletonList(sqsMessage)); @@ -279,24 +294,23 @@ protected void doHandleMessages(Collection messages) { testing.waitAndAssertTraces( trace -> trace.hasSpansSatisfyingExactly( - span -> - span.hasName("test") - .hasTotalAttributeCount(0) - .hasTotalRecordedLinks(0), + span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> span.hasName("New Name") - .hasLinks(LinkData.create(SpanContext.createFromRemoteParent( - "55555555123456789012345678901234", - "1234567890123456", - TraceFlags.getSampled(), - TraceState.getDefault()))) + .hasLinks( + LinkData.create( + SpanContext.createFromRemoteParent( + "55555555123456789012345678901234", + "1234567890123456", + TraceFlags.getSampled(), + TraceState.getDefault()))) .hasTotalRecordedLinks(1) - .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, MessageOperation.PROCESS.name()) + .hasAttribute( + SemanticAttributes.MESSAGING_OPERATION, MessageOperation.PROCESS.name()) .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") .hasTotalAttributeCount(2) .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) - .hasTraceId(parentSpan.getSpanContext().getTraceId()) - )); + .hasTraceId(parentSpan.getSpanContext().getTraceId()))); Assert.assertEquals(1, counter.get()); } From 2f912cf434368cb2228c90cbb7edc9c6fea65988 Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Fri, 21 Apr 2023 12:06:20 -0700 Subject: [PATCH 05/47] Addressing style checks and addign test for invalid upstream span context --- .../message-handler/library/README.md | 2 +- .../messagehandler/BatchMessageHandler.java | 5 +- ...ndler.java => SqsBatchMessageHandler.java} | 34 ++++++---- ...t.java => SqsBatchMessageHandlerTest.java} | 66 +++++++++++++++---- 4 files changed, 80 insertions(+), 27 deletions(-) rename instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/{SQSBatchMessageHandler.java => SqsBatchMessageHandler.java} (66%) rename instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/{SQSBatchMessageHandlerTest.java => SqsBatchMessageHandlerTest.java} (85%) diff --git a/instrumentation/message-handler/library/README.md b/instrumentation/message-handler/library/README.md index 332925c8c0f9..4d3e4474374c 100644 --- a/instrumentation/message-handler/library/README.md +++ b/instrumentation/message-handler/library/README.md @@ -19,7 +19,7 @@ The handler provides constructors to change the messaging operation and span nam ```java Collection sqsMessages; -SQSBatchMessageHandler messageHandler = new SQSBatchMessageHandler(GlobalOpenTelemetry.get()) { +SqsBatchMessageHandler messageHandler = new SqsBatchMessageHandler(GlobalOpenTelemetry.get()) { @Override protected void doHandleMessages(Collection messages) { // Do my business logic diff --git a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java index c36f195bba71..9c68232b4d29 100644 --- a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java +++ b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java @@ -18,6 +18,7 @@ import java.util.Collection; public abstract class BatchMessageHandler { + protected String messagingOperation; protected OpenTelemetry openTelemetry; protected String spanName; @@ -60,6 +61,8 @@ public void handleMessages(Collection messages) { .setParent(Context.current().with(parentSpan)) .setSpanKind(SpanKind.INTERNAL); + addMessagingAttributes(spanBuilder); + for (T t : messages) { SpanContext spanContext = getParentSpanContext(t); @@ -68,8 +71,6 @@ public void handleMessages(Collection messages) { } } - addMessagingAttributes(spanBuilder); - Span span = spanBuilder.startSpan(); try (Scope scope = span.makeCurrent()) { diff --git a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SQSBatchMessageHandler.java b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java similarity index 66% rename from instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SQSBatchMessageHandler.java rename to instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java index 7035d9419ca6..f2bb9c2c5df5 100644 --- a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SQSBatchMessageHandler.java +++ b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java @@ -17,20 +17,24 @@ import java.util.Collections; import java.util.Locale; import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +public abstract class SqsBatchMessageHandler extends BatchMessageHandler { + private static final Logger logger = Logger.getLogger(BatchMessageHandler.class.getName()); -public abstract class SQSBatchMessageHandler extends BatchMessageHandler { private static final String AWS_TRACE_HEADER_SQS_ATTRIBUTE_KEY = "AWSTraceHeader"; private static final String AWS_TRACE_HEADER_PROPAGATOR_KEY = "x-amzn-trace-id"; - public SQSBatchMessageHandler(OpenTelemetry openTelemetry) { + public SqsBatchMessageHandler(OpenTelemetry openTelemetry) { super(openTelemetry); } - public SQSBatchMessageHandler(OpenTelemetry openTelemetry, String messageOperation) { + public SqsBatchMessageHandler(OpenTelemetry openTelemetry, String messageOperation) { super(openTelemetry, messageOperation); } - public SQSBatchMessageHandler( + public SqsBatchMessageHandler( OpenTelemetry openTelemetry, String messageOperation, String spanName) { super(openTelemetry, messageOperation, spanName); } @@ -46,17 +50,21 @@ public SpanContext getParentSpanContext(SQSEvent.SQSMessage message) { String parentHeader = message.getAttributes().get(AWS_TRACE_HEADER_SQS_ATTRIBUTE_KEY); if (parentHeader != null) { - Context xrayContext = - AwsXrayPropagator.getInstance() - .extract( - Context.root(), - Collections.singletonMap(AWS_TRACE_HEADER_PROPAGATOR_KEY, parentHeader), - MapGetter.INSTANCE); + try { + Context xrayContext = + AwsXrayPropagator.getInstance() + .extract( + Context.root(), + Collections.singletonMap(AWS_TRACE_HEADER_PROPAGATOR_KEY, parentHeader), + MapGetter.INSTANCE); - SpanContext messageSpanCtx = Span.fromContext(xrayContext).getSpanContext(); + SpanContext messageSpanCtx = Span.fromContext(xrayContext).getSpanContext(); - if (messageSpanCtx.isValid()) { - return messageSpanCtx; + if (messageSpanCtx.isValid()) { + return messageSpanCtx; + } + } catch (Throwable error) { + logger.log(Level.WARNING, "Invalid upstream span context: {0}", parentHeader); } } diff --git a/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SQSBatchMessageHandlerTest.java b/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java similarity index 85% rename from instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SQSBatchMessageHandlerTest.java rename to instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java index 084b38c6acdb..9a3fd8ecfe5c 100644 --- a/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SQSBatchMessageHandlerTest.java +++ b/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java @@ -26,7 +26,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; -public class SQSBatchMessageHandlerTest { +public class SqsBatchMessageHandlerTest { @RegisterExtension public static final InstrumentationExtension testing = LibraryInstrumentationExtension.create(); @@ -42,8 +42,8 @@ public void simple() { AtomicInteger counter = new AtomicInteger(0); - SQSBatchMessageHandler messageHandler = - new SQSBatchMessageHandler(testing.getOpenTelemetrySdk()) { + SqsBatchMessageHandler messageHandler = + new SqsBatchMessageHandler(testing.getOpenTelemetrySdk()) { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); @@ -103,8 +103,8 @@ public void multipleMessages() { AtomicInteger counter = new AtomicInteger(0); - SQSBatchMessageHandler messageHandler = - new SQSBatchMessageHandler(testing.getOpenTelemetrySdk()) { + SqsBatchMessageHandler messageHandler = + new SqsBatchMessageHandler(testing.getOpenTelemetrySdk()) { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); @@ -166,8 +166,8 @@ public void multipleRunsOfTheHandler() { AtomicInteger counter = new AtomicInteger(0); - SQSBatchMessageHandler messageHandler = - new SQSBatchMessageHandler(testing.getOpenTelemetrySdk(), MessageOperation.PROCESS.name()) { + SqsBatchMessageHandler messageHandler = + new SqsBatchMessageHandler(testing.getOpenTelemetrySdk(), MessageOperation.PROCESS.name()) { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); @@ -228,8 +228,8 @@ protected void doHandleMessages(Collection messages) { public void noMessages() { AtomicInteger counter = new AtomicInteger(0); - SQSBatchMessageHandler messageHandler = - new SQSBatchMessageHandler(testing.getOpenTelemetrySdk()) { + SqsBatchMessageHandler messageHandler = + new SqsBatchMessageHandler(testing.getOpenTelemetrySdk()) { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); @@ -273,8 +273,8 @@ public void changeDefaults() { AtomicInteger counter = new AtomicInteger(0); - SQSBatchMessageHandler messageHandler = - new SQSBatchMessageHandler( + SqsBatchMessageHandler messageHandler = + new SqsBatchMessageHandler( testing.getOpenTelemetrySdk(), MessageOperation.PROCESS.name(), "New Name") { @Override protected void doHandleMessages(Collection messages) { @@ -315,6 +315,50 @@ protected void doHandleMessages(Collection messages) { Assert.assertEquals(1, counter.get()); } + @Test + public void invalidUpstreamParent() { + SQSEvent.SQSMessage sqsMessage = newMessage(); + + sqsMessage.setAttributes( + Collections.singletonMap( + "AWSTraceHeader", "Root=1-55555555-invalid;Parent=1234567890123456;Sampled=1")); + + AtomicInteger counter = new AtomicInteger(0); + + SqsBatchMessageHandler messageHandler = + new SqsBatchMessageHandler(testing.getOpenTelemetrySdk()) { + @Override + protected void doHandleMessages(Collection messages) { + counter.getAndIncrement(); + } + }; + + Span parentSpan = + testing.getOpenTelemetrySdk().getTracer("test").spanBuilder("test").startSpan(); + + try (Scope scope = parentSpan.makeCurrent()) { + messageHandler.handleMessages(Collections.singletonList(sqsMessage)); + } + + parentSpan.end(); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), + span -> + span.hasName("Batch Message Handler") + .hasTotalRecordedLinks(0) + .hasAttribute( + SemanticAttributes.MESSAGING_OPERATION, MessageOperation.RECEIVE.name()) + .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") + .hasTotalAttributeCount(2) + .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) + .hasTraceId(parentSpan.getSpanContext().getTraceId()))); + + Assert.assertEquals(1, counter.get()); + } + private static SQSEvent.SQSMessage newMessage() { try { Constructor ctor = SQSEvent.SQSMessage.class.getDeclaredConstructor(); From 9bb39f4b3080a2dc0ee74ea1b6cd816f6d904dd7 Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Fri, 21 Apr 2023 14:20:54 -0700 Subject: [PATCH 06/47] Adding OTEL format --- .../SqsBatchMessageHandler.java | 53 ++++++++++++++++--- .../SqsBatchMessageHandlerTest.java | 51 ++++++++++++++++++ 2 files changed, 98 insertions(+), 6 deletions(-) diff --git a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java index f2bb9c2c5df5..f0f48abef2d2 100644 --- a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java +++ b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java @@ -10,6 +10,7 @@ import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.SpanBuilder; import io.opentelemetry.api.trace.SpanContext; +import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator; import io.opentelemetry.context.Context; import io.opentelemetry.context.propagation.TextMapGetter; import io.opentelemetry.contrib.awsxray.propagator.AwsXrayPropagator; @@ -49,7 +50,48 @@ protected void addMessagingAttributes(SpanBuilder spanBuilder) { public SpanContext getParentSpanContext(SQSEvent.SQSMessage message) { String parentHeader = message.getAttributes().get(AWS_TRACE_HEADER_SQS_ATTRIBUTE_KEY); - if (parentHeader != null) { + if (parentHeader == null) { + return null; + } + + SpanContext spanContext = getParentSpanContextXRay(parentHeader); + + if (spanContext != null) { + return spanContext; + } + + spanContext = getParentSpanContextW3C(parentHeader); + + if (spanContext != null) { + return spanContext; + } + + logger.log(Level.WARNING, "Invalid upstream span context: {0}", parentHeader); + return null; + } + + private static SpanContext getParentSpanContextW3C(String parentHeader) { + try { + Context w3cContext = + W3CTraceContextPropagator.getInstance() + .extract( + Context.root(), + Collections.singletonMap("traceparent", parentHeader), + MapGetter.INSTANCE); + + SpanContext messageSpanCtx = Span.fromContext(w3cContext).getSpanContext(); + + if (messageSpanCtx.isValid()) { + return messageSpanCtx; + } else { + return null; + } + } catch (RuntimeException e) { + return null; + } + } + + private static SpanContext getParentSpanContextXRay(String parentHeader) { try { Context xrayContext = AwsXrayPropagator.getInstance() @@ -62,13 +104,12 @@ public SpanContext getParentSpanContext(SQSEvent.SQSMessage message) { if (messageSpanCtx.isValid()) { return messageSpanCtx; + } else { + return null; } - } catch (Throwable error) { - logger.log(Level.WARNING, "Invalid upstream span context: {0}", parentHeader); + } catch (RuntimeException e) { + return null; } - } - - return null; } private enum MapGetter implements TextMapGetter> { diff --git a/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java b/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java index 9a3fd8ecfe5c..ed2d21658033 100644 --- a/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java +++ b/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java @@ -83,6 +83,57 @@ protected void doHandleMessages(Collection messages) { Assert.assertEquals(1, counter.get()); } + @Test + public void simpleOTELUpstream() { + SQSEvent.SQSMessage sqsMessage = newMessage(); + + sqsMessage.setAttributes( + Collections.singletonMap( + "AWSTraceHeader", "00-ff000000000000000000000000000041-ff00000000000041-01")); + + AtomicInteger counter = new AtomicInteger(0); + + SqsBatchMessageHandler messageHandler = + new SqsBatchMessageHandler(testing.getOpenTelemetrySdk()) { + @Override + protected void doHandleMessages(Collection messages) { + counter.getAndIncrement(); + } + }; + + Span parentSpan = + testing.getOpenTelemetrySdk().getTracer("test").spanBuilder("test").startSpan(); + + try (Scope scope = parentSpan.makeCurrent()) { + messageHandler.handleMessages(Collections.singletonList(sqsMessage)); + } + + parentSpan.end(); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), + span -> + span.hasName("Batch Message Handler") + .hasLinks( + LinkData.create( + SpanContext.createFromRemoteParent( + "ff000000000000000000000000000041", + "ff00000000000041", + TraceFlags.getSampled(), + TraceState.getDefault()))) + .hasTotalRecordedLinks(1) + .hasAttribute( + SemanticAttributes.MESSAGING_OPERATION, MessageOperation.RECEIVE.name()) + .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") + .hasTotalAttributeCount(2) + .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) + .hasTraceId(parentSpan.getSpanContext().getTraceId()))); + + Assert.assertEquals(1, counter.get()); + } + @Test public void multipleMessages() { List sqsMessages = new LinkedList<>(); From 7aca0d47dae8e7837bb6df7005ebe5f45a6b1966 Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Sun, 23 Apr 2023 21:20:23 -0700 Subject: [PATCH 07/47] Addressing PR --- instrumentation/message-handler/library/README.md | 4 ++-- .../messagehandler/BatchMessageHandler.java | 7 +++---- .../messagehandler/SqsBatchMessageHandler.java | 4 ++-- .../messagehandler/SqsBatchMessageHandlerTest.java | 14 +++++++------- 4 files changed, 14 insertions(+), 15 deletions(-) diff --git a/instrumentation/message-handler/library/README.md b/instrumentation/message-handler/library/README.md index 4d3e4474374c..72be1da34c9c 100644 --- a/instrumentation/message-handler/library/README.md +++ b/instrumentation/message-handler/library/README.md @@ -1,8 +1,8 @@ # Message Handler -This package contains handlers to instrument message system spans. +This package contains handlers to instrument message system spans for a batch of messages. It is not designed for a for-loop case. -The handler will create a new messaging span, add span links to it, and set the messaging attributes behind the scene. These values are based off of the messages passed in. +The handler will create a single new messaging span, add span links to it, and set the messaging attributes behind the scene. These values are based off of the messages passed in. The handler provides constructors to change the messaging operation and span name of the newly created messaging span. diff --git a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java index 9c68232b4d29..2d0db0217ee7 100644 --- a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java +++ b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java @@ -18,7 +18,6 @@ import java.util.Collection; public abstract class BatchMessageHandler { - protected String messagingOperation; protected OpenTelemetry openTelemetry; protected String spanName; @@ -28,7 +27,7 @@ public BatchMessageHandler(OpenTelemetry openTelemetry) { } public BatchMessageHandler(OpenTelemetry openTelemetry, String messageOperation) { - this(openTelemetry, messageOperation, "Batch Message Handler"); + this(openTelemetry, messageOperation, "Batch Message"); } public BatchMessageHandler( @@ -75,8 +74,8 @@ public void handleMessages(Collection messages) { try (Scope scope = span.makeCurrent()) { doHandleMessages(messages); + } finally { + span.end(); } - - span.end(); } } diff --git a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java index f0f48abef2d2..7f1aafd367c4 100644 --- a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java +++ b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java @@ -54,13 +54,13 @@ public SpanContext getParentSpanContext(SQSEvent.SQSMessage message) { return null; } - SpanContext spanContext = getParentSpanContextXRay(parentHeader); + SpanContext spanContext = getParentSpanContextW3C(parentHeader); if (spanContext != null) { return spanContext; } - spanContext = getParentSpanContextW3C(parentHeader); + spanContext = getParentSpanContextXRay(parentHeader); if (spanContext != null) { return spanContext; diff --git a/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java b/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java index ed2d21658033..515e6420f222 100644 --- a/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java +++ b/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java @@ -64,7 +64,7 @@ protected void doHandleMessages(Collection messages) { trace.hasSpansSatisfyingExactly( span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> - span.hasName("Batch Message Handler") + span.hasName("Batch Message") .hasLinks( LinkData.create( SpanContext.createFromRemoteParent( @@ -115,7 +115,7 @@ protected void doHandleMessages(Collection messages) { trace.hasSpansSatisfyingExactly( span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> - span.hasName("Batch Message Handler") + span.hasName("Batch Message") .hasLinks( LinkData.create( SpanContext.createFromRemoteParent( @@ -176,7 +176,7 @@ protected void doHandleMessages(Collection messages) { trace.hasSpansSatisfyingExactly( span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> - span.hasName("Batch Message Handler") + span.hasName("Batch Message") .hasLinks( LinkData.create( SpanContext.createFromRemoteParent( @@ -240,7 +240,7 @@ protected void doHandleMessages(Collection messages) { trace.hasSpansSatisfyingExactly( span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> - span.hasName("Batch Message Handler") + span.hasName("Batch Message") .hasLinks( LinkData.create( SpanContext.createFromRemoteParent( @@ -256,7 +256,7 @@ protected void doHandleMessages(Collection messages) { .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) .hasTraceId(parentSpan.getSpanContext().getTraceId()), span -> - span.hasName("Batch Message Handler") + span.hasName("Batch Message") .hasLinks( LinkData.create( SpanContext.createFromRemoteParent( @@ -301,7 +301,7 @@ protected void doHandleMessages(Collection messages) { trace.hasSpansSatisfyingExactly( span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> - span.hasName("Batch Message Handler") + span.hasName("Batch Message") .hasTotalRecordedLinks(0) .hasAttribute( SemanticAttributes.MESSAGING_OPERATION, MessageOperation.RECEIVE.name()) @@ -398,7 +398,7 @@ protected void doHandleMessages(Collection messages) { trace.hasSpansSatisfyingExactly( span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> - span.hasName("Batch Message Handler") + span.hasName("Batch Message") .hasTotalRecordedLinks(0) .hasAttribute( SemanticAttributes.MESSAGING_OPERATION, MessageOperation.RECEIVE.name()) From d6ec4d0eda67f34524e5a199f90f35caa90b4714 Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Sun, 23 Apr 2023 21:27:31 -0700 Subject: [PATCH 08/47] Applying spot check --- .../SqsBatchMessageHandler.java | 64 +++++++++---------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java index 7f1aafd367c4..659dd9f3922a 100644 --- a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java +++ b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java @@ -71,45 +71,45 @@ public SpanContext getParentSpanContext(SQSEvent.SQSMessage message) { } private static SpanContext getParentSpanContextW3C(String parentHeader) { - try { - Context w3cContext = - W3CTraceContextPropagator.getInstance() - .extract( - Context.root(), - Collections.singletonMap("traceparent", parentHeader), - MapGetter.INSTANCE); - - SpanContext messageSpanCtx = Span.fromContext(w3cContext).getSpanContext(); - - if (messageSpanCtx.isValid()) { - return messageSpanCtx; - } else { - return null; - } - } catch (RuntimeException e) { + try { + Context w3cContext = + W3CTraceContextPropagator.getInstance() + .extract( + Context.root(), + Collections.singletonMap("traceparent", parentHeader), + MapGetter.INSTANCE); + + SpanContext messageSpanCtx = Span.fromContext(w3cContext).getSpanContext(); + + if (messageSpanCtx.isValid()) { + return messageSpanCtx; + } else { return null; } + } catch (RuntimeException e) { + return null; + } } private static SpanContext getParentSpanContextXRay(String parentHeader) { - try { - Context xrayContext = - AwsXrayPropagator.getInstance() - .extract( - Context.root(), - Collections.singletonMap(AWS_TRACE_HEADER_PROPAGATOR_KEY, parentHeader), - MapGetter.INSTANCE); - - SpanContext messageSpanCtx = Span.fromContext(xrayContext).getSpanContext(); - - if (messageSpanCtx.isValid()) { - return messageSpanCtx; - } else { - return null; - } - } catch (RuntimeException e) { + try { + Context xrayContext = + AwsXrayPropagator.getInstance() + .extract( + Context.root(), + Collections.singletonMap(AWS_TRACE_HEADER_PROPAGATOR_KEY, parentHeader), + MapGetter.INSTANCE); + + SpanContext messageSpanCtx = Span.fromContext(xrayContext).getSpanContext(); + + if (messageSpanCtx.isValid()) { + return messageSpanCtx; + } else { return null; } + } catch (RuntimeException e) { + return null; + } } private enum MapGetter implements TextMapGetter> { From 1741b7b6666c43376a6b1dbf90402982696c692a Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Sun, 23 Apr 2023 21:37:24 -0700 Subject: [PATCH 09/47] Fixing style check --- .../messagehandler/SqsBatchMessageHandlerTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java b/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java index 515e6420f222..35dc5fb46115 100644 --- a/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java +++ b/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java @@ -84,7 +84,7 @@ protected void doHandleMessages(Collection messages) { } @Test - public void simpleOTELUpstream() { + public void simpleOtelUpstream() { SQSEvent.SQSMessage sqsMessage = newMessage(); sqsMessage.setAttributes( From a34eba7643a878fd2c80369a8f10708306f7346f Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Mon, 24 Apr 2023 11:36:37 -0700 Subject: [PATCH 10/47] Adding clarification --- .../messagehandler/SqsBatchMessageHandler.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java index 659dd9f3922a..6dde7f84abe5 100644 --- a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java +++ b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java @@ -54,13 +54,16 @@ public SpanContext getParentSpanContext(SQSEvent.SQSMessage message) { return null; } - SpanContext spanContext = getParentSpanContextW3C(parentHeader); + // We do not know if the upstream is W3C or X-Ray format. + // We will first try to decode it as a X-Ray trace context. + // Then we will try to decode it as a W3C trace context. + SpanContext spanContext = getParentSpanContextXRay(parentHeader); if (spanContext != null) { return spanContext; } - spanContext = getParentSpanContextXRay(parentHeader); + spanContext = getParentSpanContextW3C(parentHeader); if (spanContext != null) { return spanContext; From b23a221ad1f48ad4e74d3cd394e710e434095b5d Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Mon, 24 Apr 2023 23:35:27 -0700 Subject: [PATCH 11/47] Refactorting some logic --- .../messagehandler/BatchMessageHandler.java | 95 +++++++++++++++++- .../SqsBatchMessageHandler.java | 96 +------------------ 2 files changed, 95 insertions(+), 96 deletions(-) diff --git a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java index 2d0db0217ee7..be0b9b9b47fa 100644 --- a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java +++ b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java @@ -11,13 +11,24 @@ import io.opentelemetry.api.trace.SpanContext; import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.api.trace.TracerBuilder; +import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator; import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; +import io.opentelemetry.context.propagation.TextMapGetter; +import io.opentelemetry.contrib.awsxray.propagator.AwsXrayPropagator; import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessageOperation; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; import java.util.Collection; +import java.util.Collections; +import java.util.Locale; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; public abstract class BatchMessageHandler { + private static final Logger logger = Logger.getLogger(BatchMessageHandler.class.getName()); + private static final String AWS_TRACE_HEADER_PROPAGATOR_KEY = "x-amzn-trace-id"; + protected String messagingOperation; protected OpenTelemetry openTelemetry; protected String spanName; @@ -37,7 +48,7 @@ public BatchMessageHandler( this.messagingOperation = messageOperation; } - public abstract SpanContext getParentSpanContext(T t); + public abstract String getParentHeaderFromMessage(T t); protected abstract void doHandleMessages(Collection messages); @@ -63,7 +74,7 @@ public void handleMessages(Collection messages) { addMessagingAttributes(spanBuilder); for (T t : messages) { - SpanContext spanContext = getParentSpanContext(t); + SpanContext spanContext = getParentSpanContextFromHeader(getParentHeaderFromMessage(t)); if (spanContext != null) { spanBuilder.addLink(spanContext); @@ -78,4 +89,84 @@ public void handleMessages(Collection messages) { span.end(); } } + + public SpanContext getParentSpanContextFromHeader(String parentHeader) { + if (parentHeader == null) { + return null; + } + + // We do not know if the upstream is W3C or X-Ray format. + // We will first try to decode it as a X-Ray trace context. + // Then we will try to decode it as a W3C trace context. + SpanContext spanContext = getParentSpanContextXRay(parentHeader); + + if (spanContext != null) { + return spanContext; + } + + spanContext = getParentSpanContextW3C(parentHeader); + + if (spanContext != null) { + return spanContext; + } + + logger.log(Level.WARNING, "Invalid upstream span context: {0}", parentHeader); + return null; + } + + private static SpanContext getParentSpanContextW3C(String parentHeader) { + try { + Context w3cContext = + W3CTraceContextPropagator.getInstance() + .extract( + Context.root(), + Collections.singletonMap("traceparent", parentHeader), + MapGetter.INSTANCE); + + SpanContext messageSpanCtx = Span.fromContext(w3cContext).getSpanContext(); + + if (messageSpanCtx.isValid()) { + return messageSpanCtx; + } else { + return null; + } + } catch (RuntimeException e) { + return null; + } + } + + private static SpanContext getParentSpanContextXRay(String parentHeader) { + try { + Context xrayContext = + AwsXrayPropagator.getInstance() + .extract( + Context.root(), + Collections.singletonMap(AWS_TRACE_HEADER_PROPAGATOR_KEY, parentHeader), + MapGetter.INSTANCE); + + SpanContext messageSpanCtx = Span.fromContext(xrayContext).getSpanContext(); + + if (messageSpanCtx.isValid()) { + return messageSpanCtx; + } else { + return null; + } + } catch (RuntimeException e) { + return null; + } + } + + private enum MapGetter implements TextMapGetter> { + INSTANCE; + + @Override + public Iterable keys(Map map) { + return map.keySet(); + } + + @Override + public String get(Map map, String s) { + return map.get(s.toLowerCase(Locale.ROOT)); + } + } } diff --git a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java index 6dde7f84abe5..ad75e944d508 100644 --- a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java +++ b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java @@ -7,25 +7,11 @@ import com.amazonaws.services.lambda.runtime.events.SQSEvent; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.SpanBuilder; -import io.opentelemetry.api.trace.SpanContext; -import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.propagation.TextMapGetter; -import io.opentelemetry.contrib.awsxray.propagator.AwsXrayPropagator; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; -import java.util.Collections; -import java.util.Locale; -import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; public abstract class SqsBatchMessageHandler extends BatchMessageHandler { - private static final Logger logger = Logger.getLogger(BatchMessageHandler.class.getName()); - private static final String AWS_TRACE_HEADER_SQS_ATTRIBUTE_KEY = "AWSTraceHeader"; - private static final String AWS_TRACE_HEADER_PROPAGATOR_KEY = "x-amzn-trace-id"; public SqsBatchMessageHandler(OpenTelemetry openTelemetry) { super(openTelemetry); @@ -47,85 +33,7 @@ protected void addMessagingAttributes(SpanBuilder spanBuilder) { } @Override - public SpanContext getParentSpanContext(SQSEvent.SQSMessage message) { - String parentHeader = message.getAttributes().get(AWS_TRACE_HEADER_SQS_ATTRIBUTE_KEY); - - if (parentHeader == null) { - return null; - } - - // We do not know if the upstream is W3C or X-Ray format. - // We will first try to decode it as a X-Ray trace context. - // Then we will try to decode it as a W3C trace context. - SpanContext spanContext = getParentSpanContextXRay(parentHeader); - - if (spanContext != null) { - return spanContext; - } - - spanContext = getParentSpanContextW3C(parentHeader); - - if (spanContext != null) { - return spanContext; - } - - logger.log(Level.WARNING, "Invalid upstream span context: {0}", parentHeader); - return null; - } - - private static SpanContext getParentSpanContextW3C(String parentHeader) { - try { - Context w3cContext = - W3CTraceContextPropagator.getInstance() - .extract( - Context.root(), - Collections.singletonMap("traceparent", parentHeader), - MapGetter.INSTANCE); - - SpanContext messageSpanCtx = Span.fromContext(w3cContext).getSpanContext(); - - if (messageSpanCtx.isValid()) { - return messageSpanCtx; - } else { - return null; - } - } catch (RuntimeException e) { - return null; - } - } - - private static SpanContext getParentSpanContextXRay(String parentHeader) { - try { - Context xrayContext = - AwsXrayPropagator.getInstance() - .extract( - Context.root(), - Collections.singletonMap(AWS_TRACE_HEADER_PROPAGATOR_KEY, parentHeader), - MapGetter.INSTANCE); - - SpanContext messageSpanCtx = Span.fromContext(xrayContext).getSpanContext(); - - if (messageSpanCtx.isValid()) { - return messageSpanCtx; - } else { - return null; - } - } catch (RuntimeException e) { - return null; - } - } - - private enum MapGetter implements TextMapGetter> { - INSTANCE; - - @Override - public Iterable keys(Map map) { - return map.keySet(); - } - - @Override - public String get(Map map, String s) { - return map.get(s.toLowerCase(Locale.ROOT)); - } + public String getParentHeaderFromMessage(SQSEvent.SQSMessage message) { + return message.getAttributes().get(AWS_TRACE_HEADER_SQS_ATTRIBUTE_KEY); } } From 1e2402ec4fd738f816355532541c4982f64c6142 Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Mon, 24 Apr 2023 23:45:49 -0700 Subject: [PATCH 12/47] Fixing stylecheck --- .../instrumentation/messagehandler/BatchMessageHandler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java index be0b9b9b47fa..efaee0df0f4d 100644 --- a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java +++ b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java @@ -98,7 +98,7 @@ public SpanContext getParentSpanContextFromHeader(String parentHeader) { // We do not know if the upstream is W3C or X-Ray format. // We will first try to decode it as a X-Ray trace context. // Then we will try to decode it as a W3C trace context. - SpanContext spanContext = getParentSpanContextXRay(parentHeader); + SpanContext spanContext = getParentSpanContextXray(parentHeader); if (spanContext != null) { return spanContext; @@ -135,7 +135,7 @@ private static SpanContext getParentSpanContextW3C(String parentHeader) { } } - private static SpanContext getParentSpanContextXRay(String parentHeader) { + private static SpanContext getParentSpanContextXray(String parentHeader) { try { Context xrayContext = AwsXrayPropagator.getInstance() From 88f04849aee4cc9653a88a322a501048061ffde9 Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Wed, 31 May 2023 10:22:48 -0700 Subject: [PATCH 13/47] Addressing PR --- .../message-handler/library/README.md | 2 +- .../messagehandler/BatchMessageHandler.java | 178 +++++------------- .../SqsBatchMessageHandler.java | 95 +++++++++- .../SqsBatchMessageHandlerTest.java | 99 +++------- 4 files changed, 159 insertions(+), 215 deletions(-) diff --git a/instrumentation/message-handler/library/README.md b/instrumentation/message-handler/library/README.md index 72be1da34c9c..b4a6b91687cd 100644 --- a/instrumentation/message-handler/library/README.md +++ b/instrumentation/message-handler/library/README.md @@ -9,7 +9,7 @@ The handler provides constructors to change the messaging operation and span nam ## Available Handlers - `SQSBatchMessageHandlerTest` - processes messages from Amazon's SQS. -## Using SQSBatchMessageHandlerTest +## Using SQSBatchMessageHandler 1. Retrieve a collection of messages to process. 2. Create a SQSBatchMessageHandler and provide the business logic on what to do with the messages. diff --git a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java index efaee0df0f4d..4a00dfc38c94 100644 --- a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java +++ b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java @@ -6,167 +6,83 @@ package io.opentelemetry.instrumentation.messagehandler; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.SpanBuilder; -import io.opentelemetry.api.trace.SpanContext; -import io.opentelemetry.api.trace.SpanKind; -import io.opentelemetry.api.trace.TracerBuilder; -import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator; +import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; -import io.opentelemetry.context.propagation.TextMapGetter; -import io.opentelemetry.contrib.awsxray.propagator.AwsXrayPropagator; +import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessageOperation; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; +import javax.annotation.Nullable; import java.util.Collection; -import java.util.Collections; -import java.util.Locale; -import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; public abstract class BatchMessageHandler { - private static final Logger logger = Logger.getLogger(BatchMessageHandler.class.getName()); - private static final String AWS_TRACE_HEADER_PROPAGATOR_KEY = "x-amzn-trace-id"; - protected String messagingOperation; protected OpenTelemetry openTelemetry; - protected String spanName; + protected SpanNameExtractor> spanNameExtractor; + + protected Instrumenter, Void> messageInstrumenter; public BatchMessageHandler(OpenTelemetry openTelemetry) { this(openTelemetry, MessageOperation.RECEIVE.name()); } public BatchMessageHandler(OpenTelemetry openTelemetry, String messageOperation) { - this(openTelemetry, messageOperation, "Batch Message"); + this(openTelemetry, messageOperation, messages -> "Batch Message"); } public BatchMessageHandler( - OpenTelemetry openTelemetry, String messageOperation, String spanName) { + OpenTelemetry openTelemetry, String messageOperation, SpanNameExtractor> spanNameExtractor) { this.openTelemetry = openTelemetry; - this.spanName = spanName; + this.spanNameExtractor = spanNameExtractor; this.messagingOperation = messageOperation; + + setup(); } - public abstract String getParentHeaderFromMessage(T t); + protected abstract void setup(); protected abstract void doHandleMessages(Collection messages); - protected void addMessagingAttributes(SpanBuilder spanBuilder) { - spanBuilder.setAttribute(SemanticAttributes.MESSAGING_OPERATION, messagingOperation); + protected AttributesExtractor, Void> getGenericAttributesExtractor() { + return + new AttributesExtractor, Void>() { + + @Override + public void onStart( + AttributesBuilder attributes, Context parentContext, Collection messages) { + attributes.put(SemanticAttributes.MESSAGING_OPERATION, messagingOperation); + } + + @Override + public void onEnd( + AttributesBuilder attributes, + Context context, + Collection messages, + @Nullable Void unused, + @Nullable Throwable error) { + + } + }; } public void handleMessages(Collection messages) { - TracerBuilder tracerBuilder = - openTelemetry - .tracerBuilder("io.opentelemetry.message.handler") - .setInstrumentationVersion("1.0"); - - Span parentSpan = Span.current(); - - SpanBuilder spanBuilder = - tracerBuilder - .build() - .spanBuilder(spanName) - .setParent(Context.current().with(parentSpan)) - .setSpanKind(SpanKind.INTERNAL); - - addMessagingAttributes(spanBuilder); - - for (T t : messages) { - SpanContext spanContext = getParentSpanContextFromHeader(getParentHeaderFromMessage(t)); - - if (spanContext != null) { - spanBuilder.addLink(spanContext); + Context parentContext = Context.current(); + if (messageInstrumenter.shouldStart(parentContext, messages)) { + io.opentelemetry.context.Context otelContext = + messageInstrumenter.start(parentContext, messages); + Throwable error = null; + try (Scope ignored = otelContext.makeCurrent()) { + doHandleMessages(messages); + } catch (Throwable t) { + error = t; + throw t; + } finally { + messageInstrumenter.end(otelContext, messages, null, error); } - } - - Span span = spanBuilder.startSpan(); - - try (Scope scope = span.makeCurrent()) { + } else { doHandleMessages(messages); - } finally { - span.end(); - } - } - - public SpanContext getParentSpanContextFromHeader(String parentHeader) { - if (parentHeader == null) { - return null; - } - - // We do not know if the upstream is W3C or X-Ray format. - // We will first try to decode it as a X-Ray trace context. - // Then we will try to decode it as a W3C trace context. - SpanContext spanContext = getParentSpanContextXray(parentHeader); - - if (spanContext != null) { - return spanContext; - } - - spanContext = getParentSpanContextW3C(parentHeader); - - if (spanContext != null) { - return spanContext; - } - - logger.log(Level.WARNING, "Invalid upstream span context: {0}", parentHeader); - return null; - } - - private static SpanContext getParentSpanContextW3C(String parentHeader) { - try { - Context w3cContext = - W3CTraceContextPropagator.getInstance() - .extract( - Context.root(), - Collections.singletonMap("traceparent", parentHeader), - MapGetter.INSTANCE); - - SpanContext messageSpanCtx = Span.fromContext(w3cContext).getSpanContext(); - - if (messageSpanCtx.isValid()) { - return messageSpanCtx; - } else { - return null; - } - } catch (RuntimeException e) { - return null; - } - } - - private static SpanContext getParentSpanContextXray(String parentHeader) { - try { - Context xrayContext = - AwsXrayPropagator.getInstance() - .extract( - Context.root(), - Collections.singletonMap(AWS_TRACE_HEADER_PROPAGATOR_KEY, parentHeader), - MapGetter.INSTANCE); - - SpanContext messageSpanCtx = Span.fromContext(xrayContext).getSpanContext(); - - if (messageSpanCtx.isValid()) { - return messageSpanCtx; - } else { - return null; - } - } catch (RuntimeException e) { - return null; - } - } - - private enum MapGetter implements TextMapGetter> { - INSTANCE; - - @Override - public Iterable keys(Map map) { - return map.keySet(); - } - - @Override - public String get(Map map, String s) { - return map.get(s.toLowerCase(Locale.ROOT)); } } } diff --git a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java index ad75e944d508..c2b622349765 100644 --- a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java +++ b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java @@ -7,12 +7,29 @@ import com.amazonaws.services.lambda.runtime.events.SQSEvent; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.trace.SpanBuilder; +import io.opentelemetry.api.common.AttributesBuilder; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanContext; +import io.opentelemetry.context.Context; +import io.opentelemetry.context.propagation.TextMapGetter; +import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; +import io.opentelemetry.instrumentation.api.instrumenter.SpanLinksExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; +import javax.annotation.Nullable; +import java.util.Collection; +import java.util.Collections; +import java.util.Locale; +import java.util.Map; public abstract class SqsBatchMessageHandler extends BatchMessageHandler { private static final String AWS_TRACE_HEADER_SQS_ATTRIBUTE_KEY = "AWSTraceHeader"; + // lower-case map getter used for extraction + static final String AWS_TRACE_HEADER_PROPAGATOR_KEY = "x-amzn-trace-id"; + public SqsBatchMessageHandler(OpenTelemetry openTelemetry) { super(openTelemetry); } @@ -22,18 +39,78 @@ public SqsBatchMessageHandler(OpenTelemetry openTelemetry, String messageOperati } public SqsBatchMessageHandler( - OpenTelemetry openTelemetry, String messageOperation, String spanName) { - super(openTelemetry, messageOperation, spanName); + OpenTelemetry openTelemetry, String messageOperation, SpanNameExtractor> spanNameExtractor) { + super(openTelemetry, messageOperation, spanNameExtractor); } @Override - protected void addMessagingAttributes(SpanBuilder spanBuilder) { - super.addMessagingAttributes(spanBuilder); - spanBuilder.setAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS"); + protected void setup() { + InstrumenterBuilder, Void> builder = Instrumenter.builder( + openTelemetry, + "io.opentelemetry.message.handler", + spanNameExtractor); + + builder.setInstrumentationVersion("1.0"); + builder.addAttributesExtractor(getGenericAttributesExtractor()); + builder.addAttributesExtractor(getAttributesExtractor()); + builder.addSpanLinksExtractor(getSpanLinksExtractor()); + + messageInstrumenter = builder.buildInstrumenter(); } - @Override - public String getParentHeaderFromMessage(SQSEvent.SQSMessage message) { - return message.getAttributes().get(AWS_TRACE_HEADER_SQS_ATTRIBUTE_KEY); + protected AttributesExtractor, Void> getAttributesExtractor() { + return + new AttributesExtractor, Void>() { + + @Override + public void onStart( + AttributesBuilder attributes, Context parentContext, Collection messages) { + attributes.put(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS"); + } + + @Override + public void onEnd( + AttributesBuilder attributes, + Context context, + Collection messages, + @Nullable Void unused, + @Nullable Throwable error) { + + } + }; + } + + protected SpanLinksExtractor> getSpanLinksExtractor() { + return (spanLinks, parentContext, sqsMessages) -> { + for (SQSEvent.SQSMessage message: sqsMessages) { + String parentHeader = message.getAttributes().get(AWS_TRACE_HEADER_SQS_ATTRIBUTE_KEY); + if (parentHeader != null) { + Context xrayContext = + openTelemetry.getPropagators().getTextMapPropagator() + .extract( + Context.root(), // We don't want the ambient context. + Collections.singletonMap(AWS_TRACE_HEADER_PROPAGATOR_KEY, parentHeader), + MapGetter.INSTANCE); + SpanContext messageSpanCtx = Span.fromContext(xrayContext).getSpanContext(); + if (messageSpanCtx.isValid()) { + spanLinks.addLink(messageSpanCtx); + } + } + } + }; + } + + private enum MapGetter implements TextMapGetter> { + INSTANCE; + + @Override + public Iterable keys(Map map) { + return map.keySet(); + } + + @Override + public String get(Map map, String s) { + return map.get(s.toLowerCase(Locale.ROOT)); + } } } diff --git a/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java b/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java index 35dc5fb46115..702e09cdf070 100644 --- a/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java +++ b/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java @@ -11,12 +11,16 @@ import io.opentelemetry.api.trace.TraceFlags; import io.opentelemetry.api.trace.TraceState; import io.opentelemetry.context.Scope; +import io.opentelemetry.context.propagation.ContextPropagators; +import io.opentelemetry.contrib.awsxray.propagator.AwsXrayPropagator; import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessageOperation; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension; +import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.trace.data.LinkData; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; import java.lang.reflect.Constructor; +import java.lang.reflect.Field; import java.util.Collection; import java.util.Collections; import java.util.LinkedList; @@ -26,10 +30,23 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; +import static org.junit.jupiter.api.Assertions.assertThrows; + public class SqsBatchMessageHandlerTest { @RegisterExtension - public static final InstrumentationExtension testing = LibraryInstrumentationExtension.create(); + private static final InstrumentationExtension testing = LibraryInstrumentationExtension.create(); + + static { + // Change to the X-Ray propagator + try { + Field field = OpenTelemetrySdk.class.getDeclaredField("propagators"); + field.setAccessible(true); + field.set(testing.getOpenTelemetrySdk(), ContextPropagators.create(AwsXrayPropagator.getInstance())); + } catch (Exception e) { + throw new RuntimeException(e); + } + } @Test public void simple() { @@ -83,57 +100,6 @@ protected void doHandleMessages(Collection messages) { Assert.assertEquals(1, counter.get()); } - @Test - public void simpleOtelUpstream() { - SQSEvent.SQSMessage sqsMessage = newMessage(); - - sqsMessage.setAttributes( - Collections.singletonMap( - "AWSTraceHeader", "00-ff000000000000000000000000000041-ff00000000000041-01")); - - AtomicInteger counter = new AtomicInteger(0); - - SqsBatchMessageHandler messageHandler = - new SqsBatchMessageHandler(testing.getOpenTelemetrySdk()) { - @Override - protected void doHandleMessages(Collection messages) { - counter.getAndIncrement(); - } - }; - - Span parentSpan = - testing.getOpenTelemetrySdk().getTracer("test").spanBuilder("test").startSpan(); - - try (Scope scope = parentSpan.makeCurrent()) { - messageHandler.handleMessages(Collections.singletonList(sqsMessage)); - } - - parentSpan.end(); - - testing.waitAndAssertTraces( - trace -> - trace.hasSpansSatisfyingExactly( - span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), - span -> - span.hasName("Batch Message") - .hasLinks( - LinkData.create( - SpanContext.createFromRemoteParent( - "ff000000000000000000000000000041", - "ff00000000000041", - TraceFlags.getSampled(), - TraceState.getDefault()))) - .hasTotalRecordedLinks(1) - .hasAttribute( - SemanticAttributes.MESSAGING_OPERATION, MessageOperation.RECEIVE.name()) - .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") - .hasTotalAttributeCount(2) - .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) - .hasTraceId(parentSpan.getSpanContext().getTraceId()))); - - Assert.assertEquals(1, counter.get()); - } - @Test public void multipleMessages() { List sqsMessages = new LinkedList<>(); @@ -326,7 +292,7 @@ public void changeDefaults() { SqsBatchMessageHandler messageHandler = new SqsBatchMessageHandler( - testing.getOpenTelemetrySdk(), MessageOperation.PROCESS.name(), "New Name") { + testing.getOpenTelemetrySdk(), MessageOperation.PROCESS.name(), messages -> "New Name") { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); @@ -387,27 +353,12 @@ protected void doHandleMessages(Collection messages) { Span parentSpan = testing.getOpenTelemetrySdk().getTracer("test").spanBuilder("test").startSpan(); - try (Scope scope = parentSpan.makeCurrent()) { - messageHandler.handleMessages(Collections.singletonList(sqsMessage)); - } - - parentSpan.end(); - - testing.waitAndAssertTraces( - trace -> - trace.hasSpansSatisfyingExactly( - span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), - span -> - span.hasName("Batch Message") - .hasTotalRecordedLinks(0) - .hasAttribute( - SemanticAttributes.MESSAGING_OPERATION, MessageOperation.RECEIVE.name()) - .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") - .hasTotalAttributeCount(2) - .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) - .hasTraceId(parentSpan.getSpanContext().getTraceId()))); - - Assert.assertEquals(1, counter.get()); + assertThrows(StringIndexOutOfBoundsException.class, + ()->{ + try (Scope scope = parentSpan.makeCurrent()) { + messageHandler.handleMessages(Collections.singletonList(sqsMessage)); + } + }); } private static SQSEvent.SQSMessage newMessage() { From d5af1fdbc3e918a358747d6cc4a71adbe78ec94d Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Wed, 31 May 2023 11:16:04 -0700 Subject: [PATCH 14/47] Running spotless --- .../messagehandler/BatchMessageHandler.java | 37 +++++++------ .../SqsBatchMessageHandler.java | 53 ++++++++++--------- .../SqsBatchMessageHandlerTest.java | 17 +++--- 3 files changed, 56 insertions(+), 51 deletions(-) diff --git a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java index 4a00dfc38c94..d84430eed96a 100644 --- a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java +++ b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java @@ -14,8 +14,8 @@ import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessageOperation; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; -import javax.annotation.Nullable; import java.util.Collection; +import javax.annotation.Nullable; public abstract class BatchMessageHandler { protected String messagingOperation; @@ -33,7 +33,9 @@ public BatchMessageHandler(OpenTelemetry openTelemetry, String messageOperation) } public BatchMessageHandler( - OpenTelemetry openTelemetry, String messageOperation, SpanNameExtractor> spanNameExtractor) { + OpenTelemetry openTelemetry, + String messageOperation, + SpanNameExtractor> spanNameExtractor) { this.openTelemetry = openTelemetry; this.spanNameExtractor = spanNameExtractor; this.messagingOperation = messageOperation; @@ -46,25 +48,22 @@ public BatchMessageHandler( protected abstract void doHandleMessages(Collection messages); protected AttributesExtractor, Void> getGenericAttributesExtractor() { - return - new AttributesExtractor, Void>() { + return new AttributesExtractor, Void>() { - @Override - public void onStart( - AttributesBuilder attributes, Context parentContext, Collection messages) { - attributes.put(SemanticAttributes.MESSAGING_OPERATION, messagingOperation); - } - - @Override - public void onEnd( - AttributesBuilder attributes, - Context context, - Collection messages, - @Nullable Void unused, - @Nullable Throwable error) { + @Override + public void onStart( + AttributesBuilder attributes, Context parentContext, Collection messages) { + attributes.put(SemanticAttributes.MESSAGING_OPERATION, messagingOperation); + } - } - }; + @Override + public void onEnd( + AttributesBuilder attributes, + Context context, + Collection messages, + @Nullable Void unused, + @Nullable Throwable error) {} + }; } public void handleMessages(Collection messages) { diff --git a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java index c2b622349765..b21e2bb0f0a5 100644 --- a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java +++ b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java @@ -18,11 +18,11 @@ import io.opentelemetry.instrumentation.api.instrumenter.SpanLinksExtractor; import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; -import javax.annotation.Nullable; import java.util.Collection; import java.util.Collections; import java.util.Locale; import java.util.Map; +import javax.annotation.Nullable; public abstract class SqsBatchMessageHandler extends BatchMessageHandler { private static final String AWS_TRACE_HEADER_SQS_ATTRIBUTE_KEY = "AWSTraceHeader"; @@ -39,16 +39,16 @@ public SqsBatchMessageHandler(OpenTelemetry openTelemetry, String messageOperati } public SqsBatchMessageHandler( - OpenTelemetry openTelemetry, String messageOperation, SpanNameExtractor> spanNameExtractor) { + OpenTelemetry openTelemetry, + String messageOperation, + SpanNameExtractor> spanNameExtractor) { super(openTelemetry, messageOperation, spanNameExtractor); } @Override protected void setup() { - InstrumenterBuilder, Void> builder = Instrumenter.builder( - openTelemetry, - "io.opentelemetry.message.handler", - spanNameExtractor); + InstrumenterBuilder, Void> builder = + Instrumenter.builder(openTelemetry, "io.opentelemetry.message.handler", spanNameExtractor); builder.setInstrumentationVersion("1.0"); builder.addAttributesExtractor(getGenericAttributesExtractor()); @@ -59,34 +59,35 @@ protected void setup() { } protected AttributesExtractor, Void> getAttributesExtractor() { - return - new AttributesExtractor, Void>() { - - @Override - public void onStart( - AttributesBuilder attributes, Context parentContext, Collection messages) { - attributes.put(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS"); - } - - @Override - public void onEnd( - AttributesBuilder attributes, - Context context, - Collection messages, - @Nullable Void unused, - @Nullable Throwable error) { + return new AttributesExtractor, Void>() { + + @Override + public void onStart( + AttributesBuilder attributes, + Context parentContext, + Collection messages) { + attributes.put(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS"); + } - } - }; + @Override + public void onEnd( + AttributesBuilder attributes, + Context context, + Collection messages, + @Nullable Void unused, + @Nullable Throwable error) {} + }; } protected SpanLinksExtractor> getSpanLinksExtractor() { return (spanLinks, parentContext, sqsMessages) -> { - for (SQSEvent.SQSMessage message: sqsMessages) { + for (SQSEvent.SQSMessage message : sqsMessages) { String parentHeader = message.getAttributes().get(AWS_TRACE_HEADER_SQS_ATTRIBUTE_KEY); if (parentHeader != null) { Context xrayContext = - openTelemetry.getPropagators().getTextMapPropagator() + openTelemetry + .getPropagators() + .getTextMapPropagator() .extract( Context.root(), // We don't want the ambient context. Collections.singletonMap(AWS_TRACE_HEADER_PROPAGATOR_KEY, parentHeader), diff --git a/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java b/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java index 702e09cdf070..759906cb9878 100644 --- a/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java +++ b/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java @@ -5,6 +5,8 @@ package io.opentelemetry.instrumentation.messagehandler; +import static org.junit.jupiter.api.Assertions.assertThrows; + import com.amazonaws.services.lambda.runtime.events.SQSEvent; import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.SpanContext; @@ -30,8 +32,6 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; -import static org.junit.jupiter.api.Assertions.assertThrows; - public class SqsBatchMessageHandlerTest { @RegisterExtension @@ -42,7 +42,9 @@ public class SqsBatchMessageHandlerTest { try { Field field = OpenTelemetrySdk.class.getDeclaredField("propagators"); field.setAccessible(true); - field.set(testing.getOpenTelemetrySdk(), ContextPropagators.create(AwsXrayPropagator.getInstance())); + field.set( + testing.getOpenTelemetrySdk(), + ContextPropagators.create(AwsXrayPropagator.getInstance())); } catch (Exception e) { throw new RuntimeException(e); } @@ -292,7 +294,9 @@ public void changeDefaults() { SqsBatchMessageHandler messageHandler = new SqsBatchMessageHandler( - testing.getOpenTelemetrySdk(), MessageOperation.PROCESS.name(), messages -> "New Name") { + testing.getOpenTelemetrySdk(), + MessageOperation.PROCESS.name(), + messages -> "New Name") { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); @@ -353,8 +357,9 @@ protected void doHandleMessages(Collection messages) { Span parentSpan = testing.getOpenTelemetrySdk().getTracer("test").spanBuilder("test").startSpan(); - assertThrows(StringIndexOutOfBoundsException.class, - ()->{ + assertThrows( + StringIndexOutOfBoundsException.class, + () -> { try (Scope scope = parentSpan.makeCurrent()) { messageHandler.handleMessages(Collections.singletonList(sqsMessage)); } From 0e08dadf84154268c801db94ef8d877d8ad7ac6b Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Wed, 31 May 2023 11:17:55 -0700 Subject: [PATCH 15/47] Fixing readme --- instrumentation/message-handler/library/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation/message-handler/library/README.md b/instrumentation/message-handler/library/README.md index b4a6b91687cd..a714beb0b844 100644 --- a/instrumentation/message-handler/library/README.md +++ b/instrumentation/message-handler/library/README.md @@ -7,7 +7,7 @@ The handler will create a single new messaging span, add span links to it, and s The handler provides constructors to change the messaging operation and span name of the newly created messaging span. ## Available Handlers -- `SQSBatchMessageHandlerTest` - processes messages from Amazon's SQS. +- `SQSBatchMessageHandler` - processes messages from Amazon's SQS. ## Using SQSBatchMessageHandler From 072f189cc2474c5ee6946bf48b72bedd3d6df028 Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Wed, 31 May 2023 11:40:51 -0700 Subject: [PATCH 16/47] Adding exception test --- .../SqsBatchMessageHandlerTest.java | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java b/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java index 759906cb9878..40f9de75b74c 100644 --- a/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java +++ b/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java @@ -366,6 +366,64 @@ protected void doHandleMessages(Collection messages) { }); } + @Test + public void exceptionInHandle() { + SQSEvent.SQSMessage sqsMessage = newMessage(); + + sqsMessage.setAttributes( + Collections.singletonMap( + "AWSTraceHeader", + "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")); + + AtomicInteger counter = new AtomicInteger(0); + + SqsBatchMessageHandler messageHandler = + new SqsBatchMessageHandler(testing.getOpenTelemetrySdk()) { + @Override + protected void doHandleMessages(Collection messages) { + counter.getAndIncrement(); + throw new RuntimeException("Injected Error"); + } + }; + + Span parentSpan = + testing.getOpenTelemetrySdk().getTracer("test").spanBuilder("test").startSpan(); + + assertThrows( + RuntimeException.class, + () -> { + try (Scope scope = parentSpan.makeCurrent()) { + messageHandler.handleMessages(Collections.singletonList(sqsMessage)); + } + }); + + parentSpan.end(); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), + span -> + span.hasName("Batch Message") + .hasLinks( + LinkData.create( + SpanContext.createFromRemoteParent( + "55555555123456789012345678901234", + "1234567890123456", + TraceFlags.getSampled(), + TraceState.getDefault()))) + .hasTotalRecordedLinks(1) + .hasException(new RuntimeException("Injected Error")) + .hasAttribute( + SemanticAttributes.MESSAGING_OPERATION, MessageOperation.RECEIVE.name()) + .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") + .hasTotalAttributeCount(2) + .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) + .hasTraceId(parentSpan.getSpanContext().getTraceId()))); + + Assert.assertEquals(1, counter.get()); + } + private static SQSEvent.SQSMessage newMessage() { try { Constructor ctor = SQSEvent.SQSMessage.class.getDeclaredConstructor(); From f0364936560ee971608462e6dae3ab0c1fbbec61 Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Thu, 1 Jun 2023 08:53:42 -0700 Subject: [PATCH 17/47] Running spotless --- .../messagehandler/SqsBatchMessageHandlerTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java b/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java index 40f9de75b74c..cdfcb8a4f96e 100644 --- a/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java +++ b/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java @@ -395,7 +395,7 @@ protected void doHandleMessages(Collection messages) { try (Scope scope = parentSpan.makeCurrent()) { messageHandler.handleMessages(Collections.singletonList(sqsMessage)); } - }); + }); parentSpan.end(); From 6874ab7aa2dd6ff175888798c536036a1c8e9e82 Mon Sep 17 00:00:00 2001 From: atshaw43 <108552302+atshaw43@users.noreply.github.com> Date: Thu, 1 Jun 2023 10:06:11 -0700 Subject: [PATCH 18/47] Update instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Christian Neumüller --- .../messagehandler/SqsBatchMessageHandler.java | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java index b21e2bb0f0a5..ced6e81f49c1 100644 --- a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java +++ b/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java @@ -47,15 +47,13 @@ public SqsBatchMessageHandler( @Override protected void setup() { - InstrumenterBuilder, Void> builder = - Instrumenter.builder(openTelemetry, "io.opentelemetry.message.handler", spanNameExtractor); - - builder.setInstrumentationVersion("1.0"); - builder.addAttributesExtractor(getGenericAttributesExtractor()); - builder.addAttributesExtractor(getAttributesExtractor()); - builder.addSpanLinksExtractor(getSpanLinksExtractor()); - - messageInstrumenter = builder.buildInstrumenter(); + messageInstrumenter = Instrumenter + .builder(openTelemetry, "io.opentelemetry.message.handler", spanNameExtractor) + .setInstrumentationVersion("1.0") + .addAttributesExtractor(getGenericAttributesExtractor()) + .addAttributesExtractor(getAttributesExtractor()) + .addSpanLinksExtractor(getSpanLinksExtractor()) + .buildInstrumenter(); } protected AttributesExtractor, Void> getAttributesExtractor() { From 9bc18647932c2dc2db9a94e0e9e538729beb48bf Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Thu, 1 Jun 2023 15:58:24 -0700 Subject: [PATCH 19/47] Merging --- ...ntelemetry-instrumentation-annotations.txt | 9 +++++- .../{library => aws}/README.md | 2 +- .../{library => aws}/build.gradle.kts | 4 +-- .../SqsBatchMessageHandler.java | 31 +++++++++---------- .../SqsBatchMessageHandlerTest.java | 31 ++++++++++--------- .../message-handler/core/README.md | 30 ++++++++++++++++++ .../message-handler/core/build.gradle.kts | 9 ++++++ .../messagehandler/BatchMessageHandler.java | 27 +++++++++------- settings.gradle.kts | 3 +- 9 files changed, 99 insertions(+), 47 deletions(-) rename instrumentation/message-handler/{library => aws}/README.md (93%) rename instrumentation/message-handler/{library => aws}/build.gradle.kts (80%) rename instrumentation/message-handler/{library => aws}/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java (81%) rename instrumentation/message-handler/{library => aws}/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java (95%) create mode 100644 instrumentation/message-handler/core/README.md create mode 100644 instrumentation/message-handler/core/build.gradle.kts rename instrumentation/message-handler/{library => core}/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java (79%) diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-instrumentation-annotations.txt b/docs/apidiffs/current_vs_latest/opentelemetry-instrumentation-annotations.txt index df26146497bf..25bc56e08667 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-instrumentation-annotations.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-instrumentation-annotations.txt @@ -1,2 +1,9 @@ Comparing source compatibility of against -No changes. \ No newline at end of file +---! REMOVED ANNOTATION: PUBLIC(-) ABSTRACT(-) io.opentelemetry.instrumentation.annotations.AddingSpanAttributes (not serializable) + --- CLASS FILE FORMAT VERSION: n.a. <- 52.0 + ---! REMOVED INTERFACE: java.lang.annotation.Annotation + ---! REMOVED SUPERCLASS: java.lang.Object + --- REMOVED ANNOTATION: java.lang.annotation.Target + --- REMOVED ELEMENT: value=java.lang.annotation.ElementType.METHOD,java.lang.annotation.ElementType.CONSTRUCTOR (-) + --- REMOVED ANNOTATION: java.lang.annotation.Retention + --- REMOVED ELEMENT: value=java.lang.annotation.RetentionPolicy.RUNTIME (-) diff --git a/instrumentation/message-handler/library/README.md b/instrumentation/message-handler/aws/README.md similarity index 93% rename from instrumentation/message-handler/library/README.md rename to instrumentation/message-handler/aws/README.md index a714beb0b844..2d44d5df5b20 100644 --- a/instrumentation/message-handler/library/README.md +++ b/instrumentation/message-handler/aws/README.md @@ -26,5 +26,5 @@ SqsBatchMessageHandler messageHandler = new SqsBatchMessageHandler(GlobalOpenTel } }; -messageHandler.handleMessages(sqsMessages); +messageHandler.handleMessages(sqsMessages, messages -> "Receiving Messages"); ``` diff --git a/instrumentation/message-handler/library/build.gradle.kts b/instrumentation/message-handler/aws/build.gradle.kts similarity index 80% rename from instrumentation/message-handler/library/build.gradle.kts rename to instrumentation/message-handler/aws/build.gradle.kts index 919c0427719b..185ab191fc09 100644 --- a/instrumentation/message-handler/library/build.gradle.kts +++ b/instrumentation/message-handler/aws/build.gradle.kts @@ -3,10 +3,10 @@ plugins { } dependencies { - api(project(":instrumentation:aws-lambda:aws-lambda-core-1.0:library")) - compileOnly("io.opentelemetry:opentelemetry-sdk") + implementation(project(":instrumentation:message-handler:core")) + library("com.amazonaws:aws-lambda-java-core:1.0.0") library("com.amazonaws:aws-lambda-java-events:2.2.1") diff --git a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java b/instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java similarity index 81% rename from instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java rename to instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java index ced6e81f49c1..6c034dea8f6a 100644 --- a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java +++ b/instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java @@ -14,7 +14,6 @@ import io.opentelemetry.context.propagation.TextMapGetter; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanLinksExtractor; import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; @@ -30,30 +29,28 @@ public abstract class SqsBatchMessageHandler extends BatchMessageHandler> spanNameExtractor) { + super(openTelemetry, spanNameExtractor); } public SqsBatchMessageHandler( OpenTelemetry openTelemetry, - String messageOperation, - SpanNameExtractor> spanNameExtractor) { - super(openTelemetry, messageOperation, spanNameExtractor); + SpanNameExtractor> spanNameExtractor, + String messageOperation) { + super(openTelemetry, spanNameExtractor, messageOperation); } @Override protected void setup() { messageInstrumenter = Instrumenter - .builder(openTelemetry, "io.opentelemetry.message.handler", spanNameExtractor) - .setInstrumentationVersion("1.0") - .addAttributesExtractor(getGenericAttributesExtractor()) - .addAttributesExtractor(getAttributesExtractor()) - .addSpanLinksExtractor(getSpanLinksExtractor()) - .buildInstrumenter(); + ., Void>builder(getOpenTelemetry(), "io.opentelemetry.message.handler", getSpanNameExtractor()) + .setInstrumentationVersion("1.0") + .addAttributesExtractor(getGenericAttributesExtractor()) + .addAttributesExtractor(getAttributesExtractor()) + .addSpanLinksExtractor(getSpanLinksExtractor()) + .buildInstrumenter(); } protected AttributesExtractor, Void> getAttributesExtractor() { @@ -83,7 +80,7 @@ protected SpanLinksExtractor> getSpanLinksExtrac String parentHeader = message.getAttributes().get(AWS_TRACE_HEADER_SQS_ATTRIBUTE_KEY); if (parentHeader != null) { Context xrayContext = - openTelemetry + getOpenTelemetry() .getPropagators() .getTextMapPropagator() .extract( diff --git a/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java b/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java similarity index 95% rename from instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java rename to instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java index cdfcb8a4f96e..c3490f9c34e8 100644 --- a/instrumentation/message-handler/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java +++ b/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java @@ -62,7 +62,7 @@ public void simple() { AtomicInteger counter = new AtomicInteger(0); SqsBatchMessageHandler messageHandler = - new SqsBatchMessageHandler(testing.getOpenTelemetrySdk()) { + new SqsBatchMessageHandler(testing.getOpenTelemetrySdk(), messages -> "Batch of Messages") { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); @@ -83,7 +83,7 @@ protected void doHandleMessages(Collection messages) { trace.hasSpansSatisfyingExactly( span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> - span.hasName("Batch Message") + span.hasName("Batch of Messages") .hasLinks( LinkData.create( SpanContext.createFromRemoteParent( @@ -123,7 +123,7 @@ public void multipleMessages() { AtomicInteger counter = new AtomicInteger(0); SqsBatchMessageHandler messageHandler = - new SqsBatchMessageHandler(testing.getOpenTelemetrySdk()) { + new SqsBatchMessageHandler(testing.getOpenTelemetrySdk(), messages -> "Batch of Messages") { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); @@ -144,7 +144,7 @@ protected void doHandleMessages(Collection messages) { trace.hasSpansSatisfyingExactly( span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> - span.hasName("Batch Message") + span.hasName("Batch of Messages") .hasLinks( LinkData.create( SpanContext.createFromRemoteParent( @@ -186,7 +186,10 @@ public void multipleRunsOfTheHandler() { AtomicInteger counter = new AtomicInteger(0); SqsBatchMessageHandler messageHandler = - new SqsBatchMessageHandler(testing.getOpenTelemetrySdk(), MessageOperation.PROCESS.name()) { + new SqsBatchMessageHandler( + testing.getOpenTelemetrySdk(), + messages -> "Batch of Messages", + MessageOperation.PROCESS.name()) { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); @@ -208,7 +211,7 @@ protected void doHandleMessages(Collection messages) { trace.hasSpansSatisfyingExactly( span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> - span.hasName("Batch Message") + span.hasName("Batch of Messages") .hasLinks( LinkData.create( SpanContext.createFromRemoteParent( @@ -224,7 +227,7 @@ protected void doHandleMessages(Collection messages) { .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) .hasTraceId(parentSpan.getSpanContext().getTraceId()), span -> - span.hasName("Batch Message") + span.hasName("Batch of Messages") .hasLinks( LinkData.create( SpanContext.createFromRemoteParent( @@ -248,7 +251,7 @@ public void noMessages() { AtomicInteger counter = new AtomicInteger(0); SqsBatchMessageHandler messageHandler = - new SqsBatchMessageHandler(testing.getOpenTelemetrySdk()) { + new SqsBatchMessageHandler(testing.getOpenTelemetrySdk(), messages -> "Batch of Messages") { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); @@ -269,7 +272,7 @@ protected void doHandleMessages(Collection messages) { trace.hasSpansSatisfyingExactly( span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> - span.hasName("Batch Message") + span.hasName("Batch of Messages") .hasTotalRecordedLinks(0) .hasAttribute( SemanticAttributes.MESSAGING_OPERATION, MessageOperation.RECEIVE.name()) @@ -295,8 +298,8 @@ public void changeDefaults() { SqsBatchMessageHandler messageHandler = new SqsBatchMessageHandler( testing.getOpenTelemetrySdk(), - MessageOperation.PROCESS.name(), - messages -> "New Name") { + messages -> "New Name", + MessageOperation.PROCESS.name()) { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); @@ -347,7 +350,7 @@ public void invalidUpstreamParent() { AtomicInteger counter = new AtomicInteger(0); SqsBatchMessageHandler messageHandler = - new SqsBatchMessageHandler(testing.getOpenTelemetrySdk()) { + new SqsBatchMessageHandler(testing.getOpenTelemetrySdk(), messages -> "Batch of Messages") { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); @@ -378,7 +381,7 @@ public void exceptionInHandle() { AtomicInteger counter = new AtomicInteger(0); SqsBatchMessageHandler messageHandler = - new SqsBatchMessageHandler(testing.getOpenTelemetrySdk()) { + new SqsBatchMessageHandler(testing.getOpenTelemetrySdk(), messages -> "Batch of Messages") { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); @@ -404,7 +407,7 @@ protected void doHandleMessages(Collection messages) { trace.hasSpansSatisfyingExactly( span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> - span.hasName("Batch Message") + span.hasName("Batch of Messages") .hasLinks( LinkData.create( SpanContext.createFromRemoteParent( diff --git a/instrumentation/message-handler/core/README.md b/instrumentation/message-handler/core/README.md new file mode 100644 index 000000000000..2d44d5df5b20 --- /dev/null +++ b/instrumentation/message-handler/core/README.md @@ -0,0 +1,30 @@ +# Message Handler + +This package contains handlers to instrument message system spans for a batch of messages. It is not designed for a for-loop case. + +The handler will create a single new messaging span, add span links to it, and set the messaging attributes behind the scene. These values are based off of the messages passed in. + +The handler provides constructors to change the messaging operation and span name of the newly created messaging span. + +## Available Handlers +- `SQSBatchMessageHandler` - processes messages from Amazon's SQS. + +## Using SQSBatchMessageHandler + +1. Retrieve a collection of messages to process. +2. Create a SQSBatchMessageHandler and provide the business logic on what to do with the messages. +3. Call the handleMessages function and pass in your messages. +4. It will call the doHandleMessages function you provided wrapped in the messaging span. + +```java +Collection sqsMessages; + +SqsBatchMessageHandler messageHandler = new SqsBatchMessageHandler(GlobalOpenTelemetry.get()) { + @Override + protected void doHandleMessages(Collection messages) { + // Do my business logic + } +}; + +messageHandler.handleMessages(sqsMessages, messages -> "Receiving Messages"); +``` diff --git a/instrumentation/message-handler/core/build.gradle.kts b/instrumentation/message-handler/core/build.gradle.kts new file mode 100644 index 000000000000..79b8946e52f7 --- /dev/null +++ b/instrumentation/message-handler/core/build.gradle.kts @@ -0,0 +1,9 @@ +plugins { + id("otel.library-instrumentation") +} + +dependencies { + api(project(":instrumentation:aws-lambda:aws-lambda-core-1.0:library")) + + compileOnly("io.opentelemetry:opentelemetry-sdk") +} diff --git a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java b/instrumentation/message-handler/core/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java similarity index 79% rename from instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java rename to instrumentation/message-handler/core/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java index d84430eed96a..cb8f0179eef1 100644 --- a/instrumentation/message-handler/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java +++ b/instrumentation/message-handler/core/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java @@ -18,24 +18,21 @@ import javax.annotation.Nullable; public abstract class BatchMessageHandler { - protected String messagingOperation; - protected OpenTelemetry openTelemetry; - protected SpanNameExtractor> spanNameExtractor; + private final String messagingOperation; + private final OpenTelemetry openTelemetry; + private final SpanNameExtractor> spanNameExtractor; protected Instrumenter, Void> messageInstrumenter; - public BatchMessageHandler(OpenTelemetry openTelemetry) { - this(openTelemetry, MessageOperation.RECEIVE.name()); - } - - public BatchMessageHandler(OpenTelemetry openTelemetry, String messageOperation) { - this(openTelemetry, messageOperation, messages -> "Batch Message"); + public BatchMessageHandler( + OpenTelemetry openTelemetry, SpanNameExtractor> spanNameExtractor) { + this(openTelemetry, spanNameExtractor, MessageOperation.RECEIVE.name()); } public BatchMessageHandler( OpenTelemetry openTelemetry, - String messageOperation, - SpanNameExtractor> spanNameExtractor) { + SpanNameExtractor> spanNameExtractor, + String messageOperation) { this.openTelemetry = openTelemetry; this.spanNameExtractor = spanNameExtractor; this.messagingOperation = messageOperation; @@ -43,6 +40,14 @@ public BatchMessageHandler( setup(); } + protected OpenTelemetry getOpenTelemetry() { + return openTelemetry; + } + + protected SpanNameExtractor> getSpanNameExtractor() { + return spanNameExtractor; + } + protected abstract void setup(); protected abstract void doHandleMessages(Collection messages); diff --git a/settings.gradle.kts b/settings.gradle.kts index 35c77675bf08..59e5868b177b 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -356,7 +356,8 @@ hideFromDependabot(":instrumentation:logback:logback-mdc-1.0:javaagent") hideFromDependabot(":instrumentation:logback:logback-mdc-1.0:library") hideFromDependabot(":instrumentation:logback:logback-mdc-1.0:testing") hideFromDependabot(":instrumentation:methods:javaagent") -hideFromDependabot(":instrumentation:message-handler:library") +hideFromDependabot(":instrumentation:message-handler:aws:testing") +hideFromDependabot(":instrumentation:message-handler:core:testing") hideFromDependabot(":instrumentation:micrometer:micrometer-1.5:javaagent") hideFromDependabot(":instrumentation:micrometer:micrometer-1.5:library") hideFromDependabot(":instrumentation:micrometer:micrometer-1.5:testing") From af3ce0fcc4d5d68fa999ec8b4486c90fb17e3fe7 Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Thu, 1 Jun 2023 16:05:58 -0700 Subject: [PATCH 20/47] Running spotlessapply --- .../messagehandler/SqsBatchMessageHandler.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java b/instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java index 6c034dea8f6a..b3dd00988081 100644 --- a/instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java +++ b/instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java @@ -44,13 +44,14 @@ public SqsBatchMessageHandler( @Override protected void setup() { - messageInstrumenter = Instrumenter - ., Void>builder(getOpenTelemetry(), "io.opentelemetry.message.handler", getSpanNameExtractor()) - .setInstrumentationVersion("1.0") - .addAttributesExtractor(getGenericAttributesExtractor()) - .addAttributesExtractor(getAttributesExtractor()) - .addSpanLinksExtractor(getSpanLinksExtractor()) - .buildInstrumenter(); + messageInstrumenter = + Instrumenter., Void>builder( + getOpenTelemetry(), "io.opentelemetry.message.handler", getSpanNameExtractor()) + .setInstrumentationVersion("1.0") + .addAttributesExtractor(getGenericAttributesExtractor()) + .addAttributesExtractor(getAttributesExtractor()) + .addSpanLinksExtractor(getSpanLinksExtractor()) + .buildInstrumenter(); } protected AttributesExtractor, Void> getAttributesExtractor() { From 3b625c41c9b707584dd2c6209d9846c73d99c6fd Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Fri, 2 Jun 2023 10:24:31 -0700 Subject: [PATCH 21/47] Changing to AWS SDK SQS message object --- .../message-handler/aws/build.gradle.kts | 3 +- .../SqsBatchMessageHandler.java | 28 ++-- .../SqsBatchMessageHandlerTest.java | 156 ++++++++++-------- .../message-handler/core/build.gradle.kts | 2 - 4 files changed, 105 insertions(+), 84 deletions(-) diff --git a/instrumentation/message-handler/aws/build.gradle.kts b/instrumentation/message-handler/aws/build.gradle.kts index 185ab191fc09..5a424a9bbbce 100644 --- a/instrumentation/message-handler/aws/build.gradle.kts +++ b/instrumentation/message-handler/aws/build.gradle.kts @@ -7,8 +7,7 @@ dependencies { implementation(project(":instrumentation:message-handler:core")) - library("com.amazonaws:aws-lambda-java-core:1.0.0") - library("com.amazonaws:aws-lambda-java-events:2.2.1") + library("software.amazon.awssdk:sqs:2.2.0") implementation("io.opentelemetry.contrib:opentelemetry-aws-xray-propagator") } diff --git a/instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java b/instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java index b3dd00988081..2f1104883b41 100644 --- a/instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java +++ b/instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java @@ -5,7 +5,6 @@ package io.opentelemetry.instrumentation.messagehandler; -import com.amazonaws.services.lambda.runtime.events.SQSEvent; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.api.trace.Span; @@ -22,22 +21,22 @@ import java.util.Locale; import java.util.Map; import javax.annotation.Nullable; +import software.amazon.awssdk.services.sqs.model.Message; -public abstract class SqsBatchMessageHandler extends BatchMessageHandler { +public abstract class SqsBatchMessageHandler extends BatchMessageHandler { private static final String AWS_TRACE_HEADER_SQS_ATTRIBUTE_KEY = "AWSTraceHeader"; // lower-case map getter used for extraction static final String AWS_TRACE_HEADER_PROPAGATOR_KEY = "x-amzn-trace-id"; public SqsBatchMessageHandler( - OpenTelemetry openTelemetry, - SpanNameExtractor> spanNameExtractor) { + OpenTelemetry openTelemetry, SpanNameExtractor> spanNameExtractor) { super(openTelemetry, spanNameExtractor); } public SqsBatchMessageHandler( OpenTelemetry openTelemetry, - SpanNameExtractor> spanNameExtractor, + SpanNameExtractor> spanNameExtractor, String messageOperation) { super(openTelemetry, spanNameExtractor, messageOperation); } @@ -45,7 +44,7 @@ public SqsBatchMessageHandler( @Override protected void setup() { messageInstrumenter = - Instrumenter., Void>builder( + Instrumenter., Void>builder( getOpenTelemetry(), "io.opentelemetry.message.handler", getSpanNameExtractor()) .setInstrumentationVersion("1.0") .addAttributesExtractor(getGenericAttributesExtractor()) @@ -54,14 +53,12 @@ protected void setup() { .buildInstrumenter(); } - protected AttributesExtractor, Void> getAttributesExtractor() { - return new AttributesExtractor, Void>() { + protected AttributesExtractor, Void> getAttributesExtractor() { + return new AttributesExtractor, Void>() { @Override public void onStart( - AttributesBuilder attributes, - Context parentContext, - Collection messages) { + AttributesBuilder attributes, Context parentContext, Collection messages) { attributes.put(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS"); } @@ -69,16 +66,17 @@ public void onStart( public void onEnd( AttributesBuilder attributes, Context context, - Collection messages, + Collection messages, @Nullable Void unused, @Nullable Throwable error) {} }; } - protected SpanLinksExtractor> getSpanLinksExtractor() { + protected SpanLinksExtractor> getSpanLinksExtractor() { return (spanLinks, parentContext, sqsMessages) -> { - for (SQSEvent.SQSMessage message : sqsMessages) { - String parentHeader = message.getAttributes().get(AWS_TRACE_HEADER_SQS_ATTRIBUTE_KEY); + for (Message message : sqsMessages) { + String parentHeader = + message.messageAttributes().get(AWS_TRACE_HEADER_SQS_ATTRIBUTE_KEY).stringValue(); if (parentHeader != null) { Context xrayContext = getOpenTelemetry() diff --git a/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java b/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java index c3490f9c34e8..ffbc5ada9aca 100644 --- a/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java +++ b/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java @@ -7,7 +7,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows; -import com.amazonaws.services.lambda.runtime.events.SQSEvent; import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.SpanContext; import io.opentelemetry.api.trace.TraceFlags; @@ -21,7 +20,6 @@ import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.trace.data.LinkData; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; -import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.util.Collection; import java.util.Collections; @@ -31,6 +29,8 @@ import org.junit.Assert; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; +import software.amazon.awssdk.services.sqs.model.Message; +import software.amazon.awssdk.services.sqs.model.MessageAttributeValue; public class SqsBatchMessageHandlerTest { @@ -52,19 +52,23 @@ public class SqsBatchMessageHandlerTest { @Test public void simple() { - SQSEvent.SQSMessage sqsMessage = newMessage(); - - sqsMessage.setAttributes( - Collections.singletonMap( - "AWSTraceHeader", - "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")); + Message sqsMessage = + Message.builder() + .messageAttributes( + Collections.singletonMap( + "AWSTraceHeader", + MessageAttributeValue.builder() + .stringValue( + "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1") + .build())) + .build(); AtomicInteger counter = new AtomicInteger(0); SqsBatchMessageHandler messageHandler = new SqsBatchMessageHandler(testing.getOpenTelemetrySdk(), messages -> "Batch of Messages") { @Override - protected void doHandleMessages(Collection messages) { + protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); } }; @@ -104,20 +108,30 @@ protected void doHandleMessages(Collection messages) { @Test public void multipleMessages() { - List sqsMessages = new LinkedList<>(); - - SQSEvent.SQSMessage sqsMessage1 = newMessage(); - sqsMessage1.setAttributes( - Collections.singletonMap( - "AWSTraceHeader", - "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")); + List sqsMessages = new LinkedList<>(); + + Message sqsMessage1 = + Message.builder() + .messageAttributes( + Collections.singletonMap( + "AWSTraceHeader", + MessageAttributeValue.builder() + .stringValue( + "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1") + .build())) + .build(); sqsMessages.add(sqsMessage1); - SQSEvent.SQSMessage sqsMessage2 = newMessage(); - sqsMessage2.setAttributes( - Collections.singletonMap( - "AWSTraceHeader", - "Root=1-44444444-123456789012345678901234;Parent=2481624816248161;Sampled=0")); + Message sqsMessage2 = + Message.builder() + .messageAttributes( + Collections.singletonMap( + "AWSTraceHeader", + MessageAttributeValue.builder() + .stringValue( + "Root=1-44444444-123456789012345678901234;Parent=2481624816248161;Sampled=0") + .build())) + .build(); sqsMessages.add(sqsMessage2); AtomicInteger counter = new AtomicInteger(0); @@ -125,7 +139,7 @@ public void multipleMessages() { SqsBatchMessageHandler messageHandler = new SqsBatchMessageHandler(testing.getOpenTelemetrySdk(), messages -> "Batch of Messages") { @Override - protected void doHandleMessages(Collection messages) { + protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); } }; @@ -171,17 +185,27 @@ protected void doHandleMessages(Collection messages) { @Test public void multipleRunsOfTheHandler() { - SQSEvent.SQSMessage sqsMessage1 = newMessage(); - sqsMessage1.setAttributes( - Collections.singletonMap( - "AWSTraceHeader", - "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")); - - SQSEvent.SQSMessage sqsMessage2 = newMessage(); - sqsMessage2.setAttributes( - Collections.singletonMap( - "AWSTraceHeader", - "Root=1-44444444-123456789012345678901234;Parent=2481624816248161;Sampled=0")); + Message sqsMessage1 = + Message.builder() + .messageAttributes( + Collections.singletonMap( + "AWSTraceHeader", + MessageAttributeValue.builder() + .stringValue( + "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1") + .build())) + .build(); + + Message sqsMessage2 = + Message.builder() + .messageAttributes( + Collections.singletonMap( + "AWSTraceHeader", + MessageAttributeValue.builder() + .stringValue( + "Root=1-44444444-123456789012345678901234;Parent=2481624816248161;Sampled=0") + .build())) + .build(); AtomicInteger counter = new AtomicInteger(0); @@ -191,7 +215,7 @@ public void multipleRunsOfTheHandler() { messages -> "Batch of Messages", MessageOperation.PROCESS.name()) { @Override - protected void doHandleMessages(Collection messages) { + protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); } }; @@ -253,7 +277,7 @@ public void noMessages() { SqsBatchMessageHandler messageHandler = new SqsBatchMessageHandler(testing.getOpenTelemetrySdk(), messages -> "Batch of Messages") { @Override - protected void doHandleMessages(Collection messages) { + protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); } }; @@ -286,12 +310,16 @@ protected void doHandleMessages(Collection messages) { @Test public void changeDefaults() { - SQSEvent.SQSMessage sqsMessage = newMessage(); - - sqsMessage.setAttributes( - Collections.singletonMap( - "AWSTraceHeader", - "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")); + Message sqsMessage = + Message.builder() + .messageAttributes( + Collections.singletonMap( + "AWSTraceHeader", + MessageAttributeValue.builder() + .stringValue( + "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1") + .build())) + .build(); AtomicInteger counter = new AtomicInteger(0); @@ -301,7 +329,7 @@ public void changeDefaults() { messages -> "New Name", MessageOperation.PROCESS.name()) { @Override - protected void doHandleMessages(Collection messages) { + protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); } }; @@ -341,18 +369,22 @@ protected void doHandleMessages(Collection messages) { @Test public void invalidUpstreamParent() { - SQSEvent.SQSMessage sqsMessage = newMessage(); - - sqsMessage.setAttributes( - Collections.singletonMap( - "AWSTraceHeader", "Root=1-55555555-invalid;Parent=1234567890123456;Sampled=1")); + Message sqsMessage = + Message.builder() + .messageAttributes( + Collections.singletonMap( + "AWSTraceHeader", + MessageAttributeValue.builder() + .stringValue("Root=1-55555555-invalid;Parent=1234567890123456;Sampled=1") + .build())) + .build(); AtomicInteger counter = new AtomicInteger(0); SqsBatchMessageHandler messageHandler = new SqsBatchMessageHandler(testing.getOpenTelemetrySdk(), messages -> "Batch of Messages") { @Override - protected void doHandleMessages(Collection messages) { + protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); } }; @@ -371,19 +403,23 @@ protected void doHandleMessages(Collection messages) { @Test public void exceptionInHandle() { - SQSEvent.SQSMessage sqsMessage = newMessage(); - - sqsMessage.setAttributes( - Collections.singletonMap( - "AWSTraceHeader", - "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")); + Message sqsMessage = + Message.builder() + .messageAttributes( + Collections.singletonMap( + "AWSTraceHeader", + MessageAttributeValue.builder() + .stringValue( + "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1") + .build())) + .build(); AtomicInteger counter = new AtomicInteger(0); SqsBatchMessageHandler messageHandler = new SqsBatchMessageHandler(testing.getOpenTelemetrySdk(), messages -> "Batch of Messages") { @Override - protected void doHandleMessages(Collection messages) { + protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); throw new RuntimeException("Injected Error"); } @@ -426,14 +462,4 @@ protected void doHandleMessages(Collection messages) { Assert.assertEquals(1, counter.get()); } - - private static SQSEvent.SQSMessage newMessage() { - try { - Constructor ctor = SQSEvent.SQSMessage.class.getDeclaredConstructor(); - ctor.setAccessible(true); - return ctor.newInstance(); - } catch (Throwable t) { - throw new AssertionError(t); - } - } } diff --git a/instrumentation/message-handler/core/build.gradle.kts b/instrumentation/message-handler/core/build.gradle.kts index 79b8946e52f7..c4d2f680d869 100644 --- a/instrumentation/message-handler/core/build.gradle.kts +++ b/instrumentation/message-handler/core/build.gradle.kts @@ -3,7 +3,5 @@ plugins { } dependencies { - api(project(":instrumentation:aws-lambda:aws-lambda-core-1.0:library")) - compileOnly("io.opentelemetry:opentelemetry-sdk") } From f9433b1376d0f066656ca1679969a235bb9fba9d Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Fri, 2 Jun 2023 13:07:32 -0700 Subject: [PATCH 22/47] Fixing annotations file --- .../opentelemetry-instrumentation-annotations.txt | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-instrumentation-annotations.txt b/docs/apidiffs/current_vs_latest/opentelemetry-instrumentation-annotations.txt index 25bc56e08667..a00ba337a61a 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-instrumentation-annotations.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-instrumentation-annotations.txt @@ -1,9 +1,2 @@ Comparing source compatibility of against ----! REMOVED ANNOTATION: PUBLIC(-) ABSTRACT(-) io.opentelemetry.instrumentation.annotations.AddingSpanAttributes (not serializable) - --- CLASS FILE FORMAT VERSION: n.a. <- 52.0 - ---! REMOVED INTERFACE: java.lang.annotation.Annotation - ---! REMOVED SUPERCLASS: java.lang.Object - --- REMOVED ANNOTATION: java.lang.annotation.Target - --- REMOVED ELEMENT: value=java.lang.annotation.ElementType.METHOD,java.lang.annotation.ElementType.CONSTRUCTOR (-) - --- REMOVED ANNOTATION: java.lang.annotation.Retention - --- REMOVED ELEMENT: value=java.lang.annotation.RetentionPolicy.RUNTIME (-) +No changes. From 149d9b68cac60712ac75c1aadd08c92f50492a8b Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Fri, 2 Jun 2023 13:34:20 -0700 Subject: [PATCH 23/47] Fixing annotations --- .../opentelemetry-instrumentation-annotations.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-instrumentation-annotations.txt b/docs/apidiffs/current_vs_latest/opentelemetry-instrumentation-annotations.txt index a00ba337a61a..df26146497bf 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-instrumentation-annotations.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-instrumentation-annotations.txt @@ -1,2 +1,2 @@ Comparing source compatibility of against -No changes. +No changes. \ No newline at end of file From 1b8273e6d2971ba5105da883eb5f0c542f6adb02 Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Mon, 5 Jun 2023 13:15:38 -0700 Subject: [PATCH 24/47] Adding customer gitter for message atribute values --- .../awssdk/v2_2/SqsMessageAccess.java | 4 +- .../awssdk/v2_2/SqsParentContext.java | 6 +- .../message-handler/aws/build.gradle.kts | 1 + .../SqsBatchMessageHandler.java | 57 ++++----- .../SqsBatchMessageHandlerTest.java | 113 +++++++++--------- 5 files changed, 84 insertions(+), 97 deletions(-) diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageAccess.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageAccess.java index e8925b0a50f8..257011ae5e6d 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageAccess.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageAccess.java @@ -30,7 +30,7 @@ * href="https://github.com/aws/aws-sdk-java-v2/blob/2.2.0/services/sqs/src/main/resources/codegen-resources/service-2.json#L821-L856">Definition * JSON */ -final class SqsMessageAccess { +public final class SqsMessageAccess { @Nullable private static final MethodHandle GET_ATTRIBUTES; @Nullable private static final MethodHandle GET_MESSAGE_ATTRIBUTES; @@ -68,7 +68,7 @@ final class SqsMessageAccess { } @SuppressWarnings("unchecked") - static Map getAttributes(Object message) { + public static Map getAttributes(Object message) { if (GET_ATTRIBUTES == null) { return Collections.emptyMap(); } diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsParentContext.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsParentContext.java index 9df3443c660e..b1c886d190a4 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsParentContext.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsParentContext.java @@ -13,7 +13,7 @@ import java.util.Map; import software.amazon.awssdk.core.SdkPojo; -final class SqsParentContext { +public final class SqsParentContext { enum StringMapGetter implements TextMapGetter> { INSTANCE; @@ -52,13 +52,13 @@ public String get(Map map, String s) { static final String AWS_TRACE_SYSTEM_ATTRIBUTE = "AWSTraceHeader"; - static Context ofMessageAttributes( + static public Context ofMessageAttributes( Map messageAttributes, TextMapPropagator propagator) { return propagator.extract( Context.root(), messageAttributes, MessageAttributeValueMapGetter.INSTANCE); } - static Context ofSystemAttributes(Map systemAttributes) { + public static Context ofSystemAttributes(Map systemAttributes) { String traceHeader = systemAttributes.get(AWS_TRACE_SYSTEM_ATTRIBUTE); return AwsXrayPropagator.getInstance() .extract( diff --git a/instrumentation/message-handler/aws/build.gradle.kts b/instrumentation/message-handler/aws/build.gradle.kts index 5a424a9bbbce..09d8446d0126 100644 --- a/instrumentation/message-handler/aws/build.gradle.kts +++ b/instrumentation/message-handler/aws/build.gradle.kts @@ -6,6 +6,7 @@ dependencies { compileOnly("io.opentelemetry:opentelemetry-sdk") implementation(project(":instrumentation:message-handler:core")) + implementation(project(":instrumentation:aws-sdk:aws-sdk-2.2:library")) library("software.amazon.awssdk:sqs:2.2.0") diff --git a/instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java b/instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java index 2f1104883b41..5d16d5e1ee2a 100644 --- a/instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java +++ b/instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java @@ -10,25 +10,21 @@ import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.SpanContext; import io.opentelemetry.context.Context; -import io.opentelemetry.context.propagation.TextMapGetter; +import io.opentelemetry.context.propagation.TextMapPropagator; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.api.instrumenter.SpanLinksExtractor; import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; +import io.opentelemetry.instrumentation.awssdk.v2_2.SqsMessageAccess; +import io.opentelemetry.instrumentation.awssdk.v2_2.SqsParentContext; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; import java.util.Collection; -import java.util.Collections; -import java.util.Locale; import java.util.Map; import javax.annotation.Nullable; +import software.amazon.awssdk.core.SdkPojo; import software.amazon.awssdk.services.sqs.model.Message; public abstract class SqsBatchMessageHandler extends BatchMessageHandler { - private static final String AWS_TRACE_HEADER_SQS_ATTRIBUTE_KEY = "AWSTraceHeader"; - - // lower-case map getter used for extraction - static final String AWS_TRACE_HEADER_PROPAGATOR_KEY = "x-amzn-trace-id"; - public SqsBatchMessageHandler( OpenTelemetry openTelemetry, SpanNameExtractor> spanNameExtractor) { super(openTelemetry, spanNameExtractor); @@ -73,39 +69,26 @@ public void onEnd( } protected SpanLinksExtractor> getSpanLinksExtractor() { + TextMapPropagator messagingPropagator = getOpenTelemetry() + .getPropagators() + .getTextMapPropagator(); + return (spanLinks, parentContext, sqsMessages) -> { for (Message message : sqsMessages) { - String parentHeader = - message.messageAttributes().get(AWS_TRACE_HEADER_SQS_ATTRIBUTE_KEY).stringValue(); - if (parentHeader != null) { - Context xrayContext = - getOpenTelemetry() - .getPropagators() - .getTextMapPropagator() - .extract( - Context.root(), // We don't want the ambient context. - Collections.singletonMap(AWS_TRACE_HEADER_PROPAGATOR_KEY, parentHeader), - MapGetter.INSTANCE); - SpanContext messageSpanCtx = Span.fromContext(xrayContext).getSpanContext(); - if (messageSpanCtx.isValid()) { - spanLinks.addLink(messageSpanCtx); - } - } - } - }; - } + Map messageAtributes = SqsMessageAccess.getMessageAttributes(message); + + Context context = SqsParentContext.ofMessageAttributes(messageAtributes, messagingPropagator); - private enum MapGetter implements TextMapGetter> { - INSTANCE; + if (context == Context.root()) { + context = SqsParentContext.ofSystemAttributes(SqsMessageAccess.getAttributes(message)); + } - @Override - public Iterable keys(Map map) { - return map.keySet(); - } + SpanContext messageSpanCtx = Span.fromContext(context).getSpanContext(); - @Override - public String get(Map map, String s) { - return map.get(s.toLowerCase(Locale.ROOT)); - } + if (messageSpanCtx.isValid()) { + spanLinks.addLink(messageSpanCtx); + } + } + }; } } diff --git a/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java b/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java index ffbc5ada9aca..beba520b837b 100644 --- a/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java +++ b/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java @@ -54,13 +54,7 @@ public class SqsBatchMessageHandlerTest { public void simple() { Message sqsMessage = Message.builder() - .messageAttributes( - Collections.singletonMap( - "AWSTraceHeader", - MessageAttributeValue.builder() - .stringValue( - "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1") - .build())) + .attributesWithStrings(Collections.singletonMap("AWSTraceHeader", "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")) .build(); AtomicInteger counter = new AtomicInteger(0); @@ -106,31 +100,69 @@ protected void doHandleMessages(Collection messages) { Assert.assertEquals(1, counter.get()); } + @Test + public void simpleMessage() { + Message sqsMessage = + Message.builder() + .messageAttributes(Collections.singletonMap("X-Amzn-Trace-Id", MessageAttributeValue.builder().stringValue("Root=1-66555555-123456789012345678901234;Parent=2234567890123456;Sampled=1").build())) + .build(); + + AtomicInteger counter = new AtomicInteger(0); + + SqsBatchMessageHandler messageHandler = + new SqsBatchMessageHandler(testing.getOpenTelemetrySdk(), messages -> "Batch of Messages") { + @Override + protected void doHandleMessages(Collection messages) { + counter.getAndIncrement(); + } + }; + + Span parentSpan = + testing.getOpenTelemetrySdk().getTracer("test").spanBuilder("test").startSpan(); + + try (Scope scope = parentSpan.makeCurrent()) { + messageHandler.handleMessages(Collections.singletonList(sqsMessage)); + } + + parentSpan.end(); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), + span -> + span.hasName("Batch of Messages") + .hasLinks( + LinkData.create( + SpanContext.createFromRemoteParent( + "66555555123456789012345678901234", + "2234567890123456", + TraceFlags.getSampled(), + TraceState.getDefault()))) + .hasTotalRecordedLinks(1) + .hasAttribute( + SemanticAttributes.MESSAGING_OPERATION, MessageOperation.RECEIVE.name()) + .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") + .hasTotalAttributeCount(2) + .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) + .hasTraceId(parentSpan.getSpanContext().getTraceId()))); + + Assert.assertEquals(1, counter.get()); + } + @Test public void multipleMessages() { List sqsMessages = new LinkedList<>(); Message sqsMessage1 = Message.builder() - .messageAttributes( - Collections.singletonMap( - "AWSTraceHeader", - MessageAttributeValue.builder() - .stringValue( - "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1") - .build())) + .attributesWithStrings(Collections.singletonMap("AWSTraceHeader", "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")) .build(); sqsMessages.add(sqsMessage1); Message sqsMessage2 = Message.builder() - .messageAttributes( - Collections.singletonMap( - "AWSTraceHeader", - MessageAttributeValue.builder() - .stringValue( - "Root=1-44444444-123456789012345678901234;Parent=2481624816248161;Sampled=0") - .build())) + .attributesWithStrings(Collections.singletonMap("AWSTraceHeader", "Root=1-44444444-123456789012345678901234;Parent=2481624816248161;Sampled=0")) .build(); sqsMessages.add(sqsMessage2); @@ -187,24 +219,12 @@ protected void doHandleMessages(Collection messages) { public void multipleRunsOfTheHandler() { Message sqsMessage1 = Message.builder() - .messageAttributes( - Collections.singletonMap( - "AWSTraceHeader", - MessageAttributeValue.builder() - .stringValue( - "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1") - .build())) + .attributesWithStrings(Collections.singletonMap("AWSTraceHeader", "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")) .build(); Message sqsMessage2 = Message.builder() - .messageAttributes( - Collections.singletonMap( - "AWSTraceHeader", - MessageAttributeValue.builder() - .stringValue( - "Root=1-44444444-123456789012345678901234;Parent=2481624816248161;Sampled=0") - .build())) + .attributesWithStrings(Collections.singletonMap("AWSTraceHeader", "Root=1-44444444-123456789012345678901234;Parent=2481624816248161;Sampled=0")) .build(); AtomicInteger counter = new AtomicInteger(0); @@ -312,13 +332,7 @@ protected void doHandleMessages(Collection messages) { public void changeDefaults() { Message sqsMessage = Message.builder() - .messageAttributes( - Collections.singletonMap( - "AWSTraceHeader", - MessageAttributeValue.builder() - .stringValue( - "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1") - .build())) + .attributesWithStrings(Collections.singletonMap("AWSTraceHeader", "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")) .build(); AtomicInteger counter = new AtomicInteger(0); @@ -371,12 +385,7 @@ protected void doHandleMessages(Collection messages) { public void invalidUpstreamParent() { Message sqsMessage = Message.builder() - .messageAttributes( - Collections.singletonMap( - "AWSTraceHeader", - MessageAttributeValue.builder() - .stringValue("Root=1-55555555-invalid;Parent=1234567890123456;Sampled=1") - .build())) + .attributesWithStrings(Collections.singletonMap("AWSTraceHeader", "Root=1-55555555-invalid;Parent=1234567890123456;Sampled=1")) .build(); AtomicInteger counter = new AtomicInteger(0); @@ -405,13 +414,7 @@ protected void doHandleMessages(Collection messages) { public void exceptionInHandle() { Message sqsMessage = Message.builder() - .messageAttributes( - Collections.singletonMap( - "AWSTraceHeader", - MessageAttributeValue.builder() - .stringValue( - "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1") - .build())) + .attributesWithStrings(Collections.singletonMap("AWSTraceHeader", "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")) .build(); AtomicInteger counter = new AtomicInteger(0); From 9a469974ad2307c521805478f7bd37df284f5415 Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Mon, 5 Jun 2023 13:20:49 -0700 Subject: [PATCH 25/47] Applying spotless --- .../awssdk/v2_2/SqsParentContext.java | 2 +- .../SqsBatchMessageHandler.java | 8 ++-- .../SqsBatchMessageHandlerTest.java | 47 +++++++++++++++---- 3 files changed, 43 insertions(+), 14 deletions(-) diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsParentContext.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsParentContext.java index b1c886d190a4..3b914b7744ec 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsParentContext.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsParentContext.java @@ -52,7 +52,7 @@ public String get(Map map, String s) { static final String AWS_TRACE_SYSTEM_ATTRIBUTE = "AWSTraceHeader"; - static public Context ofMessageAttributes( + public static Context ofMessageAttributes( Map messageAttributes, TextMapPropagator propagator) { return propagator.extract( Context.root(), messageAttributes, MessageAttributeValueMapGetter.INSTANCE); diff --git a/instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java b/instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java index 5d16d5e1ee2a..96e7b3677a63 100644 --- a/instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java +++ b/instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java @@ -69,15 +69,15 @@ public void onEnd( } protected SpanLinksExtractor> getSpanLinksExtractor() { - TextMapPropagator messagingPropagator = getOpenTelemetry() - .getPropagators() - .getTextMapPropagator(); + TextMapPropagator messagingPropagator = + getOpenTelemetry().getPropagators().getTextMapPropagator(); return (spanLinks, parentContext, sqsMessages) -> { for (Message message : sqsMessages) { Map messageAtributes = SqsMessageAccess.getMessageAttributes(message); - Context context = SqsParentContext.ofMessageAttributes(messageAtributes, messagingPropagator); + Context context = + SqsParentContext.ofMessageAttributes(messageAtributes, messagingPropagator); if (context == Context.root()) { context = SqsParentContext.ofSystemAttributes(SqsMessageAccess.getAttributes(message)); diff --git a/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java b/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java index beba520b837b..6576a93899bf 100644 --- a/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java +++ b/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java @@ -54,7 +54,10 @@ public class SqsBatchMessageHandlerTest { public void simple() { Message sqsMessage = Message.builder() - .attributesWithStrings(Collections.singletonMap("AWSTraceHeader", "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")) + .attributesWithStrings( + Collections.singletonMap( + "AWSTraceHeader", + "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")) .build(); AtomicInteger counter = new AtomicInteger(0); @@ -104,7 +107,13 @@ protected void doHandleMessages(Collection messages) { public void simpleMessage() { Message sqsMessage = Message.builder() - .messageAttributes(Collections.singletonMap("X-Amzn-Trace-Id", MessageAttributeValue.builder().stringValue("Root=1-66555555-123456789012345678901234;Parent=2234567890123456;Sampled=1").build())) + .messageAttributes( + Collections.singletonMap( + "X-Amzn-Trace-Id", + MessageAttributeValue.builder() + .stringValue( + "Root=1-66555555-123456789012345678901234;Parent=2234567890123456;Sampled=1") + .build())) .build(); AtomicInteger counter = new AtomicInteger(0); @@ -156,13 +165,19 @@ public void multipleMessages() { Message sqsMessage1 = Message.builder() - .attributesWithStrings(Collections.singletonMap("AWSTraceHeader", "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")) + .attributesWithStrings( + Collections.singletonMap( + "AWSTraceHeader", + "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")) .build(); sqsMessages.add(sqsMessage1); Message sqsMessage2 = Message.builder() - .attributesWithStrings(Collections.singletonMap("AWSTraceHeader", "Root=1-44444444-123456789012345678901234;Parent=2481624816248161;Sampled=0")) + .attributesWithStrings( + Collections.singletonMap( + "AWSTraceHeader", + "Root=1-44444444-123456789012345678901234;Parent=2481624816248161;Sampled=0")) .build(); sqsMessages.add(sqsMessage2); @@ -219,12 +234,18 @@ protected void doHandleMessages(Collection messages) { public void multipleRunsOfTheHandler() { Message sqsMessage1 = Message.builder() - .attributesWithStrings(Collections.singletonMap("AWSTraceHeader", "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")) + .attributesWithStrings( + Collections.singletonMap( + "AWSTraceHeader", + "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")) .build(); Message sqsMessage2 = Message.builder() - .attributesWithStrings(Collections.singletonMap("AWSTraceHeader", "Root=1-44444444-123456789012345678901234;Parent=2481624816248161;Sampled=0")) + .attributesWithStrings( + Collections.singletonMap( + "AWSTraceHeader", + "Root=1-44444444-123456789012345678901234;Parent=2481624816248161;Sampled=0")) .build(); AtomicInteger counter = new AtomicInteger(0); @@ -332,7 +353,10 @@ protected void doHandleMessages(Collection messages) { public void changeDefaults() { Message sqsMessage = Message.builder() - .attributesWithStrings(Collections.singletonMap("AWSTraceHeader", "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")) + .attributesWithStrings( + Collections.singletonMap( + "AWSTraceHeader", + "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")) .build(); AtomicInteger counter = new AtomicInteger(0); @@ -385,7 +409,9 @@ protected void doHandleMessages(Collection messages) { public void invalidUpstreamParent() { Message sqsMessage = Message.builder() - .attributesWithStrings(Collections.singletonMap("AWSTraceHeader", "Root=1-55555555-invalid;Parent=1234567890123456;Sampled=1")) + .attributesWithStrings( + Collections.singletonMap( + "AWSTraceHeader", "Root=1-55555555-invalid;Parent=1234567890123456;Sampled=1")) .build(); AtomicInteger counter = new AtomicInteger(0); @@ -414,7 +440,10 @@ protected void doHandleMessages(Collection messages) { public void exceptionInHandle() { Message sqsMessage = Message.builder() - .attributesWithStrings(Collections.singletonMap("AWSTraceHeader", "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")) + .attributesWithStrings( + Collections.singletonMap( + "AWSTraceHeader", + "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")) .build(); AtomicInteger counter = new AtomicInteger(0); From 1b14ab3e282f4b06a5499cdc5a155e34c01bca51 Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Wed, 7 Jun 2023 12:39:25 -0700 Subject: [PATCH 26/47] Addresing PR --- instrumentation/message-handler/aws/README.md | 17 +-- ...ageHandler.java => SqsMessageHandler.java} | 33 +++++- ...erTest.java => SqsMessageHandlerTest.java} | 109 ++++++++++++++---- .../message-handler/core/README.md | 22 +--- ...essageHandler.java => MessageHandler.java} | 18 +-- 5 files changed, 129 insertions(+), 70 deletions(-) rename instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/{SqsBatchMessageHandler.java => SqsMessageHandler.java} (73%) rename instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/{SqsBatchMessageHandlerTest.java => SqsMessageHandlerTest.java} (82%) rename instrumentation/message-handler/core/src/main/java/io/opentelemetry/instrumentation/messagehandler/{BatchMessageHandler.java => MessageHandler.java} (90%) diff --git a/instrumentation/message-handler/aws/README.md b/instrumentation/message-handler/aws/README.md index 2d44d5df5b20..6fbe37319eb6 100644 --- a/instrumentation/message-handler/aws/README.md +++ b/instrumentation/message-handler/aws/README.md @@ -1,25 +1,14 @@ -# Message Handler - -This package contains handlers to instrument message system spans for a batch of messages. It is not designed for a for-loop case. - -The handler will create a single new messaging span, add span links to it, and set the messaging attributes behind the scene. These values are based off of the messages passed in. - -The handler provides constructors to change the messaging operation and span name of the newly created messaging span. - -## Available Handlers -- `SQSBatchMessageHandler` - processes messages from Amazon's SQS. - -## Using SQSBatchMessageHandler +# Using SqsMessageHandler 1. Retrieve a collection of messages to process. -2. Create a SQSBatchMessageHandler and provide the business logic on what to do with the messages. +2. Create a SqsMessageHandler and provide the business logic on what to do with the messages. 3. Call the handleMessages function and pass in your messages. 4. It will call the doHandleMessages function you provided wrapped in the messaging span. ```java Collection sqsMessages; -SqsBatchMessageHandler messageHandler = new SqsBatchMessageHandler(GlobalOpenTelemetry.get()) { +SqsMessageHandler messageHandler = new SqsMessageHandler(opentelemetry) { @Override protected void doHandleMessages(Collection messages) { // Do my business logic diff --git a/instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java b/instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandler.java similarity index 73% rename from instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java rename to instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandler.java index 96e7b3677a63..88f7e0e54400 100644 --- a/instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandler.java +++ b/instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandler.java @@ -13,27 +13,34 @@ import io.opentelemetry.context.propagation.TextMapPropagator; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; import io.opentelemetry.instrumentation.api.instrumenter.SpanLinksExtractor; import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessageOperation; import io.opentelemetry.instrumentation.awssdk.v2_2.SqsMessageAccess; import io.opentelemetry.instrumentation.awssdk.v2_2.SqsParentContext; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; import java.util.Collection; import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; import javax.annotation.Nullable; import software.amazon.awssdk.core.SdkPojo; import software.amazon.awssdk.services.sqs.model.Message; -public abstract class SqsBatchMessageHandler extends BatchMessageHandler { - public SqsBatchMessageHandler( +public abstract class SqsMessageHandler extends MessageHandler { + private static final Logger logger = + Logger.getLogger(SqsMessageHandler.class.getName()); + + public SqsMessageHandler( OpenTelemetry openTelemetry, SpanNameExtractor> spanNameExtractor) { super(openTelemetry, spanNameExtractor); } - public SqsBatchMessageHandler( + public SqsMessageHandler( OpenTelemetry openTelemetry, SpanNameExtractor> spanNameExtractor, - String messageOperation) { + MessageOperation messageOperation) { super(openTelemetry, spanNameExtractor, messageOperation); } @@ -41,12 +48,26 @@ public SqsBatchMessageHandler( protected void setup() { messageInstrumenter = Instrumenter., Void>builder( - getOpenTelemetry(), "io.opentelemetry.message.handler", getSpanNameExtractor()) + getOpenTelemetry(), "io.opentelemetry.message-handler", getSpanNameExtractor()) .setInstrumentationVersion("1.0") .addAttributesExtractor(getGenericAttributesExtractor()) .addAttributesExtractor(getAttributesExtractor()) .addSpanLinksExtractor(getSpanLinksExtractor()) - .buildInstrumenter(); + .buildInstrumenter(getSpanKindExtractor()); + } + + protected SpanKindExtractor> getSpanKindExtractor() { + MessageOperation messageOperation = getMessagingOperation(); + + if (messageOperation == MessageOperation.RECEIVE || + messageOperation == MessageOperation.PROCESS) { + return SpanKindExtractor.alwaysConsumer(); + } else if (messageOperation == MessageOperation.SEND) { + return SpanKindExtractor.alwaysProducer(); + } else { + logger.log(Level.WARNING, "Unknown Messaging Operation {0}", new Object[] {messageOperation.name()}); + return SpanKindExtractor.alwaysConsumer(); + } } protected AttributesExtractor, Void> getAttributesExtractor() { diff --git a/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java b/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandlerTest.java similarity index 82% rename from instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java rename to instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandlerTest.java index 6576a93899bf..94c22d08ec2c 100644 --- a/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsBatchMessageHandlerTest.java +++ b/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandlerTest.java @@ -9,6 +9,7 @@ import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.SpanContext; +import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.api.trace.TraceFlags; import io.opentelemetry.api.trace.TraceState; import io.opentelemetry.context.Scope; @@ -32,7 +33,7 @@ import software.amazon.awssdk.services.sqs.model.Message; import software.amazon.awssdk.services.sqs.model.MessageAttributeValue; -public class SqsBatchMessageHandlerTest { +public class SqsMessageHandlerTest { @RegisterExtension private static final InstrumentationExtension testing = LibraryInstrumentationExtension.create(); @@ -62,8 +63,8 @@ public void simple() { AtomicInteger counter = new AtomicInteger(0); - SqsBatchMessageHandler messageHandler = - new SqsBatchMessageHandler(testing.getOpenTelemetrySdk(), messages -> "Batch of Messages") { + SqsMessageHandler messageHandler = + new SqsMessageHandler(testing.getOpenTelemetrySdk(), messages -> "Batch of Messages") { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); @@ -85,6 +86,7 @@ protected void doHandleMessages(Collection messages) { span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> span.hasName("Batch of Messages") + .hasKind(SpanKind.CONSUMER) .hasLinks( LinkData.create( SpanContext.createFromRemoteParent( @@ -118,8 +120,8 @@ public void simpleMessage() { AtomicInteger counter = new AtomicInteger(0); - SqsBatchMessageHandler messageHandler = - new SqsBatchMessageHandler(testing.getOpenTelemetrySdk(), messages -> "Batch of Messages") { + SqsMessageHandler messageHandler = + new SqsMessageHandler(testing.getOpenTelemetrySdk(), messages -> "Batch of Messages") { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); @@ -141,6 +143,7 @@ protected void doHandleMessages(Collection messages) { span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> span.hasName("Batch of Messages") + .hasKind(SpanKind.CONSUMER) .hasLinks( LinkData.create( SpanContext.createFromRemoteParent( @@ -183,8 +186,8 @@ public void multipleMessages() { AtomicInteger counter = new AtomicInteger(0); - SqsBatchMessageHandler messageHandler = - new SqsBatchMessageHandler(testing.getOpenTelemetrySdk(), messages -> "Batch of Messages") { + SqsMessageHandler messageHandler = + new SqsMessageHandler(testing.getOpenTelemetrySdk(), messages -> "Batch of Messages") { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); @@ -206,6 +209,7 @@ protected void doHandleMessages(Collection messages) { span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> span.hasName("Batch of Messages") + .hasKind(SpanKind.CONSUMER) .hasLinks( LinkData.create( SpanContext.createFromRemoteParent( @@ -250,11 +254,10 @@ public void multipleRunsOfTheHandler() { AtomicInteger counter = new AtomicInteger(0); - SqsBatchMessageHandler messageHandler = - new SqsBatchMessageHandler( + SqsMessageHandler messageHandler = + new SqsMessageHandler( testing.getOpenTelemetrySdk(), - messages -> "Batch of Messages", - MessageOperation.PROCESS.name()) { + messages -> "Batch of Messages") { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); @@ -277,6 +280,7 @@ protected void doHandleMessages(Collection messages) { span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> span.hasName("Batch of Messages") + .hasKind(SpanKind.CONSUMER) .hasLinks( LinkData.create( SpanContext.createFromRemoteParent( @@ -286,13 +290,14 @@ protected void doHandleMessages(Collection messages) { TraceState.getDefault()))) .hasTotalRecordedLinks(1) .hasAttribute( - SemanticAttributes.MESSAGING_OPERATION, MessageOperation.PROCESS.name()) + SemanticAttributes.MESSAGING_OPERATION, MessageOperation.RECEIVE.name()) .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") .hasTotalAttributeCount(2) .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) .hasTraceId(parentSpan.getSpanContext().getTraceId()), span -> span.hasName("Batch of Messages") + .hasKind(SpanKind.CONSUMER) .hasLinks( LinkData.create( SpanContext.createFromRemoteParent( @@ -302,7 +307,7 @@ protected void doHandleMessages(Collection messages) { TraceState.getDefault()))) .hasTotalRecordedLinks(1) .hasAttribute( - SemanticAttributes.MESSAGING_OPERATION, MessageOperation.PROCESS.name()) + SemanticAttributes.MESSAGING_OPERATION, MessageOperation.RECEIVE.name()) .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") .hasTotalAttributeCount(2) .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) @@ -315,8 +320,8 @@ protected void doHandleMessages(Collection messages) { public void noMessages() { AtomicInteger counter = new AtomicInteger(0); - SqsBatchMessageHandler messageHandler = - new SqsBatchMessageHandler(testing.getOpenTelemetrySdk(), messages -> "Batch of Messages") { + SqsMessageHandler messageHandler = + new SqsMessageHandler(testing.getOpenTelemetrySdk(), messages -> "Batch of Messages") { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); @@ -338,6 +343,7 @@ protected void doHandleMessages(Collection messages) { span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> span.hasName("Batch of Messages") + .hasKind(SpanKind.CONSUMER) .hasTotalRecordedLinks(0) .hasAttribute( SemanticAttributes.MESSAGING_OPERATION, MessageOperation.RECEIVE.name()) @@ -361,11 +367,11 @@ public void changeDefaults() { AtomicInteger counter = new AtomicInteger(0); - SqsBatchMessageHandler messageHandler = - new SqsBatchMessageHandler( + SqsMessageHandler messageHandler = + new SqsMessageHandler( testing.getOpenTelemetrySdk(), messages -> "New Name", - MessageOperation.PROCESS.name()) { + MessageOperation.PROCESS) { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); @@ -387,6 +393,7 @@ protected void doHandleMessages(Collection messages) { span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> span.hasName("New Name") + .hasKind(SpanKind.CONSUMER) .hasLinks( LinkData.create( SpanContext.createFromRemoteParent( @@ -405,6 +412,63 @@ protected void doHandleMessages(Collection messages) { Assert.assertEquals(1, counter.get()); } + @Test + public void testSender() { + Message sqsMessage = + Message.builder() + .attributesWithStrings( + Collections.singletonMap( + "AWSTraceHeader", + "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")) + .build(); + + AtomicInteger counter = new AtomicInteger(0); + + SqsMessageHandler messageHandler = + new SqsMessageHandler( + testing.getOpenTelemetrySdk(), + messages -> "New Name", + MessageOperation.SEND) { + @Override + protected void doHandleMessages(Collection messages) { + counter.getAndIncrement(); + } + }; + + Span parentSpan = + testing.getOpenTelemetrySdk().getTracer("test").spanBuilder("test").startSpan(); + + try (Scope scope = parentSpan.makeCurrent()) { + messageHandler.handleMessages(Collections.singletonList(sqsMessage)); + } + + parentSpan.end(); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), + span -> + span.hasName("New Name") + .hasKind(SpanKind.PRODUCER) + .hasLinks( + LinkData.create( + SpanContext.createFromRemoteParent( + "55555555123456789012345678901234", + "1234567890123456", + TraceFlags.getSampled(), + TraceState.getDefault()))) + .hasTotalRecordedLinks(1) + .hasAttribute( + SemanticAttributes.MESSAGING_OPERATION, MessageOperation.SEND.name()) + .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") + .hasTotalAttributeCount(2) + .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) + .hasTraceId(parentSpan.getSpanContext().getTraceId()))); + + Assert.assertEquals(1, counter.get()); + } + @Test public void invalidUpstreamParent() { Message sqsMessage = @@ -416,8 +480,8 @@ public void invalidUpstreamParent() { AtomicInteger counter = new AtomicInteger(0); - SqsBatchMessageHandler messageHandler = - new SqsBatchMessageHandler(testing.getOpenTelemetrySdk(), messages -> "Batch of Messages") { + SqsMessageHandler messageHandler = + new SqsMessageHandler(testing.getOpenTelemetrySdk(), messages -> "Batch of Messages") { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); @@ -448,8 +512,8 @@ public void exceptionInHandle() { AtomicInteger counter = new AtomicInteger(0); - SqsBatchMessageHandler messageHandler = - new SqsBatchMessageHandler(testing.getOpenTelemetrySdk(), messages -> "Batch of Messages") { + SqsMessageHandler messageHandler = + new SqsMessageHandler(testing.getOpenTelemetrySdk(), messages -> "Batch of Messages") { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); @@ -476,6 +540,7 @@ protected void doHandleMessages(Collection messages) { span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> span.hasName("Batch of Messages") + .hasKind(SpanKind.CONSUMER) .hasLinks( LinkData.create( SpanContext.createFromRemoteParent( diff --git a/instrumentation/message-handler/core/README.md b/instrumentation/message-handler/core/README.md index 2d44d5df5b20..4f57a6045277 100644 --- a/instrumentation/message-handler/core/README.md +++ b/instrumentation/message-handler/core/README.md @@ -7,24 +7,4 @@ The handler will create a single new messaging span, add span links to it, and s The handler provides constructors to change the messaging operation and span name of the newly created messaging span. ## Available Handlers -- `SQSBatchMessageHandler` - processes messages from Amazon's SQS. - -## Using SQSBatchMessageHandler - -1. Retrieve a collection of messages to process. -2. Create a SQSBatchMessageHandler and provide the business logic on what to do with the messages. -3. Call the handleMessages function and pass in your messages. -4. It will call the doHandleMessages function you provided wrapped in the messaging span. - -```java -Collection sqsMessages; - -SqsBatchMessageHandler messageHandler = new SqsBatchMessageHandler(GlobalOpenTelemetry.get()) { - @Override - protected void doHandleMessages(Collection messages) { - // Do my business logic - } -}; - -messageHandler.handleMessages(sqsMessages, messages -> "Receiving Messages"); -``` +- `SqsMessageHandler` - processes messages from Amazon's SQS. diff --git a/instrumentation/message-handler/core/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java b/instrumentation/message-handler/core/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageHandler.java similarity index 90% rename from instrumentation/message-handler/core/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java rename to instrumentation/message-handler/core/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageHandler.java index cb8f0179eef1..540c6bf1bbd4 100644 --- a/instrumentation/message-handler/core/src/main/java/io/opentelemetry/instrumentation/messagehandler/BatchMessageHandler.java +++ b/instrumentation/message-handler/core/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageHandler.java @@ -17,22 +17,22 @@ import java.util.Collection; import javax.annotation.Nullable; -public abstract class BatchMessageHandler { - private final String messagingOperation; +public abstract class MessageHandler { + private final MessageOperation messagingOperation; private final OpenTelemetry openTelemetry; private final SpanNameExtractor> spanNameExtractor; protected Instrumenter, Void> messageInstrumenter; - public BatchMessageHandler( + public MessageHandler( OpenTelemetry openTelemetry, SpanNameExtractor> spanNameExtractor) { - this(openTelemetry, spanNameExtractor, MessageOperation.RECEIVE.name()); + this(openTelemetry, spanNameExtractor, MessageOperation.RECEIVE); } - public BatchMessageHandler( + public MessageHandler( OpenTelemetry openTelemetry, SpanNameExtractor> spanNameExtractor, - String messageOperation) { + MessageOperation messageOperation) { this.openTelemetry = openTelemetry; this.spanNameExtractor = spanNameExtractor; this.messagingOperation = messageOperation; @@ -40,6 +40,10 @@ public BatchMessageHandler( setup(); } + protected MessageOperation getMessagingOperation() { + return messagingOperation; + } + protected OpenTelemetry getOpenTelemetry() { return openTelemetry; } @@ -58,7 +62,7 @@ protected AttributesExtractor, Void> getGenericAttributesExtractor @Override public void onStart( AttributesBuilder attributes, Context parentContext, Collection messages) { - attributes.put(SemanticAttributes.MESSAGING_OPERATION, messagingOperation); + attributes.put(SemanticAttributes.MESSAGING_OPERATION, messagingOperation.name()); } @Override From 40c7a67e94fadc469277959adccc12db7b98c4ad Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Wed, 7 Jun 2023 12:47:46 -0700 Subject: [PATCH 27/47] Applying spotless --- .../messagehandler/SqsMessageHandler.java | 10 +++++----- .../messagehandler/SqsMessageHandlerTest.java | 12 +++--------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandler.java b/instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandler.java index 88f7e0e54400..90ecbdddba6a 100644 --- a/instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandler.java +++ b/instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandler.java @@ -29,8 +29,7 @@ import software.amazon.awssdk.services.sqs.model.Message; public abstract class SqsMessageHandler extends MessageHandler { - private static final Logger logger = - Logger.getLogger(SqsMessageHandler.class.getName()); + private static final Logger logger = Logger.getLogger(SqsMessageHandler.class.getName()); public SqsMessageHandler( OpenTelemetry openTelemetry, SpanNameExtractor> spanNameExtractor) { @@ -59,13 +58,14 @@ protected void setup() { protected SpanKindExtractor> getSpanKindExtractor() { MessageOperation messageOperation = getMessagingOperation(); - if (messageOperation == MessageOperation.RECEIVE || - messageOperation == MessageOperation.PROCESS) { + if (messageOperation == MessageOperation.RECEIVE + || messageOperation == MessageOperation.PROCESS) { return SpanKindExtractor.alwaysConsumer(); } else if (messageOperation == MessageOperation.SEND) { return SpanKindExtractor.alwaysProducer(); } else { - logger.log(Level.WARNING, "Unknown Messaging Operation {0}", new Object[] {messageOperation.name()}); + logger.log( + Level.WARNING, "Unknown Messaging Operation {0}", new Object[] {messageOperation.name()}); return SpanKindExtractor.alwaysConsumer(); } } diff --git a/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandlerTest.java b/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandlerTest.java index 94c22d08ec2c..eb49cde21e89 100644 --- a/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandlerTest.java +++ b/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandlerTest.java @@ -255,9 +255,7 @@ public void multipleRunsOfTheHandler() { AtomicInteger counter = new AtomicInteger(0); SqsMessageHandler messageHandler = - new SqsMessageHandler( - testing.getOpenTelemetrySdk(), - messages -> "Batch of Messages") { + new SqsMessageHandler(testing.getOpenTelemetrySdk(), messages -> "Batch of Messages") { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); @@ -369,9 +367,7 @@ public void changeDefaults() { SqsMessageHandler messageHandler = new SqsMessageHandler( - testing.getOpenTelemetrySdk(), - messages -> "New Name", - MessageOperation.PROCESS) { + testing.getOpenTelemetrySdk(), messages -> "New Name", MessageOperation.PROCESS) { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); @@ -426,9 +422,7 @@ public void testSender() { SqsMessageHandler messageHandler = new SqsMessageHandler( - testing.getOpenTelemetrySdk(), - messages -> "New Name", - MessageOperation.SEND) { + testing.getOpenTelemetrySdk(), messages -> "New Name", MessageOperation.SEND) { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); From 6aef8cb8f4eb148641a396f54f67f6fcb617fbba Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Wed, 7 Jun 2023 14:13:04 -0700 Subject: [PATCH 28/47] Fixing test runner --- .../messagehandler/SqsMessageHandlerTest.java | 207 +++++++++++++----- 1 file changed, 155 insertions(+), 52 deletions(-) diff --git a/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandlerTest.java b/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandlerTest.java index eb49cde21e89..98aa81965f5e 100644 --- a/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandlerTest.java +++ b/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandlerTest.java @@ -5,6 +5,7 @@ package io.opentelemetry.instrumentation.messagehandler; +import static org.awaitility.Awaitility.await; import static org.junit.jupiter.api.Assertions.assertThrows; import io.opentelemetry.api.trace.Span; @@ -12,45 +13,158 @@ import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.api.trace.TraceFlags; import io.opentelemetry.api.trace.TraceState; +import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; import io.opentelemetry.context.propagation.ContextPropagators; import io.opentelemetry.contrib.awsxray.propagator.AwsXrayPropagator; import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessageOperation; -import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; -import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.util.TelemetryDataUtil; import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.common.CompletableResultCode; +import io.opentelemetry.sdk.metrics.SdkMeterProvider; +import io.opentelemetry.sdk.metrics.data.AggregationTemporality; +import io.opentelemetry.sdk.metrics.export.MetricReader; +import io.opentelemetry.sdk.metrics.export.PeriodicMetricReader; +import io.opentelemetry.sdk.testing.assertj.TraceAssert; +import io.opentelemetry.sdk.testing.assertj.TracesAssert; +import io.opentelemetry.sdk.testing.exporter.InMemoryMetricExporter; +import io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter; +import io.opentelemetry.sdk.trace.ReadWriteSpan; +import io.opentelemetry.sdk.trace.ReadableSpan; +import io.opentelemetry.sdk.trace.SdkTracerProvider; +import io.opentelemetry.sdk.trace.SpanProcessor; import io.opentelemetry.sdk.trace.data.LinkData; +import io.opentelemetry.sdk.trace.data.SpanData; +import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; -import java.lang.reflect.Field; +import java.time.Duration; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.LinkedList; import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; +import javax.annotation.Nullable; +import org.awaitility.core.ConditionTimeoutException; import org.junit.Assert; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; import software.amazon.awssdk.services.sqs.model.Message; import software.amazon.awssdk.services.sqs.model.MessageAttributeValue; public class SqsMessageHandlerTest { - - @RegisterExtension - private static final InstrumentationExtension testing = LibraryInstrumentationExtension.create(); + private static final OpenTelemetrySdk openTelemetry; + private static final InMemorySpanExporter testSpanExporter; static { - // Change to the X-Ray propagator + testSpanExporter = InMemorySpanExporter.create(); + InMemoryMetricExporter testMetricExporter = + InMemoryMetricExporter.create(AggregationTemporality.DELTA); + + MetricReader metricReader = + PeriodicMetricReader.builder(testMetricExporter) + // Set really long interval. We'll call forceFlush when we need the metrics + // instead of collecting them periodically. + .setInterval(Duration.ofNanos(Long.MAX_VALUE)) + .build(); + + openTelemetry = + OpenTelemetrySdk.builder() + .setTracerProvider( + SdkTracerProvider.builder() + .addSpanProcessor(new FlushTrackingSpanProcessor()) + .addSpanProcessor(SimpleSpanProcessor.create(testSpanExporter)) + .build()) + .setMeterProvider(SdkMeterProvider.builder().registerMetricReader(metricReader).build()) + .setPropagators(ContextPropagators.create(AwsXrayPropagator.getInstance())) + .buildAndRegisterGlobal(); + } + + private static class FlushTrackingSpanProcessor implements SpanProcessor { + @Override + public void onStart(Context parentContext, ReadWriteSpan span) {} + + @Override + public boolean isStartRequired() { + return false; + } + + @Override + public void onEnd(ReadableSpan span) {} + + @Override + public boolean isEndRequired() { + return false; + } + + @Override + public CompletableResultCode forceFlush() { + return CompletableResultCode.ofSuccess(); + } + } + + @SafeVarargs + @SuppressWarnings("varargs") + public final void waitAndAssertTraces(Consumer... assertions) { + waitAndAssertTraces(null, Arrays.asList(assertions), true); + } + + private > void waitAndAssertTraces( + @Nullable Comparator> traceComparator, + Iterable assertions, + boolean verifyScopeVersion) { + List> assertionsList = new ArrayList<>(); + assertions.forEach(assertionsList::add); + + try { + await() + .untilAsserted(() -> doAssertTraces(traceComparator, assertionsList, verifyScopeVersion)); + } catch (ConditionTimeoutException e) { + // Don't throw this failure since the stack is the awaitility thread, causing confusion. + // Instead, just assert one more time on the test thread, which will fail with a better stack + // trace. + // TODO(anuraaga): There is probably a better way to do this. + doAssertTraces(traceComparator, assertionsList, verifyScopeVersion); + } + } + + private void doAssertTraces( + @Nullable Comparator> traceComparator, + List> assertionsList, + boolean verifyScopeVersion) { + List> traces = waitForTraces(assertionsList.size()); + if (verifyScopeVersion) { + TelemetryDataUtil.assertScopeVersion(traces); + } + if (traceComparator != null) { + traces.sort(traceComparator); + } + TracesAssert.assertThat(traces).hasTracesSatisfyingExactly(assertionsList); + } + + public final List> waitForTraces(int numberOfTraces) { try { - Field field = OpenTelemetrySdk.class.getDeclaredField("propagators"); - field.setAccessible(true); - field.set( - testing.getOpenTelemetrySdk(), - ContextPropagators.create(AwsXrayPropagator.getInstance())); - } catch (Exception e) { - throw new RuntimeException(e); + return TelemetryDataUtil.waitForTraces( + this::getExportedSpans, numberOfTraces, 20, TimeUnit.SECONDS); + } catch (TimeoutException | InterruptedException e) { + throw new AssertionError("Error waiting for " + numberOfTraces + " traces", e); } } + public List getExportedSpans() { + return testSpanExporter.getFinishedSpanItems(); + } + + @AfterEach + public void resetTests() { + testSpanExporter.reset(); + } + @Test public void simple() { Message sqsMessage = @@ -64,15 +178,14 @@ public void simple() { AtomicInteger counter = new AtomicInteger(0); SqsMessageHandler messageHandler = - new SqsMessageHandler(testing.getOpenTelemetrySdk(), messages -> "Batch of Messages") { + new SqsMessageHandler(openTelemetry, messages -> "Batch of Messages") { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); } }; - Span parentSpan = - testing.getOpenTelemetrySdk().getTracer("test").spanBuilder("test").startSpan(); + Span parentSpan = openTelemetry.getTracer("test").spanBuilder("test").startSpan(); try (Scope scope = parentSpan.makeCurrent()) { messageHandler.handleMessages(Collections.singletonList(sqsMessage)); @@ -80,7 +193,7 @@ protected void doHandleMessages(Collection messages) { parentSpan.end(); - testing.waitAndAssertTraces( + waitAndAssertTraces( trace -> trace.hasSpansSatisfyingExactly( span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), @@ -121,15 +234,14 @@ public void simpleMessage() { AtomicInteger counter = new AtomicInteger(0); SqsMessageHandler messageHandler = - new SqsMessageHandler(testing.getOpenTelemetrySdk(), messages -> "Batch of Messages") { + new SqsMessageHandler(openTelemetry, messages -> "Batch of Messages") { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); } }; - Span parentSpan = - testing.getOpenTelemetrySdk().getTracer("test").spanBuilder("test").startSpan(); + Span parentSpan = openTelemetry.getTracer("test").spanBuilder("test").startSpan(); try (Scope scope = parentSpan.makeCurrent()) { messageHandler.handleMessages(Collections.singletonList(sqsMessage)); @@ -137,7 +249,7 @@ protected void doHandleMessages(Collection messages) { parentSpan.end(); - testing.waitAndAssertTraces( + waitAndAssertTraces( trace -> trace.hasSpansSatisfyingExactly( span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), @@ -187,15 +299,14 @@ public void multipleMessages() { AtomicInteger counter = new AtomicInteger(0); SqsMessageHandler messageHandler = - new SqsMessageHandler(testing.getOpenTelemetrySdk(), messages -> "Batch of Messages") { + new SqsMessageHandler(openTelemetry, messages -> "Batch of Messages") { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); } }; - Span parentSpan = - testing.getOpenTelemetrySdk().getTracer("test").spanBuilder("test").startSpan(); + Span parentSpan = openTelemetry.getTracer("test").spanBuilder("test").startSpan(); try (Scope scope = parentSpan.makeCurrent()) { messageHandler.handleMessages(sqsMessages); @@ -203,7 +314,7 @@ protected void doHandleMessages(Collection messages) { parentSpan.end(); - testing.waitAndAssertTraces( + waitAndAssertTraces( trace -> trace.hasSpansSatisfyingExactly( span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), @@ -255,15 +366,14 @@ public void multipleRunsOfTheHandler() { AtomicInteger counter = new AtomicInteger(0); SqsMessageHandler messageHandler = - new SqsMessageHandler(testing.getOpenTelemetrySdk(), messages -> "Batch of Messages") { + new SqsMessageHandler(openTelemetry, messages -> "Batch of Messages") { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); } }; - Span parentSpan = - testing.getOpenTelemetrySdk().getTracer("test").spanBuilder("test").startSpan(); + Span parentSpan = openTelemetry.getTracer("test").spanBuilder("test").startSpan(); try (Scope scope = parentSpan.makeCurrent()) { messageHandler.handleMessages(Collections.singletonList(sqsMessage1)); @@ -272,7 +382,7 @@ protected void doHandleMessages(Collection messages) { parentSpan.end(); - testing.waitAndAssertTraces( + waitAndAssertTraces( trace -> trace.hasSpansSatisfyingExactly( span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), @@ -319,15 +429,14 @@ public void noMessages() { AtomicInteger counter = new AtomicInteger(0); SqsMessageHandler messageHandler = - new SqsMessageHandler(testing.getOpenTelemetrySdk(), messages -> "Batch of Messages") { + new SqsMessageHandler(openTelemetry, messages -> "Batch of Messages") { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); } }; - Span parentSpan = - testing.getOpenTelemetrySdk().getTracer("test").spanBuilder("test").startSpan(); + Span parentSpan = openTelemetry.getTracer("test").spanBuilder("test").startSpan(); try (Scope scope = parentSpan.makeCurrent()) { messageHandler.handleMessages(Collections.emptyList()); @@ -335,7 +444,7 @@ protected void doHandleMessages(Collection messages) { parentSpan.end(); - testing.waitAndAssertTraces( + waitAndAssertTraces( trace -> trace.hasSpansSatisfyingExactly( span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), @@ -366,16 +475,14 @@ public void changeDefaults() { AtomicInteger counter = new AtomicInteger(0); SqsMessageHandler messageHandler = - new SqsMessageHandler( - testing.getOpenTelemetrySdk(), messages -> "New Name", MessageOperation.PROCESS) { + new SqsMessageHandler(openTelemetry, messages -> "New Name", MessageOperation.PROCESS) { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); } }; - Span parentSpan = - testing.getOpenTelemetrySdk().getTracer("test").spanBuilder("test").startSpan(); + Span parentSpan = openTelemetry.getTracer("test").spanBuilder("test").startSpan(); try (Scope scope = parentSpan.makeCurrent()) { messageHandler.handleMessages(Collections.singletonList(sqsMessage)); @@ -383,7 +490,7 @@ protected void doHandleMessages(Collection messages) { parentSpan.end(); - testing.waitAndAssertTraces( + waitAndAssertTraces( trace -> trace.hasSpansSatisfyingExactly( span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), @@ -421,16 +528,14 @@ public void testSender() { AtomicInteger counter = new AtomicInteger(0); SqsMessageHandler messageHandler = - new SqsMessageHandler( - testing.getOpenTelemetrySdk(), messages -> "New Name", MessageOperation.SEND) { + new SqsMessageHandler(openTelemetry, messages -> "New Name", MessageOperation.SEND) { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); } }; - Span parentSpan = - testing.getOpenTelemetrySdk().getTracer("test").spanBuilder("test").startSpan(); + Span parentSpan = openTelemetry.getTracer("test").spanBuilder("test").startSpan(); try (Scope scope = parentSpan.makeCurrent()) { messageHandler.handleMessages(Collections.singletonList(sqsMessage)); @@ -438,7 +543,7 @@ protected void doHandleMessages(Collection messages) { parentSpan.end(); - testing.waitAndAssertTraces( + waitAndAssertTraces( trace -> trace.hasSpansSatisfyingExactly( span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), @@ -475,15 +580,14 @@ public void invalidUpstreamParent() { AtomicInteger counter = new AtomicInteger(0); SqsMessageHandler messageHandler = - new SqsMessageHandler(testing.getOpenTelemetrySdk(), messages -> "Batch of Messages") { + new SqsMessageHandler(openTelemetry, messages -> "Batch of Messages") { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); } }; - Span parentSpan = - testing.getOpenTelemetrySdk().getTracer("test").spanBuilder("test").startSpan(); + Span parentSpan = openTelemetry.getTracer("test").spanBuilder("test").startSpan(); assertThrows( StringIndexOutOfBoundsException.class, @@ -507,7 +611,7 @@ public void exceptionInHandle() { AtomicInteger counter = new AtomicInteger(0); SqsMessageHandler messageHandler = - new SqsMessageHandler(testing.getOpenTelemetrySdk(), messages -> "Batch of Messages") { + new SqsMessageHandler(openTelemetry, messages -> "Batch of Messages") { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); @@ -515,8 +619,7 @@ protected void doHandleMessages(Collection messages) { } }; - Span parentSpan = - testing.getOpenTelemetrySdk().getTracer("test").spanBuilder("test").startSpan(); + Span parentSpan = openTelemetry.getTracer("test").spanBuilder("test").startSpan(); assertThrows( RuntimeException.class, @@ -528,7 +631,7 @@ protected void doHandleMessages(Collection messages) { parentSpan.end(); - testing.waitAndAssertTraces( + waitAndAssertTraces( trace -> trace.hasSpansSatisfyingExactly( span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), From dfceb723d66d2a12cb2bb65817787de71d12e4e0 Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Wed, 7 Jun 2023 14:37:31 -0700 Subject: [PATCH 29/47] Refactoring test code --- .../messagehandler/SqsMessageHandlerTest.java | 176 ++---------------- .../messagehandler/XrayTestInstrumenter.java | 148 +++++++++++++++ 2 files changed, 167 insertions(+), 157 deletions(-) create mode 100644 instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/XrayTestInstrumenter.java diff --git a/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandlerTest.java b/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandlerTest.java index 98aa81965f5e..96abc8704e74 100644 --- a/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandlerTest.java +++ b/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandlerTest.java @@ -5,7 +5,6 @@ package io.opentelemetry.instrumentation.messagehandler; -import static org.awaitility.Awaitility.await; import static org.junit.jupiter.api.Assertions.assertThrows; import io.opentelemetry.api.trace.Span; @@ -13,158 +12,21 @@ import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.api.trace.TraceFlags; import io.opentelemetry.api.trace.TraceState; -import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; -import io.opentelemetry.context.propagation.ContextPropagators; -import io.opentelemetry.contrib.awsxray.propagator.AwsXrayPropagator; import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessageOperation; -import io.opentelemetry.instrumentation.testing.util.TelemetryDataUtil; -import io.opentelemetry.sdk.OpenTelemetrySdk; -import io.opentelemetry.sdk.common.CompletableResultCode; -import io.opentelemetry.sdk.metrics.SdkMeterProvider; -import io.opentelemetry.sdk.metrics.data.AggregationTemporality; -import io.opentelemetry.sdk.metrics.export.MetricReader; -import io.opentelemetry.sdk.metrics.export.PeriodicMetricReader; -import io.opentelemetry.sdk.testing.assertj.TraceAssert; -import io.opentelemetry.sdk.testing.assertj.TracesAssert; -import io.opentelemetry.sdk.testing.exporter.InMemoryMetricExporter; -import io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter; -import io.opentelemetry.sdk.trace.ReadWriteSpan; -import io.opentelemetry.sdk.trace.ReadableSpan; -import io.opentelemetry.sdk.trace.SdkTracerProvider; -import io.opentelemetry.sdk.trace.SpanProcessor; import io.opentelemetry.sdk.trace.data.LinkData; -import io.opentelemetry.sdk.trace.data.SpanData; -import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; -import java.time.Duration; -import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.Comparator; import java.util.LinkedList; import java.util.List; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Consumer; -import javax.annotation.Nullable; -import org.awaitility.core.ConditionTimeoutException; import org.junit.Assert; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import software.amazon.awssdk.services.sqs.model.Message; import software.amazon.awssdk.services.sqs.model.MessageAttributeValue; -public class SqsMessageHandlerTest { - private static final OpenTelemetrySdk openTelemetry; - private static final InMemorySpanExporter testSpanExporter; - - static { - testSpanExporter = InMemorySpanExporter.create(); - InMemoryMetricExporter testMetricExporter = - InMemoryMetricExporter.create(AggregationTemporality.DELTA); - - MetricReader metricReader = - PeriodicMetricReader.builder(testMetricExporter) - // Set really long interval. We'll call forceFlush when we need the metrics - // instead of collecting them periodically. - .setInterval(Duration.ofNanos(Long.MAX_VALUE)) - .build(); - - openTelemetry = - OpenTelemetrySdk.builder() - .setTracerProvider( - SdkTracerProvider.builder() - .addSpanProcessor(new FlushTrackingSpanProcessor()) - .addSpanProcessor(SimpleSpanProcessor.create(testSpanExporter)) - .build()) - .setMeterProvider(SdkMeterProvider.builder().registerMetricReader(metricReader).build()) - .setPropagators(ContextPropagators.create(AwsXrayPropagator.getInstance())) - .buildAndRegisterGlobal(); - } - - private static class FlushTrackingSpanProcessor implements SpanProcessor { - @Override - public void onStart(Context parentContext, ReadWriteSpan span) {} - - @Override - public boolean isStartRequired() { - return false; - } - - @Override - public void onEnd(ReadableSpan span) {} - - @Override - public boolean isEndRequired() { - return false; - } - - @Override - public CompletableResultCode forceFlush() { - return CompletableResultCode.ofSuccess(); - } - } - - @SafeVarargs - @SuppressWarnings("varargs") - public final void waitAndAssertTraces(Consumer... assertions) { - waitAndAssertTraces(null, Arrays.asList(assertions), true); - } - - private > void waitAndAssertTraces( - @Nullable Comparator> traceComparator, - Iterable assertions, - boolean verifyScopeVersion) { - List> assertionsList = new ArrayList<>(); - assertions.forEach(assertionsList::add); - - try { - await() - .untilAsserted(() -> doAssertTraces(traceComparator, assertionsList, verifyScopeVersion)); - } catch (ConditionTimeoutException e) { - // Don't throw this failure since the stack is the awaitility thread, causing confusion. - // Instead, just assert one more time on the test thread, which will fail with a better stack - // trace. - // TODO(anuraaga): There is probably a better way to do this. - doAssertTraces(traceComparator, assertionsList, verifyScopeVersion); - } - } - - private void doAssertTraces( - @Nullable Comparator> traceComparator, - List> assertionsList, - boolean verifyScopeVersion) { - List> traces = waitForTraces(assertionsList.size()); - if (verifyScopeVersion) { - TelemetryDataUtil.assertScopeVersion(traces); - } - if (traceComparator != null) { - traces.sort(traceComparator); - } - TracesAssert.assertThat(traces).hasTracesSatisfyingExactly(assertionsList); - } - - public final List> waitForTraces(int numberOfTraces) { - try { - return TelemetryDataUtil.waitForTraces( - this::getExportedSpans, numberOfTraces, 20, TimeUnit.SECONDS); - } catch (TimeoutException | InterruptedException e) { - throw new AssertionError("Error waiting for " + numberOfTraces + " traces", e); - } - } - - public List getExportedSpans() { - return testSpanExporter.getFinishedSpanItems(); - } - - @AfterEach - public void resetTests() { - testSpanExporter.reset(); - } - +public class SqsMessageHandlerTest extends XrayTestInstrumenter { @Test public void simple() { Message sqsMessage = @@ -178,14 +40,14 @@ public void simple() { AtomicInteger counter = new AtomicInteger(0); SqsMessageHandler messageHandler = - new SqsMessageHandler(openTelemetry, messages -> "Batch of Messages") { + new SqsMessageHandler(getOpenTelemetry(), messages -> "Batch of Messages") { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); } }; - Span parentSpan = openTelemetry.getTracer("test").spanBuilder("test").startSpan(); + Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); try (Scope scope = parentSpan.makeCurrent()) { messageHandler.handleMessages(Collections.singletonList(sqsMessage)); @@ -234,14 +96,14 @@ public void simpleMessage() { AtomicInteger counter = new AtomicInteger(0); SqsMessageHandler messageHandler = - new SqsMessageHandler(openTelemetry, messages -> "Batch of Messages") { + new SqsMessageHandler(getOpenTelemetry(), messages -> "Batch of Messages") { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); } }; - Span parentSpan = openTelemetry.getTracer("test").spanBuilder("test").startSpan(); + Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); try (Scope scope = parentSpan.makeCurrent()) { messageHandler.handleMessages(Collections.singletonList(sqsMessage)); @@ -299,14 +161,14 @@ public void multipleMessages() { AtomicInteger counter = new AtomicInteger(0); SqsMessageHandler messageHandler = - new SqsMessageHandler(openTelemetry, messages -> "Batch of Messages") { + new SqsMessageHandler(getOpenTelemetry(), messages -> "Batch of Messages") { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); } }; - Span parentSpan = openTelemetry.getTracer("test").spanBuilder("test").startSpan(); + Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); try (Scope scope = parentSpan.makeCurrent()) { messageHandler.handleMessages(sqsMessages); @@ -366,14 +228,14 @@ public void multipleRunsOfTheHandler() { AtomicInteger counter = new AtomicInteger(0); SqsMessageHandler messageHandler = - new SqsMessageHandler(openTelemetry, messages -> "Batch of Messages") { + new SqsMessageHandler(getOpenTelemetry(), messages -> "Batch of Messages") { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); } }; - Span parentSpan = openTelemetry.getTracer("test").spanBuilder("test").startSpan(); + Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); try (Scope scope = parentSpan.makeCurrent()) { messageHandler.handleMessages(Collections.singletonList(sqsMessage1)); @@ -429,14 +291,14 @@ public void noMessages() { AtomicInteger counter = new AtomicInteger(0); SqsMessageHandler messageHandler = - new SqsMessageHandler(openTelemetry, messages -> "Batch of Messages") { + new SqsMessageHandler(getOpenTelemetry(), messages -> "Batch of Messages") { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); } }; - Span parentSpan = openTelemetry.getTracer("test").spanBuilder("test").startSpan(); + Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); try (Scope scope = parentSpan.makeCurrent()) { messageHandler.handleMessages(Collections.emptyList()); @@ -475,14 +337,14 @@ public void changeDefaults() { AtomicInteger counter = new AtomicInteger(0); SqsMessageHandler messageHandler = - new SqsMessageHandler(openTelemetry, messages -> "New Name", MessageOperation.PROCESS) { + new SqsMessageHandler(getOpenTelemetry(), messages -> "New Name", MessageOperation.PROCESS) { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); } }; - Span parentSpan = openTelemetry.getTracer("test").spanBuilder("test").startSpan(); + Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); try (Scope scope = parentSpan.makeCurrent()) { messageHandler.handleMessages(Collections.singletonList(sqsMessage)); @@ -528,14 +390,14 @@ public void testSender() { AtomicInteger counter = new AtomicInteger(0); SqsMessageHandler messageHandler = - new SqsMessageHandler(openTelemetry, messages -> "New Name", MessageOperation.SEND) { + new SqsMessageHandler(getOpenTelemetry(), messages -> "New Name", MessageOperation.SEND) { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); } }; - Span parentSpan = openTelemetry.getTracer("test").spanBuilder("test").startSpan(); + Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); try (Scope scope = parentSpan.makeCurrent()) { messageHandler.handleMessages(Collections.singletonList(sqsMessage)); @@ -580,14 +442,14 @@ public void invalidUpstreamParent() { AtomicInteger counter = new AtomicInteger(0); SqsMessageHandler messageHandler = - new SqsMessageHandler(openTelemetry, messages -> "Batch of Messages") { + new SqsMessageHandler(getOpenTelemetry(), messages -> "Batch of Messages") { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); } }; - Span parentSpan = openTelemetry.getTracer("test").spanBuilder("test").startSpan(); + Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); assertThrows( StringIndexOutOfBoundsException.class, @@ -611,7 +473,7 @@ public void exceptionInHandle() { AtomicInteger counter = new AtomicInteger(0); SqsMessageHandler messageHandler = - new SqsMessageHandler(openTelemetry, messages -> "Batch of Messages") { + new SqsMessageHandler(getOpenTelemetry(), messages -> "Batch of Messages") { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); @@ -619,7 +481,7 @@ protected void doHandleMessages(Collection messages) { } }; - Span parentSpan = openTelemetry.getTracer("test").spanBuilder("test").startSpan(); + Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); assertThrows( RuntimeException.class, diff --git a/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/XrayTestInstrumenter.java b/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/XrayTestInstrumenter.java new file mode 100644 index 000000000000..bf2cd0d20631 --- /dev/null +++ b/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/XrayTestInstrumenter.java @@ -0,0 +1,148 @@ +package io.opentelemetry.instrumentation.messagehandler; + +import io.opentelemetry.context.Context; +import io.opentelemetry.context.propagation.ContextPropagators; +import io.opentelemetry.contrib.awsxray.propagator.AwsXrayPropagator; +import io.opentelemetry.instrumentation.testing.util.TelemetryDataUtil; +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.common.CompletableResultCode; +import io.opentelemetry.sdk.metrics.SdkMeterProvider; +import io.opentelemetry.sdk.metrics.data.AggregationTemporality; +import io.opentelemetry.sdk.metrics.export.MetricReader; +import io.opentelemetry.sdk.metrics.export.PeriodicMetricReader; +import io.opentelemetry.sdk.testing.assertj.TraceAssert; +import io.opentelemetry.sdk.testing.assertj.TracesAssert; +import io.opentelemetry.sdk.testing.exporter.InMemoryMetricExporter; +import io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter; +import io.opentelemetry.sdk.trace.ReadWriteSpan; +import io.opentelemetry.sdk.trace.ReadableSpan; +import io.opentelemetry.sdk.trace.SdkTracerProvider; +import io.opentelemetry.sdk.trace.SpanProcessor; +import io.opentelemetry.sdk.trace.data.SpanData; +import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor; +import org.awaitility.core.ConditionTimeoutException; +import org.junit.jupiter.api.AfterEach; +import javax.annotation.Nullable; +import java.time.Duration; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.function.Consumer; + +import static org.awaitility.Awaitility.await; + +public class XrayTestInstrumenter { + private static final OpenTelemetrySdk openTelemetry; + private static final InMemorySpanExporter testSpanExporter; + + static { + testSpanExporter = InMemorySpanExporter.create(); + InMemoryMetricExporter testMetricExporter = + InMemoryMetricExporter.create(AggregationTemporality.DELTA); + + MetricReader metricReader = + PeriodicMetricReader.builder(testMetricExporter) + // Set really long interval. We'll call forceFlush when we need the metrics + // instead of collecting them periodically. + .setInterval(Duration.ofNanos(Long.MAX_VALUE)) + .build(); + + openTelemetry = + OpenTelemetrySdk.builder() + .setTracerProvider( + SdkTracerProvider.builder() + .addSpanProcessor(new FlushTrackingSpanProcessor()) + .addSpanProcessor(SimpleSpanProcessor.create(testSpanExporter)) + .build()) + .setMeterProvider(SdkMeterProvider.builder().registerMetricReader(metricReader).build()) + .setPropagators(ContextPropagators.create(AwsXrayPropagator.getInstance())) + .buildAndRegisterGlobal(); + } + + @AfterEach + public void resetTests() { + testSpanExporter.reset(); + } + + protected OpenTelemetrySdk getOpenTelemetry() { + return openTelemetry; + } + + private static class FlushTrackingSpanProcessor implements SpanProcessor { + @Override + public void onStart(Context parentContext, ReadWriteSpan span) {} + + @Override + public boolean isStartRequired() { + return false; + } + + @Override + public void onEnd(ReadableSpan span) {} + + @Override + public boolean isEndRequired() { + return false; + } + + @Override + public CompletableResultCode forceFlush() { + return CompletableResultCode.ofSuccess(); + } + } + + @SafeVarargs + @SuppressWarnings("varargs") + public final void waitAndAssertTraces(Consumer... assertions) { + waitAndAssertTraces(null, Arrays.asList(assertions), true); + } + + private > void waitAndAssertTraces( + @Nullable Comparator> traceComparator, + Iterable assertions, + boolean verifyScopeVersion) { + List> assertionsList = new ArrayList<>(); + assertions.forEach(assertionsList::add); + + try { + await() + .untilAsserted(() -> doAssertTraces(traceComparator, assertionsList, verifyScopeVersion)); + } catch (ConditionTimeoutException e) { + // Don't throw this failure since the stack is the awaitility thread, causing confusion. + // Instead, just assert one more time on the test thread, which will fail with a better stack + // trace. + // TODO(anuraaga): There is probably a better way to do this. + doAssertTraces(traceComparator, assertionsList, verifyScopeVersion); + } + } + + private void doAssertTraces( + @Nullable Comparator> traceComparator, + List> assertionsList, + boolean verifyScopeVersion) { + List> traces = waitForTraces(assertionsList.size()); + if (verifyScopeVersion) { + TelemetryDataUtil.assertScopeVersion(traces); + } + if (traceComparator != null) { + traces.sort(traceComparator); + } + TracesAssert.assertThat(traces).hasTracesSatisfyingExactly(assertionsList); + } + + public final List> waitForTraces(int numberOfTraces) { + try { + return TelemetryDataUtil.waitForTraces( + this::getExportedSpans, numberOfTraces, 20, TimeUnit.SECONDS); + } catch (TimeoutException | InterruptedException e) { + throw new AssertionError("Error waiting for " + numberOfTraces + " traces", e); + } + } + + public List getExportedSpans() { + return testSpanExporter.getFinishedSpanItems(); + } +} From a591789b0bfcf5a776c6f114eb248cb906574278 Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Thu, 8 Jun 2023 17:00:13 -0700 Subject: [PATCH 30/47] Refactoring to use Messaging Extractors --- instrumentation/message-handler/aws/README.md | 2 +- .../messagehandler/SqsMessageHandler.java | 123 ++++++++++++------ .../messagehandler/SqsMessageHandlerTest.java | 107 ++++++++------- .../messagehandler/XrayTestInstrumenter.java | 15 ++- .../messagehandler/MessageHandler.java | 68 +--------- 5 files changed, 161 insertions(+), 154 deletions(-) diff --git a/instrumentation/message-handler/aws/README.md b/instrumentation/message-handler/aws/README.md index 6fbe37319eb6..8dfdc56ceb06 100644 --- a/instrumentation/message-handler/aws/README.md +++ b/instrumentation/message-handler/aws/README.md @@ -15,5 +15,5 @@ SqsMessageHandler messageHandler = new SqsMessageHandler(opentelemetry) { } }; -messageHandler.handleMessages(sqsMessages, messages -> "Receiving Messages"); +messageHandler.handleMessages(sqsMessages, "destination.name", MessageOperation.RECEIVE); ``` diff --git a/instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandler.java b/instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandler.java index 90ecbdddba6a..5e6ba81b6fdf 100644 --- a/instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandler.java +++ b/instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandler.java @@ -6,7 +6,6 @@ package io.opentelemetry.instrumentation.messagehandler; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.SpanContext; import io.opentelemetry.context.Context; @@ -17,9 +16,11 @@ import io.opentelemetry.instrumentation.api.instrumenter.SpanLinksExtractor; import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessageOperation; +import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessagingAttributesExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessagingAttributesGetter; +import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessagingSpanNameExtractor; import io.opentelemetry.instrumentation.awssdk.v2_2.SqsMessageAccess; import io.opentelemetry.instrumentation.awssdk.v2_2.SqsParentContext; -import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; import java.util.Collection; import java.util.Map; import java.util.logging.Level; @@ -31,33 +32,93 @@ public abstract class SqsMessageHandler extends MessageHandler { private static final Logger logger = Logger.getLogger(SqsMessageHandler.class.getName()); - public SqsMessageHandler( - OpenTelemetry openTelemetry, SpanNameExtractor> spanNameExtractor) { - super(openTelemetry, spanNameExtractor); - } + private final OpenTelemetry openTelemetry; + private final MessageOperation messageOperation; + private final String destination; public SqsMessageHandler( - OpenTelemetry openTelemetry, - SpanNameExtractor> spanNameExtractor, - MessageOperation messageOperation) { - super(openTelemetry, spanNameExtractor, messageOperation); + OpenTelemetry openTelemetry, String destination, MessageOperation messageOperation) { + this.openTelemetry = openTelemetry; + this.messageOperation = messageOperation; + this.destination = destination; } @Override - protected void setup() { - messageInstrumenter = - Instrumenter., Void>builder( - getOpenTelemetry(), "io.opentelemetry.message-handler", getSpanNameExtractor()) - .setInstrumentationVersion("1.0") - .addAttributesExtractor(getGenericAttributesExtractor()) - .addAttributesExtractor(getAttributesExtractor()) - .addSpanLinksExtractor(getSpanLinksExtractor()) - .buildInstrumenter(getSpanKindExtractor()); + protected Instrumenter, Void> getMessageInstrumenter() { + return Instrumenter., Void>builder( + openTelemetry, "io.opentelemetry.message-handler", getSpanNameExtractor()) + .setInstrumentationVersion("1.0") + .addAttributesExtractor(getAttributesExtractor()) + .addSpanLinksExtractor(getSpanLinksExtractor()) + .buildInstrumenter(getSpanKindExtractor()); } - protected SpanKindExtractor> getSpanKindExtractor() { - MessageOperation messageOperation = getMessagingOperation(); + protected SpanNameExtractor> getSpanNameExtractor() { + return MessagingSpanNameExtractor.create(getMessageingAttributesGetter(), messageOperation); + } + + private MessagingAttributesGetter, Void> getMessageingAttributesGetter() { + String destination = this.destination; + + return new MessagingAttributesGetter, Void>() { + @Nullable + @Override + public String getSystem(Collection messages) { + return "AmazonSQS"; + } + + @Nullable + @Override + public String getDestinationKind(Collection messages) { + return null; + } + @Nullable + @Override + public String getDestination(Collection messages) { + return destination; + } + + @Override + public boolean isTemporaryDestination(Collection messages) { + return false; + } + + @Nullable + @Override + public String getConversationId(Collection messages) { + return null; + } + + @Nullable + @Override + public Long getMessagePayloadSize(Collection messages) { + long total = 0; + + for (Message message : messages) { + if (message.body() != null) { + total += message.body().length(); + } + } + + return total; + } + + @Nullable + @Override + public Long getMessagePayloadCompressedSize(Collection messages) { + return null; + } + + @Nullable + @Override + public String getMessageId(Collection messages, @Nullable Void unused) { + return null; + } + }; + } + + protected SpanKindExtractor> getSpanKindExtractor() { if (messageOperation == MessageOperation.RECEIVE || messageOperation == MessageOperation.PROCESS) { return SpanKindExtractor.alwaysConsumer(); @@ -71,27 +132,11 @@ protected SpanKindExtractor> getSpanKindExtractor() { } protected AttributesExtractor, Void> getAttributesExtractor() { - return new AttributesExtractor, Void>() { - - @Override - public void onStart( - AttributesBuilder attributes, Context parentContext, Collection messages) { - attributes.put(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS"); - } - - @Override - public void onEnd( - AttributesBuilder attributes, - Context context, - Collection messages, - @Nullable Void unused, - @Nullable Throwable error) {} - }; + return MessagingAttributesExtractor.create(getMessageingAttributesGetter(), messageOperation); } protected SpanLinksExtractor> getSpanLinksExtractor() { - TextMapPropagator messagingPropagator = - getOpenTelemetry().getPropagators().getTextMapPropagator(); + TextMapPropagator messagingPropagator = openTelemetry.getPropagators().getTextMapPropagator(); return (spanLinks, parentContext, sqsMessages) -> { for (Message message : sqsMessages) { diff --git a/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandlerTest.java b/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandlerTest.java index 96abc8704e74..1163df92c81f 100644 --- a/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandlerTest.java +++ b/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandlerTest.java @@ -31,6 +31,7 @@ public class SqsMessageHandlerTest extends XrayTestInstrumenter { public void simple() { Message sqsMessage = Message.builder() + .body("Hello") .attributesWithStrings( Collections.singletonMap( "AWSTraceHeader", @@ -40,7 +41,7 @@ public void simple() { AtomicInteger counter = new AtomicInteger(0); SqsMessageHandler messageHandler = - new SqsMessageHandler(getOpenTelemetry(), messages -> "Batch of Messages") { + new SqsMessageHandler(getOpenTelemetry(), "destination", MessageOperation.RECEIVE) { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); @@ -60,7 +61,7 @@ protected void doHandleMessages(Collection messages) { trace.hasSpansSatisfyingExactly( span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> - span.hasName("Batch of Messages") + span.hasName("destination receive") .hasKind(SpanKind.CONSUMER) .hasLinks( LinkData.create( @@ -70,10 +71,11 @@ protected void doHandleMessages(Collection messages) { TraceFlags.getSampled(), TraceState.getDefault()))) .hasTotalRecordedLinks(1) - .hasAttribute( - SemanticAttributes.MESSAGING_OPERATION, MessageOperation.RECEIVE.name()) + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "receive") .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") - .hasTotalAttributeCount(2) + .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") + .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 5L) + .hasTotalAttributeCount(4) .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) .hasTraceId(parentSpan.getSpanContext().getTraceId()))); @@ -84,6 +86,7 @@ protected void doHandleMessages(Collection messages) { public void simpleMessage() { Message sqsMessage = Message.builder() + .body("Hello") .messageAttributes( Collections.singletonMap( "X-Amzn-Trace-Id", @@ -96,7 +99,7 @@ public void simpleMessage() { AtomicInteger counter = new AtomicInteger(0); SqsMessageHandler messageHandler = - new SqsMessageHandler(getOpenTelemetry(), messages -> "Batch of Messages") { + new SqsMessageHandler(getOpenTelemetry(), "destination", MessageOperation.RECEIVE) { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); @@ -116,7 +119,7 @@ protected void doHandleMessages(Collection messages) { trace.hasSpansSatisfyingExactly( span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> - span.hasName("Batch of Messages") + span.hasName("destination receive") .hasKind(SpanKind.CONSUMER) .hasLinks( LinkData.create( @@ -126,10 +129,11 @@ protected void doHandleMessages(Collection messages) { TraceFlags.getSampled(), TraceState.getDefault()))) .hasTotalRecordedLinks(1) - .hasAttribute( - SemanticAttributes.MESSAGING_OPERATION, MessageOperation.RECEIVE.name()) + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "receive") .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") - .hasTotalAttributeCount(2) + .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") + .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 5L) + .hasTotalAttributeCount(4) .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) .hasTraceId(parentSpan.getSpanContext().getTraceId()))); @@ -142,6 +146,7 @@ public void multipleMessages() { Message sqsMessage1 = Message.builder() + .body("Hello") .attributesWithStrings( Collections.singletonMap( "AWSTraceHeader", @@ -161,7 +166,7 @@ public void multipleMessages() { AtomicInteger counter = new AtomicInteger(0); SqsMessageHandler messageHandler = - new SqsMessageHandler(getOpenTelemetry(), messages -> "Batch of Messages") { + new SqsMessageHandler(getOpenTelemetry(), "destination", MessageOperation.RECEIVE) { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); @@ -181,7 +186,7 @@ protected void doHandleMessages(Collection messages) { trace.hasSpansSatisfyingExactly( span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> - span.hasName("Batch of Messages") + span.hasName("destination receive") .hasKind(SpanKind.CONSUMER) .hasLinks( LinkData.create( @@ -197,10 +202,11 @@ protected void doHandleMessages(Collection messages) { TraceFlags.getDefault(), TraceState.getDefault()))) .hasTotalRecordedLinks(2) - .hasAttribute( - SemanticAttributes.MESSAGING_OPERATION, MessageOperation.RECEIVE.name()) + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "receive") .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") - .hasTotalAttributeCount(2) + .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") + .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 5L) + .hasTotalAttributeCount(4) .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) .hasTraceId(parentSpan.getSpanContext().getTraceId()))); @@ -211,6 +217,7 @@ protected void doHandleMessages(Collection messages) { public void multipleRunsOfTheHandler() { Message sqsMessage1 = Message.builder() + .body("Hello") .attributesWithStrings( Collections.singletonMap( "AWSTraceHeader", @@ -219,6 +226,7 @@ public void multipleRunsOfTheHandler() { Message sqsMessage2 = Message.builder() + .body("Hello World") .attributesWithStrings( Collections.singletonMap( "AWSTraceHeader", @@ -228,7 +236,7 @@ public void multipleRunsOfTheHandler() { AtomicInteger counter = new AtomicInteger(0); SqsMessageHandler messageHandler = - new SqsMessageHandler(getOpenTelemetry(), messages -> "Batch of Messages") { + new SqsMessageHandler(getOpenTelemetry(), "destination", MessageOperation.RECEIVE) { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); @@ -249,7 +257,7 @@ protected void doHandleMessages(Collection messages) { trace.hasSpansSatisfyingExactly( span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> - span.hasName("Batch of Messages") + span.hasName("destination receive") .hasKind(SpanKind.CONSUMER) .hasLinks( LinkData.create( @@ -259,14 +267,15 @@ protected void doHandleMessages(Collection messages) { TraceFlags.getSampled(), TraceState.getDefault()))) .hasTotalRecordedLinks(1) - .hasAttribute( - SemanticAttributes.MESSAGING_OPERATION, MessageOperation.RECEIVE.name()) + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "receive") .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") - .hasTotalAttributeCount(2) + .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") + .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 5L) + .hasTotalAttributeCount(4) .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) .hasTraceId(parentSpan.getSpanContext().getTraceId()), span -> - span.hasName("Batch of Messages") + span.hasName("destination receive") .hasKind(SpanKind.CONSUMER) .hasLinks( LinkData.create( @@ -276,10 +285,11 @@ protected void doHandleMessages(Collection messages) { TraceFlags.getDefault(), TraceState.getDefault()))) .hasTotalRecordedLinks(1) - .hasAttribute( - SemanticAttributes.MESSAGING_OPERATION, MessageOperation.RECEIVE.name()) + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "receive") .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") - .hasTotalAttributeCount(2) + .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") + .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 11L) + .hasTotalAttributeCount(4) .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) .hasTraceId(parentSpan.getSpanContext().getTraceId()))); @@ -291,7 +301,7 @@ public void noMessages() { AtomicInteger counter = new AtomicInteger(0); SqsMessageHandler messageHandler = - new SqsMessageHandler(getOpenTelemetry(), messages -> "Batch of Messages") { + new SqsMessageHandler(getOpenTelemetry(), "destination", MessageOperation.RECEIVE) { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); @@ -311,13 +321,14 @@ protected void doHandleMessages(Collection messages) { trace.hasSpansSatisfyingExactly( span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> - span.hasName("Batch of Messages") + span.hasName("destination receive") .hasKind(SpanKind.CONSUMER) .hasTotalRecordedLinks(0) - .hasAttribute( - SemanticAttributes.MESSAGING_OPERATION, MessageOperation.RECEIVE.name()) + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "receive") .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") - .hasTotalAttributeCount(2) + .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") + .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 0L) + .hasTotalAttributeCount(4) .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) .hasTraceId(parentSpan.getSpanContext().getTraceId()))); @@ -328,6 +339,7 @@ protected void doHandleMessages(Collection messages) { public void changeDefaults() { Message sqsMessage = Message.builder() + .body("Hello") .attributesWithStrings( Collections.singletonMap( "AWSTraceHeader", @@ -337,7 +349,7 @@ public void changeDefaults() { AtomicInteger counter = new AtomicInteger(0); SqsMessageHandler messageHandler = - new SqsMessageHandler(getOpenTelemetry(), messages -> "New Name", MessageOperation.PROCESS) { + new SqsMessageHandler(getOpenTelemetry(), "destination2", MessageOperation.PROCESS) { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); @@ -357,7 +369,7 @@ protected void doHandleMessages(Collection messages) { trace.hasSpansSatisfyingExactly( span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> - span.hasName("New Name") + span.hasName("destination2 process") .hasKind(SpanKind.CONSUMER) .hasLinks( LinkData.create( @@ -367,10 +379,11 @@ protected void doHandleMessages(Collection messages) { TraceFlags.getSampled(), TraceState.getDefault()))) .hasTotalRecordedLinks(1) - .hasAttribute( - SemanticAttributes.MESSAGING_OPERATION, MessageOperation.PROCESS.name()) + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") - .hasTotalAttributeCount(2) + .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination2") + .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 5L) + .hasTotalAttributeCount(4) .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) .hasTraceId(parentSpan.getSpanContext().getTraceId()))); @@ -381,6 +394,7 @@ protected void doHandleMessages(Collection messages) { public void testSender() { Message sqsMessage = Message.builder() + .body("Hello") .attributesWithStrings( Collections.singletonMap( "AWSTraceHeader", @@ -390,7 +404,7 @@ public void testSender() { AtomicInteger counter = new AtomicInteger(0); SqsMessageHandler messageHandler = - new SqsMessageHandler(getOpenTelemetry(), messages -> "New Name", MessageOperation.SEND) { + new SqsMessageHandler(getOpenTelemetry(), "destination3", MessageOperation.SEND) { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); @@ -410,7 +424,7 @@ protected void doHandleMessages(Collection messages) { trace.hasSpansSatisfyingExactly( span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> - span.hasName("New Name") + span.hasName("destination3 send") .hasKind(SpanKind.PRODUCER) .hasLinks( LinkData.create( @@ -420,10 +434,10 @@ protected void doHandleMessages(Collection messages) { TraceFlags.getSampled(), TraceState.getDefault()))) .hasTotalRecordedLinks(1) - .hasAttribute( - SemanticAttributes.MESSAGING_OPERATION, MessageOperation.SEND.name()) .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") - .hasTotalAttributeCount(2) + .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination3") + .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 5L) + .hasTotalAttributeCount(3) .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) .hasTraceId(parentSpan.getSpanContext().getTraceId()))); @@ -434,6 +448,7 @@ protected void doHandleMessages(Collection messages) { public void invalidUpstreamParent() { Message sqsMessage = Message.builder() + .body("Hello") .attributesWithStrings( Collections.singletonMap( "AWSTraceHeader", "Root=1-55555555-invalid;Parent=1234567890123456;Sampled=1")) @@ -442,7 +457,7 @@ public void invalidUpstreamParent() { AtomicInteger counter = new AtomicInteger(0); SqsMessageHandler messageHandler = - new SqsMessageHandler(getOpenTelemetry(), messages -> "Batch of Messages") { + new SqsMessageHandler(getOpenTelemetry(), "destination", MessageOperation.RECEIVE) { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); @@ -464,6 +479,7 @@ protected void doHandleMessages(Collection messages) { public void exceptionInHandle() { Message sqsMessage = Message.builder() + .body("Hello") .attributesWithStrings( Collections.singletonMap( "AWSTraceHeader", @@ -473,7 +489,7 @@ public void exceptionInHandle() { AtomicInteger counter = new AtomicInteger(0); SqsMessageHandler messageHandler = - new SqsMessageHandler(getOpenTelemetry(), messages -> "Batch of Messages") { + new SqsMessageHandler(getOpenTelemetry(), "destination", MessageOperation.RECEIVE) { @Override protected void doHandleMessages(Collection messages) { counter.getAndIncrement(); @@ -498,7 +514,7 @@ protected void doHandleMessages(Collection messages) { trace.hasSpansSatisfyingExactly( span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> - span.hasName("Batch of Messages") + span.hasName("destination receive") .hasKind(SpanKind.CONSUMER) .hasLinks( LinkData.create( @@ -509,10 +525,11 @@ protected void doHandleMessages(Collection messages) { TraceState.getDefault()))) .hasTotalRecordedLinks(1) .hasException(new RuntimeException("Injected Error")) - .hasAttribute( - SemanticAttributes.MESSAGING_OPERATION, MessageOperation.RECEIVE.name()) + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "receive") .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") - .hasTotalAttributeCount(2) + .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") + .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 5L) + .hasTotalAttributeCount(4) .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) .hasTraceId(parentSpan.getSpanContext().getTraceId()))); diff --git a/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/XrayTestInstrumenter.java b/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/XrayTestInstrumenter.java index bf2cd0d20631..33966b8c0a1e 100644 --- a/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/XrayTestInstrumenter.java +++ b/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/XrayTestInstrumenter.java @@ -1,5 +1,12 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + package io.opentelemetry.instrumentation.messagehandler; +import static org.awaitility.Awaitility.await; + import io.opentelemetry.context.Context; import io.opentelemetry.context.propagation.ContextPropagators; import io.opentelemetry.contrib.awsxray.propagator.AwsXrayPropagator; @@ -20,9 +27,6 @@ import io.opentelemetry.sdk.trace.SpanProcessor; import io.opentelemetry.sdk.trace.data.SpanData; import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor; -import org.awaitility.core.ConditionTimeoutException; -import org.junit.jupiter.api.AfterEach; -import javax.annotation.Nullable; import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; @@ -31,8 +35,9 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.function.Consumer; - -import static org.awaitility.Awaitility.await; +import javax.annotation.Nullable; +import org.awaitility.core.ConditionTimeoutException; +import org.junit.jupiter.api.AfterEach; public class XrayTestInstrumenter { private static final OpenTelemetrySdk openTelemetry; diff --git a/instrumentation/message-handler/core/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageHandler.java b/instrumentation/message-handler/core/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageHandler.java index 540c6bf1bbd4..1a72ecb1b86d 100644 --- a/instrumentation/message-handler/core/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageHandler.java +++ b/instrumentation/message-handler/core/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageHandler.java @@ -5,81 +5,21 @@ package io.opentelemetry.instrumentation.messagehandler; -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; -import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; -import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessageOperation; -import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; import java.util.Collection; -import javax.annotation.Nullable; public abstract class MessageHandler { - private final MessageOperation messagingOperation; - private final OpenTelemetry openTelemetry; - private final SpanNameExtractor> spanNameExtractor; - - protected Instrumenter, Void> messageInstrumenter; - - public MessageHandler( - OpenTelemetry openTelemetry, SpanNameExtractor> spanNameExtractor) { - this(openTelemetry, spanNameExtractor, MessageOperation.RECEIVE); - } - - public MessageHandler( - OpenTelemetry openTelemetry, - SpanNameExtractor> spanNameExtractor, - MessageOperation messageOperation) { - this.openTelemetry = openTelemetry; - this.spanNameExtractor = spanNameExtractor; - this.messagingOperation = messageOperation; - - setup(); - } - - protected MessageOperation getMessagingOperation() { - return messagingOperation; - } - - protected OpenTelemetry getOpenTelemetry() { - return openTelemetry; - } - - protected SpanNameExtractor> getSpanNameExtractor() { - return spanNameExtractor; - } - - protected abstract void setup(); + protected abstract Instrumenter, Void> getMessageInstrumenter(); protected abstract void doHandleMessages(Collection messages); - protected AttributesExtractor, Void> getGenericAttributesExtractor() { - return new AttributesExtractor, Void>() { - - @Override - public void onStart( - AttributesBuilder attributes, Context parentContext, Collection messages) { - attributes.put(SemanticAttributes.MESSAGING_OPERATION, messagingOperation.name()); - } - - @Override - public void onEnd( - AttributesBuilder attributes, - Context context, - Collection messages, - @Nullable Void unused, - @Nullable Throwable error) {} - }; - } - public void handleMessages(Collection messages) { Context parentContext = Context.current(); - if (messageInstrumenter.shouldStart(parentContext, messages)) { + if (getMessageInstrumenter().shouldStart(parentContext, messages)) { io.opentelemetry.context.Context otelContext = - messageInstrumenter.start(parentContext, messages); + getMessageInstrumenter().start(parentContext, messages); Throwable error = null; try (Scope ignored = otelContext.makeCurrent()) { doHandleMessages(messages); @@ -87,7 +27,7 @@ public void handleMessages(Collection messages) { error = t; throw t; } finally { - messageInstrumenter.end(otelContext, messages, null, error); + getMessageInstrumenter().end(otelContext, messages, null, error); } } else { doHandleMessages(messages); From 371d79339db4be0fb5b87ede31c9a9b71046c12d Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Tue, 13 Jun 2023 10:09:44 -0700 Subject: [PATCH 31/47] Refactoring moduel heirarchy --- instrumentation/message-handler/{core => }/README.md | 0 .../{aws => message-handler-aws-2.2/library}/README.md | 0 .../{aws => message-handler-aws-2.2/library}/build.gradle.kts | 2 +- .../instrumentation/messagehandler/SqsMessageHandler.java | 3 +-- .../instrumentation/messagehandler/SqsMessageHandlerTest.java | 0 .../instrumentation/messagehandler/XrayTestInstrumenter.java | 0 .../{core => message-handler-core/library}/build.gradle.kts | 0 .../instrumentation/messagehandler/MessageHandler.java | 0 settings.gradle.kts | 4 ++-- 9 files changed, 4 insertions(+), 5 deletions(-) rename instrumentation/message-handler/{core => }/README.md (100%) rename instrumentation/message-handler/{aws => message-handler-aws-2.2/library}/README.md (100%) rename instrumentation/message-handler/{aws => message-handler-aws-2.2/library}/build.gradle.kts (77%) rename instrumentation/message-handler/{aws => message-handler-aws-2.2/library}/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandler.java (97%) rename instrumentation/message-handler/{aws => message-handler-aws-2.2/library}/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandlerTest.java (100%) rename instrumentation/message-handler/{aws => message-handler-aws-2.2/library}/src/test/java/io/opentelemetry/instrumentation/messagehandler/XrayTestInstrumenter.java (100%) rename instrumentation/message-handler/{core => message-handler-core/library}/build.gradle.kts (100%) rename instrumentation/message-handler/{core => message-handler-core/library}/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageHandler.java (100%) diff --git a/instrumentation/message-handler/core/README.md b/instrumentation/message-handler/README.md similarity index 100% rename from instrumentation/message-handler/core/README.md rename to instrumentation/message-handler/README.md diff --git a/instrumentation/message-handler/aws/README.md b/instrumentation/message-handler/message-handler-aws-2.2/library/README.md similarity index 100% rename from instrumentation/message-handler/aws/README.md rename to instrumentation/message-handler/message-handler-aws-2.2/library/README.md diff --git a/instrumentation/message-handler/aws/build.gradle.kts b/instrumentation/message-handler/message-handler-aws-2.2/library/build.gradle.kts similarity index 77% rename from instrumentation/message-handler/aws/build.gradle.kts rename to instrumentation/message-handler/message-handler-aws-2.2/library/build.gradle.kts index 09d8446d0126..ce53b2c1fbca 100644 --- a/instrumentation/message-handler/aws/build.gradle.kts +++ b/instrumentation/message-handler/message-handler-aws-2.2/library/build.gradle.kts @@ -5,7 +5,7 @@ plugins { dependencies { compileOnly("io.opentelemetry:opentelemetry-sdk") - implementation(project(":instrumentation:message-handler:core")) + implementation(project(":instrumentation:message-handler:message-handler-core:library")) implementation(project(":instrumentation:aws-sdk:aws-sdk-2.2:library")) library("software.amazon.awssdk:sqs:2.2.0") diff --git a/instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandler.java b/instrumentation/message-handler/message-handler-aws-2.2/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandler.java similarity index 97% rename from instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandler.java rename to instrumentation/message-handler/message-handler-aws-2.2/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandler.java index 5e6ba81b6fdf..e9d63dcd27b4 100644 --- a/instrumentation/message-handler/aws/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandler.java +++ b/instrumentation/message-handler/message-handler-aws-2.2/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandler.java @@ -46,8 +46,7 @@ public SqsMessageHandler( @Override protected Instrumenter, Void> getMessageInstrumenter() { return Instrumenter., Void>builder( - openTelemetry, "io.opentelemetry.message-handler", getSpanNameExtractor()) - .setInstrumentationVersion("1.0") + openTelemetry, "io.opentelemetry.message-handler-aws-2.2", getSpanNameExtractor()) .addAttributesExtractor(getAttributesExtractor()) .addSpanLinksExtractor(getSpanLinksExtractor()) .buildInstrumenter(getSpanKindExtractor()); diff --git a/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandlerTest.java b/instrumentation/message-handler/message-handler-aws-2.2/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandlerTest.java similarity index 100% rename from instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandlerTest.java rename to instrumentation/message-handler/message-handler-aws-2.2/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandlerTest.java diff --git a/instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/XrayTestInstrumenter.java b/instrumentation/message-handler/message-handler-aws-2.2/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/XrayTestInstrumenter.java similarity index 100% rename from instrumentation/message-handler/aws/src/test/java/io/opentelemetry/instrumentation/messagehandler/XrayTestInstrumenter.java rename to instrumentation/message-handler/message-handler-aws-2.2/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/XrayTestInstrumenter.java diff --git a/instrumentation/message-handler/core/build.gradle.kts b/instrumentation/message-handler/message-handler-core/library/build.gradle.kts similarity index 100% rename from instrumentation/message-handler/core/build.gradle.kts rename to instrumentation/message-handler/message-handler-core/library/build.gradle.kts diff --git a/instrumentation/message-handler/core/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageHandler.java b/instrumentation/message-handler/message-handler-core/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageHandler.java similarity index 100% rename from instrumentation/message-handler/core/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageHandler.java rename to instrumentation/message-handler/message-handler-core/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageHandler.java diff --git a/settings.gradle.kts b/settings.gradle.kts index 02dfe0ed01b5..a09cdf860cef 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -356,8 +356,8 @@ hideFromDependabot(":instrumentation:logback:logback-mdc-1.0:javaagent") hideFromDependabot(":instrumentation:logback:logback-mdc-1.0:library") hideFromDependabot(":instrumentation:logback:logback-mdc-1.0:testing") hideFromDependabot(":instrumentation:methods:javaagent") -hideFromDependabot(":instrumentation:message-handler:aws:testing") -hideFromDependabot(":instrumentation:message-handler:core:testing") +hideFromDependabot(":instrumentation:message-handler:message-handler-aws-2.2:library") +hideFromDependabot(":instrumentation:message-handler:message-handler-core:library") hideFromDependabot(":instrumentation:micrometer:micrometer-1.5:javaagent") hideFromDependabot(":instrumentation:micrometer:micrometer-1.5:library") hideFromDependabot(":instrumentation:micrometer:micrometer-1.5:testing") From 5a51314289ba84921ce569644c7fe277d81c9af8 Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Tue, 13 Jun 2023 12:28:51 -0700 Subject: [PATCH 32/47] Refactoring modules --- .../aws-sdk/aws-sdk-2.2/library/README.md | 20 +++++++++++++++++++ .../aws-sdk-2.2/library/build.gradle.kts | 5 ++++- .../awssdk/v2_2/SqsMessageAccess.java | 4 ++-- .../awssdk/v2_2}/SqsMessageHandler.java | 7 +++---- .../awssdk/v2_2/SqsParentContext.java | 6 +++--- .../awssdk/v2_2}/SqsMessageHandlerTest.java | 2 +- .../awssdk/v2_2}/XrayTestInstrumenter.java | 2 +- .../library}/README.md | 0 .../library/build.gradle.kts | 0 .../messagehandler/MessageHandler.java | 0 .../message-handler-aws-2.2/library/README.md | 19 ------------------ .../library/build.gradle.kts | 14 ------------- settings.gradle.kts | 3 +-- 13 files changed, 35 insertions(+), 47 deletions(-) rename instrumentation/{message-handler/message-handler-aws-2.2/library/src/main/java/io/opentelemetry/instrumentation/messagehandler => aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2}/SqsMessageHandler.java (94%) rename instrumentation/{message-handler/message-handler-aws-2.2/library/src/test/java/io/opentelemetry/instrumentation/messagehandler => aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2}/SqsMessageHandlerTest.java (99%) rename instrumentation/{message-handler/message-handler-aws-2.2/library/src/test/java/io/opentelemetry/instrumentation/messagehandler => aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2}/XrayTestInstrumenter.java (98%) rename instrumentation/message-handler/{ => message-handler-1.0/library}/README.md (100%) rename instrumentation/message-handler/{message-handler-core => message-handler-1.0}/library/build.gradle.kts (100%) rename instrumentation/message-handler/{message-handler-core => message-handler-1.0}/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageHandler.java (100%) delete mode 100644 instrumentation/message-handler/message-handler-aws-2.2/library/README.md delete mode 100644 instrumentation/message-handler/message-handler-aws-2.2/library/build.gradle.kts diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/README.md b/instrumentation/aws-sdk/aws-sdk-2.2/library/README.md index 7e473fee406b..3cdbbc638534 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/README.md +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/README.md @@ -24,3 +24,23 @@ This format is the only format recognized by AWS managed services, and populatin propagating the trace through them. If this does not fulfill your use case, perhaps because you are using the same SDK with a different non-AWS managed service, let us know so we can provide configuration for this behavior. + +## Using SqsMessageHandler + +1. Retrieve a collection of messages to process. +2. Create a SqsMessageHandler and provide the business logic on what to do with the messages. +3. Call the handleMessages function and pass in your messages. +4. It will call the doHandleMessages function you provided wrapped in the messaging span. + +```java +Collection sqsMessages; + +SqsMessageHandler messageHandler = new SqsMessageHandler(opentelemetry) { + @Override + protected void doHandleMessages(Collection messages) { + // Do my business logic + } +}; + +messageHandler.handleMessages(sqsMessages, "destination.name", MessageOperation.RECEIVE); +``` diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts b/instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts index b84ddd1a4936..85e9524a1f40 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts @@ -5,8 +5,11 @@ plugins { dependencies { implementation("io.opentelemetry.contrib:opentelemetry-aws-xray-propagator") + implementation(project(":instrumentation:message-handler:message-handler-1.0:library")) + + library("software.amazon.awssdk:aws-core:2.2.0") library("software.amazon.awssdk:aws-core:2.2.0") - library("software.amazon.awssdk:aws-json-protocol:2.2.0") + library("software.amazon.awssdk:sqs:2.2.0") testImplementation(project(":instrumentation:aws-sdk:aws-sdk-2.2:testing")) diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageAccess.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageAccess.java index 257011ae5e6d..e8925b0a50f8 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageAccess.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageAccess.java @@ -30,7 +30,7 @@ * href="https://github.com/aws/aws-sdk-java-v2/blob/2.2.0/services/sqs/src/main/resources/codegen-resources/service-2.json#L821-L856">Definition * JSON */ -public final class SqsMessageAccess { +final class SqsMessageAccess { @Nullable private static final MethodHandle GET_ATTRIBUTES; @Nullable private static final MethodHandle GET_MESSAGE_ATTRIBUTES; @@ -68,7 +68,7 @@ public final class SqsMessageAccess { } @SuppressWarnings("unchecked") - public static Map getAttributes(Object message) { + static Map getAttributes(Object message) { if (GET_ATTRIBUTES == null) { return Collections.emptyMap(); } diff --git a/instrumentation/message-handler/message-handler-aws-2.2/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandler.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java similarity index 94% rename from instrumentation/message-handler/message-handler-aws-2.2/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandler.java rename to instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java index e9d63dcd27b4..e67b6572b504 100644 --- a/instrumentation/message-handler/message-handler-aws-2.2/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandler.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.messagehandler; +package io.opentelemetry.instrumentation.awssdk.v2_2; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.trace.Span; @@ -19,8 +19,7 @@ import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessagingAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessagingAttributesGetter; import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessagingSpanNameExtractor; -import io.opentelemetry.instrumentation.awssdk.v2_2.SqsMessageAccess; -import io.opentelemetry.instrumentation.awssdk.v2_2.SqsParentContext; +import io.opentelemetry.instrumentation.messagehandler.MessageHandler; import java.util.Collection; import java.util.Map; import java.util.logging.Level; @@ -46,7 +45,7 @@ public SqsMessageHandler( @Override protected Instrumenter, Void> getMessageInstrumenter() { return Instrumenter., Void>builder( - openTelemetry, "io.opentelemetry.message-handler-aws-2.2", getSpanNameExtractor()) + openTelemetry, "io.opentelemetry.aws-sdk-2.2", getSpanNameExtractor()) .addAttributesExtractor(getAttributesExtractor()) .addSpanLinksExtractor(getSpanLinksExtractor()) .buildInstrumenter(getSpanKindExtractor()); diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsParentContext.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsParentContext.java index 3b914b7744ec..9df3443c660e 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsParentContext.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsParentContext.java @@ -13,7 +13,7 @@ import java.util.Map; import software.amazon.awssdk.core.SdkPojo; -public final class SqsParentContext { +final class SqsParentContext { enum StringMapGetter implements TextMapGetter> { INSTANCE; @@ -52,13 +52,13 @@ public String get(Map map, String s) { static final String AWS_TRACE_SYSTEM_ATTRIBUTE = "AWSTraceHeader"; - public static Context ofMessageAttributes( + static Context ofMessageAttributes( Map messageAttributes, TextMapPropagator propagator) { return propagator.extract( Context.root(), messageAttributes, MessageAttributeValueMapGetter.INSTANCE); } - public static Context ofSystemAttributes(Map systemAttributes) { + static Context ofSystemAttributes(Map systemAttributes) { String traceHeader = systemAttributes.get(AWS_TRACE_SYSTEM_ATTRIBUTE); return AwsXrayPropagator.getInstance() .extract( diff --git a/instrumentation/message-handler/message-handler-aws-2.2/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandlerTest.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandlerTest.java similarity index 99% rename from instrumentation/message-handler/message-handler-aws-2.2/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandlerTest.java rename to instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandlerTest.java index 1163df92c81f..8576eefbcc2c 100644 --- a/instrumentation/message-handler/message-handler-aws-2.2/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/SqsMessageHandlerTest.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandlerTest.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.messagehandler; +package io.opentelemetry.instrumentation.awssdk.v2_2; import static org.junit.jupiter.api.Assertions.assertThrows; diff --git a/instrumentation/message-handler/message-handler-aws-2.2/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/XrayTestInstrumenter.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/XrayTestInstrumenter.java similarity index 98% rename from instrumentation/message-handler/message-handler-aws-2.2/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/XrayTestInstrumenter.java rename to instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/XrayTestInstrumenter.java index 33966b8c0a1e..c911aa01562d 100644 --- a/instrumentation/message-handler/message-handler-aws-2.2/library/src/test/java/io/opentelemetry/instrumentation/messagehandler/XrayTestInstrumenter.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/XrayTestInstrumenter.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.messagehandler; +package io.opentelemetry.instrumentation.awssdk.v2_2; import static org.awaitility.Awaitility.await; diff --git a/instrumentation/message-handler/README.md b/instrumentation/message-handler/message-handler-1.0/library/README.md similarity index 100% rename from instrumentation/message-handler/README.md rename to instrumentation/message-handler/message-handler-1.0/library/README.md diff --git a/instrumentation/message-handler/message-handler-core/library/build.gradle.kts b/instrumentation/message-handler/message-handler-1.0/library/build.gradle.kts similarity index 100% rename from instrumentation/message-handler/message-handler-core/library/build.gradle.kts rename to instrumentation/message-handler/message-handler-1.0/library/build.gradle.kts diff --git a/instrumentation/message-handler/message-handler-core/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageHandler.java b/instrumentation/message-handler/message-handler-1.0/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageHandler.java similarity index 100% rename from instrumentation/message-handler/message-handler-core/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageHandler.java rename to instrumentation/message-handler/message-handler-1.0/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageHandler.java diff --git a/instrumentation/message-handler/message-handler-aws-2.2/library/README.md b/instrumentation/message-handler/message-handler-aws-2.2/library/README.md deleted file mode 100644 index 8dfdc56ceb06..000000000000 --- a/instrumentation/message-handler/message-handler-aws-2.2/library/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# Using SqsMessageHandler - -1. Retrieve a collection of messages to process. -2. Create a SqsMessageHandler and provide the business logic on what to do with the messages. -3. Call the handleMessages function and pass in your messages. -4. It will call the doHandleMessages function you provided wrapped in the messaging span. - -```java -Collection sqsMessages; - -SqsMessageHandler messageHandler = new SqsMessageHandler(opentelemetry) { - @Override - protected void doHandleMessages(Collection messages) { - // Do my business logic - } -}; - -messageHandler.handleMessages(sqsMessages, "destination.name", MessageOperation.RECEIVE); -``` diff --git a/instrumentation/message-handler/message-handler-aws-2.2/library/build.gradle.kts b/instrumentation/message-handler/message-handler-aws-2.2/library/build.gradle.kts deleted file mode 100644 index ce53b2c1fbca..000000000000 --- a/instrumentation/message-handler/message-handler-aws-2.2/library/build.gradle.kts +++ /dev/null @@ -1,14 +0,0 @@ -plugins { - id("otel.library-instrumentation") -} - -dependencies { - compileOnly("io.opentelemetry:opentelemetry-sdk") - - implementation(project(":instrumentation:message-handler:message-handler-core:library")) - implementation(project(":instrumentation:aws-sdk:aws-sdk-2.2:library")) - - library("software.amazon.awssdk:sqs:2.2.0") - - implementation("io.opentelemetry.contrib:opentelemetry-aws-xray-propagator") -} diff --git a/settings.gradle.kts b/settings.gradle.kts index a09cdf860cef..b23e6157126d 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -356,8 +356,7 @@ hideFromDependabot(":instrumentation:logback:logback-mdc-1.0:javaagent") hideFromDependabot(":instrumentation:logback:logback-mdc-1.0:library") hideFromDependabot(":instrumentation:logback:logback-mdc-1.0:testing") hideFromDependabot(":instrumentation:methods:javaagent") -hideFromDependabot(":instrumentation:message-handler:message-handler-aws-2.2:library") -hideFromDependabot(":instrumentation:message-handler:message-handler-core:library") +hideFromDependabot(":instrumentation:message-handler:message-handler-1.0:library") hideFromDependabot(":instrumentation:micrometer:micrometer-1.5:javaagent") hideFromDependabot(":instrumentation:micrometer:micrometer-1.5:library") hideFromDependabot(":instrumentation:micrometer:micrometer-1.5:testing") From 46feb1593cf5169aade37ee46fd70bd660b6e92f Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Tue, 13 Jun 2023 12:43:53 -0700 Subject: [PATCH 33/47] Remove Warning --- .../instrumentation/awssdk/v2_2/SqsMessageHandler.java | 1 + 1 file changed, 1 insertion(+) diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java index e67b6572b504..07e988008c8e 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java @@ -67,6 +67,7 @@ public String getSystem(Collection messages) { @Nullable @Override + @SuppressWarnings("deprecation") public String getDestinationKind(Collection messages) { return null; } From 8505b8e0a3d66749e80d879bc964db6c0630108b Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Tue, 13 Jun 2023 12:51:41 -0700 Subject: [PATCH 34/47] Fixing spot check --- instrumentation/aws-sdk/aws-sdk-2.2/library/README.md | 4 ++-- .../instrumentation/awssdk/v2_2/SqsMessageHandler.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/README.md b/instrumentation/aws-sdk/aws-sdk-2.2/library/README.md index 3cdbbc638534..f7984c86deae 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/README.md +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/README.md @@ -33,11 +33,11 @@ configuration for this behavior. 4. It will call the doHandleMessages function you provided wrapped in the messaging span. ```java -Collection sqsMessages; +Collection sqsMessages; SqsMessageHandler messageHandler = new SqsMessageHandler(opentelemetry) { @Override - protected void doHandleMessages(Collection messages) { + protected void doHandleMessages(Collection messages) { // Do my business logic } }; diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java index 07e988008c8e..e92a2b29a6eb 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java @@ -67,7 +67,7 @@ public String getSystem(Collection messages) { @Nullable @Override - @SuppressWarnings("deprecation") + @SuppressWarnings({"deprecation"}) // Inheriting from interface public String getDestinationKind(Collection messages) { return null; } From e81aa56e14ebcfccca1119c2da511ff5c5274e94 Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Thu, 15 Jun 2023 09:23:21 -0700 Subject: [PATCH 35/47] Refactor to receiver --- .../aws-sdk/aws-sdk-2.2/library/README.md | 28 +- ...geHandler.java => SqsMessageReceiver.java} | 87 ++- .../awssdk/v2_2/SqsMessageHandlerTest.java | 538 ------------------ .../awssdk/v2_2/SqsMessageReceiverTest.java | 352 ++++++++++++ .../message-handler-1.0/library/README.md | 6 +- .../messagehandler/MessageHandler.java | 36 -- .../messagehandler/MessageReceiver.java | 42 ++ 7 files changed, 451 insertions(+), 638 deletions(-) rename instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/{SqsMessageHandler.java => SqsMessageReceiver.java} (51%) delete mode 100644 instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandlerTest.java create mode 100644 instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageReceiverTest.java delete mode 100644 instrumentation/message-handler/message-handler-1.0/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageHandler.java create mode 100644 instrumentation/message-handler/message-handler-1.0/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageReceiver.java diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/README.md b/instrumentation/aws-sdk/aws-sdk-2.2/library/README.md index f7984c86deae..fd2defeae51a 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/README.md +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/README.md @@ -25,22 +25,22 @@ propagating the trace through them. If this does not fulfill your use case, perh using the same SDK with a different non-AWS managed service, let us know so we can provide configuration for this behavior. -## Using SqsMessageHandler +## Using SqsMessageReceiver -1. Retrieve a collection of messages to process. -2. Create a SqsMessageHandler and provide the business logic on what to do with the messages. -3. Call the handleMessages function and pass in your messages. -4. It will call the doHandleMessages function you provided wrapped in the messaging span. +This instrumentation takes a ReceiveMessageRequest and returns a ReceiveMessageResponse for SQS. +A span is created for the call to SQS with appropriate attributes and span links. +Span links comes from each of the response's messages as if this were a batch of messages. -```java -Collection sqsMessages; +1. Setup SqsMessageReceiver so that it knows how to pull information from SQS. +Pass in your OpenTelemetry, the name of the destination, and SqsClient. +2. Call the receive method on SqsMessageReceiver and pass in the request. +3. It will return the response and wrap the call in a span. -SqsMessageHandler messageHandler = new SqsMessageHandler(opentelemetry) { - @Override - protected void doHandleMessages(Collection messages) { - // Do my business logic - } -}; +```java +OpenTelemetry openTelemetry; +SqsClient sqsClient; +ReceiveMessageRequest request; -messageHandler.handleMessages(sqsMessages, "destination.name", MessageOperation.RECEIVE); +SqsMessageReceiver messageReceiver = new SqsMessageReceiver(openTelemetry, "destination", sqsClient); +ReceiveMessageResponse response = messageReceiver.receive(request); ``` diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageReceiver.java similarity index 51% rename from instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java rename to instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageReceiver.java index e92a2b29a6eb..97c352824173 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageReceiver.java @@ -19,85 +19,88 @@ import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessagingAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessagingAttributesGetter; import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessagingSpanNameExtractor; -import io.opentelemetry.instrumentation.messagehandler.MessageHandler; -import java.util.Collection; +import io.opentelemetry.instrumentation.messagehandler.MessageReceiver; import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; import javax.annotation.Nullable; import software.amazon.awssdk.core.SdkPojo; +import software.amazon.awssdk.services.sqs.SqsClient; import software.amazon.awssdk.services.sqs.model.Message; +import software.amazon.awssdk.services.sqs.model.ReceiveMessageRequest; +import software.amazon.awssdk.services.sqs.model.ReceiveMessageResponse; -public abstract class SqsMessageHandler extends MessageHandler { - private static final Logger logger = Logger.getLogger(SqsMessageHandler.class.getName()); - +public class SqsMessageReceiver + extends MessageReceiver { private final OpenTelemetry openTelemetry; - private final MessageOperation messageOperation; private final String destination; + private final SqsClient sqsClient; - public SqsMessageHandler( - OpenTelemetry openTelemetry, String destination, MessageOperation messageOperation) { + public SqsMessageReceiver(OpenTelemetry openTelemetry, String destination, SqsClient sqsClient) { this.openTelemetry = openTelemetry; - this.messageOperation = messageOperation; this.destination = destination; + this.sqsClient = sqsClient; + } + + @Override + public ReceiveMessageResponse doReceive(ReceiveMessageRequest request) { + return sqsClient.receiveMessage(request); } @Override - protected Instrumenter, Void> getMessageInstrumenter() { - return Instrumenter., Void>builder( + protected Instrumenter getMessageInstrumenter() { + return Instrumenter.builder( openTelemetry, "io.opentelemetry.aws-sdk-2.2", getSpanNameExtractor()) .addAttributesExtractor(getAttributesExtractor()) .addSpanLinksExtractor(getSpanLinksExtractor()) .buildInstrumenter(getSpanKindExtractor()); } - protected SpanNameExtractor> getSpanNameExtractor() { - return MessagingSpanNameExtractor.create(getMessageingAttributesGetter(), messageOperation); + protected SpanNameExtractor getSpanNameExtractor() { + return MessagingSpanNameExtractor.create( + getMessageingAttributesGetter(), MessageOperation.RECEIVE); } - private MessagingAttributesGetter, Void> getMessageingAttributesGetter() { + protected MessagingAttributesGetter + getMessageingAttributesGetter() { String destination = this.destination; - return new MessagingAttributesGetter, Void>() { + return new MessagingAttributesGetter() { @Nullable @Override - public String getSystem(Collection messages) { + public String getSystem(ReceiveMessageResponse v) { return "AmazonSQS"; } @Nullable @Override @SuppressWarnings({"deprecation"}) // Inheriting from interface - public String getDestinationKind(Collection messages) { + public String getDestinationKind(ReceiveMessageResponse v) { return null; } @Nullable @Override - public String getDestination(Collection messages) { + public String getDestination(ReceiveMessageResponse v) { return destination; } @Override - public boolean isTemporaryDestination(Collection messages) { + public boolean isTemporaryDestination(ReceiveMessageResponse v) { return false; } @Nullable @Override - public String getConversationId(Collection messages) { + public String getConversationId(ReceiveMessageResponse v) { return null; } @Nullable @Override - public Long getMessagePayloadSize(Collection messages) { + public Long getMessagePayloadSize(ReceiveMessageResponse v) { long total = 0; - for (Message message : messages) { - if (message.body() != null) { - total += message.body().length(); - } + for (Message message : v.messages()) { + total += message.body().length(); } return total; @@ -105,40 +108,32 @@ public Long getMessagePayloadSize(Collection messages) { @Nullable @Override - public Long getMessagePayloadCompressedSize(Collection messages) { + public Long getMessagePayloadCompressedSize(ReceiveMessageResponse v) { return null; } @Nullable @Override - public String getMessageId(Collection messages, @Nullable Void unused) { + public String getMessageId(ReceiveMessageResponse request, Void v) { return null; } }; } - protected SpanKindExtractor> getSpanKindExtractor() { - if (messageOperation == MessageOperation.RECEIVE - || messageOperation == MessageOperation.PROCESS) { - return SpanKindExtractor.alwaysConsumer(); - } else if (messageOperation == MessageOperation.SEND) { - return SpanKindExtractor.alwaysProducer(); - } else { - logger.log( - Level.WARNING, "Unknown Messaging Operation {0}", new Object[] {messageOperation.name()}); - return SpanKindExtractor.alwaysConsumer(); - } + protected SpanKindExtractor getSpanKindExtractor() { + return SpanKindExtractor.alwaysConsumer(); } - protected AttributesExtractor, Void> getAttributesExtractor() { - return MessagingAttributesExtractor.create(getMessageingAttributesGetter(), messageOperation); + protected AttributesExtractor getAttributesExtractor() { + return MessagingAttributesExtractor.create( + getMessageingAttributesGetter(), MessageOperation.RECEIVE); } - protected SpanLinksExtractor> getSpanLinksExtractor() { - TextMapPropagator messagingPropagator = openTelemetry.getPropagators().getTextMapPropagator(); + protected SpanLinksExtractor getSpanLinksExtractor() { + return (spanLinks, parentContext, response) -> { + TextMapPropagator messagingPropagator = openTelemetry.getPropagators().getTextMapPropagator(); - return (spanLinks, parentContext, sqsMessages) -> { - for (Message message : sqsMessages) { + for (Message message : response.messages()) { Map messageAtributes = SqsMessageAccess.getMessageAttributes(message); Context context = diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandlerTest.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandlerTest.java deleted file mode 100644 index 8576eefbcc2c..000000000000 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandlerTest.java +++ /dev/null @@ -1,538 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.awssdk.v2_2; - -import static org.junit.jupiter.api.Assertions.assertThrows; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.SpanContext; -import io.opentelemetry.api.trace.SpanKind; -import io.opentelemetry.api.trace.TraceFlags; -import io.opentelemetry.api.trace.TraceState; -import io.opentelemetry.context.Scope; -import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessageOperation; -import io.opentelemetry.sdk.trace.data.LinkData; -import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; -import org.junit.Assert; -import org.junit.jupiter.api.Test; -import software.amazon.awssdk.services.sqs.model.Message; -import software.amazon.awssdk.services.sqs.model.MessageAttributeValue; - -public class SqsMessageHandlerTest extends XrayTestInstrumenter { - @Test - public void simple() { - Message sqsMessage = - Message.builder() - .body("Hello") - .attributesWithStrings( - Collections.singletonMap( - "AWSTraceHeader", - "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")) - .build(); - - AtomicInteger counter = new AtomicInteger(0); - - SqsMessageHandler messageHandler = - new SqsMessageHandler(getOpenTelemetry(), "destination", MessageOperation.RECEIVE) { - @Override - protected void doHandleMessages(Collection messages) { - counter.getAndIncrement(); - } - }; - - Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); - - try (Scope scope = parentSpan.makeCurrent()) { - messageHandler.handleMessages(Collections.singletonList(sqsMessage)); - } - - parentSpan.end(); - - waitAndAssertTraces( - trace -> - trace.hasSpansSatisfyingExactly( - span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), - span -> - span.hasName("destination receive") - .hasKind(SpanKind.CONSUMER) - .hasLinks( - LinkData.create( - SpanContext.createFromRemoteParent( - "55555555123456789012345678901234", - "1234567890123456", - TraceFlags.getSampled(), - TraceState.getDefault()))) - .hasTotalRecordedLinks(1) - .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "receive") - .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") - .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") - .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 5L) - .hasTotalAttributeCount(4) - .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) - .hasTraceId(parentSpan.getSpanContext().getTraceId()))); - - Assert.assertEquals(1, counter.get()); - } - - @Test - public void simpleMessage() { - Message sqsMessage = - Message.builder() - .body("Hello") - .messageAttributes( - Collections.singletonMap( - "X-Amzn-Trace-Id", - MessageAttributeValue.builder() - .stringValue( - "Root=1-66555555-123456789012345678901234;Parent=2234567890123456;Sampled=1") - .build())) - .build(); - - AtomicInteger counter = new AtomicInteger(0); - - SqsMessageHandler messageHandler = - new SqsMessageHandler(getOpenTelemetry(), "destination", MessageOperation.RECEIVE) { - @Override - protected void doHandleMessages(Collection messages) { - counter.getAndIncrement(); - } - }; - - Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); - - try (Scope scope = parentSpan.makeCurrent()) { - messageHandler.handleMessages(Collections.singletonList(sqsMessage)); - } - - parentSpan.end(); - - waitAndAssertTraces( - trace -> - trace.hasSpansSatisfyingExactly( - span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), - span -> - span.hasName("destination receive") - .hasKind(SpanKind.CONSUMER) - .hasLinks( - LinkData.create( - SpanContext.createFromRemoteParent( - "66555555123456789012345678901234", - "2234567890123456", - TraceFlags.getSampled(), - TraceState.getDefault()))) - .hasTotalRecordedLinks(1) - .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "receive") - .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") - .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") - .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 5L) - .hasTotalAttributeCount(4) - .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) - .hasTraceId(parentSpan.getSpanContext().getTraceId()))); - - Assert.assertEquals(1, counter.get()); - } - - @Test - public void multipleMessages() { - List sqsMessages = new LinkedList<>(); - - Message sqsMessage1 = - Message.builder() - .body("Hello") - .attributesWithStrings( - Collections.singletonMap( - "AWSTraceHeader", - "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")) - .build(); - sqsMessages.add(sqsMessage1); - - Message sqsMessage2 = - Message.builder() - .attributesWithStrings( - Collections.singletonMap( - "AWSTraceHeader", - "Root=1-44444444-123456789012345678901234;Parent=2481624816248161;Sampled=0")) - .build(); - sqsMessages.add(sqsMessage2); - - AtomicInteger counter = new AtomicInteger(0); - - SqsMessageHandler messageHandler = - new SqsMessageHandler(getOpenTelemetry(), "destination", MessageOperation.RECEIVE) { - @Override - protected void doHandleMessages(Collection messages) { - counter.getAndIncrement(); - } - }; - - Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); - - try (Scope scope = parentSpan.makeCurrent()) { - messageHandler.handleMessages(sqsMessages); - } - - parentSpan.end(); - - waitAndAssertTraces( - trace -> - trace.hasSpansSatisfyingExactly( - span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), - span -> - span.hasName("destination receive") - .hasKind(SpanKind.CONSUMER) - .hasLinks( - LinkData.create( - SpanContext.createFromRemoteParent( - "55555555123456789012345678901234", - "1234567890123456", - TraceFlags.getSampled(), - TraceState.getDefault())), - LinkData.create( - SpanContext.createFromRemoteParent( - "44444444123456789012345678901234", - "2481624816248161", - TraceFlags.getDefault(), - TraceState.getDefault()))) - .hasTotalRecordedLinks(2) - .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "receive") - .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") - .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") - .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 5L) - .hasTotalAttributeCount(4) - .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) - .hasTraceId(parentSpan.getSpanContext().getTraceId()))); - - Assert.assertEquals(1, counter.get()); - } - - @Test - public void multipleRunsOfTheHandler() { - Message sqsMessage1 = - Message.builder() - .body("Hello") - .attributesWithStrings( - Collections.singletonMap( - "AWSTraceHeader", - "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")) - .build(); - - Message sqsMessage2 = - Message.builder() - .body("Hello World") - .attributesWithStrings( - Collections.singletonMap( - "AWSTraceHeader", - "Root=1-44444444-123456789012345678901234;Parent=2481624816248161;Sampled=0")) - .build(); - - AtomicInteger counter = new AtomicInteger(0); - - SqsMessageHandler messageHandler = - new SqsMessageHandler(getOpenTelemetry(), "destination", MessageOperation.RECEIVE) { - @Override - protected void doHandleMessages(Collection messages) { - counter.getAndIncrement(); - } - }; - - Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); - - try (Scope scope = parentSpan.makeCurrent()) { - messageHandler.handleMessages(Collections.singletonList(sqsMessage1)); - messageHandler.handleMessages(Collections.singletonList(sqsMessage2)); - } - - parentSpan.end(); - - waitAndAssertTraces( - trace -> - trace.hasSpansSatisfyingExactly( - span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), - span -> - span.hasName("destination receive") - .hasKind(SpanKind.CONSUMER) - .hasLinks( - LinkData.create( - SpanContext.createFromRemoteParent( - "55555555123456789012345678901234", - "1234567890123456", - TraceFlags.getSampled(), - TraceState.getDefault()))) - .hasTotalRecordedLinks(1) - .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "receive") - .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") - .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") - .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 5L) - .hasTotalAttributeCount(4) - .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) - .hasTraceId(parentSpan.getSpanContext().getTraceId()), - span -> - span.hasName("destination receive") - .hasKind(SpanKind.CONSUMER) - .hasLinks( - LinkData.create( - SpanContext.createFromRemoteParent( - "44444444123456789012345678901234", - "2481624816248161", - TraceFlags.getDefault(), - TraceState.getDefault()))) - .hasTotalRecordedLinks(1) - .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "receive") - .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") - .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") - .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 11L) - .hasTotalAttributeCount(4) - .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) - .hasTraceId(parentSpan.getSpanContext().getTraceId()))); - - Assert.assertEquals(2, counter.get()); - } - - @Test - public void noMessages() { - AtomicInteger counter = new AtomicInteger(0); - - SqsMessageHandler messageHandler = - new SqsMessageHandler(getOpenTelemetry(), "destination", MessageOperation.RECEIVE) { - @Override - protected void doHandleMessages(Collection messages) { - counter.getAndIncrement(); - } - }; - - Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); - - try (Scope scope = parentSpan.makeCurrent()) { - messageHandler.handleMessages(Collections.emptyList()); - } - - parentSpan.end(); - - waitAndAssertTraces( - trace -> - trace.hasSpansSatisfyingExactly( - span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), - span -> - span.hasName("destination receive") - .hasKind(SpanKind.CONSUMER) - .hasTotalRecordedLinks(0) - .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "receive") - .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") - .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") - .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 0L) - .hasTotalAttributeCount(4) - .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) - .hasTraceId(parentSpan.getSpanContext().getTraceId()))); - - Assert.assertEquals(1, counter.get()); - } - - @Test - public void changeDefaults() { - Message sqsMessage = - Message.builder() - .body("Hello") - .attributesWithStrings( - Collections.singletonMap( - "AWSTraceHeader", - "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")) - .build(); - - AtomicInteger counter = new AtomicInteger(0); - - SqsMessageHandler messageHandler = - new SqsMessageHandler(getOpenTelemetry(), "destination2", MessageOperation.PROCESS) { - @Override - protected void doHandleMessages(Collection messages) { - counter.getAndIncrement(); - } - }; - - Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); - - try (Scope scope = parentSpan.makeCurrent()) { - messageHandler.handleMessages(Collections.singletonList(sqsMessage)); - } - - parentSpan.end(); - - waitAndAssertTraces( - trace -> - trace.hasSpansSatisfyingExactly( - span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), - span -> - span.hasName("destination2 process") - .hasKind(SpanKind.CONSUMER) - .hasLinks( - LinkData.create( - SpanContext.createFromRemoteParent( - "55555555123456789012345678901234", - "1234567890123456", - TraceFlags.getSampled(), - TraceState.getDefault()))) - .hasTotalRecordedLinks(1) - .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") - .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") - .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination2") - .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 5L) - .hasTotalAttributeCount(4) - .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) - .hasTraceId(parentSpan.getSpanContext().getTraceId()))); - - Assert.assertEquals(1, counter.get()); - } - - @Test - public void testSender() { - Message sqsMessage = - Message.builder() - .body("Hello") - .attributesWithStrings( - Collections.singletonMap( - "AWSTraceHeader", - "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")) - .build(); - - AtomicInteger counter = new AtomicInteger(0); - - SqsMessageHandler messageHandler = - new SqsMessageHandler(getOpenTelemetry(), "destination3", MessageOperation.SEND) { - @Override - protected void doHandleMessages(Collection messages) { - counter.getAndIncrement(); - } - }; - - Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); - - try (Scope scope = parentSpan.makeCurrent()) { - messageHandler.handleMessages(Collections.singletonList(sqsMessage)); - } - - parentSpan.end(); - - waitAndAssertTraces( - trace -> - trace.hasSpansSatisfyingExactly( - span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), - span -> - span.hasName("destination3 send") - .hasKind(SpanKind.PRODUCER) - .hasLinks( - LinkData.create( - SpanContext.createFromRemoteParent( - "55555555123456789012345678901234", - "1234567890123456", - TraceFlags.getSampled(), - TraceState.getDefault()))) - .hasTotalRecordedLinks(1) - .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") - .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination3") - .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 5L) - .hasTotalAttributeCount(3) - .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) - .hasTraceId(parentSpan.getSpanContext().getTraceId()))); - - Assert.assertEquals(1, counter.get()); - } - - @Test - public void invalidUpstreamParent() { - Message sqsMessage = - Message.builder() - .body("Hello") - .attributesWithStrings( - Collections.singletonMap( - "AWSTraceHeader", "Root=1-55555555-invalid;Parent=1234567890123456;Sampled=1")) - .build(); - - AtomicInteger counter = new AtomicInteger(0); - - SqsMessageHandler messageHandler = - new SqsMessageHandler(getOpenTelemetry(), "destination", MessageOperation.RECEIVE) { - @Override - protected void doHandleMessages(Collection messages) { - counter.getAndIncrement(); - } - }; - - Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); - - assertThrows( - StringIndexOutOfBoundsException.class, - () -> { - try (Scope scope = parentSpan.makeCurrent()) { - messageHandler.handleMessages(Collections.singletonList(sqsMessage)); - } - }); - } - - @Test - public void exceptionInHandle() { - Message sqsMessage = - Message.builder() - .body("Hello") - .attributesWithStrings( - Collections.singletonMap( - "AWSTraceHeader", - "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")) - .build(); - - AtomicInteger counter = new AtomicInteger(0); - - SqsMessageHandler messageHandler = - new SqsMessageHandler(getOpenTelemetry(), "destination", MessageOperation.RECEIVE) { - @Override - protected void doHandleMessages(Collection messages) { - counter.getAndIncrement(); - throw new RuntimeException("Injected Error"); - } - }; - - Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); - - assertThrows( - RuntimeException.class, - () -> { - try (Scope scope = parentSpan.makeCurrent()) { - messageHandler.handleMessages(Collections.singletonList(sqsMessage)); - } - }); - - parentSpan.end(); - - waitAndAssertTraces( - trace -> - trace.hasSpansSatisfyingExactly( - span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), - span -> - span.hasName("destination receive") - .hasKind(SpanKind.CONSUMER) - .hasLinks( - LinkData.create( - SpanContext.createFromRemoteParent( - "55555555123456789012345678901234", - "1234567890123456", - TraceFlags.getSampled(), - TraceState.getDefault()))) - .hasTotalRecordedLinks(1) - .hasException(new RuntimeException("Injected Error")) - .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "receive") - .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") - .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") - .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 5L) - .hasTotalAttributeCount(4) - .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) - .hasTraceId(parentSpan.getSpanContext().getTraceId()))); - - Assert.assertEquals(1, counter.get()); - } -} diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageReceiverTest.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageReceiverTest.java new file mode 100644 index 000000000000..ff7e2ff95997 --- /dev/null +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageReceiverTest.java @@ -0,0 +1,352 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.awssdk.v2_2; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanContext; +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.api.trace.TraceFlags; +import io.opentelemetry.api.trace.TraceState; +import io.opentelemetry.context.Scope; +import io.opentelemetry.sdk.trace.data.LinkData; +import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; +import java.util.Collections; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.services.sqs.SqsClient; +import software.amazon.awssdk.services.sqs.model.Message; +import software.amazon.awssdk.services.sqs.model.ReceiveMessageRequest; +import software.amazon.awssdk.services.sqs.model.ReceiveMessageResponse; + +public class SqsMessageReceiverTest extends XrayTestInstrumenter { + @Test + public void simple() { + SqsClient sqsClient = + getClient( + ReceiveMessageResponse.builder() + .messages( + Message.builder() + .body("Hello") + .attributesWithStrings( + Collections.singletonMap( + "AWSTraceHeader", + "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")) + .build()) + .build()); + + ReceiveMessageRequest request = ReceiveMessageRequest.builder().build(); + + SqsMessageReceiver messageHandler = + new SqsMessageReceiver(getOpenTelemetry(), "destination", sqsClient); + + Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); + + try (Scope scope = parentSpan.makeCurrent()) { + ReceiveMessageResponse response = messageHandler.receive(request); + + assertThat(response.messages().size()).isEqualTo(1); + assertThat(response.messages().get(0).body()).isEqualTo("Hello"); + assertThat(response.messages().get(0).attributesAsStrings().get("AWSTraceHeader")) + .isEqualTo("Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1"); + } + + parentSpan.end(); + + waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), + span -> + span.hasName("destination receive") + .hasKind(SpanKind.CONSUMER) + .hasLinks( + LinkData.create( + SpanContext.createFromRemoteParent( + "55555555123456789012345678901234", + "1234567890123456", + TraceFlags.getSampled(), + TraceState.getDefault()))) + .hasTotalRecordedLinks(1) + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "receive") + .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") + .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") + .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 5L) + .hasTotalAttributeCount(4) + .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) + .hasTraceId(parentSpan.getSpanContext().getTraceId()))); + } + + @Test + public void twoMessages() { + SqsClient sqsClient = + getClient( + ReceiveMessageResponse.builder() + .messages( + Message.builder() + .body("Hello") + .attributesWithStrings( + Collections.singletonMap( + "AWSTraceHeader", + "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")) + .build(), + Message.builder() + .body("Hello World") + .attributesWithStrings( + Collections.singletonMap( + "AWSTraceHeader", + "Root=1-66555555-123456789012345678901234;Parent=6634567890123456;Sampled=0")) + .build()) + .build()); + + ReceiveMessageRequest request = ReceiveMessageRequest.builder().build(); + + SqsMessageReceiver messageHandler = + new SqsMessageReceiver(getOpenTelemetry(), "destination", sqsClient); + + Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); + + try (Scope scope = parentSpan.makeCurrent()) { + ReceiveMessageResponse response = messageHandler.receive(request); + assertThat(response.messages().size()).isEqualTo(2); + + assertThat(response.messages().get(0).body()).isEqualTo("Hello"); + assertThat(response.messages().get(0).attributesAsStrings().get("AWSTraceHeader")) + .isEqualTo("Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1"); + + assertThat(response.messages().get(1).body()).isEqualTo("Hello World"); + assertThat(response.messages().get(1).attributesAsStrings().get("AWSTraceHeader")) + .isEqualTo("Root=1-66555555-123456789012345678901234;Parent=6634567890123456;Sampled=0"); + } + + parentSpan.end(); + + waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), + span -> + span.hasName("destination receive") + .hasKind(SpanKind.CONSUMER) + .hasLinks( + LinkData.create( + SpanContext.createFromRemoteParent( + "55555555123456789012345678901234", + "1234567890123456", + TraceFlags.getSampled(), + TraceState.getDefault())), + LinkData.create( + SpanContext.createFromRemoteParent( + "66555555123456789012345678901234", + "6634567890123456", + TraceFlags.getDefault(), + TraceState.getDefault()))) + .hasTotalRecordedLinks(2) + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "receive") + .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") + .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") + .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 16L) + .hasTotalAttributeCount(4) + .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) + .hasTraceId(parentSpan.getSpanContext().getTraceId()))); + } + + @Test + public void twoRuns() { + SqsClient sqsClient = + getClient( + ReceiveMessageResponse.builder() + .messages( + Message.builder() + .body("Hello") + .attributesWithStrings( + Collections.singletonMap( + "AWSTraceHeader", + "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=0")) + .build()) + .build(), + ReceiveMessageResponse.builder() + .messages( + Message.builder() + .body("SecondMessage") + .attributesWithStrings( + Collections.singletonMap( + "AWSTraceHeader", + "Root=1-77555555-123456789012345678901234;Parent=7734567890123456;Sampled=1")) + .build()) + .build()); + + ReceiveMessageRequest request = ReceiveMessageRequest.builder().build(); + + SqsMessageReceiver messageHandler = + new SqsMessageReceiver(getOpenTelemetry(), "destination", sqsClient); + + Span parentSpan1 = getOpenTelemetry().getTracer("test").spanBuilder("test1").startSpan(); + + try (Scope scope = parentSpan1.makeCurrent()) { + ReceiveMessageResponse response = messageHandler.receive(request); + + assertThat(response.messages().size()).isEqualTo(1); + assertThat(response.messages().get(0).body()).isEqualTo("Hello"); + assertThat(response.messages().get(0).attributesAsStrings().get("AWSTraceHeader")) + .isEqualTo("Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=0"); + } + + parentSpan1.end(); + + Span parentSpan2 = getOpenTelemetry().getTracer("test").spanBuilder("test2").startSpan(); + + try (Scope scope = parentSpan2.makeCurrent()) { + ReceiveMessageResponse response = messageHandler.receive(request); + + assertThat(response.messages().size()).isEqualTo(1); + assertThat(response.messages().get(0).body()).isEqualTo("SecondMessage"); + assertThat(response.messages().get(0).attributesAsStrings().get("AWSTraceHeader")) + .isEqualTo("Root=1-77555555-123456789012345678901234;Parent=7734567890123456;Sampled=1"); + } + + parentSpan2.end(); + + waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("test1").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), + span -> + span.hasName("destination receive") + .hasKind(SpanKind.CONSUMER) + .hasLinks( + LinkData.create( + SpanContext.createFromRemoteParent( + "55555555123456789012345678901234", + "1234567890123456", + TraceFlags.getDefault(), + TraceState.getDefault()))) + .hasTotalRecordedLinks(1) + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "receive") + .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") + .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") + .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 5L) + .hasTotalAttributeCount(4) + .hasParentSpanId(parentSpan1.getSpanContext().getSpanId()) + .hasTraceId(parentSpan1.getSpanContext().getTraceId())), + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("test2").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), + span -> + span.hasName("destination receive") + .hasKind(SpanKind.CONSUMER) + .hasLinks( + LinkData.create( + SpanContext.createFromRemoteParent( + "77555555123456789012345678901234", + "7734567890123456", + TraceFlags.getSampled(), + TraceState.getDefault()))) + .hasTotalRecordedLinks(1) + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "receive") + .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") + .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") + .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 13L) + .hasTotalAttributeCount(4) + .hasParentSpanId(parentSpan2.getSpanContext().getSpanId()) + .hasTraceId(parentSpan2.getSpanContext().getTraceId()))); + } + + @Test + public void noMessages() { + SqsClient sqsClient = getClient(ReceiveMessageResponse.builder().build()); + + ReceiveMessageRequest request = ReceiveMessageRequest.builder().build(); + + SqsMessageReceiver messageHandler = + new SqsMessageReceiver(getOpenTelemetry(), "destination", sqsClient); + + Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); + + try (Scope scope = parentSpan.makeCurrent()) { + ReceiveMessageResponse response = messageHandler.receive(request); + + assertThat(response.messages().size()).isEqualTo(0); + } + + parentSpan.end(); + + waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), + span -> + span.hasName("destination receive") + .hasKind(SpanKind.CONSUMER) + .hasTotalRecordedLinks(0) + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "receive") + .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") + .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") + .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 0L) + .hasTotalAttributeCount(4) + .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) + .hasTraceId(parentSpan.getSpanContext().getTraceId()))); + } + + @Test + public void malformedTraceId() { + SqsClient sqsClient = + getClient( + ReceiveMessageResponse.builder() + .messages( + Message.builder() + .body("Hello") + .attributesWithStrings( + Collections.singletonMap( + "AWSTraceHeader", + "Root=1-55555555-error;Parent=1234567890123456;Sampled=1")) + .build()) + .build()); + + ReceiveMessageRequest request = ReceiveMessageRequest.builder().build(); + + SqsMessageReceiver messageHandler = + new SqsMessageReceiver(getOpenTelemetry(), "destination", sqsClient); + + Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); + + assertThrows( + RuntimeException.class, + () -> { + try (Scope scope = parentSpan.makeCurrent()) { + ReceiveMessageResponse response = messageHandler.receive(request); + assertThat(response.messages().size()).isEqualTo(0); + } + }); + + parentSpan.end(); + + waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0))); + } + + private SqsClient getClient(ReceiveMessageResponse... responses) { + return new SqsClient() { + int messageAt = 0; + + @Override + public String serviceName() { + return "MyService"; + } + + @Override + public ReceiveMessageResponse receiveMessage(ReceiveMessageRequest request) { + return responses[messageAt++]; + } + + @Override + public void close() {} + }; + } +} diff --git a/instrumentation/message-handler/message-handler-1.0/library/README.md b/instrumentation/message-handler/message-handler-1.0/library/README.md index 4f57a6045277..a3c6be32ee78 100644 --- a/instrumentation/message-handler/message-handler-1.0/library/README.md +++ b/instrumentation/message-handler/message-handler-1.0/library/README.md @@ -1,10 +1,8 @@ # Message Handler -This package contains handlers to instrument message system spans for a batch of messages. It is not designed for a for-loop case. +This package contains handlers to instrument message system spans for a batch of messages. The handler will create a single new messaging span, add span links to it, and set the messaging attributes behind the scene. These values are based off of the messages passed in. -The handler provides constructors to change the messaging operation and span name of the newly created messaging span. - ## Available Handlers -- `SqsMessageHandler` - processes messages from Amazon's SQS. +- `SqsMessageReceiver` - Receive SQS messages diff --git a/instrumentation/message-handler/message-handler-1.0/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageHandler.java b/instrumentation/message-handler/message-handler-1.0/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageHandler.java deleted file mode 100644 index 1a72ecb1b86d..000000000000 --- a/instrumentation/message-handler/message-handler-1.0/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageHandler.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.messagehandler; - -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import java.util.Collection; - -public abstract class MessageHandler { - protected abstract Instrumenter, Void> getMessageInstrumenter(); - - protected abstract void doHandleMessages(Collection messages); - - public void handleMessages(Collection messages) { - Context parentContext = Context.current(); - if (getMessageInstrumenter().shouldStart(parentContext, messages)) { - io.opentelemetry.context.Context otelContext = - getMessageInstrumenter().start(parentContext, messages); - Throwable error = null; - try (Scope ignored = otelContext.makeCurrent()) { - doHandleMessages(messages); - } catch (Throwable t) { - error = t; - throw t; - } finally { - getMessageInstrumenter().end(otelContext, messages, null, error); - } - } else { - doHandleMessages(messages); - } - } -} diff --git a/instrumentation/message-handler/message-handler-1.0/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageReceiver.java b/instrumentation/message-handler/message-handler-1.0/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageReceiver.java new file mode 100644 index 000000000000..16771883c749 --- /dev/null +++ b/instrumentation/message-handler/message-handler-1.0/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageReceiver.java @@ -0,0 +1,42 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.messagehandler; + +import io.opentelemetry.context.Context; +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.internal.InstrumenterUtil; +import java.time.Instant; + +public abstract class MessageReceiver { + + protected abstract Instrumenter getMessageInstrumenter(); + + protected abstract RESPONSE doReceive(REQEUST request); + + public RESPONSE receive(REQEUST request) { + + Instrumenter instrumenter = getMessageInstrumenter(); + + Context parentContext = Context.current(); + + Throwable error = null; + RESPONSE response = null; + + Instant startTime = Instant.now(); + + try { + response = doReceive(request); + } catch (Throwable t) { + error = t; + throw t; + } finally { + InstrumenterUtil.startAndEnd( + instrumenter, parentContext, response, null, error, startTime, Instant.now()); + } + + return response; + } +} From 24af0c94ae83b68c23339631d18f12bc609340b0 Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Thu, 15 Jun 2023 10:28:32 -0700 Subject: [PATCH 36/47] Cleanup --- .../instrumentation/awssdk/v2_2/SqsMessageReceiverTest.java | 3 +-- .../message-handler/message-handler-1.0/library/README.md | 6 +++--- .../instrumentation/messagehandler/MessageReceiver.java | 4 ---- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageReceiverTest.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageReceiverTest.java index ff7e2ff95997..f0a1005edb8f 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageReceiverTest.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageReceiverTest.java @@ -318,8 +318,7 @@ public void malformedTraceId() { RuntimeException.class, () -> { try (Scope scope = parentSpan.makeCurrent()) { - ReceiveMessageResponse response = messageHandler.receive(request); - assertThat(response.messages().size()).isEqualTo(0); + messageHandler.receive(request); } }); diff --git a/instrumentation/message-handler/message-handler-1.0/library/README.md b/instrumentation/message-handler/message-handler-1.0/library/README.md index a3c6be32ee78..761a6f7021a6 100644 --- a/instrumentation/message-handler/message-handler-1.0/library/README.md +++ b/instrumentation/message-handler/message-handler-1.0/library/README.md @@ -1,8 +1,8 @@ # Message Handler -This package contains handlers to instrument message system spans for a batch of messages. +This package contains instrumentation for message systems. -The handler will create a single new messaging span, add span links to it, and set the messaging attributes behind the scene. These values are based off of the messages passed in. +The instrumentation will receive or process messages and wrap the calls in a span with appropriate attributes and span links. -## Available Handlers +## Available Message Receivers - `SqsMessageReceiver` - Receive SQS messages diff --git a/instrumentation/message-handler/message-handler-1.0/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageReceiver.java b/instrumentation/message-handler/message-handler-1.0/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageReceiver.java index 16771883c749..aa265750504a 100644 --- a/instrumentation/message-handler/message-handler-1.0/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageReceiver.java +++ b/instrumentation/message-handler/message-handler-1.0/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageReceiver.java @@ -17,16 +17,12 @@ public abstract class MessageReceiver { protected abstract RESPONSE doReceive(REQEUST request); public RESPONSE receive(REQEUST request) { - Instrumenter instrumenter = getMessageInstrumenter(); - Context parentContext = Context.current(); - Throwable error = null; RESPONSE response = null; Instant startTime = Instant.now(); - try { response = doReceive(request); } catch (Throwable t) { From 80eacf1b90fab273b5c2ba8ce52c1f3f278babe3 Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Fri, 21 Jul 2023 09:58:55 -0700 Subject: [PATCH 37/47] Changing to process messages only --- .../aws-sdk/aws-sdk-2.2/library/README.md | 33 +- .../aws-sdk-2.2/library/build.gradle.kts | 7 +- ...geReceiver.java => SqsMessageHandler.java} | 67 ++-- ...erTest.java => SqsMessageHandlerTest.java} | 303 ++++++++---------- .../message-handler-1.0/library/README.md | 4 +- .../messagehandler/MessageHandler.java | 36 +++ .../messagehandler/MessageReceiver.java | 38 --- 7 files changed, 228 insertions(+), 260 deletions(-) rename instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/{SqsMessageReceiver.java => SqsMessageHandler.java} (58%) rename instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/{SqsMessageReceiverTest.java => SqsMessageHandlerTest.java} (53%) create mode 100644 instrumentation/message-handler/message-handler-1.0/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageHandler.java delete mode 100644 instrumentation/message-handler/message-handler-1.0/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageReceiver.java diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/README.md b/instrumentation/aws-sdk/aws-sdk-2.2/library/README.md index fd2defeae51a..d790de42d5c3 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/README.md +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/README.md @@ -25,22 +25,27 @@ propagating the trace through them. If this does not fulfill your use case, perh using the same SDK with a different non-AWS managed service, let us know so we can provide configuration for this behavior. -## Using SqsMessageReceiver +## Using SqsMessageHandler +This instrumentation takes a collection of SQS messages. +A span wraps the function call doHandle with appropriate span attributes and span links. +Span links comes from each of the messages as if this were a batch of messages. -This instrumentation takes a ReceiveMessageRequest and returns a ReceiveMessageResponse for SQS. -A span is created for the call to SQS with appropriate attributes and span links. -Span links comes from each of the response's messages as if this were a batch of messages. - -1. Setup SqsMessageReceiver so that it knows how to pull information from SQS. -Pass in your OpenTelemetry, the name of the destination, and SqsClient. -2. Call the receive method on SqsMessageReceiver and pass in the request. -3. It will return the response and wrap the call in a span. +1. Setup SqsMessageHandler with your business logic. Pass in your OpenTelemetry, the name of the destination, and the span kind. +2. Call the "handle" method on SqsMessageHandler and pass in your collection of messages. +3. Under the hood it will call the "doHandle" method. ```java OpenTelemetry openTelemetry; -SqsClient sqsClient; -ReceiveMessageRequest request; - -SqsMessageReceiver messageReceiver = new SqsMessageReceiver(openTelemetry, "destination", sqsClient); -ReceiveMessageResponse response = messageReceiver.receive(request); +Collection messages; + +SqsMessageHandler messageHandler = + new SqsMessageHandler(openTelemetry "destination", SpanKindExtractor.alwaysServer()) { + @Override + protected Void doHandle(Collection request) { + // My business logic + return null; + } +}; + +messageHandler.handle(messages); ``` diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts b/instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts index 85e9524a1f40..5a4ca3a54c08 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts @@ -6,10 +6,11 @@ dependencies { implementation("io.opentelemetry.contrib:opentelemetry-aws-xray-propagator") implementation(project(":instrumentation:message-handler:message-handler-1.0:library")) + implementation(project(":instrumentation:aws-lambda:aws-lambda-events-2.2:library")) - library("software.amazon.awssdk:aws-core:2.2.0") - library("software.amazon.awssdk:aws-core:2.2.0") - library("software.amazon.awssdk:sqs:2.2.0") + library("software.amazon.awssdk:aws-core:2.20.0") + library("software.amazon.awssdk:aws-json-protocol:2.2.0") + library("software.amazon.awssdk:sqs:2.20.0") testImplementation(project(":instrumentation:aws-sdk:aws-sdk-2.2:testing")) diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageReceiver.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java similarity index 58% rename from instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageReceiver.java rename to instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java index 97c352824173..e88e312e4799 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageReceiver.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java @@ -19,87 +19,80 @@ import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessagingAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessagingAttributesGetter; import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessagingSpanNameExtractor; -import io.opentelemetry.instrumentation.messagehandler.MessageReceiver; +import io.opentelemetry.instrumentation.messagehandler.MessageHandler; +import java.util.Collection; import java.util.Map; import javax.annotation.Nullable; import software.amazon.awssdk.core.SdkPojo; -import software.amazon.awssdk.services.sqs.SqsClient; import software.amazon.awssdk.services.sqs.model.Message; -import software.amazon.awssdk.services.sqs.model.ReceiveMessageRequest; -import software.amazon.awssdk.services.sqs.model.ReceiveMessageResponse; -public class SqsMessageReceiver - extends MessageReceiver { +public abstract class SqsMessageHandler + extends MessageHandler, Void> { private final OpenTelemetry openTelemetry; private final String destination; - private final SqsClient sqsClient; + private final SpanKindExtractor> spanKindExtractor; - public SqsMessageReceiver(OpenTelemetry openTelemetry, String destination, SqsClient sqsClient) { + public SqsMessageHandler(OpenTelemetry openTelemetry, String destination, SpanKindExtractor> spanKindExtractor) { this.openTelemetry = openTelemetry; this.destination = destination; - this.sqsClient = sqsClient; + this.spanKindExtractor = spanKindExtractor; } @Override - public ReceiveMessageResponse doReceive(ReceiveMessageRequest request) { - return sqsClient.receiveMessage(request); - } - - @Override - protected Instrumenter getMessageInstrumenter() { - return Instrumenter.builder( + protected Instrumenter, Void> getMessageInstrumenter() { + return Instrumenter., Void>builder( openTelemetry, "io.opentelemetry.aws-sdk-2.2", getSpanNameExtractor()) .addAttributesExtractor(getAttributesExtractor()) .addSpanLinksExtractor(getSpanLinksExtractor()) - .buildInstrumenter(getSpanKindExtractor()); + .buildInstrumenter(spanKindExtractor); } - protected SpanNameExtractor getSpanNameExtractor() { + protected SpanNameExtractor> getSpanNameExtractor() { return MessagingSpanNameExtractor.create( - getMessageingAttributesGetter(), MessageOperation.RECEIVE); + getMessageingAttributesGetter(), MessageOperation.PROCESS); } - protected MessagingAttributesGetter + protected MessagingAttributesGetter, Void> getMessageingAttributesGetter() { String destination = this.destination; - return new MessagingAttributesGetter() { + return new MessagingAttributesGetter, Void>() { @Nullable @Override - public String getSystem(ReceiveMessageResponse v) { + public String getSystem(Collection v) { return "AmazonSQS"; } @Nullable @Override @SuppressWarnings({"deprecation"}) // Inheriting from interface - public String getDestinationKind(ReceiveMessageResponse v) { + public String getDestinationKind(Collection v) { return null; } @Nullable @Override - public String getDestination(ReceiveMessageResponse v) { + public String getDestination(Collection v) { return destination; } @Override - public boolean isTemporaryDestination(ReceiveMessageResponse v) { + public boolean isTemporaryDestination(Collection v) { return false; } @Nullable @Override - public String getConversationId(ReceiveMessageResponse v) { + public String getConversationId(Collection v) { return null; } @Nullable @Override - public Long getMessagePayloadSize(ReceiveMessageResponse v) { + public Long getMessagePayloadSize(Collection v) { long total = 0; - for (Message message : v.messages()) { + for (Message message : v) { total += message.body().length(); } @@ -108,32 +101,28 @@ public Long getMessagePayloadSize(ReceiveMessageResponse v) { @Nullable @Override - public Long getMessagePayloadCompressedSize(ReceiveMessageResponse v) { + public Long getMessagePayloadCompressedSize(Collection v) { return null; } @Nullable @Override - public String getMessageId(ReceiveMessageResponse request, Void v) { + public String getMessageId(Collection request, Void v) { return null; } }; } - protected SpanKindExtractor getSpanKindExtractor() { - return SpanKindExtractor.alwaysConsumer(); - } - - protected AttributesExtractor getAttributesExtractor() { + protected AttributesExtractor, Void> getAttributesExtractor() { return MessagingAttributesExtractor.create( - getMessageingAttributesGetter(), MessageOperation.RECEIVE); + getMessageingAttributesGetter(), MessageOperation.PROCESS); } - protected SpanLinksExtractor getSpanLinksExtractor() { - return (spanLinks, parentContext, response) -> { + protected SpanLinksExtractor> getSpanLinksExtractor() { + return (spanLinks, parentContext, request) -> { TextMapPropagator messagingPropagator = openTelemetry.getPropagators().getTextMapPropagator(); - for (Message message : response.messages()) { + for (Message message : request) { Map messageAtributes = SqsMessageAccess.getMessageAttributes(message); Context context = diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageReceiverTest.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandlerTest.java similarity index 53% rename from instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageReceiverTest.java rename to instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandlerTest.java index f0a1005edb8f..85c62cfeae6b 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageReceiverTest.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandlerTest.java @@ -14,56 +14,58 @@ import io.opentelemetry.api.trace.TraceFlags; import io.opentelemetry.api.trace.TraceState; import io.opentelemetry.context.Scope; +import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; import io.opentelemetry.sdk.trace.data.LinkData; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; +import java.util.Collection; import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; import org.junit.jupiter.api.Test; -import software.amazon.awssdk.services.sqs.SqsClient; import software.amazon.awssdk.services.sqs.model.Message; -import software.amazon.awssdk.services.sqs.model.ReceiveMessageRequest; -import software.amazon.awssdk.services.sqs.model.ReceiveMessageResponse; -public class SqsMessageReceiverTest extends XrayTestInstrumenter { +public class SqsMessageHandlerTest extends XrayTestInstrumenter { + @Test public void simple() { - SqsClient sqsClient = - getClient( - ReceiveMessageResponse.builder() - .messages( - Message.builder() - .body("Hello") - .attributesWithStrings( - Collections.singletonMap( - "AWSTraceHeader", - "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")) - .build()) - .build()); - - ReceiveMessageRequest request = ReceiveMessageRequest.builder().build(); - - SqsMessageReceiver messageHandler = - new SqsMessageReceiver(getOpenTelemetry(), "destination", sqsClient); + AtomicInteger handleCalls = new AtomicInteger(); + + SqsMessageHandler messageHandler = + new SqsMessageHandler(getOpenTelemetry(), "destination", SpanKindExtractor.alwaysServer()) { + @Override + protected Void doHandle(Collection request) { + handleCalls.incrementAndGet(); + return null; + } + }; + + List messages = new LinkedList<>(); + messages.add(Message.builder() + .body("Hello") + .attributesWithStrings( + Collections.singletonMap( + "AWSTraceHeader", + "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")) + .build()); Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); try (Scope scope = parentSpan.makeCurrent()) { - ReceiveMessageResponse response = messageHandler.receive(request); - - assertThat(response.messages().size()).isEqualTo(1); - assertThat(response.messages().get(0).body()).isEqualTo("Hello"); - assertThat(response.messages().get(0).attributesAsStrings().get("AWSTraceHeader")) - .isEqualTo("Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1"); + messageHandler.handle(messages); } parentSpan.end(); + assertThat(handleCalls.get()).isEqualTo(1); + waitAndAssertTraces( trace -> trace.hasSpansSatisfyingExactly( span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> - span.hasName("destination receive") - .hasKind(SpanKind.CONSUMER) + span.hasName("destination process") + .hasKind(SpanKind.SERVER) .hasLinks( LinkData.create( SpanContext.createFromRemoteParent( @@ -72,7 +74,7 @@ public void simple() { TraceFlags.getSampled(), TraceState.getDefault()))) .hasTotalRecordedLinks(1) - .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "receive") + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 5L) @@ -83,54 +85,50 @@ public void simple() { @Test public void twoMessages() { - SqsClient sqsClient = - getClient( - ReceiveMessageResponse.builder() - .messages( - Message.builder() - .body("Hello") - .attributesWithStrings( - Collections.singletonMap( - "AWSTraceHeader", - "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")) - .build(), - Message.builder() - .body("Hello World") - .attributesWithStrings( - Collections.singletonMap( - "AWSTraceHeader", - "Root=1-66555555-123456789012345678901234;Parent=6634567890123456;Sampled=0")) - .build()) - .build()); - - ReceiveMessageRequest request = ReceiveMessageRequest.builder().build(); - - SqsMessageReceiver messageHandler = - new SqsMessageReceiver(getOpenTelemetry(), "destination", sqsClient); + AtomicInteger handleCalls = new AtomicInteger(); + + List messages = new LinkedList(); + messages.add(Message.builder() + .body("Hello") + .attributesWithStrings( + Collections.singletonMap( + "AWSTraceHeader", + "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")) + .build()); + messages.add(Message.builder() + .body("Hello World") + .attributesWithStrings( + Collections.singletonMap( + "AWSTraceHeader", + "Root=1-66555555-123456789012345678901234;Parent=6634567890123456;Sampled=0")) + .build()); + + SqsMessageHandler messageHandler = + new SqsMessageHandler(getOpenTelemetry(), "destination", SpanKindExtractor.alwaysConsumer()) { + + @Override + protected Void doHandle(Collection request) { + handleCalls.incrementAndGet(); + return null; + } + }; Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); try (Scope scope = parentSpan.makeCurrent()) { - ReceiveMessageResponse response = messageHandler.receive(request); - assertThat(response.messages().size()).isEqualTo(2); - - assertThat(response.messages().get(0).body()).isEqualTo("Hello"); - assertThat(response.messages().get(0).attributesAsStrings().get("AWSTraceHeader")) - .isEqualTo("Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1"); - - assertThat(response.messages().get(1).body()).isEqualTo("Hello World"); - assertThat(response.messages().get(1).attributesAsStrings().get("AWSTraceHeader")) - .isEqualTo("Root=1-66555555-123456789012345678901234;Parent=6634567890123456;Sampled=0"); + messageHandler.handle(messages); } parentSpan.end(); + assertThat(handleCalls.get()).isEqualTo(1); + waitAndAssertTraces( trace -> trace.hasSpansSatisfyingExactly( span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> - span.hasName("destination receive") + span.hasName("destination process") .hasKind(SpanKind.CONSUMER) .hasLinks( LinkData.create( @@ -146,7 +144,7 @@ public void twoMessages() { TraceFlags.getDefault(), TraceState.getDefault()))) .hasTotalRecordedLinks(2) - .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "receive") + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 16L) @@ -157,67 +155,56 @@ public void twoMessages() { @Test public void twoRuns() { - SqsClient sqsClient = - getClient( - ReceiveMessageResponse.builder() - .messages( - Message.builder() - .body("Hello") - .attributesWithStrings( - Collections.singletonMap( - "AWSTraceHeader", - "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=0")) - .build()) - .build(), - ReceiveMessageResponse.builder() - .messages( - Message.builder() - .body("SecondMessage") - .attributesWithStrings( - Collections.singletonMap( - "AWSTraceHeader", - "Root=1-77555555-123456789012345678901234;Parent=7734567890123456;Sampled=1")) - .build()) - .build()); - - ReceiveMessageRequest request = ReceiveMessageRequest.builder().build(); - - SqsMessageReceiver messageHandler = - new SqsMessageReceiver(getOpenTelemetry(), "destination", sqsClient); + AtomicInteger handleCalls = new AtomicInteger(); + + List messages1 = new LinkedList(); + messages1.add(Message.builder() + .body("Hello") + .attributesWithStrings( + Collections.singletonMap( + "AWSTraceHeader", + "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=0")) + .build()); + + List messages2 = new LinkedList(); + messages2.add(Message.builder() + .body("SecondMessage") + .attributesWithStrings( + Collections.singletonMap( + "AWSTraceHeader", + "Root=1-77555555-123456789012345678901234;Parent=7734567890123456;Sampled=1")) + .build()); + + SqsMessageHandler messageHandler = + new SqsMessageHandler(getOpenTelemetry(), "destination", SpanKindExtractor.alwaysServer()) { + @Override + protected Void doHandle(Collection request) { + handleCalls.incrementAndGet(); + return null; + } + }; Span parentSpan1 = getOpenTelemetry().getTracer("test").spanBuilder("test1").startSpan(); - try (Scope scope = parentSpan1.makeCurrent()) { - ReceiveMessageResponse response = messageHandler.receive(request); - - assertThat(response.messages().size()).isEqualTo(1); - assertThat(response.messages().get(0).body()).isEqualTo("Hello"); - assertThat(response.messages().get(0).attributesAsStrings().get("AWSTraceHeader")) - .isEqualTo("Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=0"); + messageHandler.handle(messages1); } - parentSpan1.end(); Span parentSpan2 = getOpenTelemetry().getTracer("test").spanBuilder("test2").startSpan(); - try (Scope scope = parentSpan2.makeCurrent()) { - ReceiveMessageResponse response = messageHandler.receive(request); - - assertThat(response.messages().size()).isEqualTo(1); - assertThat(response.messages().get(0).body()).isEqualTo("SecondMessage"); - assertThat(response.messages().get(0).attributesAsStrings().get("AWSTraceHeader")) - .isEqualTo("Root=1-77555555-123456789012345678901234;Parent=7734567890123456;Sampled=1"); + messageHandler.handle(messages2); } - parentSpan2.end(); + assertThat(handleCalls.get()).isEqualTo(2); + waitAndAssertTraces( trace -> trace.hasSpansSatisfyingExactly( span -> span.hasName("test1").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> - span.hasName("destination receive") - .hasKind(SpanKind.CONSUMER) + span.hasName("destination process") + .hasKind(SpanKind.SERVER) .hasLinks( LinkData.create( SpanContext.createFromRemoteParent( @@ -226,7 +213,7 @@ public void twoRuns() { TraceFlags.getDefault(), TraceState.getDefault()))) .hasTotalRecordedLinks(1) - .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "receive") + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 5L) @@ -237,8 +224,8 @@ public void twoRuns() { trace.hasSpansSatisfyingExactly( span -> span.hasName("test2").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> - span.hasName("destination receive") - .hasKind(SpanKind.CONSUMER) + span.hasName("destination process") + .hasKind(SpanKind.SERVER) .hasLinks( LinkData.create( SpanContext.createFromRemoteParent( @@ -247,7 +234,7 @@ public void twoRuns() { TraceFlags.getSampled(), TraceState.getDefault()))) .hasTotalRecordedLinks(1) - .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "receive") + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 13L) @@ -258,32 +245,35 @@ public void twoRuns() { @Test public void noMessages() { - SqsClient sqsClient = getClient(ReceiveMessageResponse.builder().build()); + AtomicInteger handleCalls = new AtomicInteger(); - ReceiveMessageRequest request = ReceiveMessageRequest.builder().build(); + SqsMessageHandler messageHandler = + new SqsMessageHandler(getOpenTelemetry(), "destination", SpanKindExtractor.alwaysServer()) { - SqsMessageReceiver messageHandler = - new SqsMessageReceiver(getOpenTelemetry(), "destination", sqsClient); + @Override + protected Void doHandle(Collection request) { + handleCalls.incrementAndGet(); + return null; + } + }; Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); - try (Scope scope = parentSpan.makeCurrent()) { - ReceiveMessageResponse response = messageHandler.receive(request); - - assertThat(response.messages().size()).isEqualTo(0); + messageHandler.handle(new LinkedList<>()); } - parentSpan.end(); + assertThat(handleCalls.get()).isEqualTo(1); + waitAndAssertTraces( trace -> trace.hasSpansSatisfyingExactly( span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> - span.hasName("destination receive") - .hasKind(SpanKind.CONSUMER) + span.hasName("destination process") + .hasKind(SpanKind.SERVER) .hasTotalRecordedLinks(0) - .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "receive") + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 0L) @@ -294,23 +284,25 @@ public void noMessages() { @Test public void malformedTraceId() { - SqsClient sqsClient = - getClient( - ReceiveMessageResponse.builder() - .messages( - Message.builder() - .body("Hello") - .attributesWithStrings( - Collections.singletonMap( - "AWSTraceHeader", - "Root=1-55555555-error;Parent=1234567890123456;Sampled=1")) - .build()) - .build()); - - ReceiveMessageRequest request = ReceiveMessageRequest.builder().build(); - - SqsMessageReceiver messageHandler = - new SqsMessageReceiver(getOpenTelemetry(), "destination", sqsClient); + AtomicInteger handleCalls = new AtomicInteger(); + + List messages = new LinkedList(); + messages.add(Message.builder() + .body("Hello") + .attributesWithStrings( + Collections.singletonMap( + "AWSTraceHeader", + "Root=1-55555555-error;Parent=1234567890123456;Sampled=1")) + .build()); + + SqsMessageHandler messageHandler = + new SqsMessageHandler(getOpenTelemetry(), "destination", SpanKindExtractor.alwaysServer()) { + @Override + protected Void doHandle(Collection request) { + handleCalls.incrementAndGet(); + return null; + } + }; Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); @@ -318,34 +310,17 @@ public void malformedTraceId() { RuntimeException.class, () -> { try (Scope scope = parentSpan.makeCurrent()) { - messageHandler.receive(request); + messageHandler.handle(messages); } }); parentSpan.end(); + assertThat(handleCalls.get()).isEqualTo(0); + waitAndAssertTraces( trace -> trace.hasSpansSatisfyingExactly( span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0))); } - - private SqsClient getClient(ReceiveMessageResponse... responses) { - return new SqsClient() { - int messageAt = 0; - - @Override - public String serviceName() { - return "MyService"; - } - - @Override - public ReceiveMessageResponse receiveMessage(ReceiveMessageRequest request) { - return responses[messageAt++]; - } - - @Override - public void close() {} - }; - } } diff --git a/instrumentation/message-handler/message-handler-1.0/library/README.md b/instrumentation/message-handler/message-handler-1.0/library/README.md index 761a6f7021a6..48bd8e74b724 100644 --- a/instrumentation/message-handler/message-handler-1.0/library/README.md +++ b/instrumentation/message-handler/message-handler-1.0/library/README.md @@ -2,7 +2,7 @@ This package contains instrumentation for message systems. -The instrumentation will receive or process messages and wrap the calls in a span with appropriate attributes and span links. +The instrumentation will process messages and wrap the calls in a span with appropriate span attributes and span links. ## Available Message Receivers -- `SqsMessageReceiver` - Receive SQS messages +- `SqsMessageHandler` - Process SQS messages diff --git a/instrumentation/message-handler/message-handler-1.0/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageHandler.java b/instrumentation/message-handler/message-handler-1.0/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageHandler.java new file mode 100644 index 000000000000..c46468c24bbb --- /dev/null +++ b/instrumentation/message-handler/message-handler-1.0/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageHandler.java @@ -0,0 +1,36 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.messagehandler; + +import io.opentelemetry.context.Context; +import io.opentelemetry.context.Scope; +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; + +public abstract class MessageHandler { + + protected abstract Instrumenter getMessageInstrumenter(); + + protected abstract OUTPUT doHandle(INPUT request); + + public OUTPUT handle(INPUT request) { + Instrumenter instrumenter = getMessageInstrumenter(); + OUTPUT response = null; + Throwable error = null; + + Context context = instrumenter.start(Context.current(), request); + + try (Scope scope = context.makeCurrent()) { + response = doHandle(request); + } catch (Throwable t) { + error = t; + throw t; + } finally { + instrumenter.end(context, request, response, error); + } + + return response; + } +} diff --git a/instrumentation/message-handler/message-handler-1.0/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageReceiver.java b/instrumentation/message-handler/message-handler-1.0/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageReceiver.java deleted file mode 100644 index aa265750504a..000000000000 --- a/instrumentation/message-handler/message-handler-1.0/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageReceiver.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.messagehandler; - -import io.opentelemetry.context.Context; -import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.api.internal.InstrumenterUtil; -import java.time.Instant; - -public abstract class MessageReceiver { - - protected abstract Instrumenter getMessageInstrumenter(); - - protected abstract RESPONSE doReceive(REQEUST request); - - public RESPONSE receive(REQEUST request) { - Instrumenter instrumenter = getMessageInstrumenter(); - Context parentContext = Context.current(); - Throwable error = null; - RESPONSE response = null; - - Instant startTime = Instant.now(); - try { - response = doReceive(request); - } catch (Throwable t) { - error = t; - throw t; - } finally { - InstrumenterUtil.startAndEnd( - instrumenter, parentContext, response, null, error, startTime, Instant.now()); - } - - return response; - } -} From 19c419b1912d4cdd5448487b26a8037bd4994fd1 Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Fri, 21 Jul 2023 10:01:37 -0700 Subject: [PATCH 38/47] Fixing typo --- .../message-handler/message-handler-1.0/library/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation/message-handler/message-handler-1.0/library/README.md b/instrumentation/message-handler/message-handler-1.0/library/README.md index 48bd8e74b724..21f26e55d756 100644 --- a/instrumentation/message-handler/message-handler-1.0/library/README.md +++ b/instrumentation/message-handler/message-handler-1.0/library/README.md @@ -4,5 +4,5 @@ This package contains instrumentation for message systems. The instrumentation will process messages and wrap the calls in a span with appropriate span attributes and span links. -## Available Message Receivers +## Available Message Handlers - `SqsMessageHandler` - Process SQS messages From c0958a8a85b39c1f77ee50ed5bd0439d7bd97c2c Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Fri, 21 Jul 2023 10:06:05 -0700 Subject: [PATCH 39/47] Adding more information regarding what console will look like --- instrumentation/aws-sdk/aws-sdk-2.2/library/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/README.md b/instrumentation/aws-sdk/aws-sdk-2.2/library/README.md index d790de42d5c3..7282550b97b1 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/README.md +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/README.md @@ -29,6 +29,8 @@ configuration for this behavior. This instrumentation takes a collection of SQS messages. A span wraps the function call doHandle with appropriate span attributes and span links. Span links comes from each of the messages as if this were a batch of messages. +If the span kind is server, then it will show up in the console as a separate node (segment). +If the span kind is consumer, then it will show up as a subsegment. 1. Setup SqsMessageHandler with your business logic. Pass in your OpenTelemetry, the name of the destination, and the span kind. 2. Call the "handle" method on SqsMessageHandler and pass in your collection of messages. From 5f41613c5be78b0a0b8bd1eb433e07ce09186a6d Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Mon, 24 Jul 2023 23:13:44 -0700 Subject: [PATCH 40/47] Adding support for SQSEvent.SQSMessage --- .../aws-sdk-2.2/library/build.gradle.kts | 1 + .../awssdk/v2_2/SqsMessageDelegate.java | 9 + .../awssdk/v2_2/SqsMessageDelegates.java | 100 +++++ .../awssdk/v2_2/SqsMessageHandler.java | 63 +-- .../awssdk/v2_2/SqsMessageHandlerTest.java | 404 +++++++++++++++--- .../messagehandler/MessageHandler.java | 18 +- 6 files changed, 478 insertions(+), 117 deletions(-) create mode 100644 instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageDelegate.java create mode 100644 instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageDelegates.java diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts b/instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts index 5a4ca3a54c08..5471d5f8c8a8 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts @@ -11,6 +11,7 @@ dependencies { library("software.amazon.awssdk:aws-core:2.20.0") library("software.amazon.awssdk:aws-json-protocol:2.2.0") library("software.amazon.awssdk:sqs:2.20.0") + library("com.amazonaws:aws-lambda-java-events:2.2.1") testImplementation(project(":instrumentation:aws-sdk:aws-sdk-2.2:testing")) diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageDelegate.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageDelegate.java new file mode 100644 index 000000000000..5ec7d78594cb --- /dev/null +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageDelegate.java @@ -0,0 +1,9 @@ +package io.opentelemetry.instrumentation.awssdk.v2_2; + +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.trace.SpanContext; + +public abstract class SqsMessageDelegate { + public abstract int getPayloadSize(T message); + public abstract SpanContext getUpstreamContext(OpenTelemetry openTelemetry, T message); +} diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageDelegates.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageDelegates.java new file mode 100644 index 000000000000..9b9a19da2660 --- /dev/null +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageDelegates.java @@ -0,0 +1,100 @@ +package io.opentelemetry.instrumentation.awssdk.v2_2; + +import com.amazonaws.services.lambda.runtime.events.SQSEvent; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanContext; +import io.opentelemetry.context.Context; +import io.opentelemetry.context.propagation.TextMapGetter; +import io.opentelemetry.context.propagation.TextMapPropagator; +import io.opentelemetry.contrib.awsxray.propagator.AwsXrayPropagator; +import software.amazon.awssdk.core.SdkPojo; +import software.amazon.awssdk.services.sqs.model.Message; +import java.util.Collections; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +public class SqsMessageDelegates { + private static final Map, SqsMessageDelegate> messageDelegates = new HashMap<>(); + + public static void register(Class clazz, SqsMessageDelegate messageDelegate) { + messageDelegates.put(clazz, messageDelegate); + } + + static { + register(Message.class, new SqsMessageDelegate() { + @Override + public int getPayloadSize(Message message) { + return message.body().length(); + } + + @Override + public SpanContext getUpstreamContext(OpenTelemetry openTelemetry, Message message) { + TextMapPropagator messagingPropagator = openTelemetry.getPropagators() + .getTextMapPropagator(); + + Map messageAtributes = SqsMessageAccess.getMessageAttributes(message); + + Context context = + SqsParentContext.ofMessageAttributes(messageAtributes, messagingPropagator); + + if (context == Context.root()) { + context = SqsParentContext.ofSystemAttributes(SqsMessageAccess.getAttributes(message)); + } + + return Span.fromContext(context).getSpanContext(); + } + }); + + register(SQSEvent.SQSMessage.class, + new SqsMessageDelegate() { + private static final String AWS_TRACE_HEADER_SQS_ATTRIBUTE_KEY = "AWSTraceHeader"; + static final String AWS_TRACE_HEADER_PROPAGATOR_KEY = "x-amzn-trace-id"; + + @Override + public int getPayloadSize(SQSEvent.SQSMessage message) { + return message.getBody().length(); + } + + @Override + public SpanContext getUpstreamContext(OpenTelemetry openTelemetry, SQSEvent.SQSMessage message) { + String parentHeader = message.getAttributes().get(AWS_TRACE_HEADER_SQS_ATTRIBUTE_KEY); + + if (parentHeader != null) { + Context xrayContext = + AwsXrayPropagator.getInstance() + .extract( + Context.root(), + Collections.singletonMap(AWS_TRACE_HEADER_PROPAGATOR_KEY, parentHeader), + MapGetter.INSTANCE); + return Span.fromContext(xrayContext).getSpanContext(); + } + + return null; + } + }); + } + + private enum MapGetter implements TextMapGetter> { + INSTANCE; + + @Override + public Iterable keys(Map map) { + return map.keySet(); + } + + @Override + public String get(Map map, String s) { + return map.get(s.toLowerCase(Locale.ROOT)); + } + } + + private SqsMessageDelegates() { + } + + @SuppressWarnings("unchecked") + public static SqsMessageDelegate get(T message) { + return (SqsMessageDelegate) messageDelegates.get(message.getClass()); + } +} diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java index e88e312e4799..9ccf98bf1b18 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java @@ -6,10 +6,7 @@ package io.opentelemetry.instrumentation.awssdk.v2_2; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.SpanContext; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.propagation.TextMapPropagator; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; @@ -21,79 +18,75 @@ import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessagingSpanNameExtractor; import io.opentelemetry.instrumentation.messagehandler.MessageHandler; import java.util.Collection; -import java.util.Map; import javax.annotation.Nullable; -import software.amazon.awssdk.core.SdkPojo; -import software.amazon.awssdk.services.sqs.model.Message; -public abstract class SqsMessageHandler - extends MessageHandler, Void> { +public abstract class SqsMessageHandler extends MessageHandler { private final OpenTelemetry openTelemetry; private final String destination; - private final SpanKindExtractor> spanKindExtractor; + private final SpanKindExtractor> spanKindExtractor; - public SqsMessageHandler(OpenTelemetry openTelemetry, String destination, SpanKindExtractor> spanKindExtractor) { + public SqsMessageHandler(OpenTelemetry openTelemetry, String destination, SpanKindExtractor> spanKindExtractor) { this.openTelemetry = openTelemetry; this.destination = destination; this.spanKindExtractor = spanKindExtractor; } @Override - protected Instrumenter, Void> getMessageInstrumenter() { - return Instrumenter., Void>builder( + protected Instrumenter, Void> getMessageInstrumenter() { + return Instrumenter., Void>builder( openTelemetry, "io.opentelemetry.aws-sdk-2.2", getSpanNameExtractor()) .addAttributesExtractor(getAttributesExtractor()) .addSpanLinksExtractor(getSpanLinksExtractor()) .buildInstrumenter(spanKindExtractor); } - protected SpanNameExtractor> getSpanNameExtractor() { + protected SpanNameExtractor> getSpanNameExtractor() { return MessagingSpanNameExtractor.create( getMessageingAttributesGetter(), MessageOperation.PROCESS); } - protected MessagingAttributesGetter, Void> + protected MessagingAttributesGetter, Void> getMessageingAttributesGetter() { String destination = this.destination; - return new MessagingAttributesGetter, Void>() { + return new MessagingAttributesGetter, Void>() { @Nullable @Override - public String getSystem(Collection v) { + public String getSystem(Collection v) { return "AmazonSQS"; } @Nullable @Override @SuppressWarnings({"deprecation"}) // Inheriting from interface - public String getDestinationKind(Collection v) { + public String getDestinationKind(Collection v) { return null; } @Nullable @Override - public String getDestination(Collection v) { + public String getDestination(Collection v) { return destination; } @Override - public boolean isTemporaryDestination(Collection v) { + public boolean isTemporaryDestination(Collection v) { return false; } @Nullable @Override - public String getConversationId(Collection v) { + public String getConversationId(Collection v) { return null; } @Nullable @Override - public Long getMessagePayloadSize(Collection v) { + public Long getMessagePayloadSize(Collection v) { long total = 0; - for (Message message : v) { - total += message.body().length(); + for (MessageType message : v) { + total += SqsMessageDelegates.get(message).getPayloadSize(message); } return total; @@ -101,38 +94,28 @@ public Long getMessagePayloadSize(Collection v) { @Nullable @Override - public Long getMessagePayloadCompressedSize(Collection v) { + public Long getMessagePayloadCompressedSize(Collection v) { return null; } @Nullable @Override - public String getMessageId(Collection request, Void v) { + public String getMessageId(Collection request, Void v) { return null; } }; } - protected AttributesExtractor, Void> getAttributesExtractor() { + protected AttributesExtractor, Void> getAttributesExtractor() { return MessagingAttributesExtractor.create( getMessageingAttributesGetter(), MessageOperation.PROCESS); } - protected SpanLinksExtractor> getSpanLinksExtractor() { + @SuppressWarnings("unchecked") + protected SpanLinksExtractor> getSpanLinksExtractor() { return (spanLinks, parentContext, request) -> { - TextMapPropagator messagingPropagator = openTelemetry.getPropagators().getTextMapPropagator(); - - for (Message message : request) { - Map messageAtributes = SqsMessageAccess.getMessageAttributes(message); - - Context context = - SqsParentContext.ofMessageAttributes(messageAtributes, messagingPropagator); - - if (context == Context.root()) { - context = SqsParentContext.ofSystemAttributes(SqsMessageAccess.getAttributes(message)); - } - - SpanContext messageSpanCtx = Span.fromContext(context).getSpanContext(); + for (MessageType message : request) { + SpanContext messageSpanCtx = SqsMessageDelegates.get(message).getUpstreamContext(openTelemetry, message); if (messageSpanCtx.isValid()) { spanLinks.addLink(messageSpanCtx); diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandlerTest.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandlerTest.java index 85c62cfeae6b..1a3dbee2be82 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandlerTest.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandlerTest.java @@ -8,6 +8,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; +import com.amazonaws.services.lambda.runtime.events.SQSEvent; +import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.SpanContext; import io.opentelemetry.api.trace.SpanKind; @@ -17,28 +19,52 @@ import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; import io.opentelemetry.sdk.trace.data.LinkData; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; +import java.lang.reflect.Constructor; import java.util.Collection; import java.util.Collections; import java.util.LinkedList; import java.util.List; +import java.util.Map; +import java.util.TreeMap; import java.util.concurrent.atomic.AtomicInteger; import org.junit.jupiter.api.Test; import software.amazon.awssdk.services.sqs.model.Message; public class SqsMessageHandlerTest extends XrayTestInstrumenter { + private static class SqsMessageHandlerImpl extends SqsMessageHandler { + public final AtomicInteger handleCalls = new AtomicInteger(); + + public SqsMessageHandlerImpl(OpenTelemetry openTelemetry, + String destination, SpanKindExtractor> spanKindExtractor) { + super(openTelemetry, destination, spanKindExtractor); + } + + @Override + protected void doHandle(Collection request) { + handleCalls.getAndIncrement(); + } + } + + private static class LambdaSqsMessageHandlerImpl extends SqsMessageHandler { + public final AtomicInteger handleCalls = new AtomicInteger(); + + public LambdaSqsMessageHandlerImpl(OpenTelemetry openTelemetry, + String destination, SpanKindExtractor> spanKindExtractor) { + super(openTelemetry, destination, spanKindExtractor); + } + + @Override + protected void doHandle(Collection request) { + handleCalls.getAndIncrement(); + } + } @Test public void simple() { - AtomicInteger handleCalls = new AtomicInteger(); - - SqsMessageHandler messageHandler = - new SqsMessageHandler(getOpenTelemetry(), "destination", SpanKindExtractor.alwaysServer()) { - @Override - protected Void doHandle(Collection request) { - handleCalls.incrementAndGet(); - return null; - } - }; + SqsMessageHandlerImpl messageHandler = new SqsMessageHandlerImpl( + getOpenTelemetry(), + "destination", + SpanKindExtractor.alwaysServer()); List messages = new LinkedList<>(); messages.add(Message.builder() @@ -57,7 +83,7 @@ protected Void doHandle(Collection request) { parentSpan.end(); - assertThat(handleCalls.get()).isEqualTo(1); + assertThat(messageHandler.handleCalls.get()).isEqualTo(1); waitAndAssertTraces( trace -> @@ -84,34 +110,138 @@ protected Void doHandle(Collection request) { } @Test - public void twoMessages() { - AtomicInteger handleCalls = new AtomicInteger(); + public void lambdaSimple() { + LambdaSqsMessageHandlerImpl messageHandler = new LambdaSqsMessageHandlerImpl( + getOpenTelemetry(), + "destination", + SpanKindExtractor.alwaysServer()); + + List messages = new LinkedList<>(); + SQSEvent.SQSMessage message = newMessage(); + message.setBody("Hello"); + Map attributes = new TreeMap<>(); + attributes.put("AWSTraceHeader", "Root=1-99555555-123456789012345678901234;Parent=9934567890123456;Sampled=1"); + message.setAttributes(attributes); + messages.add(message); + + Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); + + try (Scope scope = parentSpan.makeCurrent()) { + messageHandler.handle(messages); + } + + parentSpan.end(); + + assertThat(messageHandler.handleCalls.get()).isEqualTo(1); + + waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), + span -> + span.hasName("destination process") + .hasKind(SpanKind.SERVER) + .hasLinks( + LinkData.create( + SpanContext.createFromRemoteParent( + "99555555123456789012345678901234", + "9934567890123456", + TraceFlags.getSampled(), + TraceState.getDefault()))) + .hasTotalRecordedLinks(1) + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") + .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") + .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") + .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 5L) + .hasTotalAttributeCount(4) + .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) + .hasTraceId(parentSpan.getSpanContext().getTraceId()))); + } + + @Test + public void lambdaTwoMessages() { + List messages = new LinkedList<>(); + SQSEvent.SQSMessage message = newMessage(); + message.setBody("Hello"); + Map attributes = new TreeMap<>(); + attributes.put("AWSTraceHeader", "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1"); + message.setAttributes(attributes); + messages.add(message); + + SQSEvent.SQSMessage message2 = newMessage(); + message2.setBody("Hello World"); + Map attributes2 = new TreeMap<>(); + attributes2.put("AWSTraceHeader", "Root=1-66555555-123456789012345678901234;Parent=6634567890123456;Sampled=0"); + message2.setAttributes(attributes2); + messages.add(message2); + + LambdaSqsMessageHandlerImpl messageHandler = new LambdaSqsMessageHandlerImpl( + getOpenTelemetry(), + "destination", + SpanKindExtractor.alwaysConsumer()); + + Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); + + try (Scope scope = parentSpan.makeCurrent()) { + messageHandler.handle(messages); + } + parentSpan.end(); + + assertThat(messageHandler.handleCalls.get()).isEqualTo(1); + + waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), + span -> + span.hasName("destination process") + .hasKind(SpanKind.CONSUMER) + .hasLinks( + LinkData.create( + SpanContext.createFromRemoteParent( + "55555555123456789012345678901234", + "1234567890123456", + TraceFlags.getSampled(), + TraceState.getDefault())), + LinkData.create( + SpanContext.createFromRemoteParent( + "66555555123456789012345678901234", + "6634567890123456", + TraceFlags.getDefault(), + TraceState.getDefault()))) + .hasTotalRecordedLinks(2) + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") + .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") + .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") + .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 16L) + .hasTotalAttributeCount(4) + .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) + .hasTraceId(parentSpan.getSpanContext().getTraceId()))); + } + + @Test + public void twoMessages() { List messages = new LinkedList(); messages.add(Message.builder() - .body("Hello") - .attributesWithStrings( - Collections.singletonMap( - "AWSTraceHeader", - "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")) - .build()); + .body("Hello") + .attributesWithStrings( + Collections.singletonMap( + "AWSTraceHeader", + "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")) + .build()); messages.add(Message.builder() - .body("Hello World") - .attributesWithStrings( - Collections.singletonMap( - "AWSTraceHeader", - "Root=1-66555555-123456789012345678901234;Parent=6634567890123456;Sampled=0")) - .build()); - - SqsMessageHandler messageHandler = - new SqsMessageHandler(getOpenTelemetry(), "destination", SpanKindExtractor.alwaysConsumer()) { + .body("Hello World") + .attributesWithStrings( + Collections.singletonMap( + "AWSTraceHeader", + "Root=1-66555555-123456789012345678901234;Parent=6634567890123456;Sampled=0")) + .build()); - @Override - protected Void doHandle(Collection request) { - handleCalls.incrementAndGet(); - return null; - } - }; + SqsMessageHandlerImpl messageHandler = new SqsMessageHandlerImpl( + getOpenTelemetry(), + "destination", + SpanKindExtractor.alwaysConsumer()); Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); @@ -121,7 +251,7 @@ protected Void doHandle(Collection request) { parentSpan.end(); - assertThat(handleCalls.get()).isEqualTo(1); + assertThat(messageHandler.handleCalls.get()).isEqualTo(1); waitAndAssertTraces( trace -> @@ -155,8 +285,6 @@ protected Void doHandle(Collection request) { @Test public void twoRuns() { - AtomicInteger handleCalls = new AtomicInteger(); - List messages1 = new LinkedList(); messages1.add(Message.builder() .body("Hello") @@ -175,14 +303,10 @@ public void twoRuns() { "Root=1-77555555-123456789012345678901234;Parent=7734567890123456;Sampled=1")) .build()); - SqsMessageHandler messageHandler = - new SqsMessageHandler(getOpenTelemetry(), "destination", SpanKindExtractor.alwaysServer()) { - @Override - protected Void doHandle(Collection request) { - handleCalls.incrementAndGet(); - return null; - } - }; + SqsMessageHandlerImpl messageHandler = new SqsMessageHandlerImpl( + getOpenTelemetry(), + "destination", + SpanKindExtractor.alwaysServer()); Span parentSpan1 = getOpenTelemetry().getTracer("test").spanBuilder("test1").startSpan(); try (Scope scope = parentSpan1.makeCurrent()) { @@ -196,7 +320,7 @@ protected Void doHandle(Collection request) { } parentSpan2.end(); - assertThat(handleCalls.get()).isEqualTo(2); + assertThat(messageHandler.handleCalls.get()).isEqualTo(2); waitAndAssertTraces( trace -> @@ -244,18 +368,93 @@ protected Void doHandle(Collection request) { } @Test - public void noMessages() { - AtomicInteger handleCalls = new AtomicInteger(); + public void lambdaTwoRuns() { + List messages1 = new LinkedList<>(); + List messages2 = new LinkedList<>(); + SQSEvent.SQSMessage message = newMessage(); + message.setBody("Hello"); + Map attributes = new TreeMap<>(); + attributes.put("AWSTraceHeader", "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=0"); + message.setAttributes(attributes); + messages1.add(message); + + SQSEvent.SQSMessage message2 = newMessage(); + message2.setBody("SecondMessage"); + Map attributes2 = new TreeMap<>(); + attributes2.put("AWSTraceHeader", "Root=1-77555555-123456789012345678901234;Parent=7734567890123456;Sampled=1"); + message2.setAttributes(attributes2); + messages2.add(message2); + + LambdaSqsMessageHandlerImpl messageHandler = new LambdaSqsMessageHandlerImpl( + getOpenTelemetry(), + "destination", + SpanKindExtractor.alwaysServer()); - SqsMessageHandler messageHandler = - new SqsMessageHandler(getOpenTelemetry(), "destination", SpanKindExtractor.alwaysServer()) { + Span parentSpan1 = getOpenTelemetry().getTracer("test").spanBuilder("test1").startSpan(); + try (Scope scope = parentSpan1.makeCurrent()) { + messageHandler.handle(messages1); + } + parentSpan1.end(); - @Override - protected Void doHandle(Collection request) { - handleCalls.incrementAndGet(); - return null; - } - }; + Span parentSpan2 = getOpenTelemetry().getTracer("test").spanBuilder("test2").startSpan(); + try (Scope scope = parentSpan2.makeCurrent()) { + messageHandler.handle(messages2); + } + parentSpan2.end(); + + assertThat(messageHandler.handleCalls.get()).isEqualTo(2); + + waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("test1").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), + span -> + span.hasName("destination process") + .hasKind(SpanKind.SERVER) + .hasLinks( + LinkData.create( + SpanContext.createFromRemoteParent( + "55555555123456789012345678901234", + "1234567890123456", + TraceFlags.getDefault(), + TraceState.getDefault()))) + .hasTotalRecordedLinks(1) + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") + .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") + .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") + .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 5L) + .hasTotalAttributeCount(4) + .hasParentSpanId(parentSpan1.getSpanContext().getSpanId()) + .hasTraceId(parentSpan1.getSpanContext().getTraceId())), + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("test2").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), + span -> + span.hasName("destination process") + .hasKind(SpanKind.SERVER) + .hasLinks( + LinkData.create( + SpanContext.createFromRemoteParent( + "77555555123456789012345678901234", + "7734567890123456", + TraceFlags.getSampled(), + TraceState.getDefault()))) + .hasTotalRecordedLinks(1) + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") + .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") + .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") + .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 13L) + .hasTotalAttributeCount(4) + .hasParentSpanId(parentSpan2.getSpanContext().getSpanId()) + .hasTraceId(parentSpan2.getSpanContext().getTraceId()))); + } + + @Test + public void lambdaNoMessages() { + LambdaSqsMessageHandlerImpl messageHandler = new LambdaSqsMessageHandlerImpl( + getOpenTelemetry(), + "destination", + SpanKindExtractor.alwaysServer()); Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); try (Scope scope = parentSpan.makeCurrent()) { @@ -263,7 +462,7 @@ protected Void doHandle(Collection request) { } parentSpan.end(); - assertThat(handleCalls.get()).isEqualTo(1); + assertThat(messageHandler.handleCalls.get()).isEqualTo(1); waitAndAssertTraces( trace -> @@ -283,9 +482,39 @@ protected Void doHandle(Collection request) { } @Test - public void malformedTraceId() { - AtomicInteger handleCalls = new AtomicInteger(); + public void noMessages() { + SqsMessageHandlerImpl messageHandler = new SqsMessageHandlerImpl( + getOpenTelemetry(), + "destination", + SpanKindExtractor.alwaysServer()); + + Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); + try (Scope scope = parentSpan.makeCurrent()) { + messageHandler.handle(new LinkedList<>()); + } + parentSpan.end(); + + assertThat(messageHandler.handleCalls.get()).isEqualTo(1); + waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), + span -> + span.hasName("destination process") + .hasKind(SpanKind.SERVER) + .hasTotalRecordedLinks(0) + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") + .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") + .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") + .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 0L) + .hasTotalAttributeCount(4) + .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) + .hasTraceId(parentSpan.getSpanContext().getTraceId()))); + } + + @Test + public void malformedTraceId() { List messages = new LinkedList(); messages.add(Message.builder() .body("Hello") @@ -295,14 +524,45 @@ public void malformedTraceId() { "Root=1-55555555-error;Parent=1234567890123456;Sampled=1")) .build()); - SqsMessageHandler messageHandler = - new SqsMessageHandler(getOpenTelemetry(), "destination", SpanKindExtractor.alwaysServer()) { - @Override - protected Void doHandle(Collection request) { - handleCalls.incrementAndGet(); - return null; + SqsMessageHandlerImpl messageHandler = new SqsMessageHandlerImpl( + getOpenTelemetry(), + "destination", + SpanKindExtractor.alwaysServer()); + + Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); + + assertThrows( + RuntimeException.class, + () -> { + try (Scope scope = parentSpan.makeCurrent()) { + messageHandler.handle(messages); } - }; + }); + + parentSpan.end(); + + assertThat(messageHandler.handleCalls.get()).isEqualTo(0); + + waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0))); + } + + @Test + public void lambdaMalformedTraceId() { + List messages = new LinkedList<>(); + SQSEvent.SQSMessage message = newMessage(); + message.setBody("Hello"); + Map attributes = new TreeMap<>(); + attributes.put("AWSTraceHeader", "Root=1-55555555-error;Parent=1234567890123456;Sampled=1"); + message.setAttributes(attributes); + messages.add(message); + + LambdaSqsMessageHandlerImpl messageHandler = new LambdaSqsMessageHandlerImpl( + getOpenTelemetry(), + "destination", + SpanKindExtractor.alwaysServer()); Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); @@ -316,11 +576,21 @@ protected Void doHandle(Collection request) { parentSpan.end(); - assertThat(handleCalls.get()).isEqualTo(0); + assertThat(messageHandler.handleCalls.get()).isEqualTo(0); waitAndAssertTraces( trace -> trace.hasSpansSatisfyingExactly( span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0))); } + + private static SQSEvent.SQSMessage newMessage() { + try { + Constructor ctor = SQSEvent.SQSMessage.class.getDeclaredConstructor(); + ctor.setAccessible(true); + return ctor.newInstance(); + } catch (Throwable t) { + throw new AssertionError(t); + } + } } diff --git a/instrumentation/message-handler/message-handler-1.0/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageHandler.java b/instrumentation/message-handler/message-handler-1.0/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageHandler.java index c46468c24bbb..36eb92f4fa5b 100644 --- a/instrumentation/message-handler/message-handler-1.0/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageHandler.java +++ b/instrumentation/message-handler/message-handler-1.0/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageHandler.java @@ -8,29 +8,27 @@ import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import java.util.Collection; -public abstract class MessageHandler { +public abstract class MessageHandler { - protected abstract Instrumenter getMessageInstrumenter(); + protected abstract Instrumenter, Void> getMessageInstrumenter(); - protected abstract OUTPUT doHandle(INPUT request); + protected abstract void doHandle(Collection request); - public OUTPUT handle(INPUT request) { - Instrumenter instrumenter = getMessageInstrumenter(); - OUTPUT response = null; + public void handle(Collection request) { + Instrumenter, Void> instrumenter = getMessageInstrumenter(); Throwable error = null; Context context = instrumenter.start(Context.current(), request); try (Scope scope = context.makeCurrent()) { - response = doHandle(request); + doHandle(request); } catch (Throwable t) { error = t; throw t; } finally { - instrumenter.end(context, request, response, error); + instrumenter.end(context, request, null, error); } - - return response; } } From b810b67e10ed2d3ac0ea11bf94082f2d299c6590 Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Mon, 14 Aug 2023 09:43:12 -0700 Subject: [PATCH 41/47] Fixing AWS SDK --- .../aws-sdk-2.2/library/build.gradle.kts | 3 +- .../awssdk/v2_2/SqsMessageDelegates.java | 29 ++- .../awssdk/v2_2/SqsMessageHandler.java | 28 +-- .../awssdk/v2_2/SqsMessageHandlerTest.java | 166 ++++++++++++++---- .../awssdk/v2_2/XrayTestInstrumenter.java | 7 + 5 files changed, 181 insertions(+), 52 deletions(-) diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts b/instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts index 5471d5f8c8a8..205ff3b66c45 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts @@ -11,7 +11,7 @@ dependencies { library("software.amazon.awssdk:aws-core:2.20.0") library("software.amazon.awssdk:aws-json-protocol:2.2.0") library("software.amazon.awssdk:sqs:2.20.0") - library("com.amazonaws:aws-lambda-java-events:2.2.1") + implementation("com.amazonaws:aws-lambda-java-events:2.2.1") testImplementation(project(":instrumentation:aws-sdk:aws-sdk-2.2:testing")) @@ -23,6 +23,7 @@ dependencies { latestDepTestLibrary("software.amazon.awssdk:rds:+") latestDepTestLibrary("software.amazon.awssdk:s3:+") latestDepTestLibrary("software.amazon.awssdk:sqs:+") + latestDepTestLibrary("software.amazon.awssdk:sqs:+") } tasks { diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageDelegates.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageDelegates.java index 9b9a19da2660..9abf6c932281 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageDelegates.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageDelegates.java @@ -34,13 +34,13 @@ public SpanContext getUpstreamContext(OpenTelemetry openTelemetry, Message messa TextMapPropagator messagingPropagator = openTelemetry.getPropagators() .getTextMapPropagator(); - Map messageAtributes = SqsMessageAccess.getMessageAttributes(message); - - Context context = - SqsParentContext.ofMessageAttributes(messageAtributes, messagingPropagator); + Context context = SqsParentContext.ofSystemAttributes(SqsMessageAccess.getAttributes(message)); if (context == Context.root()) { - context = SqsParentContext.ofSystemAttributes(SqsMessageAccess.getAttributes(message)); + Map messageAtributes = SqsMessageAccess.getMessageAttributes(message); + + context = + SqsParentContext.ofMessageAttributes(messageAtributes, messagingPropagator); } return Span.fromContext(context).getSpanContext(); @@ -59,7 +59,23 @@ public int getPayloadSize(SQSEvent.SQSMessage message) { @Override public SpanContext getUpstreamContext(OpenTelemetry openTelemetry, SQSEvent.SQSMessage message) { - String parentHeader = message.getAttributes().get(AWS_TRACE_HEADER_SQS_ATTRIBUTE_KEY); + String parentHeader = null; + + if (message.getAttributes() != null) { + parentHeader = message.getAttributes().get(AWS_TRACE_HEADER_SQS_ATTRIBUTE_KEY); + } + + if (parentHeader == null && + message.getMessageAttributes() != null) + { + // We need to do a case-insensitive search + for (Map.Entry entry: message.getMessageAttributes().entrySet()) { + if (entry.getKey().equalsIgnoreCase(AWS_TRACE_HEADER_PROPAGATOR_KEY)) { + parentHeader = entry.getValue().getStringValue(); + break; + } + } + } if (parentHeader != null) { Context xrayContext = @@ -68,6 +84,7 @@ public SpanContext getUpstreamContext(OpenTelemetry openTelemetry, SQSEvent.SQSM Context.root(), Collections.singletonMap(AWS_TRACE_HEADER_PROPAGATOR_KEY, parentHeader), MapGetter.INSTANCE); + return Span.fromContext(xrayContext).getSpanContext(); } diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java index 9ccf98bf1b18..3fc06327195a 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java @@ -15,7 +15,6 @@ import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessageOperation; import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessagingAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessagingAttributesGetter; -import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessagingSpanNameExtractor; import io.opentelemetry.instrumentation.messagehandler.MessageHandler; import java.util.Collection; import javax.annotation.Nullable; @@ -23,26 +22,31 @@ public abstract class SqsMessageHandler extends MessageHandler { private final OpenTelemetry openTelemetry; private final String destination; - private final SpanKindExtractor> spanKindExtractor; + private SpanKindExtractor> spanKindExtractor; + private SpanNameExtractor> spanNameExtractor; - public SqsMessageHandler(OpenTelemetry openTelemetry, String destination, SpanKindExtractor> spanKindExtractor) { + public SqsMessageHandler(OpenTelemetry openTelemetry, String destination) { this.openTelemetry = openTelemetry; this.destination = destination; - this.spanKindExtractor = spanKindExtractor; + this.spanKindExtractor = SpanKindExtractor.alwaysConsumer(); + spanNameExtractor = e -> destination + " process"; + } + + public void setSpanNameExtactor(SpanNameExtractor> spanNameExtractor) { + this.spanNameExtractor = spanNameExtractor; } @Override protected Instrumenter, Void> getMessageInstrumenter() { return Instrumenter., Void>builder( - openTelemetry, "io.opentelemetry.aws-sdk-2.2", getSpanNameExtractor()) - .addAttributesExtractor(getAttributesExtractor()) + openTelemetry, "io.opentelemetry.aws-sdk-2.2", spanNameExtractor) + .addAttributesExtractor(getMessageOperationAttributeExtractor()) .addSpanLinksExtractor(getSpanLinksExtractor()) .buildInstrumenter(spanKindExtractor); } - protected SpanNameExtractor> getSpanNameExtractor() { - return MessagingSpanNameExtractor.create( - getMessageingAttributesGetter(), MessageOperation.PROCESS); + public void setSpanKindExtractor(SpanKindExtractor> spanKindExtractor) { + this.spanKindExtractor = spanKindExtractor; } protected MessagingAttributesGetter, Void> @@ -106,18 +110,18 @@ public String getMessageId(Collection request, Void v) { }; } - protected AttributesExtractor, Void> getAttributesExtractor() { + protected AttributesExtractor, Void> getMessageOperationAttributeExtractor() { return MessagingAttributesExtractor.create( getMessageingAttributesGetter(), MessageOperation.PROCESS); } - @SuppressWarnings("unchecked") + //@SuppressWarnings("unchecked") protected SpanLinksExtractor> getSpanLinksExtractor() { return (spanLinks, parentContext, request) -> { for (MessageType message : request) { SpanContext messageSpanCtx = SqsMessageDelegates.get(message).getUpstreamContext(openTelemetry, message); - if (messageSpanCtx.isValid()) { + if (messageSpanCtx!= null && messageSpanCtx.isValid()) { spanLinks.addLink(messageSpanCtx); } } diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandlerTest.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandlerTest.java index 1a3dbee2be82..502114c0603d 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandlerTest.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandlerTest.java @@ -29,14 +29,15 @@ import java.util.concurrent.atomic.AtomicInteger; import org.junit.jupiter.api.Test; import software.amazon.awssdk.services.sqs.model.Message; +import software.amazon.awssdk.services.sqs.model.MessageAttributeValue; public class SqsMessageHandlerTest extends XrayTestInstrumenter { private static class SqsMessageHandlerImpl extends SqsMessageHandler { public final AtomicInteger handleCalls = new AtomicInteger(); public SqsMessageHandlerImpl(OpenTelemetry openTelemetry, - String destination, SpanKindExtractor> spanKindExtractor) { - super(openTelemetry, destination, spanKindExtractor); + String destination) { + super(openTelemetry, destination); } @Override @@ -49,8 +50,8 @@ private static class LambdaSqsMessageHandlerImpl extends SqsMessageHandler> spanKindExtractor) { - super(openTelemetry, destination, spanKindExtractor); + String destination) { + super(openTelemetry, destination); } @Override @@ -63,8 +64,9 @@ protected void doHandle(Collection request) { public void simple() { SqsMessageHandlerImpl messageHandler = new SqsMessageHandlerImpl( getOpenTelemetry(), - "destination", - SpanKindExtractor.alwaysServer()); + "destination"); + + messageHandler.setSpanNameExtactor(e-> "MySpan"); List messages = new LinkedList<>(); messages.add(Message.builder() @@ -85,13 +87,65 @@ public void simple() { assertThat(messageHandler.handleCalls.get()).isEqualTo(1); + waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), + span -> + span.hasName("MySpan") + .hasKind(SpanKind.CONSUMER) + .hasLinks( + LinkData.create( + SpanContext.createFromRemoteParent( + "55555555123456789012345678901234", + "1234567890123456", + TraceFlags.getSampled(), + TraceState.getDefault()))) + .hasTotalRecordedLinks(1) + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") + .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") + .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") + .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 5L) + .hasTotalAttributeCount(4) + .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) + .hasTraceId(parentSpan.getSpanContext().getTraceId()))); + } + + @Test + public void simpleUseMessageAttribute() { + SqsMessageHandlerImpl messageHandler = new SqsMessageHandlerImpl( + getOpenTelemetry(), + "destination"); + + List messages = new LinkedList<>(); + messages.add(Message.builder() + .body("Hello") + .messageAttributes(Collections.singletonMap("X-Amzn-Trace-Id", + MessageAttributeValue.builder().dataType("String") + .stringValue("Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1") + .build())) + .build()); + + Span parentSpan = getOpenTelemetry() + .getTracer("test") + .spanBuilder("test") + .startSpan(); + + try (Scope scope = parentSpan.makeCurrent()) { + messageHandler.handle(messages); + } + + parentSpan.end(); + + assertThat(messageHandler.handleCalls.get()).isEqualTo(1); + waitAndAssertTraces( trace -> trace.hasSpansSatisfyingExactly( span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> span.hasName("destination process") - .hasKind(SpanKind.SERVER) + .hasKind(SpanKind.CONSUMER) .hasLinks( LinkData.create( SpanContext.createFromRemoteParent( @@ -113,8 +167,7 @@ public void simple() { public void lambdaSimple() { LambdaSqsMessageHandlerImpl messageHandler = new LambdaSqsMessageHandlerImpl( getOpenTelemetry(), - "destination", - SpanKindExtractor.alwaysServer()); + "destination"); List messages = new LinkedList<>(); SQSEvent.SQSMessage message = newMessage(); @@ -140,7 +193,58 @@ public void lambdaSimple() { span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> span.hasName("destination process") - .hasKind(SpanKind.SERVER) + .hasKind(SpanKind.CONSUMER) + .hasLinks( + LinkData.create( + SpanContext.createFromRemoteParent( + "99555555123456789012345678901234", + "9934567890123456", + TraceFlags.getSampled(), + TraceState.getDefault()))) + .hasTotalRecordedLinks(1) + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") + .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") + .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") + .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 5L) + .hasTotalAttributeCount(4) + .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) + .hasTraceId(parentSpan.getSpanContext().getTraceId()))); + } + + @Test + public void lambdaSimpleUseMessageAttribute() { + LambdaSqsMessageHandlerImpl messageHandler = new LambdaSqsMessageHandlerImpl( + getOpenTelemetry(), + "destination"); + + List messages = new LinkedList<>(); + SQSEvent.SQSMessage message = newMessage(); + message.setBody("Hello"); + Map attributes = new TreeMap<>(); + SQSEvent.MessageAttribute value = new SQSEvent.MessageAttribute(); + value.setDataType("String"); + value.setStringValue("Root=1-99555555-123456789012345678901234;Parent=9934567890123456;Sampled=1"); + attributes.put("X-Amzn-Trace-Id", value); + message.setMessageAttributes(attributes); + messages.add(message); + + Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); + + try (Scope scope = parentSpan.makeCurrent()) { + messageHandler.handle(messages); + } + + parentSpan.end(); + + assertThat(messageHandler.handleCalls.get()).isEqualTo(1); + + waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), + span -> + span.hasName("destination process") + .hasKind(SpanKind.CONSUMER) .hasLinks( LinkData.create( SpanContext.createFromRemoteParent( @@ -177,8 +281,9 @@ public void lambdaTwoMessages() { LambdaSqsMessageHandlerImpl messageHandler = new LambdaSqsMessageHandlerImpl( getOpenTelemetry(), - "destination", - SpanKindExtractor.alwaysConsumer()); + "destination"); + + messageHandler.setSpanKindExtractor(SpanKindExtractor.alwaysServer()); Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); @@ -196,7 +301,7 @@ public void lambdaTwoMessages() { span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> span.hasName("destination process") - .hasKind(SpanKind.CONSUMER) + .hasKind(SpanKind.SERVER) .hasLinks( LinkData.create( SpanContext.createFromRemoteParent( @@ -240,8 +345,9 @@ public void twoMessages() { SqsMessageHandlerImpl messageHandler = new SqsMessageHandlerImpl( getOpenTelemetry(), - "destination", - SpanKindExtractor.alwaysConsumer()); + "destination"); + + messageHandler.setSpanKindExtractor(SpanKindExtractor.alwaysConsumer()); Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); @@ -305,8 +411,7 @@ public void twoRuns() { SqsMessageHandlerImpl messageHandler = new SqsMessageHandlerImpl( getOpenTelemetry(), - "destination", - SpanKindExtractor.alwaysServer()); + "destination"); Span parentSpan1 = getOpenTelemetry().getTracer("test").spanBuilder("test1").startSpan(); try (Scope scope = parentSpan1.makeCurrent()) { @@ -328,7 +433,7 @@ public void twoRuns() { span -> span.hasName("test1").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> span.hasName("destination process") - .hasKind(SpanKind.SERVER) + .hasKind(SpanKind.CONSUMER) .hasLinks( LinkData.create( SpanContext.createFromRemoteParent( @@ -349,7 +454,7 @@ public void twoRuns() { span -> span.hasName("test2").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> span.hasName("destination process") - .hasKind(SpanKind.SERVER) + .hasKind(SpanKind.CONSUMER) .hasLinks( LinkData.create( SpanContext.createFromRemoteParent( @@ -387,8 +492,7 @@ public void lambdaTwoRuns() { LambdaSqsMessageHandlerImpl messageHandler = new LambdaSqsMessageHandlerImpl( getOpenTelemetry(), - "destination", - SpanKindExtractor.alwaysServer()); + "destination"); Span parentSpan1 = getOpenTelemetry().getTracer("test").spanBuilder("test1").startSpan(); try (Scope scope = parentSpan1.makeCurrent()) { @@ -410,7 +514,7 @@ public void lambdaTwoRuns() { span -> span.hasName("test1").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> span.hasName("destination process") - .hasKind(SpanKind.SERVER) + .hasKind(SpanKind.CONSUMER) .hasLinks( LinkData.create( SpanContext.createFromRemoteParent( @@ -431,7 +535,7 @@ public void lambdaTwoRuns() { span -> span.hasName("test2").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> span.hasName("destination process") - .hasKind(SpanKind.SERVER) + .hasKind(SpanKind.CONSUMER) .hasLinks( LinkData.create( SpanContext.createFromRemoteParent( @@ -453,8 +557,7 @@ public void lambdaTwoRuns() { public void lambdaNoMessages() { LambdaSqsMessageHandlerImpl messageHandler = new LambdaSqsMessageHandlerImpl( getOpenTelemetry(), - "destination", - SpanKindExtractor.alwaysServer()); + "destination"); Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); try (Scope scope = parentSpan.makeCurrent()) { @@ -470,7 +573,7 @@ public void lambdaNoMessages() { span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> span.hasName("destination process") - .hasKind(SpanKind.SERVER) + .hasKind(SpanKind.CONSUMER) .hasTotalRecordedLinks(0) .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") @@ -485,8 +588,7 @@ public void lambdaNoMessages() { public void noMessages() { SqsMessageHandlerImpl messageHandler = new SqsMessageHandlerImpl( getOpenTelemetry(), - "destination", - SpanKindExtractor.alwaysServer()); + "destination"); Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); try (Scope scope = parentSpan.makeCurrent()) { @@ -502,7 +604,7 @@ public void noMessages() { span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> span.hasName("destination process") - .hasKind(SpanKind.SERVER) + .hasKind(SpanKind.CONSUMER) .hasTotalRecordedLinks(0) .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") @@ -526,8 +628,7 @@ public void malformedTraceId() { SqsMessageHandlerImpl messageHandler = new SqsMessageHandlerImpl( getOpenTelemetry(), - "destination", - SpanKindExtractor.alwaysServer()); + "destination"); Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); @@ -561,8 +662,7 @@ public void lambdaMalformedTraceId() { LambdaSqsMessageHandlerImpl messageHandler = new LambdaSqsMessageHandlerImpl( getOpenTelemetry(), - "destination", - SpanKindExtractor.alwaysServer()); + "destination"); Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/XrayTestInstrumenter.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/XrayTestInstrumenter.java index c911aa01562d..a2af1d01c2eb 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/XrayTestInstrumenter.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/XrayTestInstrumenter.java @@ -5,8 +5,10 @@ package io.opentelemetry.instrumentation.awssdk.v2_2; +import static io.opentelemetry.semconv.resource.attributes.ResourceAttributes.SERVICE_NAME; import static org.awaitility.Awaitility.await; +import io.opentelemetry.api.common.Attributes; import io.opentelemetry.context.Context; import io.opentelemetry.context.propagation.ContextPropagators; import io.opentelemetry.contrib.awsxray.propagator.AwsXrayPropagator; @@ -17,6 +19,7 @@ import io.opentelemetry.sdk.metrics.data.AggregationTemporality; import io.opentelemetry.sdk.metrics.export.MetricReader; import io.opentelemetry.sdk.metrics.export.PeriodicMetricReader; +import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.sdk.testing.assertj.TraceAssert; import io.opentelemetry.sdk.testing.assertj.TracesAssert; import io.opentelemetry.sdk.testing.exporter.InMemoryMetricExporter; @@ -55,10 +58,14 @@ public class XrayTestInstrumenter { .setInterval(Duration.ofNanos(Long.MAX_VALUE)) .build(); + Resource resource = Resource.getDefault().merge(Resource.create( + Attributes.of(SERVICE_NAME, "MyServiceName"))); + openTelemetry = OpenTelemetrySdk.builder() .setTracerProvider( SdkTracerProvider.builder() + .setResource(resource) .addSpanProcessor(new FlushTrackingSpanProcessor()) .addSpanProcessor(SimpleSpanProcessor.create(testSpanExporter)) .build()) From 1e0104ede5e1da9cd7f8b6de41242d0312519122 Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Wed, 16 Aug 2023 15:33:35 -0700 Subject: [PATCH 42/47] Splitting out lambda --- .../library/build.gradle.kts | 1 + .../v2_2/SqsMessageHandler.java | 192 +++++++++ .../v2_2/SqsMessageHandlerTest.java | 404 ++++++++++++++++++ .../v2_2/XrayTestInstrumenter.java | 160 +++++++ .../aws-sdk-2.2/library/build.gradle.kts | 2 - .../awssdk/v2_2/SqsMessageDelegate.java | 9 - .../awssdk/v2_2/SqsMessageDelegates.java | 117 ----- .../awssdk/v2_2/SqsMessageHandler.java | 74 ++-- .../awssdk/v2_2/SqsMessageHandlerTest.java | 350 ++------------- 9 files changed, 836 insertions(+), 473 deletions(-) create mode 100644 instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/SqsMessageHandler.java create mode 100644 instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/test/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/SqsMessageHandlerTest.java create mode 100644 instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/test/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/XrayTestInstrumenter.java delete mode 100644 instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageDelegate.java delete mode 100644 instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageDelegates.java diff --git a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/build.gradle.kts b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/build.gradle.kts index 02899f461ec1..5612078509a7 100644 --- a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/build.gradle.kts +++ b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/build.gradle.kts @@ -34,6 +34,7 @@ dependencies { testImplementation("io.opentelemetry:opentelemetry-extension-trace-propagators") testImplementation("com.google.guava:guava") + implementation(project(":instrumentation:message-handler:message-handler-1.0:library")) testImplementation(project(":instrumentation:aws-lambda:aws-lambda-events-2.2:testing")) testImplementation("uk.org.webcompere:system-stubs-jupiter") } diff --git a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/SqsMessageHandler.java b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/SqsMessageHandler.java new file mode 100644 index 000000000000..e46879f2b0cd --- /dev/null +++ b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/SqsMessageHandler.java @@ -0,0 +1,192 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.awslambdaevents.v2_2; + +import com.amazonaws.services.lambda.runtime.events.SQSEvent; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanContext; +import io.opentelemetry.context.Context; +import io.opentelemetry.context.propagation.TextMapGetter; +import io.opentelemetry.contrib.awsxray.propagator.AwsXrayPropagator; +import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.SpanLinksExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessageOperation; +import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessagingAttributesExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessagingAttributesGetter; +import io.opentelemetry.instrumentation.messagehandler.MessageHandler; +import javax.annotation.Nullable; +import java.util.Collection; +import java.util.Collections; +import java.util.Locale; +import java.util.Map; + +public abstract class SqsMessageHandler extends MessageHandler { + private static final String AWS_TRACE_HEADER_SQS_ATTRIBUTE_KEY = "AWSTraceHeader"; + static final String AWS_TRACE_HEADER_PROPAGATOR_KEY = "x-amzn-trace-id"; + + private final OpenTelemetry openTelemetry; + private final String destination; + private SpanKindExtractor> spanKindExtractor; + private SpanNameExtractor> spanNameExtractor; + + public SqsMessageHandler(OpenTelemetry openTelemetry, String destination) { + this.openTelemetry = openTelemetry; + this.destination = destination; + this.spanKindExtractor = SpanKindExtractor.alwaysConsumer(); + spanNameExtractor = e -> destination + " process"; + } + + public void setSpanNameExtactor(SpanNameExtractor> spanNameExtractor) { + this.spanNameExtractor = spanNameExtractor; + } + + @Override + protected Instrumenter, Void> getMessageInstrumenter() { + return Instrumenter., Void>builder( + openTelemetry, "io.opentelemetry.aws-lambda-events-2.2", spanNameExtractor) + .addAttributesExtractor(getMessageOperationAttributeExtractor()) + .addSpanLinksExtractor(getSpanLinksExtractor()) + .buildInstrumenter(spanKindExtractor); + } + + public void setSpanKindExtractor(SpanKindExtractor> spanKindExtractor) { + this.spanKindExtractor = spanKindExtractor; + } + + protected MessagingAttributesGetter, Void> + getMessageingAttributesGetter() { + String destination = this.destination; + + return new MessagingAttributesGetter, Void>() { + @Nullable + @Override + public String getSystem(Collection v) { + return "AmazonSQS"; + } + + @Nullable + @Override + @SuppressWarnings({"deprecation"}) // Inheriting from interface + public String getDestinationKind(Collection v) { + return null; + } + + @Nullable + @Override + public String getDestination(Collection v) { + return destination; + } + + @Override + public boolean isTemporaryDestination(Collection v) { + return false; + } + + @Nullable + @Override + public String getConversationId(Collection v) { + return null; + } + + @Nullable + @Override + public Long getMessagePayloadSize(Collection v) { + long total = 0; + + for (SQSEvent.SQSMessage message : v) { + total += getPayloadSize(message); + } + + return total; + } + + @Nullable + @Override + public Long getMessagePayloadCompressedSize(Collection v) { + return null; + } + + @Nullable + @Override + public String getMessageId(Collection request, Void v) { + return null; + } + }; + } + + protected AttributesExtractor, Void> getMessageOperationAttributeExtractor() { + return MessagingAttributesExtractor.create( + getMessageingAttributesGetter(), MessageOperation.PROCESS); + } + + //@SuppressWarnings("unchecked") + protected SpanLinksExtractor> getSpanLinksExtractor() { + return (spanLinks, parentContext, request) -> { + for (SQSEvent.SQSMessage message : request) { + SpanContext messageSpanCtx = getUpstreamContext(openTelemetry, message); + + if (messageSpanCtx!= null && messageSpanCtx.isValid() && messageSpanCtx.isSampled()) { + spanLinks.addLink(messageSpanCtx); + } + } + }; + } + + public int getPayloadSize(SQSEvent.SQSMessage message) { + return message.getBody().length(); + } + + public SpanContext getUpstreamContext(OpenTelemetry openTelemetry, SQSEvent.SQSMessage message) { + String parentHeader = null; + + if (message.getAttributes() != null) { + parentHeader = message.getAttributes().get(AWS_TRACE_HEADER_SQS_ATTRIBUTE_KEY); + } + + if (parentHeader == null && + message.getMessageAttributes() != null) + { + // We need to do a case-insensitive search + for (Map.Entry entry: message.getMessageAttributes().entrySet()) { + if (entry.getKey().equalsIgnoreCase(AWS_TRACE_HEADER_PROPAGATOR_KEY)) { + parentHeader = entry.getValue().getStringValue(); + break; + } + } + } + + if (parentHeader != null) { + Context xrayContext = + AwsXrayPropagator.getInstance() + .extract( + Context.root(), + Collections.singletonMap(AWS_TRACE_HEADER_PROPAGATOR_KEY, parentHeader), + MapGetter.INSTANCE); + + return Span.fromContext(xrayContext).getSpanContext(); + } + + return null; + } + + private enum MapGetter implements TextMapGetter> { + INSTANCE; + + @Override + public Iterable keys(Map map) { + return map.keySet(); + } + + @Override + public String get(Map map, String s) { + return map.get(s.toLowerCase(Locale.ROOT)); + } + } +} diff --git a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/test/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/SqsMessageHandlerTest.java b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/test/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/SqsMessageHandlerTest.java new file mode 100644 index 000000000000..51ff35fc06de --- /dev/null +++ b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/test/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/SqsMessageHandlerTest.java @@ -0,0 +1,404 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.awslambdaevents.v2_2; + +import com.amazonaws.services.lambda.runtime.events.SQSEvent; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanContext; +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.api.trace.TraceFlags; +import io.opentelemetry.api.trace.TraceState; +import io.opentelemetry.context.Scope; +import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; +import io.opentelemetry.sdk.trace.data.LinkData; +import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; +import org.junit.jupiter.api.Test; +import java.lang.reflect.Constructor; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class SqsMessageHandlerTest extends XrayTestInstrumenter { + private static class SqsMessageHandlerImpl extends SqsMessageHandler { + public final AtomicInteger handleCalls = new AtomicInteger(); + + public SqsMessageHandlerImpl(OpenTelemetry openTelemetry, + String destination) { + super(openTelemetry, destination); + } + + @Override + protected void doHandle(Collection request) { + handleCalls.getAndIncrement(); + } + } + + @Test + public void simple() { + SqsMessageHandlerImpl messageHandler = new SqsMessageHandlerImpl( + getOpenTelemetry(), + "destination"); + + List messages = new LinkedList<>(); + SQSEvent.SQSMessage message = newMessage(); + message.setBody("Hello"); + Map attributes = new TreeMap<>(); + attributes.put("AWSTraceHeader", "Root=1-99555555-123456789012345678901234;Parent=9934567890123456;Sampled=1"); + message.setAttributes(attributes); + messages.add(message); + + Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); + + try (Scope scope = parentSpan.makeCurrent()) { + messageHandler.handle(messages); + } + + parentSpan.end(); + + assertThat(messageHandler.handleCalls.get()).isEqualTo(1); + + waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), + span -> + span.hasName("destination process") + .hasKind(SpanKind.CONSUMER) + .hasLinks( + LinkData.create( + SpanContext.createFromRemoteParent( + "99555555123456789012345678901234", + "9934567890123456", + TraceFlags.getSampled(), + TraceState.getDefault()))) + .hasTotalRecordedLinks(1) + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") + .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") + .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") + .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 5L) + .hasTotalAttributeCount(4) + .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) + .hasTraceId(parentSpan.getSpanContext().getTraceId()))); + } + + @Test + public void simpleUnsampled() { + SqsMessageHandlerImpl messageHandler = new SqsMessageHandlerImpl( + getOpenTelemetry(), + "destination"); + + List messages = new LinkedList<>(); + SQSEvent.SQSMessage message = newMessage(); + message.setBody("Hello"); + Map attributes = new TreeMap<>(); + attributes.put("AWSTraceHeader", "Root=1-99555555-123456789012345678901234;Parent=9934567890123456;Sampled=0"); + message.setAttributes(attributes); + messages.add(message); + + Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); + + try (Scope scope = parentSpan.makeCurrent()) { + messageHandler.handle(messages); + } + + parentSpan.end(); + + assertThat(messageHandler.handleCalls.get()).isEqualTo(1); + + waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), + span -> + span.hasName("destination process") + .hasKind(SpanKind.CONSUMER) + .hasTotalRecordedLinks(0) + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") + .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") + .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") + .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 5L) + .hasTotalAttributeCount(4) + .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) + .hasTraceId(parentSpan.getSpanContext().getTraceId()))); + } + + @Test + public void simpleUseMessageAttribute() { + SqsMessageHandlerImpl messageHandler = new SqsMessageHandlerImpl( + getOpenTelemetry(), + "destination"); + + List messages = new LinkedList<>(); + SQSEvent.SQSMessage message = newMessage(); + message.setBody("Hello"); + Map attributes = new TreeMap<>(); + SQSEvent.MessageAttribute value = new SQSEvent.MessageAttribute(); + value.setDataType("String"); + value.setStringValue("Root=1-99555555-123456789012345678901234;Parent=9934567890123456;Sampled=1"); + attributes.put("X-Amzn-Trace-Id", value); + message.setMessageAttributes(attributes); + messages.add(message); + + Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); + + try (Scope scope = parentSpan.makeCurrent()) { + messageHandler.handle(messages); + } + + parentSpan.end(); + + assertThat(messageHandler.handleCalls.get()).isEqualTo(1); + + waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), + span -> + span.hasName("destination process") + .hasKind(SpanKind.CONSUMER) + .hasLinks( + LinkData.create( + SpanContext.createFromRemoteParent( + "99555555123456789012345678901234", + "9934567890123456", + TraceFlags.getSampled(), + TraceState.getDefault()))) + .hasTotalRecordedLinks(1) + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") + .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") + .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") + .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 5L) + .hasTotalAttributeCount(4) + .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) + .hasTraceId(parentSpan.getSpanContext().getTraceId()))); + } + + @Test + public void twoMessages() { + List messages = new LinkedList<>(); + SQSEvent.SQSMessage message = newMessage(); + message.setBody("Hello"); + Map attributes = new TreeMap<>(); + attributes.put("AWSTraceHeader", "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1"); + message.setAttributes(attributes); + messages.add(message); + + SQSEvent.SQSMessage message2 = newMessage(); + message2.setBody("Hello World"); + Map attributes2 = new TreeMap<>(); + attributes2.put("AWSTraceHeader", "Root=1-66555555-123456789012345678901234;Parent=6634567890123456;Sampled=1"); + message2.setAttributes(attributes2); + messages.add(message2); + + SqsMessageHandlerImpl messageHandler = new SqsMessageHandlerImpl( + getOpenTelemetry(), + "destination"); + + messageHandler.setSpanKindExtractor(SpanKindExtractor.alwaysServer()); + + Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); + + try (Scope scope = parentSpan.makeCurrent()) { + messageHandler.handle(messages); + } + + parentSpan.end(); + + assertThat(messageHandler.handleCalls.get()).isEqualTo(1); + + waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), + span -> + span.hasName("destination process") + .hasKind(SpanKind.SERVER) + .hasLinks( + LinkData.create( + SpanContext.createFromRemoteParent( + "55555555123456789012345678901234", + "1234567890123456", + TraceFlags.getSampled(), + TraceState.getDefault())), + LinkData.create( + SpanContext.createFromRemoteParent( + "66555555123456789012345678901234", + "6634567890123456", + TraceFlags.getSampled(), + TraceState.getDefault()))) + .hasTotalRecordedLinks(2) + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") + .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") + .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") + .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 16L) + .hasTotalAttributeCount(4) + .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) + .hasTraceId(parentSpan.getSpanContext().getTraceId()))); + } + + @Test + public void twoRuns() { + List messages1 = new LinkedList<>(); + List messages2 = new LinkedList<>(); + SQSEvent.SQSMessage message = newMessage(); + message.setBody("Hello"); + Map attributes = new TreeMap<>(); + attributes.put("AWSTraceHeader", "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1"); + message.setAttributes(attributes); + messages1.add(message); + + SQSEvent.SQSMessage message2 = newMessage(); + message2.setBody("SecondMessage"); + Map attributes2 = new TreeMap<>(); + attributes2.put("AWSTraceHeader", "Root=1-77555555-123456789012345678901234;Parent=7734567890123456;Sampled=1"); + message2.setAttributes(attributes2); + messages2.add(message2); + + SqsMessageHandlerImpl messageHandler = new SqsMessageHandlerImpl( + getOpenTelemetry(), + "destination"); + + Span parentSpan1 = getOpenTelemetry().getTracer("test").spanBuilder("test1").startSpan(); + try (Scope scope = parentSpan1.makeCurrent()) { + messageHandler.handle(messages1); + } + parentSpan1.end(); + + Span parentSpan2 = getOpenTelemetry().getTracer("test").spanBuilder("test2").startSpan(); + try (Scope scope = parentSpan2.makeCurrent()) { + messageHandler.handle(messages2); + } + parentSpan2.end(); + + assertThat(messageHandler.handleCalls.get()).isEqualTo(2); + + waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("test1").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), + span -> + span.hasName("destination process") + .hasKind(SpanKind.CONSUMER) + .hasLinks( + LinkData.create( + SpanContext.createFromRemoteParent( + "55555555123456789012345678901234", + "1234567890123456", + TraceFlags.getSampled(), + TraceState.getDefault()))) + .hasTotalRecordedLinks(1) + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") + .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") + .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") + .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 5L) + .hasTotalAttributeCount(4) + .hasParentSpanId(parentSpan1.getSpanContext().getSpanId()) + .hasTraceId(parentSpan1.getSpanContext().getTraceId())), + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("test2").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), + span -> + span.hasName("destination process") + .hasKind(SpanKind.CONSUMER) + .hasLinks( + LinkData.create( + SpanContext.createFromRemoteParent( + "77555555123456789012345678901234", + "7734567890123456", + TraceFlags.getSampled(), + TraceState.getDefault()))) + .hasTotalRecordedLinks(1) + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") + .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") + .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") + .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 13L) + .hasTotalAttributeCount(4) + .hasParentSpanId(parentSpan2.getSpanContext().getSpanId()) + .hasTraceId(parentSpan2.getSpanContext().getTraceId()))); + } + + @Test + public void noMessages() { + SqsMessageHandlerImpl messageHandler = new SqsMessageHandlerImpl( + getOpenTelemetry(), + "destination"); + + Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); + try (Scope scope = parentSpan.makeCurrent()) { + messageHandler.handle(new LinkedList<>()); + } + parentSpan.end(); + + assertThat(messageHandler.handleCalls.get()).isEqualTo(1); + + waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), + span -> + span.hasName("destination process") + .hasKind(SpanKind.CONSUMER) + .hasTotalRecordedLinks(0) + .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") + .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") + .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") + .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 0L) + .hasTotalAttributeCount(4) + .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) + .hasTraceId(parentSpan.getSpanContext().getTraceId()))); + } + + @Test + public void malformedTraceId() { + List messages = new LinkedList<>(); + SQSEvent.SQSMessage message = newMessage(); + message.setBody("Hello"); + Map attributes = new TreeMap<>(); + attributes.put("AWSTraceHeader", "Root=1-55555555-error;Parent=1234567890123456;Sampled=1"); + message.setAttributes(attributes); + messages.add(message); + + SqsMessageHandlerImpl messageHandler = new SqsMessageHandlerImpl( + getOpenTelemetry(), + "destination"); + + Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); + + assertThrows( + RuntimeException.class, + () -> { + try (Scope scope = parentSpan.makeCurrent()) { + messageHandler.handle(messages); + } + }); + + parentSpan.end(); + + assertThat(messageHandler.handleCalls.get()).isEqualTo(0); + + waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0))); + } + + private static SQSEvent.SQSMessage newMessage() { + try { + Constructor ctor = SQSEvent.SQSMessage.class.getDeclaredConstructor(); + ctor.setAccessible(true); + return ctor.newInstance(); + } catch (Throwable t) { + throw new AssertionError(t); + } + } +} diff --git a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/test/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/XrayTestInstrumenter.java b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/test/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/XrayTestInstrumenter.java new file mode 100644 index 000000000000..8718a740ac6e --- /dev/null +++ b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/test/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/XrayTestInstrumenter.java @@ -0,0 +1,160 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.awslambdaevents.v2_2; + +import static io.opentelemetry.semconv.resource.attributes.ResourceAttributes.SERVICE_NAME; +import static org.awaitility.Awaitility.await; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.context.Context; +import io.opentelemetry.context.propagation.ContextPropagators; +import io.opentelemetry.contrib.awsxray.propagator.AwsXrayPropagator; +import io.opentelemetry.instrumentation.testing.util.TelemetryDataUtil; +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.common.CompletableResultCode; +import io.opentelemetry.sdk.metrics.SdkMeterProvider; +import io.opentelemetry.sdk.metrics.data.AggregationTemporality; +import io.opentelemetry.sdk.metrics.export.MetricReader; +import io.opentelemetry.sdk.metrics.export.PeriodicMetricReader; +import io.opentelemetry.sdk.resources.Resource; +import io.opentelemetry.sdk.testing.assertj.TraceAssert; +import io.opentelemetry.sdk.testing.assertj.TracesAssert; +import io.opentelemetry.sdk.testing.exporter.InMemoryMetricExporter; +import io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter; +import io.opentelemetry.sdk.trace.ReadWriteSpan; +import io.opentelemetry.sdk.trace.ReadableSpan; +import io.opentelemetry.sdk.trace.SdkTracerProvider; +import io.opentelemetry.sdk.trace.SpanProcessor; +import io.opentelemetry.sdk.trace.data.SpanData; +import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor; +import java.time.Duration; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.function.Consumer; +import javax.annotation.Nullable; +import org.awaitility.core.ConditionTimeoutException; +import org.junit.jupiter.api.AfterEach; + +public class XrayTestInstrumenter { + private static final OpenTelemetrySdk openTelemetry; + private static final InMemorySpanExporter testSpanExporter; + + static { + testSpanExporter = InMemorySpanExporter.create(); + InMemoryMetricExporter testMetricExporter = + InMemoryMetricExporter.create(AggregationTemporality.DELTA); + + MetricReader metricReader = + PeriodicMetricReader.builder(testMetricExporter) + // Set really long interval. We'll call forceFlush when we need the metrics + // instead of collecting them periodically. + .setInterval(Duration.ofNanos(Long.MAX_VALUE)) + .build(); + + Resource resource = Resource.getDefault().merge(Resource.create( + Attributes.of(SERVICE_NAME, "MyServiceName"))); + + openTelemetry = + OpenTelemetrySdk.builder() + .setTracerProvider( + SdkTracerProvider.builder() + .setResource(resource) + .addSpanProcessor(new FlushTrackingSpanProcessor()) + .addSpanProcessor(SimpleSpanProcessor.create(testSpanExporter)) + .build()) + .setMeterProvider(SdkMeterProvider.builder().registerMetricReader(metricReader).build()) + .setPropagators(ContextPropagators.create(AwsXrayPropagator.getInstance())) + .buildAndRegisterGlobal(); + } + + @AfterEach + public void resetTests() { + testSpanExporter.reset(); + } + + protected OpenTelemetrySdk getOpenTelemetry() { + return openTelemetry; + } + + private static class FlushTrackingSpanProcessor implements SpanProcessor { + @Override + public void onStart(Context parentContext, ReadWriteSpan span) {} + + @Override + public boolean isStartRequired() { + return false; + } + + @Override + public void onEnd(ReadableSpan span) {} + + @Override + public boolean isEndRequired() { + return false; + } + + @Override + public CompletableResultCode forceFlush() { + return CompletableResultCode.ofSuccess(); + } + } + + @SafeVarargs + @SuppressWarnings("varargs") + public final void waitAndAssertTraces(Consumer... assertions) { + waitAndAssertTraces(null, Arrays.asList(assertions), true); + } + + private > void waitAndAssertTraces( + @Nullable Comparator> traceComparator, + Iterable assertions, + boolean verifyScopeVersion) { + List> assertionsList = new ArrayList<>(); + assertions.forEach(assertionsList::add); + + try { + await() + .untilAsserted(() -> doAssertTraces(traceComparator, assertionsList, verifyScopeVersion)); + } catch (ConditionTimeoutException e) { + // Don't throw this failure since the stack is the awaitility thread, causing confusion. + // Instead, just assert one more time on the test thread, which will fail with a better stack + // trace. + // TODO(anuraaga): There is probably a better way to do this. + doAssertTraces(traceComparator, assertionsList, verifyScopeVersion); + } + } + + private void doAssertTraces( + @Nullable Comparator> traceComparator, + List> assertionsList, + boolean verifyScopeVersion) { + List> traces = waitForTraces(assertionsList.size()); + if (verifyScopeVersion) { + TelemetryDataUtil.assertScopeVersion(traces); + } + if (traceComparator != null) { + traces.sort(traceComparator); + } + TracesAssert.assertThat(traces).hasTracesSatisfyingExactly(assertionsList); + } + + public final List> waitForTraces(int numberOfTraces) { + try { + return TelemetryDataUtil.waitForTraces( + this::getExportedSpans, numberOfTraces, 20, TimeUnit.SECONDS); + } catch (TimeoutException | InterruptedException e) { + throw new AssertionError("Error waiting for " + numberOfTraces + " traces", e); + } + } + + public List getExportedSpans() { + return testSpanExporter.getFinishedSpanItems(); + } +} diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts b/instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts index 205ff3b66c45..bb91221a93f6 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts @@ -6,12 +6,10 @@ dependencies { implementation("io.opentelemetry.contrib:opentelemetry-aws-xray-propagator") implementation(project(":instrumentation:message-handler:message-handler-1.0:library")) - implementation(project(":instrumentation:aws-lambda:aws-lambda-events-2.2:library")) library("software.amazon.awssdk:aws-core:2.20.0") library("software.amazon.awssdk:aws-json-protocol:2.2.0") library("software.amazon.awssdk:sqs:2.20.0") - implementation("com.amazonaws:aws-lambda-java-events:2.2.1") testImplementation(project(":instrumentation:aws-sdk:aws-sdk-2.2:testing")) diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageDelegate.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageDelegate.java deleted file mode 100644 index 5ec7d78594cb..000000000000 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageDelegate.java +++ /dev/null @@ -1,9 +0,0 @@ -package io.opentelemetry.instrumentation.awssdk.v2_2; - -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.trace.SpanContext; - -public abstract class SqsMessageDelegate { - public abstract int getPayloadSize(T message); - public abstract SpanContext getUpstreamContext(OpenTelemetry openTelemetry, T message); -} diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageDelegates.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageDelegates.java deleted file mode 100644 index 9abf6c932281..000000000000 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageDelegates.java +++ /dev/null @@ -1,117 +0,0 @@ -package io.opentelemetry.instrumentation.awssdk.v2_2; - -import com.amazonaws.services.lambda.runtime.events.SQSEvent; -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.SpanContext; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.propagation.TextMapGetter; -import io.opentelemetry.context.propagation.TextMapPropagator; -import io.opentelemetry.contrib.awsxray.propagator.AwsXrayPropagator; -import software.amazon.awssdk.core.SdkPojo; -import software.amazon.awssdk.services.sqs.model.Message; -import java.util.Collections; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; - -public class SqsMessageDelegates { - private static final Map, SqsMessageDelegate> messageDelegates = new HashMap<>(); - - public static void register(Class clazz, SqsMessageDelegate messageDelegate) { - messageDelegates.put(clazz, messageDelegate); - } - - static { - register(Message.class, new SqsMessageDelegate() { - @Override - public int getPayloadSize(Message message) { - return message.body().length(); - } - - @Override - public SpanContext getUpstreamContext(OpenTelemetry openTelemetry, Message message) { - TextMapPropagator messagingPropagator = openTelemetry.getPropagators() - .getTextMapPropagator(); - - Context context = SqsParentContext.ofSystemAttributes(SqsMessageAccess.getAttributes(message)); - - if (context == Context.root()) { - Map messageAtributes = SqsMessageAccess.getMessageAttributes(message); - - context = - SqsParentContext.ofMessageAttributes(messageAtributes, messagingPropagator); - } - - return Span.fromContext(context).getSpanContext(); - } - }); - - register(SQSEvent.SQSMessage.class, - new SqsMessageDelegate() { - private static final String AWS_TRACE_HEADER_SQS_ATTRIBUTE_KEY = "AWSTraceHeader"; - static final String AWS_TRACE_HEADER_PROPAGATOR_KEY = "x-amzn-trace-id"; - - @Override - public int getPayloadSize(SQSEvent.SQSMessage message) { - return message.getBody().length(); - } - - @Override - public SpanContext getUpstreamContext(OpenTelemetry openTelemetry, SQSEvent.SQSMessage message) { - String parentHeader = null; - - if (message.getAttributes() != null) { - parentHeader = message.getAttributes().get(AWS_TRACE_HEADER_SQS_ATTRIBUTE_KEY); - } - - if (parentHeader == null && - message.getMessageAttributes() != null) - { - // We need to do a case-insensitive search - for (Map.Entry entry: message.getMessageAttributes().entrySet()) { - if (entry.getKey().equalsIgnoreCase(AWS_TRACE_HEADER_PROPAGATOR_KEY)) { - parentHeader = entry.getValue().getStringValue(); - break; - } - } - } - - if (parentHeader != null) { - Context xrayContext = - AwsXrayPropagator.getInstance() - .extract( - Context.root(), - Collections.singletonMap(AWS_TRACE_HEADER_PROPAGATOR_KEY, parentHeader), - MapGetter.INSTANCE); - - return Span.fromContext(xrayContext).getSpanContext(); - } - - return null; - } - }); - } - - private enum MapGetter implements TextMapGetter> { - INSTANCE; - - @Override - public Iterable keys(Map map) { - return map.keySet(); - } - - @Override - public String get(Map map, String s) { - return map.get(s.toLowerCase(Locale.ROOT)); - } - } - - private SqsMessageDelegates() { - } - - @SuppressWarnings("unchecked") - public static SqsMessageDelegate get(T message) { - return (SqsMessageDelegate) messageDelegates.get(message.getClass()); - } -} diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java index 3fc06327195a..36a25afe58c6 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java @@ -6,7 +6,10 @@ package io.opentelemetry.instrumentation.awssdk.v2_2; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.SpanContext; +import io.opentelemetry.context.Context; +import io.opentelemetry.context.propagation.TextMapPropagator; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; @@ -16,14 +19,17 @@ import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessagingAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessagingAttributesGetter; import io.opentelemetry.instrumentation.messagehandler.MessageHandler; +import software.amazon.awssdk.core.SdkPojo; +import software.amazon.awssdk.services.sqs.model.Message; import java.util.Collection; +import java.util.Map; import javax.annotation.Nullable; -public abstract class SqsMessageHandler extends MessageHandler { +public abstract class SqsMessageHandler extends MessageHandler { private final OpenTelemetry openTelemetry; private final String destination; - private SpanKindExtractor> spanKindExtractor; - private SpanNameExtractor> spanNameExtractor; + private SpanKindExtractor> spanKindExtractor; + private SpanNameExtractor> spanNameExtractor; public SqsMessageHandler(OpenTelemetry openTelemetry, String destination) { this.openTelemetry = openTelemetry; @@ -32,65 +38,65 @@ public SqsMessageHandler(OpenTelemetry openTelemetry, String destination) { spanNameExtractor = e -> destination + " process"; } - public void setSpanNameExtactor(SpanNameExtractor> spanNameExtractor) { + public void setSpanNameExtactor(SpanNameExtractor> spanNameExtractor) { this.spanNameExtractor = spanNameExtractor; } @Override - protected Instrumenter, Void> getMessageInstrumenter() { - return Instrumenter., Void>builder( + protected Instrumenter, Void> getMessageInstrumenter() { + return Instrumenter., Void>builder( openTelemetry, "io.opentelemetry.aws-sdk-2.2", spanNameExtractor) .addAttributesExtractor(getMessageOperationAttributeExtractor()) .addSpanLinksExtractor(getSpanLinksExtractor()) .buildInstrumenter(spanKindExtractor); } - public void setSpanKindExtractor(SpanKindExtractor> spanKindExtractor) { + public void setSpanKindExtractor(SpanKindExtractor> spanKindExtractor) { this.spanKindExtractor = spanKindExtractor; } - protected MessagingAttributesGetter, Void> + protected MessagingAttributesGetter, Void> getMessageingAttributesGetter() { String destination = this.destination; - return new MessagingAttributesGetter, Void>() { + return new MessagingAttributesGetter, Void>() { @Nullable @Override - public String getSystem(Collection v) { + public String getSystem(Collection v) { return "AmazonSQS"; } @Nullable @Override @SuppressWarnings({"deprecation"}) // Inheriting from interface - public String getDestinationKind(Collection v) { + public String getDestinationKind(Collection v) { return null; } @Nullable @Override - public String getDestination(Collection v) { + public String getDestination(Collection v) { return destination; } @Override - public boolean isTemporaryDestination(Collection v) { + public boolean isTemporaryDestination(Collection v) { return false; } @Nullable @Override - public String getConversationId(Collection v) { + public String getConversationId(Collection v) { return null; } @Nullable @Override - public Long getMessagePayloadSize(Collection v) { + public Long getMessagePayloadSize(Collection v) { long total = 0; - for (MessageType message : v) { - total += SqsMessageDelegates.get(message).getPayloadSize(message); + for (Message message : v) { + total += getPayloadSize(message); } return total; @@ -98,33 +104,53 @@ public Long getMessagePayloadSize(Collection v) { @Nullable @Override - public Long getMessagePayloadCompressedSize(Collection v) { + public Long getMessagePayloadCompressedSize(Collection v) { return null; } @Nullable @Override - public String getMessageId(Collection request, Void v) { + public String getMessageId(Collection request, Void v) { return null; } }; } - protected AttributesExtractor, Void> getMessageOperationAttributeExtractor() { + protected AttributesExtractor, Void> getMessageOperationAttributeExtractor() { return MessagingAttributesExtractor.create( getMessageingAttributesGetter(), MessageOperation.PROCESS); } //@SuppressWarnings("unchecked") - protected SpanLinksExtractor> getSpanLinksExtractor() { + protected SpanLinksExtractor> getSpanLinksExtractor() { return (spanLinks, parentContext, request) -> { - for (MessageType message : request) { - SpanContext messageSpanCtx = SqsMessageDelegates.get(message).getUpstreamContext(openTelemetry, message); + for (Message message : request) { + SpanContext messageSpanCtx = getUpstreamContext(openTelemetry, message); - if (messageSpanCtx!= null && messageSpanCtx.isValid()) { + if (messageSpanCtx!= null && messageSpanCtx.isValid() && messageSpanCtx.isSampled()) { spanLinks.addLink(messageSpanCtx); } } }; } + + public int getPayloadSize(Message message) { + return message.body().length(); + } + + public SpanContext getUpstreamContext(OpenTelemetry openTelemetry, Message message) { + TextMapPropagator messagingPropagator = openTelemetry.getPropagators() + .getTextMapPropagator(); + + Context context = SqsParentContext.ofSystemAttributes(SqsMessageAccess.getAttributes(message)); + + if (context == Context.root()) { + Map messageAtributes = SqsMessageAccess.getMessageAttributes(message); + + context = + SqsParentContext.ofMessageAttributes(messageAtributes, messagingPropagator); + } + + return Span.fromContext(context).getSpanContext(); + } } diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandlerTest.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandlerTest.java index 502114c0603d..ab3fb8aece8f 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandlerTest.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandlerTest.java @@ -8,7 +8,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; -import com.amazonaws.services.lambda.runtime.events.SQSEvent; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.SpanContext; @@ -19,20 +18,17 @@ import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; import io.opentelemetry.sdk.trace.data.LinkData; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; -import java.lang.reflect.Constructor; import java.util.Collection; import java.util.Collections; import java.util.LinkedList; import java.util.List; -import java.util.Map; -import java.util.TreeMap; import java.util.concurrent.atomic.AtomicInteger; import org.junit.jupiter.api.Test; import software.amazon.awssdk.services.sqs.model.Message; import software.amazon.awssdk.services.sqs.model.MessageAttributeValue; public class SqsMessageHandlerTest extends XrayTestInstrumenter { - private static class SqsMessageHandlerImpl extends SqsMessageHandler { + private static class SqsMessageHandlerImpl extends SqsMessageHandler { public final AtomicInteger handleCalls = new AtomicInteger(); public SqsMessageHandlerImpl(OpenTelemetry openTelemetry, @@ -46,20 +42,6 @@ protected void doHandle(Collection request) { } } - private static class LambdaSqsMessageHandlerImpl extends SqsMessageHandler { - public final AtomicInteger handleCalls = new AtomicInteger(); - - public LambdaSqsMessageHandlerImpl(OpenTelemetry openTelemetry, - String destination) { - super(openTelemetry, destination); - } - - @Override - protected void doHandle(Collection request) { - handleCalls.getAndIncrement(); - } - } - @Test public void simple() { SqsMessageHandlerImpl messageHandler = new SqsMessageHandlerImpl( @@ -112,71 +94,22 @@ public void simple() { } @Test - public void simpleUseMessageAttribute() { + public void simpleUnsampled() { SqsMessageHandlerImpl messageHandler = new SqsMessageHandlerImpl( getOpenTelemetry(), "destination"); + messageHandler.setSpanNameExtactor(e-> "MySpan"); + List messages = new LinkedList<>(); messages.add(Message.builder() .body("Hello") - .messageAttributes(Collections.singletonMap("X-Amzn-Trace-Id", - MessageAttributeValue.builder().dataType("String") - .stringValue("Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1") - .build())) + .attributesWithStrings( + Collections.singletonMap( + "AWSTraceHeader", + "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=0")) .build()); - Span parentSpan = getOpenTelemetry() - .getTracer("test") - .spanBuilder("test") - .startSpan(); - - try (Scope scope = parentSpan.makeCurrent()) { - messageHandler.handle(messages); - } - - parentSpan.end(); - - assertThat(messageHandler.handleCalls.get()).isEqualTo(1); - - waitAndAssertTraces( - trace -> - trace.hasSpansSatisfyingExactly( - span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), - span -> - span.hasName("destination process") - .hasKind(SpanKind.CONSUMER) - .hasLinks( - LinkData.create( - SpanContext.createFromRemoteParent( - "55555555123456789012345678901234", - "1234567890123456", - TraceFlags.getSampled(), - TraceState.getDefault()))) - .hasTotalRecordedLinks(1) - .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") - .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") - .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") - .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 5L) - .hasTotalAttributeCount(4) - .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) - .hasTraceId(parentSpan.getSpanContext().getTraceId()))); - } - - @Test - public void lambdaSimple() { - LambdaSqsMessageHandlerImpl messageHandler = new LambdaSqsMessageHandlerImpl( - getOpenTelemetry(), - "destination"); - - List messages = new LinkedList<>(); - SQSEvent.SQSMessage message = newMessage(); - message.setBody("Hello"); - Map attributes = new TreeMap<>(); - attributes.put("AWSTraceHeader", "Root=1-99555555-123456789012345678901234;Parent=9934567890123456;Sampled=1"); - message.setAttributes(attributes); - messages.add(message); - Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); try (Scope scope = parentSpan.makeCurrent()) { @@ -192,16 +125,9 @@ public void lambdaSimple() { trace.hasSpansSatisfyingExactly( span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), span -> - span.hasName("destination process") + span.hasName("MySpan") .hasKind(SpanKind.CONSUMER) - .hasLinks( - LinkData.create( - SpanContext.createFromRemoteParent( - "99555555123456789012345678901234", - "9934567890123456", - TraceFlags.getSampled(), - TraceState.getDefault()))) - .hasTotalRecordedLinks(1) + .hasTotalRecordedLinks(0) .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") @@ -212,23 +138,24 @@ public void lambdaSimple() { } @Test - public void lambdaSimpleUseMessageAttribute() { - LambdaSqsMessageHandlerImpl messageHandler = new LambdaSqsMessageHandlerImpl( + public void simpleUseMessageAttribute() { + SqsMessageHandlerImpl messageHandler = new SqsMessageHandlerImpl( getOpenTelemetry(), "destination"); - List messages = new LinkedList<>(); - SQSEvent.SQSMessage message = newMessage(); - message.setBody("Hello"); - Map attributes = new TreeMap<>(); - SQSEvent.MessageAttribute value = new SQSEvent.MessageAttribute(); - value.setDataType("String"); - value.setStringValue("Root=1-99555555-123456789012345678901234;Parent=9934567890123456;Sampled=1"); - attributes.put("X-Amzn-Trace-Id", value); - message.setMessageAttributes(attributes); - messages.add(message); + List messages = new LinkedList<>(); + messages.add(Message.builder() + .body("Hello") + .messageAttributes(Collections.singletonMap("X-Amzn-Trace-Id", + MessageAttributeValue.builder().dataType("String") + .stringValue("Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1") + .build())) + .build()); - Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); + Span parentSpan = getOpenTelemetry() + .getTracer("test") + .spanBuilder("test") + .startSpan(); try (Scope scope = parentSpan.makeCurrent()) { messageHandler.handle(messages); @@ -245,81 +172,18 @@ public void lambdaSimpleUseMessageAttribute() { span -> span.hasName("destination process") .hasKind(SpanKind.CONSUMER) - .hasLinks( - LinkData.create( - SpanContext.createFromRemoteParent( - "99555555123456789012345678901234", - "9934567890123456", - TraceFlags.getSampled(), - TraceState.getDefault()))) - .hasTotalRecordedLinks(1) - .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") - .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") - .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") - .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 5L) - .hasTotalAttributeCount(4) - .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) - .hasTraceId(parentSpan.getSpanContext().getTraceId()))); - } - - @Test - public void lambdaTwoMessages() { - List messages = new LinkedList<>(); - SQSEvent.SQSMessage message = newMessage(); - message.setBody("Hello"); - Map attributes = new TreeMap<>(); - attributes.put("AWSTraceHeader", "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1"); - message.setAttributes(attributes); - messages.add(message); - - SQSEvent.SQSMessage message2 = newMessage(); - message2.setBody("Hello World"); - Map attributes2 = new TreeMap<>(); - attributes2.put("AWSTraceHeader", "Root=1-66555555-123456789012345678901234;Parent=6634567890123456;Sampled=0"); - message2.setAttributes(attributes2); - messages.add(message2); - - LambdaSqsMessageHandlerImpl messageHandler = new LambdaSqsMessageHandlerImpl( - getOpenTelemetry(), - "destination"); - - messageHandler.setSpanKindExtractor(SpanKindExtractor.alwaysServer()); - - Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); - - try (Scope scope = parentSpan.makeCurrent()) { - messageHandler.handle(messages); - } - - parentSpan.end(); - - assertThat(messageHandler.handleCalls.get()).isEqualTo(1); - - waitAndAssertTraces( - trace -> - trace.hasSpansSatisfyingExactly( - span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), - span -> - span.hasName("destination process") - .hasKind(SpanKind.SERVER) .hasLinks( LinkData.create( SpanContext.createFromRemoteParent( "55555555123456789012345678901234", "1234567890123456", TraceFlags.getSampled(), - TraceState.getDefault())), - LinkData.create( - SpanContext.createFromRemoteParent( - "66555555123456789012345678901234", - "6634567890123456", - TraceFlags.getDefault(), TraceState.getDefault()))) - .hasTotalRecordedLinks(2) + .hasTotalRecordedLinks(1) .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") - .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 16L) + .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 5L) .hasTotalAttributeCount(4) .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) .hasTraceId(parentSpan.getSpanContext().getTraceId()))); @@ -340,7 +204,7 @@ public void twoMessages() { .attributesWithStrings( Collections.singletonMap( "AWSTraceHeader", - "Root=1-66555555-123456789012345678901234;Parent=6634567890123456;Sampled=0")) + "Root=1-66555555-123456789012345678901234;Parent=6634567890123456;Sampled=1")) .build()); SqsMessageHandlerImpl messageHandler = new SqsMessageHandlerImpl( @@ -377,7 +241,7 @@ public void twoMessages() { SpanContext.createFromRemoteParent( "66555555123456789012345678901234", "6634567890123456", - TraceFlags.getDefault(), + TraceFlags.getSampled(), TraceState.getDefault()))) .hasTotalRecordedLinks(2) .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") @@ -397,7 +261,7 @@ public void twoRuns() { .attributesWithStrings( Collections.singletonMap( "AWSTraceHeader", - "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=0")) + "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=1")) .build()); List messages2 = new LinkedList(); @@ -439,93 +303,12 @@ public void twoRuns() { SpanContext.createFromRemoteParent( "55555555123456789012345678901234", "1234567890123456", - TraceFlags.getDefault(), - TraceState.getDefault()))) - .hasTotalRecordedLinks(1) - .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") - .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") - .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") - .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 5L) - .hasTotalAttributeCount(4) - .hasParentSpanId(parentSpan1.getSpanContext().getSpanId()) - .hasTraceId(parentSpan1.getSpanContext().getTraceId())), - trace -> - trace.hasSpansSatisfyingExactly( - span -> span.hasName("test2").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), - span -> - span.hasName("destination process") - .hasKind(SpanKind.CONSUMER) - .hasLinks( - LinkData.create( - SpanContext.createFromRemoteParent( - "77555555123456789012345678901234", - "7734567890123456", TraceFlags.getSampled(), TraceState.getDefault()))) .hasTotalRecordedLinks(1) .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") - .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 13L) - .hasTotalAttributeCount(4) - .hasParentSpanId(parentSpan2.getSpanContext().getSpanId()) - .hasTraceId(parentSpan2.getSpanContext().getTraceId()))); - } - - @Test - public void lambdaTwoRuns() { - List messages1 = new LinkedList<>(); - List messages2 = new LinkedList<>(); - SQSEvent.SQSMessage message = newMessage(); - message.setBody("Hello"); - Map attributes = new TreeMap<>(); - attributes.put("AWSTraceHeader", "Root=1-55555555-123456789012345678901234;Parent=1234567890123456;Sampled=0"); - message.setAttributes(attributes); - messages1.add(message); - - SQSEvent.SQSMessage message2 = newMessage(); - message2.setBody("SecondMessage"); - Map attributes2 = new TreeMap<>(); - attributes2.put("AWSTraceHeader", "Root=1-77555555-123456789012345678901234;Parent=7734567890123456;Sampled=1"); - message2.setAttributes(attributes2); - messages2.add(message2); - - LambdaSqsMessageHandlerImpl messageHandler = new LambdaSqsMessageHandlerImpl( - getOpenTelemetry(), - "destination"); - - Span parentSpan1 = getOpenTelemetry().getTracer("test").spanBuilder("test1").startSpan(); - try (Scope scope = parentSpan1.makeCurrent()) { - messageHandler.handle(messages1); - } - parentSpan1.end(); - - Span parentSpan2 = getOpenTelemetry().getTracer("test").spanBuilder("test2").startSpan(); - try (Scope scope = parentSpan2.makeCurrent()) { - messageHandler.handle(messages2); - } - parentSpan2.end(); - - assertThat(messageHandler.handleCalls.get()).isEqualTo(2); - - waitAndAssertTraces( - trace -> - trace.hasSpansSatisfyingExactly( - span -> span.hasName("test1").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), - span -> - span.hasName("destination process") - .hasKind(SpanKind.CONSUMER) - .hasLinks( - LinkData.create( - SpanContext.createFromRemoteParent( - "55555555123456789012345678901234", - "1234567890123456", - TraceFlags.getDefault(), - TraceState.getDefault()))) - .hasTotalRecordedLinks(1) - .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") - .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") - .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 5L) .hasTotalAttributeCount(4) .hasParentSpanId(parentSpan1.getSpanContext().getSpanId()) @@ -553,37 +336,6 @@ public void lambdaTwoRuns() { .hasTraceId(parentSpan2.getSpanContext().getTraceId()))); } - @Test - public void lambdaNoMessages() { - LambdaSqsMessageHandlerImpl messageHandler = new LambdaSqsMessageHandlerImpl( - getOpenTelemetry(), - "destination"); - - Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); - try (Scope scope = parentSpan.makeCurrent()) { - messageHandler.handle(new LinkedList<>()); - } - parentSpan.end(); - - assertThat(messageHandler.handleCalls.get()).isEqualTo(1); - - waitAndAssertTraces( - trace -> - trace.hasSpansSatisfyingExactly( - span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0), - span -> - span.hasName("destination process") - .hasKind(SpanKind.CONSUMER) - .hasTotalRecordedLinks(0) - .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") - .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") - .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") - .hasAttribute(SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, 0L) - .hasTotalAttributeCount(4) - .hasParentSpanId(parentSpan.getSpanContext().getSpanId()) - .hasTraceId(parentSpan.getSpanContext().getTraceId()))); - } - @Test public void noMessages() { SqsMessageHandlerImpl messageHandler = new SqsMessageHandlerImpl( @@ -649,48 +401,4 @@ public void malformedTraceId() { trace.hasSpansSatisfyingExactly( span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0))); } - - @Test - public void lambdaMalformedTraceId() { - List messages = new LinkedList<>(); - SQSEvent.SQSMessage message = newMessage(); - message.setBody("Hello"); - Map attributes = new TreeMap<>(); - attributes.put("AWSTraceHeader", "Root=1-55555555-error;Parent=1234567890123456;Sampled=1"); - message.setAttributes(attributes); - messages.add(message); - - LambdaSqsMessageHandlerImpl messageHandler = new LambdaSqsMessageHandlerImpl( - getOpenTelemetry(), - "destination"); - - Span parentSpan = getOpenTelemetry().getTracer("test").spanBuilder("test").startSpan(); - - assertThrows( - RuntimeException.class, - () -> { - try (Scope scope = parentSpan.makeCurrent()) { - messageHandler.handle(messages); - } - }); - - parentSpan.end(); - - assertThat(messageHandler.handleCalls.get()).isEqualTo(0); - - waitAndAssertTraces( - trace -> - trace.hasSpansSatisfyingExactly( - span -> span.hasName("test").hasTotalAttributeCount(0).hasTotalRecordedLinks(0))); - } - - private static SQSEvent.SQSMessage newMessage() { - try { - Constructor ctor = SQSEvent.SQSMessage.class.getDeclaredConstructor(); - ctor.setAccessible(true); - return ctor.newInstance(); - } catch (Throwable t) { - throw new AssertionError(t); - } - } } From ed4d6d2fa93c6a07bcc5270609fe9724272a201f Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Tue, 22 Aug 2023 13:53:49 -0700 Subject: [PATCH 43/47] Fixing tests --- .../awslambdaevents/v2_2/SqsMessageHandler.java | 3 +-- .../awslambdaevents/v2_2/SqsMessageHandlerTest.java | 8 +++++++- .../instrumentation/awssdk/v2_2/SqsMessageHandler.java | 3 +-- .../awssdk/v2_2/SqsMessageHandlerTest.java | 8 +++++++- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/SqsMessageHandler.java b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/SqsMessageHandler.java index e46879f2b0cd..94726ec50a1c 100644 --- a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/SqsMessageHandler.java +++ b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/SqsMessageHandler.java @@ -126,13 +126,12 @@ protected AttributesExtractor, Void> getMessageO getMessageingAttributesGetter(), MessageOperation.PROCESS); } - //@SuppressWarnings("unchecked") protected SpanLinksExtractor> getSpanLinksExtractor() { return (spanLinks, parentContext, request) -> { for (SQSEvent.SQSMessage message : request) { SpanContext messageSpanCtx = getUpstreamContext(openTelemetry, message); - if (messageSpanCtx!= null && messageSpanCtx.isValid() && messageSpanCtx.isSampled()) { + if (messageSpanCtx!= null && messageSpanCtx.isValid()) { spanLinks.addLink(messageSpanCtx); } } diff --git a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/test/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/SqsMessageHandlerTest.java b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/test/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/SqsMessageHandlerTest.java index 51ff35fc06de..d9bee924a648 100644 --- a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/test/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/SqsMessageHandlerTest.java +++ b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/test/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/SqsMessageHandlerTest.java @@ -122,7 +122,13 @@ public void simpleUnsampled() { span -> span.hasName("destination process") .hasKind(SpanKind.CONSUMER) - .hasTotalRecordedLinks(0) + .hasLinks( + LinkData.create( + SpanContext.createFromRemoteParent( + "99555555123456789012345678901234", + "9934567890123456", + TraceFlags.getDefault(), + TraceState.getDefault()))) .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java index 36a25afe58c6..65c983eca28d 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java @@ -121,13 +121,12 @@ protected AttributesExtractor, Void> getMessageOperationAttr getMessageingAttributesGetter(), MessageOperation.PROCESS); } - //@SuppressWarnings("unchecked") protected SpanLinksExtractor> getSpanLinksExtractor() { return (spanLinks, parentContext, request) -> { for (Message message : request) { SpanContext messageSpanCtx = getUpstreamContext(openTelemetry, message); - if (messageSpanCtx!= null && messageSpanCtx.isValid() && messageSpanCtx.isSampled()) { + if (messageSpanCtx!= null && messageSpanCtx.isValid()) { spanLinks.addLink(messageSpanCtx); } } diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandlerTest.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandlerTest.java index ab3fb8aece8f..ed2f723670b4 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandlerTest.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandlerTest.java @@ -127,7 +127,13 @@ public void simpleUnsampled() { span -> span.hasName("MySpan") .hasKind(SpanKind.CONSUMER) - .hasTotalRecordedLinks(0) + .hasLinks( + LinkData.create( + SpanContext.createFromRemoteParent( + "55555555123456789012345678901234", + "1234567890123456", + TraceFlags.getDefault(), + TraceState.getDefault()))) .hasAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") .hasAttribute(SemanticAttributes.MESSAGING_SYSTEM, "AmazonSQS") .hasAttribute(SemanticAttributes.MESSAGING_DESTINATION_NAME, "destination") From 018cd532b5ec51c3ef2cc8bb8647b09e39cc711d Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Sun, 27 Aug 2023 23:29:37 -0700 Subject: [PATCH 44/47] Polishing --- .../aws-lambda-events-2.2/library/README.md | 24 +++++++++++++++++++ .../v2_2/SqsMessageHandler.java | 1 - .../aws-sdk/aws-sdk-2.2/library/README.md | 11 ++++----- .../aws-sdk-2.2/library/build.gradle.kts | 2 -- .../message-handler-1.0/library/README.md | 2 +- 5 files changed, 29 insertions(+), 11 deletions(-) diff --git a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/README.md b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/README.md index c200496bbdf0..52da42a17f7d 100644 --- a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/README.md +++ b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/README.md @@ -132,3 +132,27 @@ In order to enable requested propagation for a handler, configure it on the SDK ``` If using the wrappers, set the `OTEL_PROPAGATORS` environment variable as described [here](https://github.com/open-telemetry/opentelemetry-java/blob/main/sdk-extensions/autoconfigure/README.md#propagator). + +## Using SqsMessageHandler +This instrumentation takes a collection of SQS messages. +A span wraps the function call doHandle with appropriate span attributes and span links. +Span links are added for each of the messages as if this were a batch of messages. + +1. Setup SqsMessageHandler with your business logic. Pass in your OpenTelemetry and the name of the destination. +2. Call the "handle" method on SqsMessageHandler and pass in your collection of messages. +3. Under the hood it will call the "doHandle" method. + +```java +OpenTelemetry openTelemetry; +Collection messages; + +SqsMessageHandler messageHandler = + new SqsMessageHandler(openTelemetry, "destination") { + @Override + protected void doHandle(Collection messages) { + // My business logic + } +}; + +messageHandler.handle(messages); +``` diff --git a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/SqsMessageHandler.java b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/SqsMessageHandler.java index 94726ec50a1c..2580c50a0a8d 100644 --- a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/SqsMessageHandler.java +++ b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/SqsMessageHandler.java @@ -73,7 +73,6 @@ public String getSystem(Collection v) { @Nullable @Override - @SuppressWarnings({"deprecation"}) // Inheriting from interface public String getDestinationKind(Collection v) { return null; } diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/README.md b/instrumentation/aws-sdk/aws-sdk-2.2/library/README.md index 7282550b97b1..e9e70d63f409 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/README.md +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/README.md @@ -28,11 +28,9 @@ configuration for this behavior. ## Using SqsMessageHandler This instrumentation takes a collection of SQS messages. A span wraps the function call doHandle with appropriate span attributes and span links. -Span links comes from each of the messages as if this were a batch of messages. -If the span kind is server, then it will show up in the console as a separate node (segment). -If the span kind is consumer, then it will show up as a subsegment. +Span links are added for each of the messages as if this were a batch of messages. -1. Setup SqsMessageHandler with your business logic. Pass in your OpenTelemetry, the name of the destination, and the span kind. +1. Setup SqsMessageHandler with your business logic. Pass in your OpenTelemetry and the name of the destination. 2. Call the "handle" method on SqsMessageHandler and pass in your collection of messages. 3. Under the hood it will call the "doHandle" method. @@ -41,11 +39,10 @@ OpenTelemetry openTelemetry; Collection messages; SqsMessageHandler messageHandler = - new SqsMessageHandler(openTelemetry "destination", SpanKindExtractor.alwaysServer()) { + new SqsMessageHandler(openTelemetry, "destination") { @Override - protected Void doHandle(Collection request) { + protected void doHandle(Collection messages) { // My business logic - return null; } }; diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts b/instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts index bb91221a93f6..c94603b2d726 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts @@ -7,7 +7,6 @@ dependencies { implementation(project(":instrumentation:message-handler:message-handler-1.0:library")) - library("software.amazon.awssdk:aws-core:2.20.0") library("software.amazon.awssdk:aws-json-protocol:2.2.0") library("software.amazon.awssdk:sqs:2.20.0") @@ -21,7 +20,6 @@ dependencies { latestDepTestLibrary("software.amazon.awssdk:rds:+") latestDepTestLibrary("software.amazon.awssdk:s3:+") latestDepTestLibrary("software.amazon.awssdk:sqs:+") - latestDepTestLibrary("software.amazon.awssdk:sqs:+") } tasks { diff --git a/instrumentation/message-handler/message-handler-1.0/library/README.md b/instrumentation/message-handler/message-handler-1.0/library/README.md index 21f26e55d756..74e7aa3c7322 100644 --- a/instrumentation/message-handler/message-handler-1.0/library/README.md +++ b/instrumentation/message-handler/message-handler-1.0/library/README.md @@ -5,4 +5,4 @@ This package contains instrumentation for message systems. The instrumentation will process messages and wrap the calls in a span with appropriate span attributes and span links. ## Available Message Handlers -- `SqsMessageHandler` - Process SQS messages +- `SqsMessageHandler` - Process SQS messages for message in the Lambda instrumentation or AWS SDK library. From bbbc0aaf26682bf32efc528f67e77fda7eb2d1b8 Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Mon, 28 Aug 2023 13:56:59 -0700 Subject: [PATCH 45/47] Addressing PR --- .../awslambdaevents/v2_2/SqsMessageHandler.java | 4 ++-- .../awslambdaevents/v2_2/SqsMessageHandlerTest.java | 2 +- .../instrumentation/awssdk/v2_2/SqsMessageHandler.java | 4 ++-- .../awssdk/v2_2/SqsMessageHandlerTest.java | 2 +- .../message-handler/message-handler-1.0/library/README.md | 3 ++- .../message-handler-1.0/library/build.gradle.kts | 2 +- .../instrumentation/messagehandler/MessageHandler.java | 8 ++++---- 7 files changed, 13 insertions(+), 12 deletions(-) diff --git a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/SqsMessageHandler.java b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/SqsMessageHandler.java index 2580c50a0a8d..de1c5d409f41 100644 --- a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/SqsMessageHandler.java +++ b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/SqsMessageHandler.java @@ -27,7 +27,7 @@ import java.util.Locale; import java.util.Map; -public abstract class SqsMessageHandler extends MessageHandler { +public abstract class SqsMessageHandler implements MessageHandler { private static final String AWS_TRACE_HEADER_SQS_ATTRIBUTE_KEY = "AWSTraceHeader"; static final String AWS_TRACE_HEADER_PROPAGATOR_KEY = "x-amzn-trace-id"; @@ -48,7 +48,7 @@ public void setSpanNameExtactor(SpanNameExtractor, Void> getMessageInstrumenter() { + public Instrumenter, Void> getMessageInstrumenter() { return Instrumenter., Void>builder( openTelemetry, "io.opentelemetry.aws-lambda-events-2.2", spanNameExtractor) .addAttributesExtractor(getMessageOperationAttributeExtractor()) diff --git a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/test/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/SqsMessageHandlerTest.java b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/test/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/SqsMessageHandlerTest.java index d9bee924a648..c78c6c69af37 100644 --- a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/test/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/SqsMessageHandlerTest.java +++ b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/test/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/SqsMessageHandlerTest.java @@ -38,7 +38,7 @@ public SqsMessageHandlerImpl(OpenTelemetry openTelemetry, } @Override - protected void doHandle(Collection request) { + public void doHandle(Collection request) { handleCalls.getAndIncrement(); } } diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java index 65c983eca28d..529bae7b0f5b 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandler.java @@ -25,7 +25,7 @@ import java.util.Map; import javax.annotation.Nullable; -public abstract class SqsMessageHandler extends MessageHandler { +public abstract class SqsMessageHandler implements MessageHandler { private final OpenTelemetry openTelemetry; private final String destination; private SpanKindExtractor> spanKindExtractor; @@ -43,7 +43,7 @@ public void setSpanNameExtactor(SpanNameExtractor> spanNameE } @Override - protected Instrumenter, Void> getMessageInstrumenter() { + public Instrumenter, Void> getMessageInstrumenter() { return Instrumenter., Void>builder( openTelemetry, "io.opentelemetry.aws-sdk-2.2", spanNameExtractor) .addAttributesExtractor(getMessageOperationAttributeExtractor()) diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandlerTest.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandlerTest.java index ed2f723670b4..9b5c1cf280a0 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandlerTest.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsMessageHandlerTest.java @@ -37,7 +37,7 @@ public SqsMessageHandlerImpl(OpenTelemetry openTelemetry, } @Override - protected void doHandle(Collection request) { + public void doHandle(Collection request) { handleCalls.getAndIncrement(); } } diff --git a/instrumentation/message-handler/message-handler-1.0/library/README.md b/instrumentation/message-handler/message-handler-1.0/library/README.md index 74e7aa3c7322..718815c7bbc0 100644 --- a/instrumentation/message-handler/message-handler-1.0/library/README.md +++ b/instrumentation/message-handler/message-handler-1.0/library/README.md @@ -5,4 +5,5 @@ This package contains instrumentation for message systems. The instrumentation will process messages and wrap the calls in a span with appropriate span attributes and span links. ## Available Message Handlers -- `SqsMessageHandler` - Process SQS messages for message in the Lambda instrumentation or AWS SDK library. +- `io.opentelemetry.instrumentation.awssdk.v2_2.SqsMessageHandler` - Process SQS messages for the AWS SDK library. This is found in io.opentelemetry.aws-sdk-2.2. +- `io.opentelemetry.instrumentation.awslambdaevents.v2_2.SqsMessageHandler` - Process SQS messages for the Lambda instrumentation. This is found in io.opentelemetry.aws-lambda-events-2.2. diff --git a/instrumentation/message-handler/message-handler-1.0/library/build.gradle.kts b/instrumentation/message-handler/message-handler-1.0/library/build.gradle.kts index c4d2f680d869..9ac5eeb86863 100644 --- a/instrumentation/message-handler/message-handler-1.0/library/build.gradle.kts +++ b/instrumentation/message-handler/message-handler-1.0/library/build.gradle.kts @@ -3,5 +3,5 @@ plugins { } dependencies { - compileOnly("io.opentelemetry:opentelemetry-sdk") + implementation("io.opentelemetry:opentelemetry-sdk") } diff --git a/instrumentation/message-handler/message-handler-1.0/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageHandler.java b/instrumentation/message-handler/message-handler-1.0/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageHandler.java index 36eb92f4fa5b..1f7772120b3a 100644 --- a/instrumentation/message-handler/message-handler-1.0/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageHandler.java +++ b/instrumentation/message-handler/message-handler-1.0/library/src/main/java/io/opentelemetry/instrumentation/messagehandler/MessageHandler.java @@ -10,13 +10,13 @@ import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import java.util.Collection; -public abstract class MessageHandler { +public interface MessageHandler { - protected abstract Instrumenter, Void> getMessageInstrumenter(); + Instrumenter, Void> getMessageInstrumenter(); - protected abstract void doHandle(Collection request); + void doHandle(Collection request); - public void handle(Collection request) { + default void handle(Collection request) { Instrumenter, Void> instrumenter = getMessageInstrumenter(); Throwable error = null; From c14d4c1dc3a9d65ea070e5e917ce77be05fd74b7 Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Mon, 28 Aug 2023 14:09:49 -0700 Subject: [PATCH 46/47] Fixing Read Me --- .../aws-lambda/aws-lambda-events-2.2/library/README.md | 2 +- instrumentation/aws-sdk/aws-sdk-2.2/library/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/README.md b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/README.md index 52da42a17f7d..cb6891804eb5 100644 --- a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/README.md +++ b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/README.md @@ -149,7 +149,7 @@ Collection messages; SqsMessageHandler messageHandler = new SqsMessageHandler(openTelemetry, "destination") { @Override - protected void doHandle(Collection messages) { + public void doHandle(Collection messages) { // My business logic } }; diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/README.md b/instrumentation/aws-sdk/aws-sdk-2.2/library/README.md index e9e70d63f409..68432d08a552 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/README.md +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/README.md @@ -41,7 +41,7 @@ Collection messages; SqsMessageHandler messageHandler = new SqsMessageHandler(openTelemetry, "destination") { @Override - protected void doHandle(Collection messages) { + public void doHandle(Collection messages) { // My business logic } }; From c6a0fd858a936073562c88e0f0040b8af8793287 Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Mon, 28 Aug 2023 14:53:08 -0700 Subject: [PATCH 47/47] Adding back removed import --- instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts b/instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts index c94603b2d726..3d2ed10ae727 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts @@ -5,6 +5,7 @@ plugins { dependencies { implementation("io.opentelemetry.contrib:opentelemetry-aws-xray-propagator") + library("software.amazon.awssdk:aws-core:2.2.0") implementation(project(":instrumentation:message-handler:message-handler-1.0:library")) library("software.amazon.awssdk:aws-json-protocol:2.2.0")