SQS propagation for AWS SDK 1.1 (#2114)
This commit is contained in:
parent
0a74799419
commit
77922d4834
|
@ -9,6 +9,7 @@ import static io.opentelemetry.api.trace.Span.Kind.CLIENT;
|
||||||
|
|
||||||
import io.opentelemetry.api.GlobalOpenTelemetry;
|
import io.opentelemetry.api.GlobalOpenTelemetry;
|
||||||
import io.opentelemetry.api.trace.Span;
|
import io.opentelemetry.api.trace.Span;
|
||||||
|
import io.opentelemetry.api.trace.Span.Kind;
|
||||||
import io.opentelemetry.api.trace.SpanBuilder;
|
import io.opentelemetry.api.trace.SpanBuilder;
|
||||||
import io.opentelemetry.api.trace.Tracer;
|
import io.opentelemetry.api.trace.Tracer;
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
|
@ -69,14 +70,20 @@ public abstract class HttpClientTracer<REQUEST, CARRIER, RESPONSE> extends BaseT
|
||||||
}
|
}
|
||||||
|
|
||||||
public Context startSpan(
|
public Context startSpan(
|
||||||
Context parentContext, REQUEST request, CARRIER carrier, long startTimeNanos) {
|
Kind kind, Context parentContext, REQUEST request, CARRIER carrier, long startTimeNanos) {
|
||||||
Span span =
|
Span span =
|
||||||
internalStartSpan(parentContext, request, spanNameForRequest(request), startTimeNanos);
|
internalStartSpan(
|
||||||
|
kind, parentContext, request, spanNameForRequest(request), startTimeNanos);
|
||||||
Context context = withClientSpan(parentContext, span);
|
Context context = withClientSpan(parentContext, span);
|
||||||
inject(context, carrier);
|
inject(context, carrier);
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Context startSpan(
|
||||||
|
Context parentContext, REQUEST request, CARRIER carrier, long startTimeNanos) {
|
||||||
|
return startSpan(Kind.CLIENT, parentContext, request, carrier, startTimeNanos);
|
||||||
|
}
|
||||||
|
|
||||||
protected void inject(Context context, CARRIER carrier) {
|
protected void inject(Context context, CARRIER carrier) {
|
||||||
Setter<CARRIER> setter = getSetter();
|
Setter<CARRIER> setter = getSetter();
|
||||||
if (setter == null) {
|
if (setter == null) {
|
||||||
|
@ -130,8 +137,8 @@ public abstract class HttpClientTracer<REQUEST, CARRIER, RESPONSE> extends BaseT
|
||||||
}
|
}
|
||||||
|
|
||||||
private Span internalStartSpan(
|
private Span internalStartSpan(
|
||||||
Context parentContext, REQUEST request, String name, long startTimeNanos) {
|
Kind kind, Context parentContext, REQUEST request, String name, long startTimeNanos) {
|
||||||
SpanBuilder spanBuilder = tracer.spanBuilder(name).setSpanKind(CLIENT).setParent(parentContext);
|
SpanBuilder spanBuilder = tracer.spanBuilder(name).setSpanKind(kind).setParent(parentContext);
|
||||||
if (startTimeNanos > 0) {
|
if (startTimeNanos > 0) {
|
||||||
spanBuilder.setStartTimestamp(startTimeNanos, TimeUnit.NANOSECONDS);
|
spanBuilder.setStartTimestamp(startTimeNanos, TimeUnit.NANOSECONDS);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,8 +33,11 @@ dependencies {
|
||||||
|
|
||||||
testImplementation 'javax.xml.bind:jaxb-api:2.3.1'
|
testImplementation 'javax.xml.bind:jaxb-api:2.3.1'
|
||||||
|
|
||||||
|
/**
|
||||||
testImplementation deps.testcontainers
|
testImplementation deps.testcontainers
|
||||||
testImplementation "org.testcontainers:localstack:1.15.0-rc2"
|
testImplementation "org.testcontainers:localstack:1.15.0-rc2"**/
|
||||||
|
|
||||||
|
testLibrary group: 'org.elasticmq', name: 'elasticmq-rest-sqs_2.12', version: '1.0.0'
|
||||||
|
|
||||||
latestDepTestLibrary group: 'org.apache.camel', name: 'camel-core', version: '2.+'
|
latestDepTestLibrary group: 'org.apache.camel', name: 'camel-core', version: '2.+'
|
||||||
|
|
||||||
|
|
|
@ -54,10 +54,10 @@ class ActiveSpanManager {
|
||||||
* @param exchange The exchange
|
* @param exchange The exchange
|
||||||
* @param span The span
|
* @param span The span
|
||||||
*/
|
*/
|
||||||
public static void activate(Exchange exchange, Span span, CamelDirection direction) {
|
public static void activate(Exchange exchange, Span span, Span.Kind spanKind) {
|
||||||
|
|
||||||
SpanWithScope parent = exchange.getProperty(ACTIVE_SPAN_PROPERTY, SpanWithScope.class);
|
SpanWithScope parent = exchange.getProperty(ACTIVE_SPAN_PROPERTY, SpanWithScope.class);
|
||||||
SpanWithScope spanWithScope = SpanWithScope.activate(span, parent, direction);
|
SpanWithScope spanWithScope = SpanWithScope.activate(span, parent, spanKind);
|
||||||
exchange.setProperty(ACTIVE_SPAN_PROPERTY, spanWithScope);
|
exchange.setProperty(ACTIVE_SPAN_PROPERTY, spanWithScope);
|
||||||
LOG.debug("Activated a span: {}", spanWithScope);
|
LOG.debug("Activated a span: {}", spanWithScope);
|
||||||
}
|
}
|
||||||
|
@ -91,10 +91,9 @@ class ActiveSpanManager {
|
||||||
this.scope = scope;
|
this.scope = scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SpanWithScope activate(
|
public static SpanWithScope activate(Span span, SpanWithScope parent, Span.Kind spanKind) {
|
||||||
Span span, SpanWithScope parent, CamelDirection direction) {
|
|
||||||
Scope scope = null;
|
Scope scope = null;
|
||||||
if (CamelDirection.OUTBOUND.equals(direction)) {
|
if (isClientSpan(spanKind)) {
|
||||||
scope = CamelTracer.TRACER.startClientScope(span);
|
scope = CamelTracer.TRACER.startClientScope(span);
|
||||||
} else {
|
} else {
|
||||||
scope = CamelTracer.TRACER.startScope(span);
|
scope = CamelTracer.TRACER.startScope(span);
|
||||||
|
@ -103,6 +102,10 @@ class ActiveSpanManager {
|
||||||
return new SpanWithScope(parent, span, scope);
|
return new SpanWithScope(parent, span, scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isClientSpan(Span.Kind kind) {
|
||||||
|
return (Span.Kind.CLIENT.equals(kind) || Span.Kind.PRODUCER.equals(kind));
|
||||||
|
}
|
||||||
|
|
||||||
public SpanWithScope getParent() {
|
public SpanWithScope getParent() {
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@ final class CamelEventNotifier extends EventNotifierSupport {
|
||||||
sd.getOperationName(ese.getExchange(), ese.getEndpoint(), CamelDirection.OUTBOUND);
|
sd.getOperationName(ese.getExchange(), ese.getEndpoint(), CamelDirection.OUTBOUND);
|
||||||
Span span = CamelTracer.TRACER.startSpan(name, sd.getInitiatorSpanKind());
|
Span span = CamelTracer.TRACER.startSpan(name, sd.getInitiatorSpanKind());
|
||||||
sd.pre(span, ese.getExchange(), ese.getEndpoint(), CamelDirection.OUTBOUND);
|
sd.pre(span, ese.getExchange(), ese.getEndpoint(), CamelDirection.OUTBOUND);
|
||||||
ActiveSpanManager.activate(ese.getExchange(), span, CamelDirection.OUTBOUND);
|
ActiveSpanManager.activate(ese.getExchange(), span, sd.getInitiatorSpanKind());
|
||||||
CamelPropagationUtil.injectParent(Context.current(), ese.getExchange().getIn().getHeaders());
|
CamelPropagationUtil.injectParent(Context.current(), ese.getExchange().getIn().getHeaders());
|
||||||
|
|
||||||
LOG.debug("[Exchange sending] Initiator span started: {}", span);
|
LOG.debug("[Exchange sending] Initiator span started: {}", span);
|
||||||
|
|
|
@ -36,13 +36,13 @@ final class CamelRoutePolicy extends RoutePolicySupport {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(CamelRoutePolicy.class);
|
private static final Logger LOG = LoggerFactory.getLogger(CamelRoutePolicy.class);
|
||||||
|
|
||||||
private Span spanOnExchangeBegin(Route route, Exchange exchange, SpanDecorator sd) {
|
private Span spanOnExchangeBegin(
|
||||||
|
Route route, Exchange exchange, SpanDecorator sd, Span.Kind spanKind) {
|
||||||
Span activeSpan = CamelTracer.TRACER.getCurrentSpan();
|
Span activeSpan = CamelTracer.TRACER.getCurrentSpan();
|
||||||
String name = sd.getOperationName(exchange, route.getEndpoint(), CamelDirection.INBOUND);
|
String name = sd.getOperationName(exchange, route.getEndpoint(), CamelDirection.INBOUND);
|
||||||
SpanBuilder builder = CamelTracer.TRACER.spanBuilder(name);
|
SpanBuilder builder = CamelTracer.TRACER.spanBuilder(name);
|
||||||
|
builder.setSpanKind(spanKind);
|
||||||
if (!activeSpan.getSpanContext().isValid()) {
|
if (!activeSpan.getSpanContext().isValid()) {
|
||||||
// root operation, set kind, otherwise - INTERNAL
|
|
||||||
builder.setSpanKind(sd.getReceiverSpanKind());
|
|
||||||
Context parentContext = CamelPropagationUtil.extractParent(exchange.getIn().getHeaders());
|
Context parentContext = CamelPropagationUtil.extractParent(exchange.getIn().getHeaders());
|
||||||
if (parentContext != null) {
|
if (parentContext != null) {
|
||||||
builder.setParent(parentContext);
|
builder.setParent(parentContext);
|
||||||
|
@ -51,6 +51,12 @@ final class CamelRoutePolicy extends RoutePolicySupport {
|
||||||
return builder.startSpan();
|
return builder.startSpan();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Span.Kind spanKind(SpanDecorator sd) {
|
||||||
|
Span activeSpan = CamelTracer.TRACER.getCurrentSpan();
|
||||||
|
// if there's an active span, this is not a root span which we always mark as INTERNAL
|
||||||
|
return (activeSpan.getSpanContext().isValid() ? Span.Kind.INTERNAL : sd.getReceiverSpanKind());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Route exchange started, ie request could have been already captured by upper layer
|
* Route exchange started, ie request could have been already captured by upper layer
|
||||||
* instrumentation.
|
* instrumentation.
|
||||||
|
@ -59,9 +65,10 @@ final class CamelRoutePolicy extends RoutePolicySupport {
|
||||||
public void onExchangeBegin(Route route, Exchange exchange) {
|
public void onExchangeBegin(Route route, Exchange exchange) {
|
||||||
try {
|
try {
|
||||||
SpanDecorator sd = CamelTracer.TRACER.getSpanDecorator(route.getEndpoint());
|
SpanDecorator sd = CamelTracer.TRACER.getSpanDecorator(route.getEndpoint());
|
||||||
Span span = spanOnExchangeBegin(route, exchange, sd);
|
Span.Kind spanKind = spanKind(sd);
|
||||||
|
Span span = spanOnExchangeBegin(route, exchange, sd, spanKind);
|
||||||
sd.pre(span, exchange, route.getEndpoint(), CamelDirection.INBOUND);
|
sd.pre(span, exchange, route.getEndpoint(), CamelDirection.INBOUND);
|
||||||
ActiveSpanManager.activate(exchange, span, CamelDirection.INBOUND);
|
ActiveSpanManager.activate(exchange, span, spanKind);
|
||||||
LOG.debug("[Route start] Receiver span started {}", span);
|
LOG.debug("[Route start] Receiver span started {}", span);
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
LOG.warn("Failed to capture tracing data", t);
|
LOG.warn("Failed to capture tracing data", t);
|
||||||
|
|
|
@ -94,12 +94,22 @@ class MessagingSpanDecorator extends BaseSpanDecorator {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Span.Kind getInitiatorSpanKind() {
|
public Span.Kind getInitiatorSpanKind() {
|
||||||
return Kind.PRODUCER;
|
switch (component) {
|
||||||
|
case "aws-sqs":
|
||||||
|
return Kind.INTERNAL;
|
||||||
|
default:
|
||||||
|
return Kind.PRODUCER;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Span.Kind getReceiverSpanKind() {
|
public Span.Kind getReceiverSpanKind() {
|
||||||
return Kind.CONSUMER;
|
switch (component) {
|
||||||
|
case "aws-sqs":
|
||||||
|
return Kind.INTERNAL;
|
||||||
|
default:
|
||||||
|
return Kind.CONSUMER;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -11,14 +11,13 @@ import static io.opentelemetry.api.trace.Span.Kind.INTERNAL
|
||||||
import static io.opentelemetry.api.trace.Span.Kind.PRODUCER
|
import static io.opentelemetry.api.trace.Span.Kind.PRODUCER
|
||||||
|
|
||||||
import io.opentelemetry.instrumentation.test.AgentTestRunner
|
import io.opentelemetry.instrumentation.test.AgentTestRunner
|
||||||
|
import io.opentelemetry.instrumentation.test.utils.PortUtils
|
||||||
import org.apache.camel.CamelContext
|
import org.apache.camel.CamelContext
|
||||||
import org.apache.camel.ProducerTemplate
|
import org.apache.camel.ProducerTemplate
|
||||||
|
import org.elasticmq.rest.sqs.SQSRestServerBuilder
|
||||||
import org.springframework.boot.SpringApplication
|
import org.springframework.boot.SpringApplication
|
||||||
import org.springframework.context.ApplicationContextInitializer
|
|
||||||
import org.springframework.context.ConfigurableApplicationContext
|
import org.springframework.context.ConfigurableApplicationContext
|
||||||
import org.springframework.context.support.AbstractApplicationContext
|
import org.testcontainers.shaded.com.google.common.collect.ImmutableMap
|
||||||
import org.testcontainers.containers.localstack.LocalStackContainer
|
|
||||||
import org.testcontainers.utility.DockerImageName
|
|
||||||
import spock.lang.Shared
|
import spock.lang.Shared
|
||||||
|
|
||||||
class SqsCamelTest extends AgentTestRunner {
|
class SqsCamelTest extends AgentTestRunner {
|
||||||
|
@ -33,6 +32,9 @@ class SqsCamelTest extends AgentTestRunner {
|
||||||
|
|
||||||
def setupSpec() {
|
def setupSpec() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Temporarily using emq instead of localstack till the latter supports AWS trace propagation
|
||||||
|
*
|
||||||
sqs = new LocalStackContainer(DockerImageName.parse("localstack/localstack:latest"))
|
sqs = new LocalStackContainer(DockerImageName.parse("localstack/localstack:latest"))
|
||||||
.withServices(LocalStackContainer.Service.SQS)
|
.withServices(LocalStackContainer.Service.SQS)
|
||||||
sqs.start()
|
sqs.start()
|
||||||
|
@ -45,6 +47,14 @@ class SqsCamelTest extends AgentTestRunner {
|
||||||
applicationContext.getBeanFactory().registerSingleton("localStack", sqs)
|
applicationContext.getBeanFactory().registerSingleton("localStack", sqs)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
server = app.run()**/
|
||||||
|
|
||||||
|
sqsPort = PortUtils.randomOpenPort()
|
||||||
|
sqs = SQSRestServerBuilder.withPort(sqsPort).withInterface("localhost").start()
|
||||||
|
println getClass().name + " SQS server started at: localhost:$sqsPort/"
|
||||||
|
|
||||||
|
def app = new SpringApplication(SqsConfig)
|
||||||
|
app.setDefaultProperties(ImmutableMap.of("sqs.port", sqsPort))
|
||||||
server = app.run()
|
server = app.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +64,7 @@ class SqsCamelTest extends AgentTestRunner {
|
||||||
server = null
|
server = null
|
||||||
}
|
}
|
||||||
if (sqs != null) {
|
if (sqs != null) {
|
||||||
sqs.stop()
|
sqs.stopAndWait()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,8 +77,8 @@ class SqsCamelTest extends AgentTestRunner {
|
||||||
template.sendBody("direct:input", "{\"type\": \"hello\"}")
|
template.sendBody("direct:input", "{\"type\": \"hello\"}")
|
||||||
|
|
||||||
then:
|
then:
|
||||||
assertTraces(5) {
|
assertTraces(6) {
|
||||||
trace(0, 3) {
|
trace(0, 5) {
|
||||||
|
|
||||||
span(0) {
|
span(0) {
|
||||||
name "input"
|
name "input"
|
||||||
|
@ -80,7 +90,7 @@ class SqsCamelTest extends AgentTestRunner {
|
||||||
}
|
}
|
||||||
span(1) {
|
span(1) {
|
||||||
name "sqsCamelTest"
|
name "sqsCamelTest"
|
||||||
kind PRODUCER
|
kind INTERNAL
|
||||||
childOf span(0)
|
childOf span(0)
|
||||||
attributes {
|
attributes {
|
||||||
"apache-camel.uri" "aws-sqs://sqsCamelTest?amazonSQSClient=%23sqsClient"
|
"apache-camel.uri" "aws-sqs://sqsCamelTest?amazonSQSClient=%23sqsClient"
|
||||||
|
@ -88,8 +98,47 @@ class SqsCamelTest extends AgentTestRunner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
span(2) {
|
span(2) {
|
||||||
name "sqsCamelTest"
|
name "SQS.SendMessage"
|
||||||
|
kind PRODUCER
|
||||||
|
childOf span(1)
|
||||||
|
attributes {
|
||||||
|
"aws.agent" "java-aws-sdk"
|
||||||
|
"aws.endpoint" "http://localhost:$sqsPort"
|
||||||
|
"aws.operation" "SendMessageRequest"
|
||||||
|
"aws.queue.url" "http://localhost:$sqsPort/queue/sqsCamelTest"
|
||||||
|
"aws.service" "AmazonSQS"
|
||||||
|
"http.flavor" "1.1"
|
||||||
|
"http.method" "POST"
|
||||||
|
"http.status_code" 200
|
||||||
|
"http.url" "http://localhost:$sqsPort"
|
||||||
|
"net.peer.name" "localhost"
|
||||||
|
"net.peer.port" sqsPort
|
||||||
|
"net.transport" "IP.TCP"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
span(3) {
|
||||||
|
name "SQS.ReceiveMessage"
|
||||||
kind CONSUMER
|
kind CONSUMER
|
||||||
|
childOf span(2)
|
||||||
|
attributes {
|
||||||
|
"aws.agent" "java-aws-sdk"
|
||||||
|
"aws.endpoint" "http://localhost:$sqsPort"
|
||||||
|
"aws.operation" "ReceiveMessageRequest"
|
||||||
|
"aws.queue.url" "http://localhost:$sqsPort/queue/sqsCamelTest"
|
||||||
|
"aws.service" "AmazonSQS"
|
||||||
|
"http.flavor" "1.1"
|
||||||
|
"http.method" "POST"
|
||||||
|
"http.status_code" 200
|
||||||
|
"http.url" "http://localhost:$sqsPort"
|
||||||
|
"http.user_agent" String
|
||||||
|
"net.peer.name" "localhost"
|
||||||
|
"net.peer.port" sqsPort
|
||||||
|
"net.transport" "IP.TCP"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
span(4) {
|
||||||
|
name "sqsCamelTest"
|
||||||
|
kind INTERNAL
|
||||||
childOf span(1)
|
childOf span(1)
|
||||||
attributes {
|
attributes {
|
||||||
"apache-camel.uri" "aws-sqs://sqsCamelTest?amazonSQSClient=%23sqsClient&messageAttributeNames=traceparent"
|
"apache-camel.uri" "aws-sqs://sqsCamelTest?amazonSQSClient=%23sqsClient&messageAttributeNames=traceparent"
|
||||||
|
@ -105,15 +154,15 @@ class SqsCamelTest extends AgentTestRunner {
|
||||||
hasNoParent()
|
hasNoParent()
|
||||||
attributes {
|
attributes {
|
||||||
"aws.agent" "java-aws-sdk"
|
"aws.agent" "java-aws-sdk"
|
||||||
"aws.endpoint" "http://127.0.0.1:$sqsPort"
|
"aws.endpoint" "http://localhost:$sqsPort"
|
||||||
"aws.operation" "ReceiveMessageRequest"
|
"aws.operation" "ReceiveMessageRequest"
|
||||||
"aws.queue.url" "http://localhost:$sqsPort/000000000000/sqsCamelTest"
|
"aws.queue.url" "http://localhost:$sqsPort/queue/sqsCamelTest"
|
||||||
"aws.service" "AmazonSQS"
|
"aws.service" "AmazonSQS"
|
||||||
"http.flavor" "1.1"
|
"http.flavor" "1.1"
|
||||||
"http.method" "POST"
|
"http.method" "POST"
|
||||||
"http.status_code" 200
|
"http.status_code" 200
|
||||||
"http.url" "http://127.0.0.1:$sqsPort"
|
"http.url" "http://localhost:$sqsPort"
|
||||||
"net.peer.name" "127.0.0.1"
|
"net.peer.name" "localhost"
|
||||||
"net.peer.port" sqsPort
|
"net.peer.port" sqsPort
|
||||||
"net.transport" "IP.TCP"
|
"net.transport" "IP.TCP"
|
||||||
}
|
}
|
||||||
|
@ -126,15 +175,15 @@ class SqsCamelTest extends AgentTestRunner {
|
||||||
hasNoParent()
|
hasNoParent()
|
||||||
attributes {
|
attributes {
|
||||||
"aws.agent" "java-aws-sdk"
|
"aws.agent" "java-aws-sdk"
|
||||||
"aws.endpoint" "http://127.0.0.1:$sqsPort"
|
"aws.endpoint" "http://localhost:$sqsPort"
|
||||||
"aws.operation" "DeleteMessageRequest"
|
"aws.operation" "DeleteMessageRequest"
|
||||||
"aws.queue.url" "http://localhost:$sqsPort/000000000000/sqsCamelTest"
|
"aws.queue.url" "http://localhost:$sqsPort/queue/sqsCamelTest"
|
||||||
"aws.service" "AmazonSQS"
|
"aws.service" "AmazonSQS"
|
||||||
"http.flavor" "1.1"
|
"http.flavor" "1.1"
|
||||||
"http.method" "POST"
|
"http.method" "POST"
|
||||||
"http.status_code" 200
|
"http.status_code" 200
|
||||||
"http.url" "http://127.0.0.1:$sqsPort"
|
"http.url" "http://localhost:$sqsPort"
|
||||||
"net.peer.name" "127.0.0.1"
|
"net.peer.name" "localhost"
|
||||||
"net.peer.port" sqsPort
|
"net.peer.port" sqsPort
|
||||||
"net.transport" "IP.TCP"
|
"net.transport" "IP.TCP"
|
||||||
}
|
}
|
||||||
|
@ -147,15 +196,15 @@ class SqsCamelTest extends AgentTestRunner {
|
||||||
hasNoParent()
|
hasNoParent()
|
||||||
attributes {
|
attributes {
|
||||||
"aws.agent" "java-aws-sdk"
|
"aws.agent" "java-aws-sdk"
|
||||||
"aws.endpoint" "http://127.0.0.1:$sqsPort"
|
"aws.endpoint" "http://localhost:$sqsPort"
|
||||||
"aws.operation" "ReceiveMessageRequest"
|
"aws.operation" "ReceiveMessageRequest"
|
||||||
"aws.queue.url" "http://localhost:$sqsPort/000000000000/sqsCamelTest"
|
"aws.queue.url" "http://localhost:$sqsPort/queue/sqsCamelTest"
|
||||||
"aws.service" "AmazonSQS"
|
"aws.service" "AmazonSQS"
|
||||||
"http.flavor" "1.1"
|
"http.flavor" "1.1"
|
||||||
"http.method" "POST"
|
"http.method" "POST"
|
||||||
"http.status_code" 200
|
"http.status_code" 200
|
||||||
"http.url" "http://127.0.0.1:$sqsPort"
|
"http.url" "http://localhost:$sqsPort"
|
||||||
"net.peer.name" "127.0.0.1"
|
"net.peer.name" "localhost"
|
||||||
"net.peer.port" sqsPort
|
"net.peer.port" sqsPort
|
||||||
"net.transport" "IP.TCP"
|
"net.transport" "IP.TCP"
|
||||||
}
|
}
|
||||||
|
@ -168,15 +217,36 @@ class SqsCamelTest extends AgentTestRunner {
|
||||||
hasNoParent()
|
hasNoParent()
|
||||||
attributes {
|
attributes {
|
||||||
"aws.agent" "java-aws-sdk"
|
"aws.agent" "java-aws-sdk"
|
||||||
"aws.endpoint" "http://127.0.0.1:$sqsPort"
|
"aws.endpoint" "http://localhost:$sqsPort"
|
||||||
"aws.operation" "ReceiveMessageRequest"
|
"aws.operation" "ReceiveMessageRequest"
|
||||||
"aws.queue.url" "http://localhost:$sqsPort/000000000000/sqsCamelTest"
|
"aws.queue.url" "http://localhost:$sqsPort/queue/sqsCamelTest"
|
||||||
"aws.service" "AmazonSQS"
|
"aws.service" "AmazonSQS"
|
||||||
"http.flavor" "1.1"
|
"http.flavor" "1.1"
|
||||||
"http.method" "POST"
|
"http.method" "POST"
|
||||||
"http.status_code" 200
|
"http.status_code" 200
|
||||||
"http.url" "http://127.0.0.1:$sqsPort"
|
"http.url" "http://localhost:$sqsPort"
|
||||||
"net.peer.name" "127.0.0.1"
|
"net.peer.name" "localhost"
|
||||||
|
"net.peer.port" sqsPort
|
||||||
|
"net.transport" "IP.TCP"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
trace(5, 1) {
|
||||||
|
it.span(0) {
|
||||||
|
name "SQS.ReceiveMessage"
|
||||||
|
kind CLIENT
|
||||||
|
hasNoParent()
|
||||||
|
attributes {
|
||||||
|
"aws.agent" "java-aws-sdk"
|
||||||
|
"aws.endpoint" "http://localhost:$sqsPort"
|
||||||
|
"aws.operation" "ReceiveMessageRequest"
|
||||||
|
"aws.queue.url" "http://localhost:$sqsPort/queue/sqsCamelTest"
|
||||||
|
"aws.service" "AmazonSQS"
|
||||||
|
"http.flavor" "1.1"
|
||||||
|
"http.method" "POST"
|
||||||
|
"http.status_code" 200
|
||||||
|
"http.url" "http://localhost:$sqsPort"
|
||||||
|
"net.peer.name" "localhost"
|
||||||
"net.peer.port" sqsPort
|
"net.peer.port" sqsPort
|
||||||
"net.transport" "IP.TCP"
|
"net.transport" "IP.TCP"
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,15 +5,17 @@
|
||||||
|
|
||||||
package test
|
package test
|
||||||
|
|
||||||
|
import com.amazonaws.auth.AWSStaticCredentialsProvider
|
||||||
|
import com.amazonaws.auth.BasicAWSCredentials
|
||||||
|
import com.amazonaws.client.builder.AwsClientBuilder
|
||||||
import com.amazonaws.services.sqs.AmazonSQSAsync
|
import com.amazonaws.services.sqs.AmazonSQSAsync
|
||||||
import com.amazonaws.services.sqs.AmazonSQSAsyncClient
|
import com.amazonaws.services.sqs.AmazonSQSAsyncClient
|
||||||
import org.apache.camel.LoggingLevel
|
import org.apache.camel.LoggingLevel
|
||||||
import org.apache.camel.builder.RouteBuilder
|
import org.apache.camel.builder.RouteBuilder
|
||||||
|
import org.springframework.beans.factory.annotation.Value
|
||||||
import org.springframework.boot.SpringBootConfiguration
|
import org.springframework.boot.SpringBootConfiguration
|
||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
|
||||||
import org.springframework.context.annotation.Bean
|
import org.springframework.context.annotation.Bean
|
||||||
import org.testcontainers.containers.localstack.LocalStackContainer
|
|
||||||
|
|
||||||
@SpringBootConfiguration
|
@SpringBootConfiguration
|
||||||
@EnableAutoConfiguration
|
@EnableAutoConfiguration
|
||||||
|
@ -46,11 +48,21 @@ class SqsConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Temporarily using emq instead of localstack till the latter supports AWS trace propagation
|
||||||
|
*
|
||||||
@Bean
|
@Bean
|
||||||
AmazonSQSAsync sqsClient(LocalStackContainer localstack) {
|
AmazonSQSAsync sqsClient(LocalStackContainer localstack) {
|
||||||
|
|
||||||
return AmazonSQSAsyncClient.asyncBuilder().withEndpointConfiguration(localstack.getEndpointConfiguration(LocalStackContainer.Service.SQS))
|
return AmazonSQSAsyncClient.asyncBuilder().withEndpointConfiguration(localstack.getEndpointConfiguration(LocalStackContainer.Service.SQS))
|
||||||
.withCredentials(localstack.getDefaultCredentialsProvider())
|
.withCredentials(localstack.getDefaultCredentialsProvider())
|
||||||
.build()
|
.build()
|
||||||
|
}**/
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
AmazonSQSAsync sqsClient(@Value("\${sqs.port}") int port) {
|
||||||
|
def credentials = new AWSStaticCredentialsProvider(new BasicAWSCredentials("x", "x"))
|
||||||
|
def endpointConfiguration = new AwsClientBuilder.EndpointConfiguration("http://localhost:"+port, "elasticmq")
|
||||||
|
return AmazonSQSAsyncClient.asyncBuilder().withCredentials(credentials).withEndpointConfiguration(endpointConfiguration).build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,9 @@ dependencies {
|
||||||
compileOnly deps.opentelemetryTraceProps
|
compileOnly deps.opentelemetryTraceProps
|
||||||
|
|
||||||
library group: 'com.amazonaws', name: 'aws-java-sdk-core', version: '1.11.0'
|
library group: 'com.amazonaws', name: 'aws-java-sdk-core', version: '1.11.0'
|
||||||
|
implementation deps.opentelemetryTraceProps
|
||||||
|
|
||||||
|
compileOnly group: 'com.amazonaws', name: 'aws-java-sdk-sqs', version: '1.11.106'
|
||||||
|
|
||||||
// Include httpclient instrumentation for testing because it is a dependency for aws-sdk.
|
// Include httpclient instrumentation for testing because it is a dependency for aws-sdk.
|
||||||
testInstrumentation project(':instrumentation:apache-httpclient:apache-httpclient-4.0:javaagent')
|
testInstrumentation project(':instrumentation:apache-httpclient:apache-httpclient-4.0:javaagent')
|
||||||
|
@ -55,8 +58,8 @@ dependencies {
|
||||||
testLibrary group: 'com.amazonaws', name: 'aws-java-sdk-rds', version: '1.11.106'
|
testLibrary group: 'com.amazonaws', name: 'aws-java-sdk-rds', version: '1.11.106'
|
||||||
testLibrary group: 'com.amazonaws', name: 'aws-java-sdk-ec2', version: '1.11.106'
|
testLibrary group: 'com.amazonaws', name: 'aws-java-sdk-ec2', version: '1.11.106'
|
||||||
testLibrary group: 'com.amazonaws', name: 'aws-java-sdk-kinesis', version: '1.11.106'
|
testLibrary group: 'com.amazonaws', name: 'aws-java-sdk-kinesis', version: '1.11.106'
|
||||||
testLibrary group: 'com.amazonaws', name: 'aws-java-sdk-sqs', version: '1.11.106'
|
|
||||||
testLibrary group: 'com.amazonaws', name: 'aws-java-sdk-dynamodb', version: '1.11.106'
|
testLibrary group: 'com.amazonaws', name: 'aws-java-sdk-dynamodb', version: '1.11.106'
|
||||||
|
testLibrary group: 'com.amazonaws', name: 'aws-java-sdk-sqs', version: '1.11.106'
|
||||||
|
|
||||||
// Make sure doesn't add HTTP headers
|
// Make sure doesn't add HTTP headers
|
||||||
testInstrumentation project(':instrumentation:apache-httpclient:apache-httpclient-4.0:javaagent')
|
testInstrumentation project(':instrumentation:apache-httpclient:apache-httpclient-4.0:javaagent')
|
||||||
|
@ -64,6 +67,9 @@ dependencies {
|
||||||
// needed for kinesis:
|
// needed for kinesis:
|
||||||
testImplementation group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-cbor', version: versions.jackson
|
testImplementation group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-cbor', version: versions.jackson
|
||||||
|
|
||||||
|
// needed for SQS - using emq directly as localstack references emq v0.15.7 ie WITHOUT AWS trace header propagation
|
||||||
|
testLibrary group: 'org.elasticmq', name: 'elasticmq-rest-sqs_2.12', version: '1.0.0'
|
||||||
|
|
||||||
test_before_1_11_106Implementation(group: 'com.amazonaws', name: 'aws-java-sdk-s3', version: '1.11.0')
|
test_before_1_11_106Implementation(group: 'com.amazonaws', name: 'aws-java-sdk-s3', version: '1.11.0')
|
||||||
test_before_1_11_106Implementation(group: 'com.amazonaws', name: 'aws-java-sdk-rds', version: '1.11.0')
|
test_before_1_11_106Implementation(group: 'com.amazonaws', name: 'aws-java-sdk-rds', version: '1.11.0')
|
||||||
test_before_1_11_106Implementation(group: 'com.amazonaws', name: 'aws-java-sdk-ec2', version: '1.11.0')
|
test_before_1_11_106Implementation(group: 'com.amazonaws', name: 'aws-java-sdk-ec2', version: '1.11.0')
|
||||||
|
|
|
@ -46,8 +46,9 @@ public class AwsSdkClientTracer extends HttpClientTracer<Request<?>, Request<?>,
|
||||||
return qualifiedOperation(awsServiceName, awsOperation);
|
return qualifiedOperation(awsServiceName, awsOperation);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Context startSpan(Context parentContext, Request<?> request, RequestMeta requestMeta) {
|
public Context startSpan(
|
||||||
Context context = super.startSpan(parentContext, request, request);
|
Span.Kind kind, Context parentContext, Request<?> request, RequestMeta requestMeta) {
|
||||||
|
Context context = super.startSpan(kind, parentContext, request, request, -1);
|
||||||
Span span = Span.fromContext(context);
|
Span span = Span.fromContext(context);
|
||||||
|
|
||||||
String awsServiceName = request.getServiceName();
|
String awsServiceName = request.getServiceName();
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.javaagent.instrumentation.awssdk.v1_11;
|
||||||
|
|
||||||
|
import io.opentelemetry.context.Context;
|
||||||
|
import io.opentelemetry.context.propagation.TextMapPropagator;
|
||||||
|
import io.opentelemetry.extension.trace.propagation.AwsXrayPropagator;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
class SqsParentContext {
|
||||||
|
|
||||||
|
private static class MapGetter implements TextMapPropagator.Getter<Map<String, String>> {
|
||||||
|
|
||||||
|
private static final MapGetter INSTANCE = new MapGetter();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<String> keys(Map<String, String> map) {
|
||||||
|
return map.keySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String get(Map<String, String> map, String s) {
|
||||||
|
return map.get(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static final String AWS_TRACE_SYSTEM_ATTRIBUTE = "AWSTraceHeader";
|
||||||
|
|
||||||
|
static Context ofSystemAttributes(Map<String, String> systemAttributes) {
|
||||||
|
String traceHeader = systemAttributes.get(AWS_TRACE_SYSTEM_ATTRIBUTE);
|
||||||
|
return AwsXrayPropagator.getInstance()
|
||||||
|
.extract(
|
||||||
|
Context.current(),
|
||||||
|
Collections.singletonMap("X-Amzn-Trace-Id", traceHeader),
|
||||||
|
MapGetter.INSTANCE);
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,9 +12,15 @@ import com.amazonaws.AmazonWebServiceRequest;
|
||||||
import com.amazonaws.Request;
|
import com.amazonaws.Request;
|
||||||
import com.amazonaws.Response;
|
import com.amazonaws.Response;
|
||||||
import com.amazonaws.handlers.RequestHandler2;
|
import com.amazonaws.handlers.RequestHandler2;
|
||||||
|
import com.amazonaws.services.sqs.model.Message;
|
||||||
|
import com.amazonaws.services.sqs.model.ReceiveMessageRequest;
|
||||||
|
import com.amazonaws.services.sqs.model.ReceiveMessageResult;
|
||||||
|
import com.amazonaws.services.sqs.model.SendMessageRequest;
|
||||||
|
import io.opentelemetry.api.trace.Span;
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
import io.opentelemetry.context.Scope;
|
import io.opentelemetry.context.Scope;
|
||||||
import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
|
import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/** Tracing Request Handler. */
|
/** Tracing Request Handler. */
|
||||||
public class TracingRequestHandler extends RequestHandler2 {
|
public class TracingRequestHandler extends RequestHandler2 {
|
||||||
|
@ -27,19 +33,40 @@ public class TracingRequestHandler extends RequestHandler2 {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void beforeRequest(Request<?> request) {
|
public void beforeRequest(Request<?> request) {
|
||||||
|
|
||||||
AmazonWebServiceRequest originalRequest = request.getOriginalRequest();
|
AmazonWebServiceRequest originalRequest = request.getOriginalRequest();
|
||||||
|
Span.Kind kind = (isSqsProducer(originalRequest) ? Span.Kind.PRODUCER : Span.Kind.CLIENT);
|
||||||
|
|
||||||
RequestMeta requestMeta = contextStore.get(originalRequest);
|
RequestMeta requestMeta = contextStore.get(originalRequest);
|
||||||
Context parentContext = Context.current();
|
Context parentContext = Context.current();
|
||||||
if (!tracer().shouldStartSpan(parentContext)) {
|
if (!tracer().shouldStartSpan(parentContext)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Context context = tracer().startSpan(parentContext, request, requestMeta);
|
Context context = tracer().startSpan(kind, parentContext, request, requestMeta);
|
||||||
Scope scope = context.makeCurrent();
|
Scope scope = context.makeCurrent();
|
||||||
request.addHandlerContext(CONTEXT_SCOPE_PAIR_CONTEXT_KEY, new ContextScopePair(context, scope));
|
request.addHandlerContext(CONTEXT_SCOPE_PAIR_CONTEXT_KEY, new ContextScopePair(context, scope));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isSqsProducer(AmazonWebServiceRequest request) {
|
||||||
|
return (request instanceof SendMessageRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AmazonWebServiceRequest beforeMarshalling(AmazonWebServiceRequest request) {
|
||||||
|
if (isSqsConsumer(request)) {
|
||||||
|
ReceiveMessageRequest receiveMessageRequest = (ReceiveMessageRequest) request;
|
||||||
|
receiveMessageRequest.withAttributeNames(SqsParentContext.AWS_TRACE_SYSTEM_ATTRIBUTE);
|
||||||
|
}
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterResponse(Request<?> request, Response<?> response) {
|
public void afterResponse(Request<?> request, Response<?> response) {
|
||||||
|
if (isSqsConsumer(request.getOriginalRequest())) {
|
||||||
|
afterConsumerResponse(
|
||||||
|
(Request<ReceiveMessageRequest>) request, (Response<ReceiveMessageResult>) response);
|
||||||
|
}
|
||||||
|
// close outstanding "client" span
|
||||||
ContextScopePair scope = request.getHandlerContext(CONTEXT_SCOPE_PAIR_CONTEXT_KEY);
|
ContextScopePair scope = request.getHandlerContext(CONTEXT_SCOPE_PAIR_CONTEXT_KEY);
|
||||||
if (scope == null) {
|
if (scope == null) {
|
||||||
return;
|
return;
|
||||||
|
@ -49,6 +76,28 @@ public class TracingRequestHandler extends RequestHandler2 {
|
||||||
tracer().end(scope.getContext(), response);
|
tracer().end(scope.getContext(), response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isSqsConsumer(AmazonWebServiceRequest request) {
|
||||||
|
return (request instanceof ReceiveMessageRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Create and close CONSUMER span for each message consumed. */
|
||||||
|
private void afterConsumerResponse(
|
||||||
|
Request<ReceiveMessageRequest> request, Response<ReceiveMessageResult> response) {
|
||||||
|
ReceiveMessageResult receiveMessageResult = response.getAwsResponse();
|
||||||
|
List<Message> messages = receiveMessageResult.getMessages();
|
||||||
|
for (Message message : messages) {
|
||||||
|
createConsumerSpan(message, request, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createConsumerSpan(Message message, Request<?> request, Response<?> response) {
|
||||||
|
Context parentContext = SqsParentContext.ofSystemAttributes(message.getAttributes());
|
||||||
|
AmazonWebServiceRequest originalRequest = request.getOriginalRequest();
|
||||||
|
RequestMeta requestMeta = contextStore.get(originalRequest);
|
||||||
|
Context context = tracer().startSpan(Span.Kind.CONSUMER, parentContext, request, requestMeta);
|
||||||
|
tracer().end(context, response);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterError(Request<?> request, Response<?> response, Exception e) {
|
public void afterError(Request<?> request, Response<?> response, Exception e) {
|
||||||
ContextScopePair scope = request.getHandlerContext(CONTEXT_SCOPE_PAIR_CONTEXT_KEY);
|
ContextScopePair scope = request.getHandlerContext(CONTEXT_SCOPE_PAIR_CONTEXT_KEY);
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import static io.opentelemetry.api.trace.Span.Kind.CLIENT
|
import static io.opentelemetry.api.trace.Span.Kind.CLIENT
|
||||||
|
import static io.opentelemetry.api.trace.Span.Kind.PRODUCER
|
||||||
import static io.opentelemetry.instrumentation.test.server.http.TestHttpServer.httpServer
|
import static io.opentelemetry.instrumentation.test.server.http.TestHttpServer.httpServer
|
||||||
import static io.opentelemetry.instrumentation.test.utils.PortUtils.UNUSABLE_PORT
|
import static io.opentelemetry.instrumentation.test.utils.PortUtils.UNUSABLE_PORT
|
||||||
|
|
||||||
|
@ -137,7 +138,7 @@ class Aws1ClientTest extends AgentTestRunner {
|
||||||
trace(0, 1) {
|
trace(0, 1) {
|
||||||
span(0) {
|
span(0) {
|
||||||
name "$service.$operation"
|
name "$service.$operation"
|
||||||
kind CLIENT
|
kind operation == "SendMessage" ? PRODUCER : CLIENT
|
||||||
errored false
|
errored false
|
||||||
hasNoParent()
|
hasNoParent()
|
||||||
attributes {
|
attributes {
|
||||||
|
|
|
@ -0,0 +1,147 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import static io.opentelemetry.api.trace.Span.Kind.CLIENT
|
||||||
|
import static io.opentelemetry.api.trace.Span.Kind.CONSUMER
|
||||||
|
import static io.opentelemetry.api.trace.Span.Kind.PRODUCER
|
||||||
|
|
||||||
|
import com.amazonaws.auth.AWSStaticCredentialsProvider
|
||||||
|
import com.amazonaws.auth.BasicAWSCredentials
|
||||||
|
import com.amazonaws.client.builder.AwsClientBuilder
|
||||||
|
import com.amazonaws.services.sqs.AmazonSQSAsyncClient
|
||||||
|
import com.amazonaws.services.sqs.model.SendMessageRequest
|
||||||
|
import io.opentelemetry.instrumentation.test.AgentTestRunner
|
||||||
|
import io.opentelemetry.instrumentation.test.utils.PortUtils
|
||||||
|
import org.elasticmq.rest.sqs.SQSRestServerBuilder
|
||||||
|
import spock.lang.Shared
|
||||||
|
|
||||||
|
class SqsTracingTest extends AgentTestRunner {
|
||||||
|
|
||||||
|
@Shared
|
||||||
|
def sqs
|
||||||
|
@Shared
|
||||||
|
AmazonSQSAsyncClient client
|
||||||
|
@Shared
|
||||||
|
int sqsPort
|
||||||
|
|
||||||
|
def setupSpec() {
|
||||||
|
|
||||||
|
sqsPort = PortUtils.randomOpenPort()
|
||||||
|
sqs = SQSRestServerBuilder.withPort(sqsPort).withInterface("localhost").start()
|
||||||
|
println getClass().name + " SQS server started at: localhost:$sqsPort/"
|
||||||
|
|
||||||
|
def credentials = new AWSStaticCredentialsProvider(new BasicAWSCredentials("x", "x"))
|
||||||
|
def endpointConfiguration = new AwsClientBuilder.EndpointConfiguration("http://localhost:"+sqsPort, "elasticmq")
|
||||||
|
client = AmazonSQSAsyncClient.asyncBuilder().withCredentials(credentials).withEndpointConfiguration(endpointConfiguration).build()
|
||||||
|
}
|
||||||
|
|
||||||
|
def cleanupSpec() {
|
||||||
|
if (sqs != null) {
|
||||||
|
sqs.stopAndWait()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def "simple sqs producer-consumer services"() {
|
||||||
|
setup:
|
||||||
|
client.createQueue("testSdkSqs")
|
||||||
|
|
||||||
|
when:
|
||||||
|
SendMessageRequest send = new SendMessageRequest("http://localhost:$sqsPort/000000000000/testSdkSqs", "{\"type\": \"hello\"}")
|
||||||
|
client.sendMessage(send)
|
||||||
|
client.receiveMessage("http://localhost:$sqsPort/000000000000/testSdkSqs")
|
||||||
|
|
||||||
|
then:
|
||||||
|
assertTraces(3) {
|
||||||
|
trace(0, 1) {
|
||||||
|
|
||||||
|
span(0) {
|
||||||
|
name "SQS.CreateQueue"
|
||||||
|
kind CLIENT
|
||||||
|
hasNoParent()
|
||||||
|
attributes {
|
||||||
|
"aws.agent" "java-aws-sdk"
|
||||||
|
"aws.endpoint" "http://localhost:$sqsPort"
|
||||||
|
"aws.operation" "CreateQueueRequest"
|
||||||
|
"aws.queue.name" "testSdkSqs"
|
||||||
|
"aws.service" "AmazonSQS"
|
||||||
|
"http.flavor" "1.1"
|
||||||
|
"http.method" "POST"
|
||||||
|
"http.status_code" 200
|
||||||
|
"http.url" "http://localhost:$sqsPort"
|
||||||
|
"net.peer.name" "localhost"
|
||||||
|
"net.peer.port" sqsPort
|
||||||
|
"net.transport" "IP.TCP"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
trace(1, 2) {
|
||||||
|
span(0) {
|
||||||
|
name "SQS.SendMessage"
|
||||||
|
kind PRODUCER
|
||||||
|
hasNoParent()
|
||||||
|
attributes {
|
||||||
|
"aws.agent" "java-aws-sdk"
|
||||||
|
"aws.endpoint" "http://localhost:$sqsPort"
|
||||||
|
"aws.operation" "SendMessageRequest"
|
||||||
|
"aws.queue.url" "http://localhost:$sqsPort/000000000000/testSdkSqs"
|
||||||
|
"aws.service" "AmazonSQS"
|
||||||
|
"http.flavor" "1.1"
|
||||||
|
"http.method" "POST"
|
||||||
|
"http.status_code" 200
|
||||||
|
"http.url" "http://localhost:$sqsPort"
|
||||||
|
"net.peer.name" "localhost"
|
||||||
|
"net.peer.port" sqsPort
|
||||||
|
"net.transport" "IP.TCP"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
span(1) {
|
||||||
|
name "SQS.ReceiveMessage"
|
||||||
|
kind CONSUMER
|
||||||
|
childOf span(0)
|
||||||
|
attributes {
|
||||||
|
"aws.agent" "java-aws-sdk"
|
||||||
|
"aws.endpoint" "http://localhost:$sqsPort"
|
||||||
|
"aws.operation" "ReceiveMessageRequest"
|
||||||
|
"aws.queue.url" "http://localhost:$sqsPort/000000000000/testSdkSqs"
|
||||||
|
"aws.service" "AmazonSQS"
|
||||||
|
"http.flavor" "1.1"
|
||||||
|
"http.method" "POST"
|
||||||
|
"http.status_code" 200
|
||||||
|
"http.url" "http://localhost:$sqsPort"
|
||||||
|
"http.user_agent" String
|
||||||
|
"net.peer.name" "localhost"
|
||||||
|
"net.peer.port" sqsPort
|
||||||
|
"net.transport" "IP.TCP"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This span represents HTTP "sending of receive message" operation. It's always single, while there can be multiple CONSUMER spans (one per consumed message).
|
||||||
|
* This one could be suppressed (by IF in TracingRequestHandler#beforeRequest but then HTTP instrumentation span would appear
|
||||||
|
*/
|
||||||
|
trace(2, 1) {
|
||||||
|
span(0) {
|
||||||
|
name "SQS.ReceiveMessage"
|
||||||
|
kind CLIENT
|
||||||
|
hasNoParent()
|
||||||
|
attributes {
|
||||||
|
"aws.agent" "java-aws-sdk"
|
||||||
|
"aws.endpoint" "http://localhost:$sqsPort"
|
||||||
|
"aws.operation" "ReceiveMessageRequest"
|
||||||
|
"aws.queue.url" "http://localhost:$sqsPort/000000000000/testSdkSqs"
|
||||||
|
"aws.service" "AmazonSQS"
|
||||||
|
"http.flavor" "1.1"
|
||||||
|
"http.method" "POST"
|
||||||
|
"http.status_code" 200
|
||||||
|
"http.url" "http://localhost:$sqsPort"
|
||||||
|
"net.peer.name" "localhost"
|
||||||
|
"net.peer.port" sqsPort
|
||||||
|
"net.transport" "IP.TCP"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration>
|
||||||
|
|
||||||
|
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<layout class="ch.qos.logback.classic.PatternLayout">
|
||||||
|
<Pattern>
|
||||||
|
%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||||
|
</Pattern>
|
||||||
|
</layout>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<root level="DEBUG">
|
||||||
|
<appender-ref ref="console"/>
|
||||||
|
</root>
|
||||||
|
|
||||||
|
<logger name="org.elasticmq" level="debug" />
|
||||||
|
|
||||||
|
</configuration>
|
Loading…
Reference in New Issue