diff --git a/bom/application/pom.xml b/bom/application/pom.xml
index a32f6bc0d3bdc..ef34da4666ce4 100644
--- a/bom/application/pom.xml
+++ b/bom/application/pom.xml
@@ -354,6 +354,13 @@
pom
import
+
+ io.opentelemetry.instrumentation
+ opentelemetry-instrumentation-bom-alpha
+ ${opentelemetry-alpha.version}
+ pom
+ import
+
diff --git a/extensions/opentelemetry/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/OpenTelemetryProcessor.java b/extensions/opentelemetry/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/OpenTelemetryProcessor.java
index 200e236c13cd3..f27f323dee72b 100644
--- a/extensions/opentelemetry/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/OpenTelemetryProcessor.java
+++ b/extensions/opentelemetry/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/OpenTelemetryProcessor.java
@@ -1,10 +1,19 @@
package io.quarkus.opentelemetry.deployment;
+import java.util.List;
import java.util.Optional;
+import java.util.Set;
import java.util.function.BooleanSupplier;
+import org.jboss.jandex.AnnotationTarget;
+import org.jboss.jandex.DotName;
+
+import io.opentelemetry.extension.annotations.WithSpan;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
+import io.quarkus.arc.deployment.AnnotationsTransformerBuildItem;
+import io.quarkus.arc.deployment.InterceptorBindingRegistrarBuildItem;
+import io.quarkus.arc.processor.InterceptorBindingRegistrar;
import io.quarkus.deployment.Feature;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
@@ -19,6 +28,7 @@
import io.quarkus.opentelemetry.runtime.OpenTelemetryProducer;
import io.quarkus.opentelemetry.runtime.OpenTelemetryRecorder;
import io.quarkus.opentelemetry.runtime.QuarkusContextStorage;
+import io.quarkus.opentelemetry.runtime.tracing.cdi.WithSpanInterceptor;
import io.quarkus.runtime.LaunchMode;
import io.quarkus.runtime.RuntimeValue;
import io.quarkus.vertx.core.deployment.CoreVertxBuildItem;
@@ -56,6 +66,36 @@ void registerOpenTelemetryContextStorage(
.produce(new ReflectiveClassBuildItem(true, true, QuarkusContextStorage.class));
}
+ @BuildStep(onlyIf = OpenTelemetryEnabled.class)
+ void registerWithSpan(
+ BuildProducer interceptorBindingRegistrar,
+ BuildProducer additionalBeans) {
+
+ interceptorBindingRegistrar.produce(new InterceptorBindingRegistrarBuildItem(
+ new InterceptorBindingRegistrar() {
+ @Override
+ public List getAdditionalBindings() {
+ return List.of(InterceptorBinding.of(WithSpan.class, Set.of("value", "kind")));
+ }
+ }));
+
+ additionalBeans.produce(new AdditionalBeanBuildItem(WithSpanInterceptor.class));
+ }
+
+ @BuildStep(onlyIf = OpenTelemetryEnabled.class)
+ void transformWithSpan(
+ BuildProducer annotationsTransformer) {
+
+ annotationsTransformer.produce(new AnnotationsTransformerBuildItem(transformationContext -> {
+ AnnotationTarget target = transformationContext.getTarget();
+ if (target.kind().equals(AnnotationTarget.Kind.CLASS)) {
+ if (target.asClass().name().equals(DotName.createSimple(WithSpanInterceptor.class.getName()))) {
+ transformationContext.transform().add(DotName.createSimple(WithSpan.class.getName())).done();
+ }
+ }
+ }));
+ }
+
@BuildStep(onlyIf = OpenTelemetryEnabled.class)
@Record(ExecutionTime.STATIC_INIT)
void createOpenTelemetry(OpenTelemetryConfig openTelemetryConfig,
diff --git a/extensions/opentelemetry/opentelemetry/deployment/src/test/java/io/quarkus/opentelemetry/deployment/OpenTelemetryHttpCDITest.java b/extensions/opentelemetry/opentelemetry/deployment/src/test/java/io/quarkus/opentelemetry/deployment/OpenTelemetryHttpCDITest.java
new file mode 100644
index 0000000000000..f137f0eeca416
--- /dev/null
+++ b/extensions/opentelemetry/opentelemetry/deployment/src/test/java/io/quarkus/opentelemetry/deployment/OpenTelemetryHttpCDITest.java
@@ -0,0 +1,71 @@
+package io.quarkus.opentelemetry.deployment;
+
+import static io.opentelemetry.api.trace.SpanKind.INTERNAL;
+import static io.opentelemetry.api.trace.SpanKind.SERVER;
+import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.List;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import io.opentelemetry.extension.annotations.WithSpan;
+import io.opentelemetry.sdk.trace.data.SpanData;
+import io.quarkus.test.QuarkusUnitTest;
+import io.restassured.RestAssured;
+
+public class OpenTelemetryHttpCDITest {
+ @RegisterExtension
+ static final QuarkusUnitTest TEST = new QuarkusUnitTest()
+ .setArchiveProducer(
+ () -> ShrinkWrap.create(JavaArchive.class)
+ .addClass(HelloResource.class)
+ .addClass(HelloBean.class)
+ .addClass(TestSpanExporter.class));
+
+ @Inject
+ TestSpanExporter spanExporter;
+
+ @Test
+ void telemetry() {
+ RestAssured.when()
+ .get("/hello").then()
+ .statusCode(200)
+ .body(is("hello"));
+
+ List spanItems = spanExporter.getFinishedSpanItems();
+ assertEquals(2, spanItems.size());
+ assertEquals("HelloBean.hello", spanItems.get(0).getName());
+ assertEquals(INTERNAL, spanItems.get(0).getKind());
+ assertEquals("hello", spanItems.get(1).getName());
+ assertEquals(SERVER, spanItems.get(1).getKind());
+ assertEquals(spanItems.get(0).getParentSpanId(), spanItems.get(1).getSpanId());
+ }
+
+ @Path("/hello")
+ public static class HelloResource {
+ @Inject
+ HelloBean helloBean;
+
+ @GET
+ public String hello() {
+ return helloBean.hello();
+ }
+ }
+
+ @ApplicationScoped
+ public static class HelloBean {
+ @WithSpan
+ public String hello() {
+ return "hello";
+ }
+ }
+}
diff --git a/extensions/opentelemetry/opentelemetry/deployment/src/test/java/io/quarkus/opentelemetry/deployment/WithSpanInterceptorTest.java b/extensions/opentelemetry/opentelemetry/deployment/src/test/java/io/quarkus/opentelemetry/deployment/WithSpanInterceptorTest.java
new file mode 100644
index 0000000000000..71eb337321e69
--- /dev/null
+++ b/extensions/opentelemetry/opentelemetry/deployment/src/test/java/io/quarkus/opentelemetry/deployment/WithSpanInterceptorTest.java
@@ -0,0 +1,126 @@
+package io.quarkus.opentelemetry.deployment;
+
+import static io.opentelemetry.api.trace.SpanKind.INTERNAL;
+import static io.opentelemetry.api.trace.SpanKind.SERVER;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.List;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import io.opentelemetry.api.common.AttributeKey;
+import io.opentelemetry.extension.annotations.SpanAttribute;
+import io.opentelemetry.extension.annotations.WithSpan;
+import io.opentelemetry.sdk.trace.data.SpanData;
+import io.quarkus.test.QuarkusUnitTest;
+
+public class WithSpanInterceptorTest {
+ @RegisterExtension
+ static final QuarkusUnitTest TEST = new QuarkusUnitTest()
+ .setArchiveProducer(
+ () -> ShrinkWrap.create(JavaArchive.class).addClass(SpanBean.class).addClass(TestSpanExporter.class));
+
+ @Inject
+ SpanBean spanBean;
+ @Inject
+ TestSpanExporter spanExporter;
+
+ @AfterEach
+ void tearDown() {
+ spanExporter.reset();
+ }
+
+ @Test
+ void span() {
+ spanBean.span();
+ List spanItems = spanExporter.getFinishedSpanItems();
+ assertEquals(1, spanItems.size());
+ assertEquals("SpanBean.span", spanItems.get(0).getName());
+ assertEquals(INTERNAL, spanItems.get(0).getKind());
+ }
+
+ @Test
+ void spanName() {
+ spanBean.spanName();
+ List spanItems = spanExporter.getFinishedSpanItems();
+ assertEquals(1, spanItems.size());
+ assertEquals("name", spanItems.get(0).getName());
+ assertEquals(INTERNAL, spanItems.get(0).getKind());
+ }
+
+ @Test
+ void spanKind() {
+ spanBean.spanKind();
+ List spanItems = spanExporter.getFinishedSpanItems();
+ assertEquals(1, spanItems.size());
+ assertEquals("SpanBean.spanKind", spanItems.get(0).getName());
+ assertEquals(SERVER, spanItems.get(0).getKind());
+ }
+
+ @Test
+ void spanArgs() {
+ spanBean.spanArgs("argument");
+ List spanItems = spanExporter.getFinishedSpanItems();
+ assertEquals(1, spanItems.size());
+ assertEquals("SpanBean.spanArgs", spanItems.get(0).getName());
+ assertEquals(INTERNAL, spanItems.get(0).getKind());
+ assertEquals("argument", spanItems.get(0).getAttributes().get(AttributeKey.stringKey("arg")));
+ }
+
+ @Test
+ void spanChild() {
+ spanBean.spanChild();
+ List spanItems = spanExporter.getFinishedSpanItems();
+ assertEquals(2, spanItems.size());
+
+ assertEquals("SpanChildBean.spanChild", spanItems.get(0).getName());
+ assertEquals("SpanBean.spanChild", spanItems.get(1).getName());
+ assertEquals(spanItems.get(0).getParentSpanId(), spanItems.get(1).getSpanId());
+ }
+
+ @ApplicationScoped
+ public static class SpanBean {
+ @WithSpan
+ public void span() {
+
+ }
+
+ @WithSpan("name")
+ public void spanName() {
+
+ }
+
+ @WithSpan(kind = SERVER)
+ public void spanKind() {
+
+ }
+
+ @WithSpan
+ public void spanArgs(@SpanAttribute(value = "arg") String arg) {
+
+ }
+
+ @Inject
+ SpanChildBean spanChildBean;
+
+ @WithSpan
+ public void spanChild() {
+ spanChildBean.spanChild();
+ }
+ }
+
+ @ApplicationScoped
+ public static class SpanChildBean {
+ @WithSpan
+ public void spanChild() {
+
+ }
+ }
+}
diff --git a/extensions/opentelemetry/opentelemetry/runtime/pom.xml b/extensions/opentelemetry/opentelemetry/runtime/pom.xml
index bb64d869fac0a..1271ff1e96fc2 100644
--- a/extensions/opentelemetry/opentelemetry/runtime/pom.xml
+++ b/extensions/opentelemetry/opentelemetry/runtime/pom.xml
@@ -44,6 +44,18 @@
io.opentelemetry
opentelemetry-sdk
+
+ io.opentelemetry
+ opentelemetry-extension-annotations
+
+
+ io.opentelemetry.instrumentation
+ opentelemetry-instrumentation-api
+
+
+ io.opentelemetry.instrumentation
+ opentelemetry-instrumentation-api-annotation-support
+
io.opentelemetry
opentelemetry-sdk-extension-autoconfigure-spi
diff --git a/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/OpenTelemetryConfig.java b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/OpenTelemetryConfig.java
index ec1ad00138284..e3663dd349240 100644
--- a/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/OpenTelemetryConfig.java
+++ b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/OpenTelemetryConfig.java
@@ -8,6 +8,7 @@
@ConfigRoot(name = "opentelemetry")
public final class OpenTelemetryConfig {
+ public static final String INSTRUMENTATION_NAME = "io.quarkus.opentelemetry";
/**
* OpenTelemetry support.
diff --git a/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/TracerProducer.java b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/TracerProducer.java
index 4b4d0c85d9921..bfc5449f04909 100644
--- a/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/TracerProducer.java
+++ b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/TracerProducer.java
@@ -1,5 +1,7 @@
package io.quarkus.opentelemetry.runtime.tracing;
+import static io.quarkus.opentelemetry.runtime.OpenTelemetryConfig.INSTRUMENTATION_NAME;
+
import javax.enterprise.inject.Produces;
import javax.inject.Singleton;
@@ -25,6 +27,6 @@ public LateBoundSampler getLateBoundSampler() {
@Singleton
@DefaultBean
public Tracer getTracer() {
- return GlobalOpenTelemetry.getTracer("io.quarkus.opentelemetry");
+ return GlobalOpenTelemetry.getTracer(INSTRUMENTATION_NAME);
}
}
diff --git a/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/cdi/MethodRequest.java b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/cdi/MethodRequest.java
new file mode 100644
index 0000000000000..6a65fd1abac2f
--- /dev/null
+++ b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/cdi/MethodRequest.java
@@ -0,0 +1,21 @@
+package io.quarkus.opentelemetry.runtime.tracing.cdi;
+
+import java.lang.reflect.Method;
+
+final class MethodRequest {
+ private final Method method;
+ private final Object[] args;
+
+ public MethodRequest(final Method method, final Object[] args) {
+ this.method = method;
+ this.args = args;
+ }
+
+ public Method getMethod() {
+ return method;
+ }
+
+ public Object[] getArgs() {
+ return args;
+ }
+}
diff --git a/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/cdi/WithSpanInterceptor.java b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/cdi/WithSpanInterceptor.java
new file mode 100644
index 0000000000000..513a197935774
--- /dev/null
+++ b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/cdi/WithSpanInterceptor.java
@@ -0,0 +1,159 @@
+package io.quarkus.opentelemetry.runtime.tracing.cdi;
+
+import static io.quarkus.opentelemetry.runtime.OpenTelemetryConfig.INSTRUMENTATION_NAME;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
+
+import javax.annotation.Priority;
+import javax.interceptor.AroundInvoke;
+import javax.interceptor.Interceptor;
+import javax.interceptor.InvocationContext;
+
+import io.opentelemetry.api.OpenTelemetry;
+import io.opentelemetry.api.trace.SpanKind;
+import io.opentelemetry.api.trace.Tracer;
+import io.opentelemetry.api.trace.TracerBuilder;
+import io.opentelemetry.api.trace.TracerProvider;
+import io.opentelemetry.context.Context;
+import io.opentelemetry.context.Scope;
+import io.opentelemetry.context.propagation.ContextPropagators;
+import io.opentelemetry.extension.annotations.SpanAttribute;
+import io.opentelemetry.extension.annotations.WithSpan;
+import io.opentelemetry.instrumentation.api.annotation.support.MethodSpanAttributesExtractor;
+import io.opentelemetry.instrumentation.api.annotation.support.ParameterAttributeNamesExtractor;
+import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
+import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder;
+import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor;
+import io.opentelemetry.instrumentation.api.tracer.SpanNames;
+
+@SuppressWarnings("CdiInterceptorInspection")
+@Interceptor
+@Priority(Interceptor.Priority.PLATFORM_BEFORE)
+public class WithSpanInterceptor {
+ private final Instrumenter instrumenter;
+
+ public WithSpanInterceptor(final OpenTelemetry openTelemetry) {
+ InstrumenterBuilder builder = Instrumenter.newBuilder(new OpenTelemetryInstrumenter(openTelemetry),
+ INSTRUMENTATION_NAME,
+ new MethodRequestSpanNameExtractor());
+
+ MethodSpanAttributesExtractor attributesExtractor = MethodSpanAttributesExtractor.newInstance(
+ MethodRequest::getMethod,
+ new WithSpanParameterAttributeNamesExtractor(),
+ MethodRequest::getArgs);
+
+ this.instrumenter = builder.addAttributesExtractor(attributesExtractor)
+ .newInstrumenter(methodRequest -> spanKindFromMethod(methodRequest.getMethod()));
+ }
+
+ @AroundInvoke
+ public Object span(final InvocationContext invocationContext) throws Exception {
+ MethodRequest methodRequest = new MethodRequest(invocationContext.getMethod(), invocationContext.getParameters());
+
+ Context parentContext = Context.current();
+ Context spanContext = null;
+ Scope scope = null;
+ boolean shouldStart = instrumenter.shouldStart(parentContext, methodRequest);
+ if (shouldStart) {
+ spanContext = instrumenter.start(parentContext, methodRequest);
+ scope = spanContext.makeCurrent();
+ }
+
+ try {
+ Object result = invocationContext.proceed();
+
+ if (shouldStart) {
+ instrumenter.end(spanContext, methodRequest, null, null);
+ }
+
+ return result;
+ } finally {
+ if (scope != null) {
+ scope.close();
+ }
+ }
+ }
+
+ private static SpanKind spanKindFromMethod(Method method) {
+ WithSpan annotation = method.getDeclaredAnnotation(WithSpan.class);
+ if (annotation == null) {
+ return SpanKind.INTERNAL;
+ }
+ return annotation.kind();
+ }
+
+ // To ignore the version and find our Tracer, because the version is hardcoded in the Instrumenter constructor.
+ private static final class OpenTelemetryInstrumenter implements OpenTelemetry {
+ private final OpenTelemetry openTelemetry;
+
+ public OpenTelemetryInstrumenter(final OpenTelemetry openTelemetry) {
+ this.openTelemetry = openTelemetry;
+ }
+
+ @Override
+ public TracerProvider getTracerProvider() {
+ return openTelemetry.getTracerProvider();
+ }
+
+ @Override
+ public Tracer getTracer(final String instrumentationName) {
+ return openTelemetry.getTracer(instrumentationName);
+ }
+
+ @Override
+ public Tracer getTracer(
+ final String instrumentationName,
+ final String instrumentationVersion) {
+ return openTelemetry.getTracer(instrumentationName);
+ }
+
+ @Override
+ public TracerBuilder tracerBuilder(final String instrumentationName) {
+ return openTelemetry.tracerBuilder(instrumentationName);
+ }
+
+ @Override
+ public ContextPropagators getPropagators() {
+ return openTelemetry.getPropagators();
+ }
+ }
+
+ private static final class MethodRequestSpanNameExtractor implements SpanNameExtractor {
+ @Override
+ public String extract(final MethodRequest methodRequest) {
+ WithSpan annotation = methodRequest.getMethod().getDeclaredAnnotation(WithSpan.class);
+ String spanName = annotation.value();
+ if (spanName.isEmpty()) {
+ spanName = SpanNames.fromMethod(methodRequest.getMethod());
+ }
+ return spanName;
+ }
+ }
+
+ private static final class WithSpanParameterAttributeNamesExtractor implements ParameterAttributeNamesExtractor {
+ @Override
+ public String[] extract(final Method method, final Parameter[] parameters) {
+ String[] attributeNames = new String[parameters.length];
+ for (int i = 0; i < parameters.length; i++) {
+ attributeNames[i] = attributeName(parameters[i]);
+ }
+ return attributeNames;
+ }
+
+ private static String attributeName(Parameter parameter) {
+ SpanAttribute spanAttribute = parameter.getDeclaredAnnotation(SpanAttribute.class);
+ if (spanAttribute == null) {
+ return null;
+ }
+ String value = spanAttribute.value();
+ if (!value.isEmpty()) {
+ return value;
+ } else if (parameter.isNamePresent()) {
+ return parameter.getName();
+ } else {
+ return null;
+ }
+ }
+ }
+}
diff --git a/integration-tests/opentelemetry/src/main/java/io/quarkus/it/opentelemetry/TracedService.java b/integration-tests/opentelemetry/src/main/java/io/quarkus/it/opentelemetry/TracedService.java
index 4d938e5b97d2a..a901d4ef4f89f 100644
--- a/integration-tests/opentelemetry/src/main/java/io/quarkus/it/opentelemetry/TracedService.java
+++ b/integration-tests/opentelemetry/src/main/java/io/quarkus/it/opentelemetry/TracedService.java
@@ -2,8 +2,11 @@
import javax.enterprise.context.ApplicationScoped;
+import io.opentelemetry.extension.annotations.WithSpan;
+
@ApplicationScoped
public class TracedService {
+ @WithSpan
public String call() {
return "Chained trace";
}
diff --git a/integration-tests/opentelemetry/src/test/java/io/quarkus/it/opentelemetry/OpenTelemetryTestCase.java b/integration-tests/opentelemetry/src/test/java/io/quarkus/it/opentelemetry/OpenTelemetryTestCase.java
index 9d203cf3c13f3..96c17d9c9a904 100644
--- a/integration-tests/opentelemetry/src/test/java/io/quarkus/it/opentelemetry/OpenTelemetryTestCase.java
+++ b/integration-tests/opentelemetry/src/test/java/io/quarkus/it/opentelemetry/OpenTelemetryTestCase.java
@@ -328,8 +328,8 @@ void testChainedResourceTracing() {
.statusCode(200)
.body("message", equalTo("Chained trace"));
- Awaitility.await().atMost(Duration.ofMinutes(2)).until(() -> getSpans().size() == 1);
- Map spanData = getSpans().get(0);
+ Awaitility.await().atMost(Duration.ofMinutes(2)).until(() -> getSpans().size() == 2);
+ Map spanData = getSpans().get(1);
Assertions.assertNotNull(spanData);
Assertions.assertNotNull(spanData.get("spanId"));
@@ -353,7 +353,11 @@ void testChainedResourceTracing() {
Assertions.assertNotNull(spanData.get("attr_http.client_ip"));
Assertions.assertNotNull(spanData.get("attr_http.user_agent"));
- //TODO Update this when we support internal methods being traced
+ // CDI call
+ spanData = getSpans().get(0);
+ Assertions.assertEquals("TracedService.call", spanData.get("name"));
+ Assertions.assertEquals(SpanKind.INTERNAL.toString(), spanData.get("kind"));
+ Assertions.assertEquals(getSpans().get(1).get("spanId"), spanData.get("parent_spanId"));
}
@Test