Improve AWS1.x SDK integration

For AWS11.x SDK make sure that http client span is actually a child of
aws span.
This commit is contained in:
Nikolay Martynov 2019-01-17 18:09:00 -05:00
parent 7b0e3ffd1c
commit 76999fc9f9
3 changed files with 62 additions and 62 deletions

View File

@ -18,7 +18,7 @@ import com.amazonaws.Request;
import com.amazonaws.Response; import com.amazonaws.Response;
import com.amazonaws.handlers.HandlerContextKey; import com.amazonaws.handlers.HandlerContextKey;
import com.amazonaws.handlers.RequestHandler2; import com.amazonaws.handlers.RequestHandler2;
import io.opentracing.Span; import io.opentracing.Scope;
import io.opentracing.SpanContext; import io.opentracing.SpanContext;
import io.opentracing.Tracer; import io.opentracing.Tracer;
import io.opentracing.propagation.Format; import io.opentracing.propagation.Format;
@ -28,7 +28,11 @@ import io.opentracing.tag.Tags;
/** Tracing Request Handler */ /** Tracing Request Handler */
public class TracingRequestHandler extends RequestHandler2 { public class TracingRequestHandler extends RequestHandler2 {
private final HandlerContextKey<Span> contextKey = new HandlerContextKey<>("span"); // Note: aws1.x sdk doesn't have any truly async clients so we can store scope in request context
// safely.
private static final HandlerContextKey<Scope> SCOPE_CONTEXT_KEY =
new HandlerContextKey<>("DatadogScope");
private final SpanContext parentContext; // for Async Client private final SpanContext parentContext; // for Async Client
private final Tracer tracer; private final Tracer tracer;
@ -64,30 +68,32 @@ public class TracingRequestHandler extends RequestHandler2 {
spanBuilder.asChildOf(parentContext); spanBuilder.asChildOf(parentContext);
} }
final Span span = spanBuilder.start(); final Scope scope = spanBuilder.startActive(true);
SpanDecorator.onRequest(request, span); SpanDecorator.onRequest(request, scope.span());
// We inject headers at aws-client level because aws requests may be signed and adding headers
// on http-client level may break signature.
tracer.inject( tracer.inject(
span.context(), scope.span().context(),
Format.Builtin.HTTP_HEADERS, Format.Builtin.HTTP_HEADERS,
new TextMapInjectAdapter(request.getHeaders())); new TextMapInjectAdapter(request.getHeaders()));
request.addHandlerContext(contextKey, span); request.addHandlerContext(SCOPE_CONTEXT_KEY, scope);
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public void afterResponse(final Request<?> request, final Response<?> response) { public void afterResponse(final Request<?> request, final Response<?> response) {
final Span span = request.getHandlerContext(contextKey); final Scope scope = request.getHandlerContext(SCOPE_CONTEXT_KEY);
SpanDecorator.onResponse(response, span); SpanDecorator.onResponse(response, scope.span());
span.finish(); scope.close();
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public void afterError(final Request<?> request, final Response<?> response, final Exception e) { public void afterError(final Request<?> request, final Response<?> response, final Exception e) {
final Span span = request.getHandlerContext(contextKey); final Scope scope = request.getHandlerContext(SCOPE_CONTEXT_KEY);
SpanDecorator.onError(e, span); SpanDecorator.onError(e, scope.span());
span.finish(); scope.close();
} }
} }

View File

@ -73,27 +73,8 @@ class AWSClientTest extends AgentTestRunner {
client.requestHandler2s.size() == handlerCount client.requestHandler2s.size() == handlerCount
client.requestHandler2s.get(0).getClass().getSimpleName() == "TracingRequestHandler" client.requestHandler2s.get(0).getClass().getSimpleName() == "TracingRequestHandler"
assertTraces(2) { assertTraces(1) {
trace(0, 1) { trace(0, 2) {
span(0) {
operationName "http.request"
resourceName "$method /$url"
errored false
parent() // FIXME: This should be a child of the aws.http call.
tags {
"$Tags.COMPONENT.key" "apache-httpclient"
"$Tags.HTTP_STATUS.key" 200
"$Tags.HTTP_URL.key" "$server.address/$url"
"$Tags.PEER_HOSTNAME.key" "localhost"
"$Tags.PEER_PORT.key" server.address.port
"$Tags.HTTP_METHOD.key" "$method"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
"$DDTags.SPAN_TYPE" DDSpanTypes.HTTP_CLIENT
defaultTags()
}
}
}
trace(1, 1) {
span(0) { span(0) {
serviceName "java-aws-sdk" serviceName "java-aws-sdk"
operationName "aws.http" operationName "aws.http"
@ -107,18 +88,34 @@ class AWSClientTest extends AgentTestRunner {
"$Tags.HTTP_METHOD.key" "$method" "$Tags.HTTP_METHOD.key" "$method"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT "$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
"$DDTags.SPAN_TYPE" DDSpanTypes.HTTP_CLIENT "$DDTags.SPAN_TYPE" DDSpanTypes.HTTP_CLIENT
"aws.service" String "aws.service" { it.contains(service) }
"aws.endpoint" "$server.address" "aws.endpoint" "$server.address"
"aws.operation" "${operation}Request" "aws.operation" "${operation}Request"
"aws.agent" "java-aws-sdk" "aws.agent" "java-aws-sdk"
defaultTags() defaultTags()
} }
} }
span(1) {
operationName "http.request"
resourceName "$method /$url"
errored false
childOf(span(0))
tags {
"$Tags.COMPONENT.key" "apache-httpclient"
"$Tags.HTTP_STATUS.key" 200
"$Tags.HTTP_URL.key" "$server.address/$url"
"$Tags.PEER_HOSTNAME.key" "localhost"
"$Tags.PEER_PORT.key" server.address.port
"$Tags.HTTP_METHOD.key" "$method"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
"$DDTags.SPAN_TYPE" DDSpanTypes.HTTP_CLIENT
defaultTags()
} }
} }
// Not sure why these are children of the aws.http span: }
server.lastRequest.headers.get("x-datadog-trace-id") == TEST_WRITER[1][0].traceId }
server.lastRequest.headers.get("x-datadog-parent-id") == TEST_WRITER[1][0].spanId server.lastRequest.headers.get("x-datadog-trace-id") == TEST_WRITER[0][0].traceId
server.lastRequest.headers.get("x-datadog-parent-id") == TEST_WRITER[0][0].spanId
where: where:
service | operation | method | url | handlerCount | call | body | client service | operation | method | url | handlerCount | call | body | client

View File

@ -102,27 +102,8 @@ class AWSClientTest extends AgentTestRunner {
client.requestHandler2s.size() == handlerCount client.requestHandler2s.size() == handlerCount
client.requestHandler2s.get(0).getClass().getSimpleName() == "TracingRequestHandler" client.requestHandler2s.get(0).getClass().getSimpleName() == "TracingRequestHandler"
assertTraces(2) { assertTraces(1) {
trace(0, 1) { trace(0, 2) {
span(0) {
operationName "http.request"
resourceName "$method /$url"
errored false
parent() // FIXME: This should be a child of the aws.http call.
tags {
"$Tags.COMPONENT.key" "apache-httpclient"
"$Tags.HTTP_STATUS.key" 200
"$Tags.HTTP_URL.key" "$server.address/$url"
"$Tags.PEER_HOSTNAME.key" "localhost"
"$Tags.PEER_PORT.key" server.address.port
"$Tags.HTTP_METHOD.key" "$method"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
"$DDTags.SPAN_TYPE" DDSpanTypes.HTTP_CLIENT
defaultTags()
}
}
}
trace(1, 1) {
span(0) { span(0) {
serviceName "java-aws-sdk" serviceName "java-aws-sdk"
operationName "aws.http" operationName "aws.http"
@ -136,18 +117,34 @@ class AWSClientTest extends AgentTestRunner {
"$Tags.HTTP_METHOD.key" "$method" "$Tags.HTTP_METHOD.key" "$method"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT "$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
"$DDTags.SPAN_TYPE" DDSpanTypes.HTTP_CLIENT "$DDTags.SPAN_TYPE" DDSpanTypes.HTTP_CLIENT
"aws.service" String "aws.service" { it.contains(service) }
"aws.endpoint" "$server.address" "aws.endpoint" "$server.address"
"aws.operation" "${operation}Request" "aws.operation" "${operation}Request"
"aws.agent" "java-aws-sdk" "aws.agent" "java-aws-sdk"
defaultTags() defaultTags()
} }
} }
span(1) {
operationName "http.request"
resourceName "$method /$url"
errored false
childOf(span(0))
tags {
"$Tags.COMPONENT.key" "apache-httpclient"
"$Tags.HTTP_STATUS.key" 200
"$Tags.HTTP_URL.key" "$server.address/$url"
"$Tags.PEER_HOSTNAME.key" "localhost"
"$Tags.PEER_PORT.key" server.address.port
"$Tags.HTTP_METHOD.key" "$method"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
"$DDTags.SPAN_TYPE" DDSpanTypes.HTTP_CLIENT
defaultTags()
} }
} }
// Not sure why these are children of the aws.http span: }
server.lastRequest.headers.get("x-datadog-trace-id") == TEST_WRITER[1][0].traceId }
server.lastRequest.headers.get("x-datadog-parent-id") == TEST_WRITER[1][0].spanId server.lastRequest.headers.get("x-datadog-trace-id") == TEST_WRITER[0][0].traceId
server.lastRequest.headers.get("x-datadog-parent-id") == TEST_WRITER[0][0].spanId
where: where:
service | operation | method | url | handlerCount | call | body | client service | operation | method | url | handlerCount | call | body | client