Merge pull request #969 from DataDog/labbati/jax-rs-op-name
Static operation names for JaxRS instrumentation to be used as root span
This commit is contained in:
commit
a693c42dc1
|
@ -3,6 +3,7 @@ package datadog.trace.instrumentation.jaxrs;
|
||||||
import static datadog.trace.bootstrap.WeakMap.Provider.newWeakMap;
|
import static datadog.trace.bootstrap.WeakMap.Provider.newWeakMap;
|
||||||
|
|
||||||
import datadog.trace.agent.decorator.BaseDecorator;
|
import datadog.trace.agent.decorator.BaseDecorator;
|
||||||
|
import datadog.trace.api.DDSpanTypes;
|
||||||
import datadog.trace.api.DDTags;
|
import datadog.trace.api.DDTags;
|
||||||
import datadog.trace.bootstrap.WeakMap;
|
import datadog.trace.bootstrap.WeakMap;
|
||||||
import io.opentracing.Scope;
|
import io.opentracing.Scope;
|
||||||
|
@ -36,13 +37,41 @@ public class JaxRsAnnotationsDecorator extends BaseDecorator {
|
||||||
return "jax-rs-controller";
|
return "jax-rs-controller";
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateParent(final Scope scope, final Method method) {
|
public void onControllerStart(final Scope scope, final Scope parent, final Method method) {
|
||||||
|
final String resourceName = getPathResourceName(method);
|
||||||
|
updateParent(parent, resourceName);
|
||||||
|
|
||||||
|
final Span span = scope.span();
|
||||||
|
span.setTag(DDTags.SPAN_TYPE, DDSpanTypes.HTTP_SERVER);
|
||||||
|
|
||||||
|
// When jax-rs is the root, we want to name using the path, otherwise use the class/method.
|
||||||
|
final boolean isRootScope = parent == null;
|
||||||
|
if (isRootScope && !resourceName.isEmpty()) {
|
||||||
|
span.setTag(DDTags.RESOURCE_NAME, resourceName);
|
||||||
|
} else {
|
||||||
|
span.setTag(DDTags.RESOURCE_NAME, DECORATE.spanNameForMethod(method));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateParent(final Scope scope, final String resourceName) {
|
||||||
if (scope == null) {
|
if (scope == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final Span span = scope.span();
|
final Span span = scope.span();
|
||||||
Tags.COMPONENT.set(span, "jax-rs");
|
Tags.COMPONENT.set(span, "jax-rs");
|
||||||
|
|
||||||
|
if (!resourceName.isEmpty()) {
|
||||||
|
span.setTag(DDTags.RESOURCE_NAME, resourceName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the resource name given a JaxRS annotated method. Results are cached so this method can
|
||||||
|
* be called multiple times without significantly impacting performance.
|
||||||
|
*
|
||||||
|
* @return The result can be an empty string but will never be {@code null}.
|
||||||
|
*/
|
||||||
|
private String getPathResourceName(final Method method) {
|
||||||
final Class<?> target = method.getDeclaringClass();
|
final Class<?> target = method.getDeclaringClass();
|
||||||
Map<Method, String> classMap = resourceNames.get(target);
|
Map<Method, String> classMap = resourceNames.get(target);
|
||||||
|
|
||||||
|
@ -61,9 +90,7 @@ public class JaxRsAnnotationsDecorator extends BaseDecorator {
|
||||||
classMap.put(method, resourceName);
|
classMap.put(method, resourceName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!resourceName.isEmpty()) {
|
return resourceName;
|
||||||
span.setTag(DDTags.RESOURCE_NAME, resourceName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String locateHttpMethod(final Method method) {
|
private String locateHttpMethod(final Method method) {
|
||||||
|
|
|
@ -10,6 +10,7 @@ import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||||
import com.google.auto.service.AutoService;
|
import com.google.auto.service.AutoService;
|
||||||
import datadog.trace.agent.tooling.Instrumenter;
|
import datadog.trace.agent.tooling.Instrumenter;
|
||||||
import io.opentracing.Scope;
|
import io.opentracing.Scope;
|
||||||
|
import io.opentracing.Tracer;
|
||||||
import io.opentracing.util.GlobalTracer;
|
import io.opentracing.util.GlobalTracer;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -21,6 +22,8 @@ import net.bytebuddy.matcher.ElementMatcher;
|
||||||
@AutoService(Instrumenter.class)
|
@AutoService(Instrumenter.class)
|
||||||
public final class JaxRsAnnotationsInstrumentation extends Instrumenter.Default {
|
public final class JaxRsAnnotationsInstrumentation extends Instrumenter.Default {
|
||||||
|
|
||||||
|
private static final String JAX_ENDPOINT_OPERATION_NAME = "jax-rs.request";
|
||||||
|
|
||||||
public JaxRsAnnotationsInstrumentation() {
|
public JaxRsAnnotationsInstrumentation() {
|
||||||
super("jax-rs", "jaxrs", "jax-rs-annotations");
|
super("jax-rs", "jaxrs", "jax-rs-annotations");
|
||||||
}
|
}
|
||||||
|
@ -57,13 +60,12 @@ public final class JaxRsAnnotationsInstrumentation extends Instrumenter.Default
|
||||||
|
|
||||||
@Advice.OnMethodEnter(suppress = Throwable.class)
|
@Advice.OnMethodEnter(suppress = Throwable.class)
|
||||||
public static Scope nameSpan(@Advice.Origin final Method method) {
|
public static Scope nameSpan(@Advice.Origin final Method method) {
|
||||||
|
final Tracer tracer = GlobalTracer.get();
|
||||||
// Rename the parent span according to the path represented by these annotations.
|
// Rename the parent span according to the path represented by these annotations.
|
||||||
final Scope scope = GlobalTracer.get().scopeManager().active();
|
final Scope parent = tracer.scopeManager().active();
|
||||||
DECORATE.updateParent(scope, method);
|
final Scope scope = tracer.buildSpan(JAX_ENDPOINT_OPERATION_NAME).startActive(true);
|
||||||
|
DECORATE.onControllerStart(scope, parent, method);
|
||||||
// Now create a span representing the method execution.
|
return DECORATE.afterStart(scope);
|
||||||
final String operationName = DECORATE.spanNameForMethod(method);
|
|
||||||
return DECORATE.afterStart(GlobalTracer.get().buildSpan(operationName).startActive(true));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||||
|
|
|
@ -14,7 +14,31 @@ import static datadog.trace.instrumentation.jaxrs.JaxRsAnnotationsDecorator.DECO
|
||||||
|
|
||||||
class JaxRsAnnotationsInstrumentationTest extends AgentTestRunner {
|
class JaxRsAnnotationsInstrumentationTest extends AgentTestRunner {
|
||||||
|
|
||||||
def "span named '#name' from annotations on class"() {
|
def "instrumentation can be used as root span and resource is set to METHOD PATH"() {
|
||||||
|
setup:
|
||||||
|
new Jax() {
|
||||||
|
@POST
|
||||||
|
@Path("/a")
|
||||||
|
void call() {}
|
||||||
|
}.call()
|
||||||
|
|
||||||
|
expect:
|
||||||
|
assertTraces(1) {
|
||||||
|
trace(0, 1) {
|
||||||
|
span(0) {
|
||||||
|
operationName "jax-rs.request"
|
||||||
|
resourceName "POST /a"
|
||||||
|
spanType "web"
|
||||||
|
tags {
|
||||||
|
"$Tags.COMPONENT.key" "jax-rs-controller"
|
||||||
|
defaultTags()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def "span named '#name' from annotations on class when is not root span"() {
|
||||||
setup:
|
setup:
|
||||||
def startingCacheSize = DECORATE.resourceNames.size()
|
def startingCacheSize = DECORATE.resourceNames.size()
|
||||||
runUnderTrace("test") {
|
runUnderTrace("test") {
|
||||||
|
@ -34,8 +58,9 @@ class JaxRsAnnotationsInstrumentationTest extends AgentTestRunner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
span(1) {
|
span(1) {
|
||||||
operationName "${className}.call"
|
operationName "jax-rs.request"
|
||||||
resourceName "${className}.call"
|
resourceName "${className}.call"
|
||||||
|
spanType "web"
|
||||||
childOf span(0)
|
childOf span(0)
|
||||||
tags {
|
tags {
|
||||||
"$Tags.COMPONENT.key" "jax-rs-controller"
|
"$Tags.COMPONENT.key" "jax-rs-controller"
|
||||||
|
|
Loading…
Reference in New Issue