diff --git a/dd-java-agent/instrumentation/grpc-1.5/src/main/java/datadog/trace/instrumentation/grpc/server/GrpcServerBuilderInstrumentation.java b/dd-java-agent/instrumentation/grpc-1.5/src/main/java/datadog/trace/instrumentation/grpc/server/GrpcServerBuilderInstrumentation.java index 2baaa04ff6..6159deb5ff 100644 --- a/dd-java-agent/instrumentation/grpc-1.5/src/main/java/datadog/trace/instrumentation/grpc/server/GrpcServerBuilderInstrumentation.java +++ b/dd-java-agent/instrumentation/grpc-1.5/src/main/java/datadog/trace/instrumentation/grpc/server/GrpcServerBuilderInstrumentation.java @@ -31,6 +31,7 @@ public class GrpcServerBuilderInstrumentation extends Instrumenter.Default { public String[] helperClassNames() { return new String[] { "datadog.trace.instrumentation.grpc.server.TracingServerInterceptor", + "datadog.trace.instrumentation.grpc.server.TracingServerInterceptor$TracingServerCall", "datadog.trace.instrumentation.grpc.server.TracingServerInterceptor$TracingServerCallListener", "datadog.trace.agent.decorator.BaseDecorator", "datadog.trace.agent.decorator.ServerDecorator", diff --git a/dd-java-agent/instrumentation/grpc-1.5/src/main/java/datadog/trace/instrumentation/grpc/server/GrpcServerDecorator.java b/dd-java-agent/instrumentation/grpc-1.5/src/main/java/datadog/trace/instrumentation/grpc/server/GrpcServerDecorator.java index 004fe0e77d..5866c8e131 100644 --- a/dd-java-agent/instrumentation/grpc-1.5/src/main/java/datadog/trace/instrumentation/grpc/server/GrpcServerDecorator.java +++ b/dd-java-agent/instrumentation/grpc-1.5/src/main/java/datadog/trace/instrumentation/grpc/server/GrpcServerDecorator.java @@ -2,6 +2,9 @@ package datadog.trace.instrumentation.grpc.server; import datadog.trace.agent.decorator.ServerDecorator; import datadog.trace.api.DDSpanTypes; +import io.grpc.Status; +import io.opentracing.Span; +import io.opentracing.tag.Tags; public class GrpcServerDecorator extends ServerDecorator { public static final GrpcServerDecorator DECORATE = new GrpcServerDecorator(); @@ -20,4 +23,17 @@ public class GrpcServerDecorator extends ServerDecorator { protected String component() { return "grpc-server"; } + + public Span onClose(final Span span, final Status status) { + + span.setTag("status.code", status.getCode().name()); + span.setTag("status.description", status.getDescription()); + + onError(span, status.getCause()); + if (!status.isOk()) { + Tags.ERROR.set(span, true); + } + + return span; + } } diff --git a/dd-java-agent/instrumentation/grpc-1.5/src/main/java/datadog/trace/instrumentation/grpc/server/TracingServerInterceptor.java b/dd-java-agent/instrumentation/grpc-1.5/src/main/java/datadog/trace/instrumentation/grpc/server/TracingServerInterceptor.java index d54fc23630..e4198eec0e 100644 --- a/dd-java-agent/instrumentation/grpc-1.5/src/main/java/datadog/trace/instrumentation/grpc/server/TracingServerInterceptor.java +++ b/dd-java-agent/instrumentation/grpc-1.5/src/main/java/datadog/trace/instrumentation/grpc/server/TracingServerInterceptor.java @@ -4,11 +4,13 @@ import static datadog.trace.instrumentation.grpc.server.GrpcServerDecorator.DECO import datadog.trace.api.DDTags; import datadog.trace.context.TraceScope; +import io.grpc.ForwardingServerCall; import io.grpc.ForwardingServerCallListener; import io.grpc.Metadata; import io.grpc.ServerCall; import io.grpc.ServerCallHandler; import io.grpc.ServerInterceptor; +import io.grpc.Status; import io.opentracing.Scope; import io.opentracing.Span; import io.opentracing.SpanContext; @@ -60,8 +62,13 @@ public class TracingServerInterceptor implements ServerInterceptor { final ServerCall.Listener result; try { + // Wrap the server call so that we can decorate the span + // with the resulting status + TracingServerCall tracingServerCall = + new TracingServerCall<>(tracer, span, call); + // call other interceptors - result = next.startCall(call, headers); + result = next.startCall(tracingServerCall, headers); } catch (final Throwable e) { DECORATE.onError(span, e); DECORATE.beforeFinish(span); @@ -78,6 +85,36 @@ public class TracingServerInterceptor implements ServerInterceptor { return new TracingServerCallListener<>(tracer, span, result); } + static final class TracingServerCall + extends ForwardingServerCall.SimpleForwardingServerCall { + final Tracer tracer; + final Span span; + + TracingServerCall( + final Tracer tracer, final Span span, final ServerCall delegate) { + super(delegate); + this.tracer = tracer; + this.span = span; + } + + @Override + public void close(final Status status, final Metadata trailers) { + DECORATE.onClose(span, status); + try (final Scope scope = tracer.scopeManager().activate(span, false)) { + if (scope instanceof TraceScope) { + ((TraceScope) scope).setAsyncPropagation(true); + } + delegate().close(status, trailers); + if (scope instanceof TraceScope) { + ((TraceScope) scope).setAsyncPropagation(false); + } + } catch (final Throwable e) { + DECORATE.onError(span, e); + throw e; + } + } + } + static final class TracingServerCallListener extends ForwardingServerCallListener.SimpleForwardingServerCallListener { final Tracer tracer; diff --git a/dd-java-agent/instrumentation/grpc-1.5/src/test/groovy/GrpcStreamingTest.groovy b/dd-java-agent/instrumentation/grpc-1.5/src/test/groovy/GrpcStreamingTest.groovy index a2e7ca0fd8..0a982f1e43 100644 --- a/dd-java-agent/instrumentation/grpc-1.5/src/test/groovy/GrpcStreamingTest.groovy +++ b/dd-java-agent/instrumentation/grpc-1.5/src/test/groovy/GrpcStreamingTest.groovy @@ -91,6 +91,7 @@ class GrpcStreamingTest extends AgentTestRunner { childOf trace(1).get(0) errored false tags { + "status.code" "OK" "$Tags.SPAN_KIND.key" Tags.SPAN_KIND_SERVER "$Tags.COMPONENT.key" "grpc-server" defaultTags(true) diff --git a/dd-java-agent/instrumentation/grpc-1.5/src/test/groovy/GrpcTest.groovy b/dd-java-agent/instrumentation/grpc-1.5/src/test/groovy/GrpcTest.groovy index bc00f3113f..985eea3efb 100644 --- a/dd-java-agent/instrumentation/grpc-1.5/src/test/groovy/GrpcTest.groovy +++ b/dd-java-agent/instrumentation/grpc-1.5/src/test/groovy/GrpcTest.groovy @@ -47,6 +47,7 @@ class GrpcTest extends AgentTestRunner { childOf trace(1).get(0) errored false tags { + "status.code" "OK" "$Tags.SPAN_KIND.key" Tags.SPAN_KIND_SERVER "$Tags.COMPONENT.key" "grpc-server" defaultTags(true) @@ -136,10 +137,17 @@ class GrpcTest extends AgentTestRunner { resourceName "example.Greeter/SayHello" spanType DDSpanTypes.RPC childOf trace(1).get(0) - errored false + errored true tags { + "status.code" "${status.code.name()}" + "status.description" description "$Tags.SPAN_KIND.key" Tags.SPAN_KIND_SERVER "$Tags.COMPONENT.key" "grpc-server" + if(status.cause != null){ + errorTags status.cause.class, status.cause.message + }else{ + tag "error", true + } defaultTags(true) } }