|
@@ -6,11 +6,12 @@
|
|
|
package io.opentelemetry.javaagent.instrumentation.kotlinxcoroutines
|
|
|
|
|
|
import io.opentelemetry.context.Context
|
|
|
+import io.opentelemetry.context.ContextKey
|
|
|
import io.opentelemetry.extension.kotlin.asContextElement
|
|
|
+import io.opentelemetry.extension.kotlin.getOpenTelemetryContext
|
|
|
import io.opentelemetry.instrumentation.reactor.ContextPropagationOperator
|
|
|
import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension
|
|
|
import io.opentelemetry.instrumentation.testing.util.TelemetryDataUtil.orderByRootSpanName
|
|
|
-import io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat
|
|
|
import io.opentelemetry.sdk.testing.assertj.TraceAssert
|
|
|
import kotlinx.coroutines.CompletableDeferred
|
|
|
import kotlinx.coroutines.CoroutineDispatcher
|
|
@@ -38,6 +39,7 @@ import kotlinx.coroutines.selects.select
|
|
|
import kotlinx.coroutines.withContext
|
|
|
import kotlinx.coroutines.withTimeout
|
|
|
import kotlinx.coroutines.yield
|
|
|
+import org.assertj.core.api.Assertions.assertThat
|
|
|
import org.awaitility.Awaitility.await
|
|
|
import org.junit.jupiter.api.AfterAll
|
|
|
import org.junit.jupiter.api.Test
|
|
@@ -92,41 +94,33 @@ class KotlinCoroutinesInstrumentationTest {
|
|
|
|
|
|
testing.waitAndAssertTraces(
|
|
|
{ trace ->
|
|
|
- // TODO(anuraaga): Need hasSpansSatisfyingExactlyInAnyOrder sometimes
|
|
|
- trace.satisfiesExactlyInAnyOrder(
|
|
|
- Consumer {
|
|
|
- assertThat(it)
|
|
|
- .hasName("parent")
|
|
|
+ trace.hasSpansSatisfyingExactlyInAnyOrder(
|
|
|
+ {
|
|
|
+ it.hasName("parent")
|
|
|
.hasNoParent()
|
|
|
},
|
|
|
- Consumer {
|
|
|
- assertThat(it)
|
|
|
- .hasName("produce_0")
|
|
|
+ {
|
|
|
+ it.hasName("produce_0")
|
|
|
.hasParent(trace.getSpan(0))
|
|
|
},
|
|
|
- Consumer {
|
|
|
- assertThat(it)
|
|
|
- .hasName("consume_0")
|
|
|
+ {
|
|
|
+ it.hasName("consume_0")
|
|
|
.hasParent(trace.getSpan(0))
|
|
|
},
|
|
|
- Consumer {
|
|
|
- assertThat(it)
|
|
|
- .hasName("produce_1")
|
|
|
+ {
|
|
|
+ it.hasName("produce_1")
|
|
|
.hasParent(trace.getSpan(0))
|
|
|
},
|
|
|
- Consumer {
|
|
|
- assertThat(it)
|
|
|
- .hasName("consume_1")
|
|
|
+ {
|
|
|
+ it.hasName("consume_1")
|
|
|
.hasParent(trace.getSpan(0))
|
|
|
},
|
|
|
- Consumer {
|
|
|
- assertThat(it)
|
|
|
- .hasName("produce_2")
|
|
|
+ {
|
|
|
+ it.hasName("produce_2")
|
|
|
.hasParent(trace.getSpan(0))
|
|
|
},
|
|
|
- Consumer {
|
|
|
- assertThat(it)
|
|
|
- .hasName("consume_2")
|
|
|
+ {
|
|
|
+ it.hasName("consume_2")
|
|
|
.hasParent(trace.getSpan(0))
|
|
|
}
|
|
|
)
|
|
@@ -225,25 +219,25 @@ class KotlinCoroutinesInstrumentationTest {
|
|
|
|
|
|
testing.waitAndAssertTraces(
|
|
|
{ trace ->
|
|
|
- trace.satisfiesExactlyInAnyOrder(
|
|
|
- Consumer {
|
|
|
- assertThat(it).hasName("parent")
|
|
|
+ trace.hasSpansSatisfyingExactlyInAnyOrder(
|
|
|
+ {
|
|
|
+ it.hasName("parent")
|
|
|
.hasNoParent()
|
|
|
},
|
|
|
- Consumer {
|
|
|
- assertThat(it).hasName("future1")
|
|
|
+ {
|
|
|
+ it.hasName("future1")
|
|
|
.hasParent(trace.getSpan(0))
|
|
|
},
|
|
|
- Consumer {
|
|
|
- assertThat(it).hasName("keptPromise")
|
|
|
+ {
|
|
|
+ it.hasName("keptPromise")
|
|
|
.hasParent(trace.getSpan(0))
|
|
|
},
|
|
|
- Consumer {
|
|
|
- assertThat(it).hasName("keptPromise2")
|
|
|
+ {
|
|
|
+ it.hasName("keptPromise2")
|
|
|
.hasParent(trace.getSpan(0))
|
|
|
},
|
|
|
- Consumer {
|
|
|
- assertThat(it).hasName("brokenPromise")
|
|
|
+ {
|
|
|
+ it.hasName("brokenPromise")
|
|
|
.hasParent(trace.getSpan(0))
|
|
|
}
|
|
|
)
|
|
@@ -280,25 +274,24 @@ class KotlinCoroutinesInstrumentationTest {
|
|
|
|
|
|
testing.waitAndAssertTraces(
|
|
|
{ trace ->
|
|
|
- // TODO(anuraaga): Need hasSpansSatisfyingExactlyInAnyOrder sometimes
|
|
|
- trace.satisfiesExactlyInAnyOrder(
|
|
|
- Consumer {
|
|
|
- assertThat(it)
|
|
|
+ trace.hasSpansSatisfyingExactlyInAnyOrder(
|
|
|
+ {
|
|
|
+ it
|
|
|
.hasName("parent")
|
|
|
.hasNoParent()
|
|
|
},
|
|
|
- Consumer {
|
|
|
- assertThat(it)
|
|
|
+ {
|
|
|
+ it
|
|
|
.hasName("timeout1")
|
|
|
.hasParent(trace.getSpan(0))
|
|
|
},
|
|
|
- Consumer {
|
|
|
- assertThat(it)
|
|
|
+ {
|
|
|
+ it
|
|
|
.hasName("timeout2")
|
|
|
.hasParent(trace.getSpan(0))
|
|
|
},
|
|
|
- Consumer {
|
|
|
- assertThat(it)
|
|
|
+ {
|
|
|
+ it
|
|
|
.hasName("timeout3")
|
|
|
.hasParent(trace.getSpan(0))
|
|
|
}
|
|
@@ -459,6 +452,45 @@ class KotlinCoroutinesInstrumentationTest {
|
|
|
)
|
|
|
}
|
|
|
|
|
|
+ private val ANIMAL: ContextKey<String> = ContextKey.named("animal")
|
|
|
+
|
|
|
+ @ParameterizedTest
|
|
|
+ @ArgumentsSource(DispatchersSource::class)
|
|
|
+ fun `context contains expected value`(dispatcher: DispatcherWrapper) {
|
|
|
+ runTest(dispatcher) {
|
|
|
+ val context1 = Context.current().with(ANIMAL, "cat")
|
|
|
+ runBlocking(context1.asContextElement()) {
|
|
|
+ assertThat(Context.current().get(ANIMAL)).isEqualTo("cat")
|
|
|
+ assertThat(coroutineContext.getOpenTelemetryContext().get(ANIMAL)).isEqualTo("cat")
|
|
|
+ tracedChild("nested1")
|
|
|
+ withContext(context1.with(ANIMAL, "dog").asContextElement()) {
|
|
|
+ assertThat(Context.current().get(ANIMAL)).isEqualTo("dog")
|
|
|
+ assertThat(coroutineContext.getOpenTelemetryContext().get(ANIMAL)).isEqualTo("dog")
|
|
|
+ tracedChild("nested2")
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ testing.waitAndAssertTraces(
|
|
|
+ { trace ->
|
|
|
+ trace.hasSpansSatisfyingExactly(
|
|
|
+ {
|
|
|
+ it.hasName("parent")
|
|
|
+ .hasNoParent()
|
|
|
+ },
|
|
|
+ {
|
|
|
+ it.hasName("nested1")
|
|
|
+ .hasParent(trace.getSpan(0))
|
|
|
+ },
|
|
|
+ {
|
|
|
+ it.hasName("nested2")
|
|
|
+ .hasParent(trace.getSpan(0))
|
|
|
+ }
|
|
|
+ )
|
|
|
+ }
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
private fun tracedChild(opName: String) {
|
|
|
tracer.spanBuilder(opName).startSpan().end()
|
|
|
}
|