Skip to content

Commit

Permalink
Merge pull request #46365 from brunobat/withspan-attributes-class-method
Browse files Browse the repository at this point in the history
Add class and method to WithSpan attributes
  • Loading branch information
ozangunalp authored Feb 19, 2025
2 parents d213527 + 34943a4 commit d8941dd
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 25 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package io.quarkus.opentelemetry.deployment.interceptor;

import static io.opentelemetry.api.trace.SpanKind.INTERNAL;
import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_FUNCTION;
import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_NAMESPACE;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
Expand Down Expand Up @@ -104,9 +106,11 @@ void withSpanAttributesTest_newSpan() {
SpanData spanDataOut = spanItems.get(0);
assertEquals("HelloRouter.withSpanTakesPrecedence", spanDataOut.getName());
assertEquals(INTERNAL, spanDataOut.getKind());
assertEquals(2, spanDataOut.getAttributes().size());
assertEquals(4, spanDataOut.getAttributes().size());
assertEquals("implicit", getAttribute(spanDataOut, "implicitName"));
assertEquals("explicit", getAttribute(spanDataOut, "explicitName"));
assertEquals("withSpanTakesPrecedence", spanDataOut.getAttributes().get((CODE_FUNCTION)));
assertEquals(HelloRouter.class.getName(), spanDataOut.getAttributes().get((CODE_NAMESPACE)));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import static io.opentelemetry.api.trace.SpanKind.INTERNAL;
import static io.opentelemetry.api.trace.SpanKind.SERVER;
import static io.opentelemetry.api.trace.StatusCode.ERROR;
import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_FUNCTION;
import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_NAMESPACE;
import static io.quarkus.opentelemetry.deployment.common.exporter.TestSpanExporter.getSpanByKindAndParentId;
import static java.net.HttpURLConnection.HTTP_OK;
import static org.junit.jupiter.api.Assertions.assertEquals;
Expand Down Expand Up @@ -87,17 +89,21 @@ void spanName() {
void spanKind() {
spanBean.spanKind();
List<SpanData> spanItems = spanExporter.getFinishedSpanItems(1);
assertEquals("SpanBean.spanKind", spanItems.get(0).getName());
assertEquals(SERVER, spanItems.get(0).getKind());
SpanData span = spanItems.get(0);
assertEquals("SpanBean.spanKind", span.getName());
assertEquals(SERVER, span.getKind());
assertClassMethodNames(span, SpanBean.class, "spanKind");
}

@Test
void spanArgs() {
spanBean.spanArgs("argument");
List<SpanData> spanItems = spanExporter.getFinishedSpanItems(1);
assertEquals("SpanBean.spanArgs", spanItems.get(0).getName());
assertEquals(INTERNAL, spanItems.get(0).getKind());
assertEquals("argument", spanItems.get(0).getAttributes().get(AttributeKey.stringKey("arg")));
SpanData span = spanItems.get(0);
assertEquals("SpanBean.spanArgs", span.getName());
assertEquals(INTERNAL, span.getKind());
assertEquals("argument", span.getAttributes().get(AttributeKey.stringKey("arg")));
assertClassMethodNames(span, SpanBean.class, "spanArgs");
}

@Test
Expand All @@ -107,9 +113,12 @@ void spanChild() {

final SpanData parent = getSpanByKindAndParentId(spans, INTERNAL, "0000000000000000");
assertEquals("SpanBean.spanChild", parent.getName());
assertClassMethodNames(parent, SpanBean.class, "spanChild");

final SpanData child = getSpanByKindAndParentId(spans, INTERNAL, parent.getSpanId());
assertEquals("SpanChildBean.spanChild", child.getName());
assertClassMethodNames(child, SpanChildBean.class, "spanChild");

}

@Test
Expand All @@ -120,7 +129,7 @@ void spanCdiRest() {
final SpanData parent = getSpanByKindAndParentId(spans, INTERNAL, "0000000000000000");
final SpanData child = getSpanByKindAndParentId(spans, INTERNAL, parent.getSpanId());
final SpanData client = getSpanByKindAndParentId(spans, CLIENT, child.getSpanId());
final SpanData server = getSpanByKindAndParentId(spans, SERVER, client.getSpanId());
getSpanByKindAndParentId(spans, SERVER, client.getSpanId());
}

@Test
Expand All @@ -134,12 +143,14 @@ void spanWithException() {
});
}
List<SpanData> spanItems = spanExporter.getFinishedSpanItems(1);
assertEquals("SpanBean.spanWithException", spanItems.get(0).getName());
assertEquals(INTERNAL, spanItems.get(0).getKind());
assertEquals(ERROR, spanItems.get(0).getStatus().getStatusCode());
assertEquals(1, spanItems.get(0).getEvents().size());
SpanData span = spanItems.get(0);
assertEquals("SpanBean.spanWithException", span.getName());
assertEquals(INTERNAL, span.getKind());
assertEquals(ERROR, span.getStatus().getStatusCode());
assertEquals(1, span.getEvents().size());
assertEquals("spanWithException for tests",
((ExceptionEventData) spanItems.get(0).getEvents().get(0)).getException().getMessage());
((ExceptionEventData) span.getEvents().get(0)).getException().getMessage());
assertClassMethodNames(span, SpanBean.class, "spanWithException");
}

@Test
Expand All @@ -150,6 +161,7 @@ void spanUni() {
final SpanData parent = getSpanByKindAndParentId(spans, INTERNAL, "0000000000000000");
assertEquals("withSpanAndUni", parent.getName());
assertEquals(StatusCode.UNSET, parent.getStatus().getStatusCode());
assertClassMethodNames(parent, SpanBean.class, "spanUni");
}

@Test
Expand All @@ -163,12 +175,14 @@ void spanUniWithException() {
});
}
List<SpanData> spanItems = spanExporter.getFinishedSpanItems(1);
assertEquals("withSpanAndUni", spanItems.get(0).getName());
assertEquals(INTERNAL, spanItems.get(0).getKind());
assertEquals(ERROR, spanItems.get(0).getStatus().getStatusCode());
assertEquals(1, spanItems.get(0).getEvents().size());
SpanData span = spanItems.get(0);
assertEquals("withSpanAndUni", span.getName());
assertEquals(INTERNAL, span.getKind());
assertEquals(ERROR, span.getStatus().getStatusCode());
assertEquals(1, span.getEvents().size());
assertEquals("hello Uni",
((ExceptionEventData) spanItems.get(0).getEvents().get(0)).getException().getMessage());
((ExceptionEventData) span.getEvents().get(0)).getException().getMessage());
assertClassMethodNames(span, SpanBean.class, "spanUniWithException");
}

@Test
Expand All @@ -179,6 +193,7 @@ void spanMulti() {
final SpanData parent = getSpanByKindAndParentId(spans, INTERNAL, "0000000000000000");
assertEquals("withSpanAndMulti", parent.getName());
assertEquals(StatusCode.UNSET, parent.getStatus().getStatusCode());
assertClassMethodNames(parent, SpanBean.class, "spanMulti");
}

@Test
Expand All @@ -198,6 +213,12 @@ void spanMultiWithException() {
assertEquals(1, spanItems.get(0).getEvents().size());
assertEquals("hello Multi",
((ExceptionEventData) spanItems.get(0).getEvents().get(0)).getException().getMessage());
assertClassMethodNames(spanItems.get(0), SpanBean.class, "spanMultiWithException");
}

private void assertClassMethodNames(SpanData span, Class<?> clazz, String method) {
assertEquals(method, span.getAttributes().get((CODE_FUNCTION)));
assertEquals(clazz.getName(), span.getAttributes().get((CODE_NAMESPACE)));
}

@ApplicationScoped
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ void withSpan() {

final SpanData withSpan = getSpanByKindAndParentId(spans, INTERNAL, server.getSpanId());
assertEquals("withSpan", withSpan.getName());
assertEquals(2, withSpan.getAttributes().size());

final SpanData bean = getSpanByKindAndParentId(spans, INTERNAL, withSpan.getSpanId());
assertEquals("HelloBean.hello", bean.getName());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.quarkus.opentelemetry.runtime.tracing.cdi;

import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_FUNCTION;
import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_NAMESPACE;
import static io.quarkus.opentelemetry.runtime.config.build.OTelBuildConfig.INSTRUMENTATION_NAME;

import java.lang.annotation.Annotation;
Expand All @@ -15,6 +17,7 @@
import jakarta.interceptor.Interceptor;

import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.common.AttributesBuilder;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
Expand All @@ -23,6 +26,7 @@
import io.opentelemetry.instrumentation.api.annotation.support.MethodSpanAttributesExtractor;
import io.opentelemetry.instrumentation.api.annotation.support.ParameterAttributeNamesExtractor;
import io.opentelemetry.instrumentation.api.incubator.semconv.util.SpanNames;
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder;
import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor;
Expand Down Expand Up @@ -52,7 +56,8 @@ public WithSpanInterceptor(final OpenTelemetry openTelemetry, final OTelRuntimeC
new WithSpanParameterAttributeNamesExtractor(),
MethodRequest::getArgs);

this.instrumenter = builder.addAttributesExtractor(attributesExtractor)
this.instrumenter = builder.addAttributesExtractor(ClassMethodNameAttributesExtractor.INSTANCE)
.addAttributesExtractor(attributesExtractor)
.buildInstrumenter(new SpanKindExtractor<MethodRequest>() {
@Override
public SpanKind extract(MethodRequest methodRequest) {
Expand Down Expand Up @@ -158,6 +163,26 @@ public void accept(Object o, Throwable throwable) {
}
}

private static final class ClassMethodNameAttributesExtractor implements AttributesExtractor<MethodRequest, Void> {
private static final ClassMethodNameAttributesExtractor INSTANCE = new ClassMethodNameAttributesExtractor();

private ClassMethodNameAttributesExtractor() {
//no-op
}

@Override
public void onStart(AttributesBuilder attributesBuilder, Context context, MethodRequest methodRequest) {
attributesBuilder.put(CODE_NAMESPACE, methodRequest.getMethod().getDeclaringClass().getName());
attributesBuilder.put(CODE_FUNCTION, methodRequest.getMethod().getName());
}

@Override
public void onEnd(AttributesBuilder attributesBuilder, Context context, MethodRequest methodRequest, Void unused,
Throwable throwable) {
// no-op
}
}

private static boolean isUni(Class<?> clazz) {
return Uni.class.isAssignableFrom(clazz);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ io.quarkus.it.rest.client.main.ParamClient/mp-rest/url=${test.url}
quarkus.rest-client.logging.scope=request-response

# speed up build
quarkus.otel.bsp.schedule.delay=100
quarkus.otel.bsp.schedule.delay=10
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
import java.util.stream.Collectors;

import org.awaitility.Awaitility;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import io.opentelemetry.api.trace.SpanId;
Expand All @@ -38,6 +40,13 @@ public class BasicTest {
@TestHTTPResource("/params")
String paramsUrl;

@BeforeEach
@AfterEach
public void clear() {
// Reset captured traces
RestAssured.given().when().get("/export-clear").then().statusCode(200);
}

@Test
public void shouldMakeTextRequest() {
Response response = with().body(helloUrl).post("/call-hello-client");
Expand Down Expand Up @@ -139,9 +148,6 @@ void shouldApplyInterfaceLevelInterceptorBinding() {

@Test
void shouldCreateClientSpans() {
// Reset captured traces
RestAssured.given().when().get("/export-clear").then().statusCode(200);

Response response = with().body(helloUrl).post("/call-hello-client-trace");
assertThat(response.asString()).isEqualTo("Hello, MaryMaryMary");

Expand Down Expand Up @@ -179,7 +185,7 @@ void shouldCreateClientSpans() {
Assertions.assertNotNull(initialServerSpan.get("attr_client.address"));
Assertions.assertNotNull(initialServerSpan.get("attr_user_agent.original"));

Awaitility.await().atMost(Duration.ofSeconds(30))
Awaitility.await().atMost(Duration.ofSeconds(5))
.until(() -> getClientSpansFromFullUrl("POST", "http://localhost:8081/hello?count=3").size() > 0);

spans = getClientSpansFromFullUrl("POST", "http://localhost:8081/hello?count=3");
Expand Down Expand Up @@ -210,10 +216,10 @@ void shouldCreateClientSpans() {

clientSpanId = (String) clientSpan.get("spanId");

Awaitility.await().atMost(Duration.ofSeconds(30))
Awaitility.await().atMost(Duration.ofSeconds(5))
.until(() -> getServerSpansFromPath("POST /hello", "/hello").size() > 0);
spans = getServerSpansFromPath("POST /hello", "/hello");
Assertions.assertEquals(1, spans.size());
Assertions.assertEquals(1, spans.size(), "found: " + spans);

final Map<String, Object> serverSpanClientSide = spans.get(0);
Assertions.assertNotNull(serverSpanClientSide);
Expand Down

0 comments on commit d8941dd

Please sign in to comment.