Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JAX-RS: add code.namespace and code.function attributes #2805

Merged
merged 4 commits into from
Apr 14, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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 appending 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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

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