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 datadog.trace.agent.decorator.BaseDecorator;
|
||||
import datadog.trace.api.DDSpanTypes;
|
||||
import datadog.trace.api.DDTags;
|
||||
import datadog.trace.bootstrap.WeakMap;
|
||||
import io.opentracing.Scope;
|
||||
|
@ -36,13 +37,41 @@ public class JaxRsAnnotationsDecorator extends BaseDecorator {
|
|||
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) {
|
||||
return;
|
||||
}
|
||||
final Span span = scope.span();
|
||||
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();
|
||||
Map<Method, String> classMap = resourceNames.get(target);
|
||||
|
||||
|
@ -61,9 +90,7 @@ public class JaxRsAnnotationsDecorator extends BaseDecorator {
|
|||
classMap.put(method, resourceName);
|
||||
}
|
||||
|
||||
if (!resourceName.isEmpty()) {
|
||||
span.setTag(DDTags.RESOURCE_NAME, resourceName);
|
||||
}
|
||||
return resourceName;
|
||||
}
|
||||
|
||||
private String locateHttpMethod(final Method method) {
|
||||
|
|
|
@ -10,6 +10,7 @@ import static net.bytebuddy.matcher.ElementMatchers.named;
|
|||
import com.google.auto.service.AutoService;
|
||||
import datadog.trace.agent.tooling.Instrumenter;
|
||||
import io.opentracing.Scope;
|
||||
import io.opentracing.Tracer;
|
||||
import io.opentracing.util.GlobalTracer;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
@ -21,6 +22,8 @@ import net.bytebuddy.matcher.ElementMatcher;
|
|||
@AutoService(Instrumenter.class)
|
||||
public final class JaxRsAnnotationsInstrumentation extends Instrumenter.Default {
|
||||
|
||||
private static final String JAX_ENDPOINT_OPERATION_NAME = "jax-rs.request";
|
||||
|
||||
public JaxRsAnnotationsInstrumentation() {
|
||||
super("jax-rs", "jaxrs", "jax-rs-annotations");
|
||||
}
|
||||
|
@ -57,13 +60,12 @@ public final class JaxRsAnnotationsInstrumentation extends Instrumenter.Default
|
|||
|
||||
@Advice.OnMethodEnter(suppress = Throwable.class)
|
||||
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.
|
||||
final Scope scope = GlobalTracer.get().scopeManager().active();
|
||||
DECORATE.updateParent(scope, method);
|
||||
|
||||
// Now create a span representing the method execution.
|
||||
final String operationName = DECORATE.spanNameForMethod(method);
|
||||
return DECORATE.afterStart(GlobalTracer.get().buildSpan(operationName).startActive(true));
|
||||
final Scope parent = tracer.scopeManager().active();
|
||||
final Scope scope = tracer.buildSpan(JAX_ENDPOINT_OPERATION_NAME).startActive(true);
|
||||
DECORATE.onControllerStart(scope, parent, method);
|
||||
return DECORATE.afterStart(scope);
|
||||
}
|
||||
|
||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||
|
|
|
@ -14,7 +14,31 @@ import static datadog.trace.instrumentation.jaxrs.JaxRsAnnotationsDecorator.DECO
|
|||
|
||||
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:
|
||||
def startingCacheSize = DECORATE.resourceNames.size()
|
||||
runUnderTrace("test") {
|
||||
|
@ -34,8 +58,9 @@ class JaxRsAnnotationsInstrumentationTest extends AgentTestRunner {
|
|||
}
|
||||
}
|
||||
span(1) {
|
||||
operationName "${className}.call"
|
||||
operationName "jax-rs.request"
|
||||
resourceName "${className}.call"
|
||||
spanType "web"
|
||||
childOf span(0)
|
||||
tags {
|
||||
"$Tags.COMPONENT.key" "jax-rs-controller"
|
||||
|
|
Loading…
Reference in New Issue