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

Add class and method to WithSpan attributes #46365

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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