Skip to content

Commit

Permalink
Support root span when availlable (#125)
Browse files Browse the repository at this point in the history
  • Loading branch information
cleidiano authored Oct 26, 2023
1 parent 46c1221 commit 4809397
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 22 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
java: [8, 11, 17]
java: [11, 17, 21]
name: Run with Java ${{ matrix.java }}
steps:
- uses: actions/checkout@v2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import io.opentelemetry.api.metrics.Meter
import io.opentelemetry.api.trace.Span
import io.opentelemetry.api.trace.Tracer
import io.opentelemetry.context.Context
import io.opentelemetry.instrumentation.api.instrumenter.LocalRootSpan
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpServerRoute
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpServerRouteSource
import java.io.Closeable
Expand All @@ -30,6 +31,7 @@ class OpenTelemetryTracer : TracerEngine, ThreadContextManager<Span> {
}

override fun setOperationName(name: String) {
currentSpan().updateName(name)
HttpServerRoute.update(
Context.current(),
HttpServerRouteSource.CONTROLLER,
Expand All @@ -39,27 +41,27 @@ class OpenTelemetryTracer : TracerEngine, ThreadContextManager<Span> {
}

override fun addProperty(key: String, value: String?) {
Span.current()?.addProperty(key, value)
currentSpan().addProperty(key, value)
}

override fun addRootProperty(key: String, value: String?) {
currentSpan()?.addProperty(key, value)
rootSpan().addProperty(key, value)
}

override fun addProperty(key: String, value: Number?) {
Span.current()?.addProperty(key, value)
currentSpan().addProperty(key, value)
}

override fun addRootProperty(key: String, value: Number?) {
currentSpan()?.addProperty(key, value)
rootSpan().addProperty(key, value)
}

override fun addProperty(key: String, value: Boolean?) {
Span.current()?.addProperty(key, value)
currentSpan().addProperty(key, value)
}

override fun addRootProperty(key: String, value: Boolean?) {
currentSpan()?.addProperty(key, value)
rootSpan().addProperty(key, value)
}

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

override fun notifyError(exception: Throwable, expected: Boolean) {
Span.current()?.let { span ->
OpenTelemetryUtils.notifyError(span, exception, expected)
}
OpenTelemetryUtils.notifyError(currentSpan(), exception, expected)
}

override fun notifyRootError(exception: Throwable, expected: Boolean) {
currentSpan()?.let { span ->
OpenTelemetryUtils.notifyError(span, exception, expected)
}
OpenTelemetryUtils.notifyError(rootSpan(), exception, expected)
}

override fun notifyError(message: String, params: Map<String, String?>, expected: Boolean) {
Span.current()?.let { span ->
OpenTelemetryUtils.notifyError(span, message, params, expected)
}
OpenTelemetryUtils.notifyError(currentSpan(), message, params, expected)
}

override fun notifyRootError(message: String, params: Map<String, String?>, expected: Boolean) {
currentSpan()?.let { span ->
OpenTelemetryUtils.notifyError(span, message, params, expected)
}
OpenTelemetryUtils.notifyError(rootSpan(), message, params, expected)
}

override fun clear() {}
Expand Down Expand Up @@ -146,7 +140,12 @@ class OpenTelemetryTracer : TracerEngine, ThreadContextManager<Span> {
else -> resolveByPrimitiveTypeRepresentationOnJvm(tClass, k)
}

private fun currentSpan(): Span? = Span.current()
private fun currentSpan(): Span = Span.current()

private fun rootSpan(): Span {
val root = LocalRootSpan.current().takeIf { it != Span.getInvalid() }
return root ?: Span.current()
}

private class Setter<T, R : Any>(private val key: AttributeKey<R>, private val transformer: (T) -> R) {
fun setAttributeIn(span: Span, value: T) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,36 @@
package br.com.guiabolso.tracing.engine.opentelemetry

import br.com.guiabolso.tracing.engine.opentelemetry.OpenTelemetryTracer.Companion.TRACER_NAME
import br.com.guiabolso.tracing.utils.opentelemetry.DefaultUnspecifiedException
import io.mockk.clearStaticMockk
import io.mockk.every
import io.mockk.mockk
import io.mockk.mockkStatic
import io.mockk.spyk
import io.mockk.verify
import io.opentelemetry.api.GlobalOpenTelemetry
import io.opentelemetry.api.OpenTelemetry
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.api.common.Attributes
import io.opentelemetry.api.trace.Span
import io.opentelemetry.api.trace.StatusCode
import io.opentelemetry.instrumentation.api.instrumenter.LocalRootSpan
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertInstanceOf
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test

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

class OpenTelemetryTracerTest {
private val openTelemetryTracer = OpenTelemetryTracer()

@BeforeEach
fun before() {
clearStaticMockk(Span::class)
clearStaticMockk(LocalRootSpan::class)
}

@Test
fun `should add all supported properties successfully`() {
val span = currentSpyiedSpan()
Expand Down Expand Up @@ -69,12 +87,66 @@ class OpenTelemetryTracerTest {
}

@Test
fun `should set operation name successfully`() {
fun `should update the span name when set operation`() {
mockkStatic(Span::current)
mockkStatic(LocalRootSpan::current)
val span = mockk<Span>(relaxed = true)
every { LocalRootSpan.current() } returns span
every { Span.current() } returns span

openTelemetryTracer.setOperationName("my-operation")

verify {
span.updateName("my-operation")
}
}

@Test
fun `should add property to root span`() {
mockkStatic(LocalRootSpan::current)
val span = mockk<Span>(relaxed = true)
every { LocalRootSpan.current() } returns span

openTelemetryTracer.addRootProperty("number", 1)
openTelemetryTracer.addRootProperty("bool", true)
openTelemetryTracer.addRootProperty("string", "my-string")

verify(exactly = 1) {
span.setAttribute(AttributeKey.longKey("number"), 1L)
span.setAttribute(AttributeKey.booleanKey("bool"), true)
span.setAttribute(AttributeKey.stringKey("string"), "my-string")
}
}

@Test
fun `should report error on root span`() {
mockkStatic(LocalRootSpan::current)

val span = mockk<Span>(relaxed = true)
every { LocalRootSpan.current() } returns span

val ex = NotImplementedError()
openTelemetryTracer.notifyRootError(ex, expected = false)
openTelemetryTracer.notifyRootError("my error", mapOf("tag" to "1"), expected = false)

verify(exactly = 2) {
span.setStatus(StatusCode.ERROR)
}

verify {
span.recordException(ex)
span.recordException(
withArg {
assertInstanceOf(DefaultUnspecifiedException::class.java, it)
assertEquals("my error", it.message)
},
Attributes.builder().put("tag", "1").build()
)
}
}

private fun currentSpyiedSpan(): Span {
return otel.getTracer(OpenTelemetryTracer.TRACER_NAME)
return otel.getTracer(TRACER_NAME)
.spanBuilder("name")
.setNoParent()
.startSpan()
Expand Down

0 comments on commit 4809397

Please sign in to comment.