Skip to content

Commit

Permalink
JAX-RS: add code.namespace and code.function attributes (#2805)
Browse files Browse the repository at this point in the history
  • Loading branch information
laurit authored Apr 14, 2021
1 parent 437547d commit d1ff1e1
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@
package io.opentelemetry.javaagent.instrumentation.jaxrs.v1_0;

import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.SpanBuilder;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.context.Context;
import io.opentelemetry.instrumentation.api.servlet.ServletContextPath;
import io.opentelemetry.instrumentation.api.tracer.BaseTracer;
import io.opentelemetry.instrumentation.api.tracer.ServerSpan;
import io.opentelemetry.javaagent.instrumentation.api.ClassHierarchyIterable;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Map;
Expand Down Expand Up @@ -49,7 +51,17 @@ public Context startSpan(Class<?> target, Method method) {
updateServerSpanName(parentContext, serverSpan, pathBasedSpanName);
}

return startSpan(parentContext, spanName, SpanKind.INTERNAL);
SpanBuilder spanBuilder = spanBuilder(parentContext, spanName, SpanKind.INTERNAL);
setCodeAttributes(spanBuilder, target, method);
Span span = spanBuilder.startSpan();
return parentContext.with(span);
}

private void setCodeAttributes(SpanBuilder spanBuilder, Class<?> target, Method method) {
spanBuilder.setAttribute(SemanticAttributes.CODE_NAMESPACE, target.getName());
if (method != null) {
spanBuilder.setAttribute(SemanticAttributes.CODE_FUNCTION, method.getName());
}
}

private void updateServerSpanName(Context context, Span span, String spanName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import static io.opentelemetry.instrumentation.test.utils.ClassUtils.getClassNam
import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderServerTrace

import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import javax.ws.rs.DELETE
import javax.ws.rs.GET
import javax.ws.rs.HEAD
Expand All @@ -21,19 +22,22 @@ class JaxRsAnnotations1InstrumentationTest extends AgentInstrumentationSpecifica

def "instrumentation can be used as root span and resource is set to METHOD PATH"() {
setup:
new Jax() {
def jax = new Jax() {
@POST
@Path("/a")
void call() {
}
}.call()
}
jax.call()

expect:
assertTraces(1) {
trace(0, 1) {
span(0) {
name "/a"
attributes {
"${SemanticAttributes.CODE_NAMESPACE.key}" jax.getClass().getName()
"${SemanticAttributes.CODE_FUNCTION.key}" "call"
}
}
}
Expand Down Expand Up @@ -61,6 +65,8 @@ class JaxRsAnnotations1InstrumentationTest extends AgentInstrumentationSpecifica
name "${className}.call"
childOf span(0)
attributes {
"${SemanticAttributes.CODE_NAMESPACE.key}" obj.getClass().getName()
"${SemanticAttributes.CODE_FUNCTION.key}" "call"
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderSer

import io.dropwizard.testing.junit.ResourceTestRule
import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import org.junit.ClassRule
import spock.lang.Shared
import spock.lang.Unroll
Expand Down Expand Up @@ -47,6 +48,8 @@ class JerseyTest extends AgentInstrumentationSpecification {
childOf span(0)
name controllerName
attributes {
"${SemanticAttributes.CODE_NAMESPACE.key}" ~/Resource[$]Test*/
"${SemanticAttributes.CODE_FUNCTION.key}" "hello"
}
}
}
Expand Down Expand Up @@ -83,6 +86,8 @@ class JerseyTest extends AgentInstrumentationSpecification {
name controller1Name
kind INTERNAL
attributes {
"${SemanticAttributes.CODE_NAMESPACE.key}" ~/Resource[$]Test*/
"${SemanticAttributes.CODE_FUNCTION.key}" "nested"
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@
import static io.opentelemetry.api.trace.SpanKind.INTERNAL;

import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.SpanBuilder;
import io.opentelemetry.context.Context;
import io.opentelemetry.instrumentation.api.servlet.ServletContextPath;
import io.opentelemetry.instrumentation.api.tracer.BaseTracer;
import io.opentelemetry.instrumentation.api.tracer.ServerSpan;
import io.opentelemetry.javaagent.instrumentation.api.ClassHierarchyIterable;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Map;
Expand Down Expand Up @@ -48,15 +50,24 @@ public Context startSpan(Context parentContext, Class<?> target, Method method)
// We create span and immediately update its name
// We do that in order to reuse logic inside updateSpanNames method, which is used externally as
// well.
Span span = spanBuilder(parentContext, "jax-rs.request", INTERNAL).startSpan();
SpanBuilder spanBuilder = spanBuilder(parentContext, "jax-rs.request", INTERNAL);
setCodeAttributes(spanBuilder, target, method);
Span span = spanBuilder.startSpan();
updateSpanNames(
parentContext, span, ServerSpan.fromContextOrNull(parentContext), target, method);
return parentContext.with(span);
}

public void updateSpanNames(
Context context, Span span, Span serverSpan, Class<?> target, Method method) {
String pathBasedSpanName = ServletContextPath.prepend(context, getPathSpanName(target, method));
String pathBasedSpanName = getPathSpanName(target, method);
// If path based name is empty skip prepending context path so that path based name would
// remain as an empty string for which we skip updating span name. Path base span name is
// empty when method and class don't have a jax-rs path annotation, this can happen when
// creating an "abort" span, see RequestContextHelper.
if (!pathBasedSpanName.isEmpty()) {
pathBasedSpanName = ServletContextPath.prepend(context, pathBasedSpanName);
}
if (serverSpan == null) {
updateSpanName(span, pathBasedSpanName);
} else {
Expand All @@ -71,6 +82,13 @@ private void updateSpanName(Span span, String spanName) {
}
}

private void setCodeAttributes(SpanBuilder spanBuilder, Class<?> target, Method method) {
spanBuilder.setAttribute(SemanticAttributes.CODE_NAMESPACE, target.getName());
if (method != null) {
spanBuilder.setAttribute(SemanticAttributes.CODE_FUNCTION, method.getName());
}
}

/**
* Returns the span name given a JaxRS annotated method. Results are cached so this method can be
* called multiple times without significantly impacting performance.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import static io.opentelemetry.instrumentation.test.utils.ClassUtils.getClassNam
import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderServerTrace

import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import javax.ws.rs.DELETE
import javax.ws.rs.GET
import javax.ws.rs.HEAD
Expand All @@ -21,19 +22,22 @@ abstract class JaxRsAnnotationsInstrumentationTest extends AgentInstrumentationS

def "instrumentation can be used as root span and resource is set to METHOD PATH"() {
setup:
new Jax() {
def jax = new Jax() {
@POST
@Path("/a")
void call() {
}
}.call()
}
jax.call()

expect:
assertTraces(1) {
trace(0, 1) {
span(0) {
name "/a"
attributes {
"${SemanticAttributes.CODE_NAMESPACE.key}" jax.getClass().getName()
"${SemanticAttributes.CODE_FUNCTION.key}" "call"
}
}
}
Expand Down Expand Up @@ -61,6 +65,8 @@ abstract class JaxRsAnnotationsInstrumentationTest extends AgentInstrumentationS
name "${className}.call"
childOf span(0)
attributes {
"${SemanticAttributes.CODE_NAMESPACE.key}" obj.getClass().getName()
"${SemanticAttributes.CODE_FUNCTION.key}" "call"
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import static io.opentelemetry.api.trace.SpanKind.SERVER
import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderServerTrace

import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import javax.ws.rs.container.ContainerRequestContext
import javax.ws.rs.container.ContainerRequestFilter
import javax.ws.rs.container.PreMatching
Expand Down Expand Up @@ -83,8 +84,15 @@ abstract class JaxRsFilterTest extends AgentInstrumentationSpecification {
span(1) {
childOf span(0)
name controllerName
if (!runsOnServer()) {
if (abortPrematch) {
attributes {
"${SemanticAttributes.CODE_NAMESPACE.key}" "JaxRsFilterTest\$PrematchRequestFilter"
"${SemanticAttributes.CODE_FUNCTION.key}" "filter"
}
} else {
attributes {
"${SemanticAttributes.CODE_NAMESPACE.key}" ~/Resource[$]Test*/
"${SemanticAttributes.CODE_FUNCTION.key}" "hello"
}
}
}
Expand Down Expand Up @@ -135,9 +143,9 @@ abstract class JaxRsFilterTest extends AgentInstrumentationSpecification {
childOf span(0)
name controller1Name
kind INTERNAL
if (!runsOnServer()) {
attributes {
}
attributes {
"${SemanticAttributes.CODE_NAMESPACE.key}" ~/Resource[$]Test*/
"${SemanticAttributes.CODE_FUNCTION.key}" "nested"
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,8 @@ abstract class JaxRsHttpServerTest<S> extends HttpServerTest<S> implements Agent
}
childOf((SpanData) parent)
attributes {
"${SemanticAttributes.CODE_NAMESPACE.key}" "JaxRsTestResource"
"${SemanticAttributes.CODE_FUNCTION.key}" methodName
if (isCancelled) {
"jaxrs.canceled" true
}
Expand Down

0 comments on commit d1ff1e1

Please sign in to comment.