|
@@ -0,0 +1,327 @@
|
|
|
|
+/*
|
|
|
|
+ * Copyright The OpenTelemetry Authors
|
|
|
|
+ * SPDX-License-Identifier: Apache-2.0
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+package io.opentelemetry.opencensusshim;
|
|
|
|
+
|
|
|
|
+import io.opencensus.trace.AttributeValue;
|
|
|
|
+import io.opencensus.trace.Tracing;
|
|
|
|
+import io.opencensus.trace.samplers.Samplers;
|
|
|
|
+import io.opentelemetry.api.common.AttributeKey;
|
|
|
|
+import io.opentelemetry.api.trace.Span;
|
|
|
|
+import io.opentelemetry.api.trace.SpanKind;
|
|
|
|
+import io.opentelemetry.api.trace.Tracer;
|
|
|
|
+import io.opentelemetry.context.Scope;
|
|
|
|
+import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
|
|
|
|
+import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
|
|
|
|
+import io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions;
|
|
|
|
+import org.assertj.core.api.AbstractBooleanAssert;
|
|
|
|
+import org.junit.jupiter.api.BeforeEach;
|
|
|
|
+import org.junit.jupiter.api.Test;
|
|
|
|
+import org.junit.jupiter.api.extension.RegisterExtension;
|
|
|
|
+
|
|
|
|
+public class JavaagentInstrumentationTest {
|
|
|
|
+
|
|
|
|
+ @RegisterExtension
|
|
|
|
+ static final InstrumentationExtension testing = AgentInstrumentationExtension.create();
|
|
|
|
+
|
|
|
|
+ @BeforeEach
|
|
|
|
+ void setup() {
|
|
|
|
+ // by default in opencensus, a probability sampling is used which is not 100%;
|
|
|
|
+ // we specifically set this configuration here to always sample to ensure traces are emitted for
|
|
|
|
+ // our tests
|
|
|
|
+ Tracing.getTraceConfig()
|
|
|
|
+ .updateActiveTraceParams(
|
|
|
|
+ Tracing.getTraceConfig().getActiveTraceParams().toBuilder()
|
|
|
|
+ .setSampler(Samplers.alwaysSample())
|
|
|
|
+ .build());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Test
|
|
|
|
+ void testInterleavedSpansOcFirst() {
|
|
|
|
+ io.opencensus.trace.Tracer ocTracer = Tracing.getTracer();
|
|
|
|
+ Tracer otelTracer = testing.getOpenTelemetry().getTracer("test");
|
|
|
|
+
|
|
|
|
+ io.opencensus.trace.Span outerSpan = ocTracer.spanBuilder("outer-span").startSpan();
|
|
|
|
+ Span midSpan;
|
|
|
|
+ io.opencensus.trace.Span innerSpan;
|
|
|
|
+
|
|
|
|
+ outerSpan.putAttribute("outer", AttributeValue.booleanAttributeValue(true));
|
|
|
|
+
|
|
|
|
+ try (io.opencensus.common.Scope outerScope = ocTracer.withSpan(outerSpan)) {
|
|
|
|
+ midSpan =
|
|
|
|
+ otelTracer
|
|
|
|
+ .spanBuilder("mid-span")
|
|
|
|
+ .setSpanKind(SpanKind.INTERNAL)
|
|
|
|
+ .setAttribute("middle", true)
|
|
|
|
+ .startSpan();
|
|
|
|
+ try (Scope midScope = midSpan.makeCurrent()) {
|
|
|
|
+ innerSpan = ocTracer.spanBuilder("inner-span").startSpan();
|
|
|
|
+ innerSpan.putAttribute("inner", AttributeValue.booleanAttributeValue(true));
|
|
|
|
+
|
|
|
|
+ // make current and immediately close -- avoid empty try block
|
|
|
|
+ ocTracer.withSpan(innerSpan).close();
|
|
|
|
+
|
|
|
|
+ innerSpan.end();
|
|
|
|
+ } finally {
|
|
|
|
+ midSpan.end();
|
|
|
|
+ }
|
|
|
|
+ } finally {
|
|
|
|
+ outerSpan.end();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Tracing.getExportComponent().shutdown();
|
|
|
|
+
|
|
|
|
+ // expecting 1 trace with 3 spans
|
|
|
|
+ testing.waitAndAssertTraces(
|
|
|
|
+ ta ->
|
|
|
|
+ // ensure each span's attributes haven't seeped into parents or children
|
|
|
|
+ ta.hasSpansSatisfyingExactly(
|
|
|
|
+ // outer span
|
|
|
|
+ sa ->
|
|
|
|
+ sa.hasName("outer-span")
|
|
|
|
+ .hasNoParent()
|
|
|
|
+ .hasAttribute(AttributeKey.booleanKey("outer"), true)
|
|
|
|
+ .hasAttributesSatisfying(
|
|
|
|
+ OpenTelemetryAssertions.satisfies(
|
|
|
|
+ AttributeKey.booleanKey("inner"), AbstractBooleanAssert::isNull),
|
|
|
|
+ OpenTelemetryAssertions.satisfies(
|
|
|
|
+ AttributeKey.booleanKey("middle"), AbstractBooleanAssert::isNull)),
|
|
|
|
+ // middle span
|
|
|
|
+ sa ->
|
|
|
|
+ sa.hasName("mid-span")
|
|
|
|
+ .hasParent(ta.getSpan(0))
|
|
|
|
+ .hasAttribute(AttributeKey.booleanKey("middle"), true)
|
|
|
|
+ .hasAttributesSatisfying(
|
|
|
|
+ OpenTelemetryAssertions.satisfies(
|
|
|
|
+ AttributeKey.booleanKey("inner"), AbstractBooleanAssert::isNull),
|
|
|
|
+ OpenTelemetryAssertions.satisfies(
|
|
|
|
+ AttributeKey.booleanKey("outer"), AbstractBooleanAssert::isNull)),
|
|
|
|
+ // inner span
|
|
|
|
+ sa ->
|
|
|
|
+ sa.hasName("inner-span")
|
|
|
|
+ .hasParent(ta.getSpan(1))
|
|
|
|
+ .hasAttribute(AttributeKey.booleanKey("inner"), true)
|
|
|
|
+ .hasAttributesSatisfying(
|
|
|
|
+ OpenTelemetryAssertions.satisfies(
|
|
|
|
+ AttributeKey.booleanKey("middle"), AbstractBooleanAssert::isNull),
|
|
|
|
+ OpenTelemetryAssertions.satisfies(
|
|
|
|
+ AttributeKey.booleanKey("outer"), AbstractBooleanAssert::isNull))));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Test
|
|
|
|
+ void testInterleavedSpansOtelFirst() {
|
|
|
|
+ io.opencensus.trace.Tracer ocTracer = Tracing.getTracer();
|
|
|
|
+ Tracer otelTracer = testing.getOpenTelemetry().getTracer("test");
|
|
|
|
+
|
|
|
|
+ Span outerSpan =
|
|
|
|
+ otelTracer
|
|
|
|
+ .spanBuilder("outer-span")
|
|
|
|
+ .setSpanKind(SpanKind.INTERNAL)
|
|
|
|
+ .setAttribute("outer", true)
|
|
|
|
+ .startSpan();
|
|
|
|
+ io.opencensus.trace.Span midSpan;
|
|
|
|
+ Span innerSpan;
|
|
|
|
+
|
|
|
|
+ try (Scope outerScope = outerSpan.makeCurrent()) {
|
|
|
|
+ midSpan = ocTracer.spanBuilder("mid-span").startSpan();
|
|
|
|
+ midSpan.putAttribute("middle", AttributeValue.booleanAttributeValue(true));
|
|
|
|
+ try (io.opencensus.common.Scope midScope = ocTracer.withSpan(midSpan)) {
|
|
|
|
+ innerSpan =
|
|
|
|
+ otelTracer
|
|
|
|
+ .spanBuilder("inner-span")
|
|
|
|
+ .setSpanKind(SpanKind.INTERNAL)
|
|
|
|
+ .setAttribute("inner", true)
|
|
|
|
+ .startSpan();
|
|
|
|
+
|
|
|
|
+ // make current and immediately close -- avoid empty try block
|
|
|
|
+ innerSpan.makeCurrent().close();
|
|
|
|
+
|
|
|
|
+ innerSpan.end();
|
|
|
|
+ } finally {
|
|
|
|
+ midSpan.end();
|
|
|
|
+ }
|
|
|
|
+ } finally {
|
|
|
|
+ outerSpan.end();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Tracing.getExportComponent().shutdown();
|
|
|
|
+
|
|
|
|
+ // expecting 1 trace with 3 spans
|
|
|
|
+ testing.waitAndAssertTraces(
|
|
|
|
+ ta ->
|
|
|
|
+ // ensure each span's attributes haven't seeped into parents or children
|
|
|
|
+ ta.hasSpansSatisfyingExactly(
|
|
|
|
+ // outer span
|
|
|
|
+ sa ->
|
|
|
|
+ sa.hasName("outer-span")
|
|
|
|
+ .hasNoParent()
|
|
|
|
+ .hasAttribute(AttributeKey.booleanKey("outer"), true)
|
|
|
|
+ .hasAttributesSatisfying(
|
|
|
|
+ OpenTelemetryAssertions.satisfies(
|
|
|
|
+ AttributeKey.booleanKey("inner"), AbstractBooleanAssert::isNull),
|
|
|
|
+ OpenTelemetryAssertions.satisfies(
|
|
|
|
+ AttributeKey.booleanKey("middle"), AbstractBooleanAssert::isNull)),
|
|
|
|
+ // middle span
|
|
|
|
+ sa ->
|
|
|
|
+ sa.hasName("mid-span")
|
|
|
|
+ .hasParent(ta.getSpan(0))
|
|
|
|
+ .hasAttribute(AttributeKey.booleanKey("middle"), true)
|
|
|
|
+ .hasAttributesSatisfying(
|
|
|
|
+ OpenTelemetryAssertions.satisfies(
|
|
|
|
+ AttributeKey.booleanKey("inner"), AbstractBooleanAssert::isNull),
|
|
|
|
+ OpenTelemetryAssertions.satisfies(
|
|
|
|
+ AttributeKey.booleanKey("outer"), AbstractBooleanAssert::isNull)),
|
|
|
|
+ // inner span
|
|
|
|
+ sa ->
|
|
|
|
+ sa.hasName("inner-span")
|
|
|
|
+ .hasParent(ta.getSpan(1))
|
|
|
|
+ .hasAttribute(AttributeKey.booleanKey("inner"), true)
|
|
|
|
+ .hasAttributesSatisfying(
|
|
|
|
+ OpenTelemetryAssertions.satisfies(
|
|
|
|
+ AttributeKey.booleanKey("middle"), AbstractBooleanAssert::isNull),
|
|
|
|
+ OpenTelemetryAssertions.satisfies(
|
|
|
|
+ AttributeKey.booleanKey("outer"), AbstractBooleanAssert::isNull))));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Test
|
|
|
|
+ void testStartingWithOtelSpan() {
|
|
|
|
+ io.opencensus.trace.Tracer ocTracer = Tracing.getTracer();
|
|
|
|
+ Tracer otelTracer = testing.getOpenTelemetry().getTracer("test");
|
|
|
|
+
|
|
|
|
+ Span otelSpan =
|
|
|
|
+ otelTracer
|
|
|
|
+ .spanBuilder("otel-span")
|
|
|
|
+ .setSpanKind(SpanKind.INTERNAL)
|
|
|
|
+ .setAttribute("present-on-otel", true)
|
|
|
|
+ .startSpan();
|
|
|
|
+
|
|
|
|
+ io.opencensus.trace.Span ocSpan;
|
|
|
|
+ try (Scope scope = otelSpan.makeCurrent()) {
|
|
|
|
+ ocSpan = ocTracer.spanBuilder("oc-span").startSpan();
|
|
|
|
+ try (io.opencensus.common.Scope ocScope = ocTracer.withSpan(ocSpan)) {
|
|
|
|
+ ocTracer
|
|
|
|
+ .getCurrentSpan()
|
|
|
|
+ .putAttribute("present-on-oc", AttributeValue.booleanAttributeValue(true));
|
|
|
|
+ }
|
|
|
|
+ ocSpan.end();
|
|
|
|
+ }
|
|
|
|
+ otelSpan.end();
|
|
|
|
+
|
|
|
|
+ Tracing.getExportComponent().shutdown();
|
|
|
|
+
|
|
|
|
+ testing.waitAndAssertTraces(
|
|
|
|
+ trace ->
|
|
|
|
+ trace.hasSpansSatisfyingExactly(
|
|
|
|
+ span ->
|
|
|
|
+ span.hasName("otel-span")
|
|
|
|
+ .hasNoParent()
|
|
|
|
+ .hasAttribute(AttributeKey.booleanKey("present-on-otel"), true),
|
|
|
|
+ span ->
|
|
|
|
+ span.hasName("oc-span")
|
|
|
|
+ .hasParent(trace.getSpan(0))
|
|
|
|
+ .hasAttribute(AttributeKey.booleanKey("present-on-oc"), true)));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Test
|
|
|
|
+ void testStartingWithOpenCensusSpan() {
|
|
|
|
+ io.opencensus.trace.Tracer ocTracer = Tracing.getTracer();
|
|
|
|
+ Tracer otelTracer = testing.getOpenTelemetry().getTracer("test");
|
|
|
|
+
|
|
|
|
+ io.opencensus.trace.Span ocSpan = ocTracer.spanBuilder("oc-span").startSpan();
|
|
|
|
+
|
|
|
|
+ ocSpan.putAttribute("present-on-oc", AttributeValue.booleanAttributeValue(true));
|
|
|
|
+
|
|
|
|
+ Span otelSpan;
|
|
|
|
+ try (io.opencensus.common.Scope ocScope = ocTracer.withSpan(ocSpan)) {
|
|
|
|
+ otelSpan = otelTracer.spanBuilder("otel-span").setSpanKind(SpanKind.INTERNAL).startSpan();
|
|
|
|
+ try (Scope scope = otelSpan.makeCurrent()) {
|
|
|
|
+ Span.current().setAttribute("present-on-otel", true);
|
|
|
|
+ }
|
|
|
|
+ otelSpan.end();
|
|
|
|
+ }
|
|
|
|
+ ocSpan.end();
|
|
|
|
+
|
|
|
|
+ Tracing.getExportComponent().shutdown();
|
|
|
|
+
|
|
|
|
+ testing.waitAndAssertTraces(
|
|
|
|
+ trace ->
|
|
|
|
+ trace.hasSpansSatisfyingExactly(
|
|
|
|
+ span ->
|
|
|
|
+ span.hasName("oc-span")
|
|
|
|
+ .hasNoParent()
|
|
|
|
+ .hasAttribute(AttributeKey.booleanKey("present-on-oc"), true),
|
|
|
|
+ span ->
|
|
|
|
+ span.hasName("otel-span")
|
|
|
|
+ .hasParent(trace.getSpan(0))
|
|
|
|
+ .hasAttribute(AttributeKey.booleanKey("present-on-otel"), true)));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Test
|
|
|
|
+ void testNestedOpenCensusSpans() {
|
|
|
|
+ io.opencensus.trace.Tracer ocTracer = Tracing.getTracer();
|
|
|
|
+
|
|
|
|
+ io.opencensus.trace.Span outerSpan = ocTracer.spanBuilder("outer-span").startSpan();
|
|
|
|
+ io.opencensus.trace.Span midSpan;
|
|
|
|
+ io.opencensus.trace.Span innerSpan;
|
|
|
|
+
|
|
|
|
+ outerSpan.putAttribute("outer", AttributeValue.booleanAttributeValue(true));
|
|
|
|
+
|
|
|
|
+ try (io.opencensus.common.Scope outerScope = ocTracer.withSpan(outerSpan)) {
|
|
|
|
+ midSpan = ocTracer.spanBuilder("mid-span").startSpan();
|
|
|
|
+ midSpan.putAttribute("middle", AttributeValue.booleanAttributeValue(true));
|
|
|
|
+ try (io.opencensus.common.Scope midScope = ocTracer.withSpan(midSpan)) {
|
|
|
|
+ innerSpan = ocTracer.spanBuilder("inner-span").startSpan();
|
|
|
|
+ innerSpan.putAttribute("inner", AttributeValue.booleanAttributeValue(true));
|
|
|
|
+
|
|
|
|
+ // make current and immediately close -- avoid empty try block
|
|
|
|
+ ocTracer.withSpan(innerSpan).close();
|
|
|
|
+
|
|
|
|
+ innerSpan.end();
|
|
|
|
+ } finally {
|
|
|
|
+ midSpan.end();
|
|
|
|
+ }
|
|
|
|
+ } finally {
|
|
|
|
+ outerSpan.end();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Tracing.getExportComponent().shutdown();
|
|
|
|
+
|
|
|
|
+ // expecting 1 trace with 3 spans
|
|
|
|
+ testing.waitAndAssertTraces(
|
|
|
|
+ ta ->
|
|
|
|
+ // ensure each span's attributes haven't seeped into parents or children
|
|
|
|
+ ta.hasSpansSatisfyingExactly(
|
|
|
|
+ // outer span
|
|
|
|
+ sa ->
|
|
|
|
+ sa.hasName("outer-span")
|
|
|
|
+ .hasNoParent()
|
|
|
|
+ .hasAttribute(AttributeKey.booleanKey("outer"), true)
|
|
|
|
+ .hasAttributesSatisfying(
|
|
|
|
+ OpenTelemetryAssertions.satisfies(
|
|
|
|
+ AttributeKey.booleanKey("inner"), AbstractBooleanAssert::isNull),
|
|
|
|
+ OpenTelemetryAssertions.satisfies(
|
|
|
|
+ AttributeKey.booleanKey("middle"), AbstractBooleanAssert::isNull)),
|
|
|
|
+ // middle span
|
|
|
|
+ sa ->
|
|
|
|
+ sa.hasName("mid-span")
|
|
|
|
+ .hasParent(ta.getSpan(0))
|
|
|
|
+ .hasAttribute(AttributeKey.booleanKey("middle"), true)
|
|
|
|
+ .hasAttributesSatisfying(
|
|
|
|
+ OpenTelemetryAssertions.satisfies(
|
|
|
|
+ AttributeKey.booleanKey("inner"), AbstractBooleanAssert::isNull),
|
|
|
|
+ OpenTelemetryAssertions.satisfies(
|
|
|
|
+ AttributeKey.booleanKey("outer"), AbstractBooleanAssert::isNull)),
|
|
|
|
+ // inner span
|
|
|
|
+ sa ->
|
|
|
|
+ sa.hasName("inner-span")
|
|
|
|
+ .hasParent(ta.getSpan(1))
|
|
|
|
+ .hasAttribute(AttributeKey.booleanKey("inner"), true)
|
|
|
|
+ .hasAttributesSatisfying(
|
|
|
|
+ OpenTelemetryAssertions.satisfies(
|
|
|
|
+ AttributeKey.booleanKey("middle"), AbstractBooleanAssert::isNull),
|
|
|
|
+ OpenTelemetryAssertions.satisfies(
|
|
|
|
+ AttributeKey.booleanKey("outer"), AbstractBooleanAssert::isNull))));
|
|
|
|
+ }
|
|
|
|
+}
|