Skip to content

Commit 4809397

Browse files
authored
Support root span when availlable (#125)
1 parent 46c1221 commit 4809397

3 files changed

Lines changed: 93 additions & 22 deletions

File tree

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ jobs:
66
runs-on: ubuntu-latest
77
strategy:
88
matrix:
9-
java: [8, 11, 17]
9+
java: [11, 17, 21]
1010
name: Run with Java ${{ matrix.java }}
1111
steps:
1212
- uses: actions/checkout@v2

impl/java/tracing/src/main/kotlin/br/com/guiabolso/tracing/engine/opentelemetry/OpenTelemetryTracer.kt

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import io.opentelemetry.api.metrics.Meter
1111
import io.opentelemetry.api.trace.Span
1212
import io.opentelemetry.api.trace.Tracer
1313
import io.opentelemetry.context.Context
14+
import io.opentelemetry.instrumentation.api.instrumenter.LocalRootSpan
1415
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpServerRoute
1516
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpServerRouteSource
1617
import java.io.Closeable
@@ -30,6 +31,7 @@ class OpenTelemetryTracer : TracerEngine, ThreadContextManager<Span> {
3031
}
3132

3233
override fun setOperationName(name: String) {
34+
currentSpan().updateName(name)
3335
HttpServerRoute.update(
3436
Context.current(),
3537
HttpServerRouteSource.CONTROLLER,
@@ -39,27 +41,27 @@ class OpenTelemetryTracer : TracerEngine, ThreadContextManager<Span> {
3941
}
4042

4143
override fun addProperty(key: String, value: String?) {
42-
Span.current()?.addProperty(key, value)
44+
currentSpan().addProperty(key, value)
4345
}
4446

4547
override fun addRootProperty(key: String, value: String?) {
46-
currentSpan()?.addProperty(key, value)
48+
rootSpan().addProperty(key, value)
4749
}
4850

4951
override fun addProperty(key: String, value: Number?) {
50-
Span.current()?.addProperty(key, value)
52+
currentSpan().addProperty(key, value)
5153
}
5254

5355
override fun addRootProperty(key: String, value: Number?) {
54-
currentSpan()?.addProperty(key, value)
56+
rootSpan().addProperty(key, value)
5557
}
5658

5759
override fun addProperty(key: String, value: Boolean?) {
58-
Span.current()?.addProperty(key, value)
60+
currentSpan().addProperty(key, value)
5961
}
6062

6163
override fun addRootProperty(key: String, value: Boolean?) {
62-
currentSpan()?.addProperty(key, value)
64+
rootSpan().addProperty(key, value)
6365
}
6466

6567
override fun addProperty(key: String, value: List<*>) {
@@ -90,27 +92,19 @@ class OpenTelemetryTracer : TracerEngine, ThreadContextManager<Span> {
9092
}
9193

9294
override fun notifyError(exception: Throwable, expected: Boolean) {
93-
Span.current()?.let { span ->
94-
OpenTelemetryUtils.notifyError(span, exception, expected)
95-
}
95+
OpenTelemetryUtils.notifyError(currentSpan(), exception, expected)
9696
}
9797

9898
override fun notifyRootError(exception: Throwable, expected: Boolean) {
99-
currentSpan()?.let { span ->
100-
OpenTelemetryUtils.notifyError(span, exception, expected)
101-
}
99+
OpenTelemetryUtils.notifyError(rootSpan(), exception, expected)
102100
}
103101

104102
override fun notifyError(message: String, params: Map<String, String?>, expected: Boolean) {
105-
Span.current()?.let { span ->
106-
OpenTelemetryUtils.notifyError(span, message, params, expected)
107-
}
103+
OpenTelemetryUtils.notifyError(currentSpan(), message, params, expected)
108104
}
109105

110106
override fun notifyRootError(message: String, params: Map<String, String?>, expected: Boolean) {
111-
currentSpan()?.let { span ->
112-
OpenTelemetryUtils.notifyError(span, message, params, expected)
113-
}
107+
OpenTelemetryUtils.notifyError(rootSpan(), message, params, expected)
114108
}
115109

116110
override fun clear() {}
@@ -146,7 +140,12 @@ class OpenTelemetryTracer : TracerEngine, ThreadContextManager<Span> {
146140
else -> resolveByPrimitiveTypeRepresentationOnJvm(tClass, k)
147141
}
148142

149-
private fun currentSpan(): Span? = Span.current()
143+
private fun currentSpan(): Span = Span.current()
144+
145+
private fun rootSpan(): Span {
146+
val root = LocalRootSpan.current().takeIf { it != Span.getInvalid() }
147+
return root ?: Span.current()
148+
}
150149

151150
private class Setter<T, R : Any>(private val key: AttributeKey<R>, private val transformer: (T) -> R) {
152151
fun setAttributeIn(span: Span, value: T) {

impl/java/tracing/src/test/kotlin/br/com/guiabolso/tracing/engine/opentelemetry/OpenTelemetryTracerTest.kt

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,36 @@
11
package br.com.guiabolso.tracing.engine.opentelemetry
22

3+
import br.com.guiabolso.tracing.engine.opentelemetry.OpenTelemetryTracer.Companion.TRACER_NAME
4+
import br.com.guiabolso.tracing.utils.opentelemetry.DefaultUnspecifiedException
5+
import io.mockk.clearStaticMockk
6+
import io.mockk.every
7+
import io.mockk.mockk
8+
import io.mockk.mockkStatic
39
import io.mockk.spyk
410
import io.mockk.verify
511
import io.opentelemetry.api.GlobalOpenTelemetry
612
import io.opentelemetry.api.OpenTelemetry
713
import io.opentelemetry.api.common.AttributeKey
14+
import io.opentelemetry.api.common.Attributes
815
import io.opentelemetry.api.trace.Span
16+
import io.opentelemetry.api.trace.StatusCode
17+
import io.opentelemetry.instrumentation.api.instrumenter.LocalRootSpan
18+
import org.junit.jupiter.api.Assertions.assertEquals
19+
import org.junit.jupiter.api.Assertions.assertInstanceOf
20+
import org.junit.jupiter.api.BeforeEach
921
import org.junit.jupiter.api.Test
1022

1123
private val otel = OpenTelemetry.noop().apply(GlobalOpenTelemetry::set)
1224

1325
class OpenTelemetryTracerTest {
1426
private val openTelemetryTracer = OpenTelemetryTracer()
1527

28+
@BeforeEach
29+
fun before() {
30+
clearStaticMockk(Span::class)
31+
clearStaticMockk(LocalRootSpan::class)
32+
}
33+
1634
@Test
1735
fun `should add all supported properties successfully`() {
1836
val span = currentSpyiedSpan()
@@ -69,12 +87,66 @@ class OpenTelemetryTracerTest {
6987
}
7088

7189
@Test
72-
fun `should set operation name successfully`() {
90+
fun `should update the span name when set operation`() {
91+
mockkStatic(Span::current)
92+
mockkStatic(LocalRootSpan::current)
93+
val span = mockk<Span>(relaxed = true)
94+
every { LocalRootSpan.current() } returns span
95+
every { Span.current() } returns span
96+
7397
openTelemetryTracer.setOperationName("my-operation")
98+
99+
verify {
100+
span.updateName("my-operation")
101+
}
102+
}
103+
104+
@Test
105+
fun `should add property to root span`() {
106+
mockkStatic(LocalRootSpan::current)
107+
val span = mockk<Span>(relaxed = true)
108+
every { LocalRootSpan.current() } returns span
109+
110+
openTelemetryTracer.addRootProperty("number", 1)
111+
openTelemetryTracer.addRootProperty("bool", true)
112+
openTelemetryTracer.addRootProperty("string", "my-string")
113+
114+
verify(exactly = 1) {
115+
span.setAttribute(AttributeKey.longKey("number"), 1L)
116+
span.setAttribute(AttributeKey.booleanKey("bool"), true)
117+
span.setAttribute(AttributeKey.stringKey("string"), "my-string")
118+
}
119+
}
120+
121+
@Test
122+
fun `should report error on root span`() {
123+
mockkStatic(LocalRootSpan::current)
124+
125+
val span = mockk<Span>(relaxed = true)
126+
every { LocalRootSpan.current() } returns span
127+
128+
val ex = NotImplementedError()
129+
openTelemetryTracer.notifyRootError(ex, expected = false)
130+
openTelemetryTracer.notifyRootError("my error", mapOf("tag" to "1"), expected = false)
131+
132+
verify(exactly = 2) {
133+
span.setStatus(StatusCode.ERROR)
134+
}
135+
136+
verify {
137+
span.recordException(ex)
138+
span.recordException(
139+
withArg {
140+
assertInstanceOf(DefaultUnspecifiedException::class.java, it)
141+
assertEquals("my error", it.message)
142+
},
143+
Attributes.builder().put("tag", "1").build()
144+
)
145+
}
74146
}
75147

76148
private fun currentSpyiedSpan(): Span {
77-
return otel.getTracer(OpenTelemetryTracer.TRACER_NAME)
149+
return otel.getTracer(TRACER_NAME)
78150
.spanBuilder("name")
79151
.setNoParent()
80152
.startSpan()

0 commit comments

Comments
 (0)