Skip to content

Commit

Permalink
support root span when availlable (#126)
Browse files Browse the repository at this point in the history
  • Loading branch information
cleidiano authored Oct 26, 2023
1 parent 9a53baa commit 811aa17
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 26 deletions.
2 changes: 1 addition & 1 deletion impl/java/tracing/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ dependencies {

// Open Telemetry
api("io.opentelemetry:opentelemetry-api:1.28.0")

api("io.opentelemetry.instrumentation:opentelemetry-instrumentation-api-semconv:1.30.0-alpha")
// AspectJ
implementation("org.aspectj:aspectjweaver:1.9.7")
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ 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
import java.util.concurrent.ConcurrentHashMap

Expand All @@ -28,32 +31,37 @@ class OpenTelemetryTracer : TracerEngine, ThreadContextManager<Span> {
}

override fun setOperationName(name: String) {
val span = currentSpan()
span?.updateName(name)
currentSpan().updateName(name)
HttpServerRoute.update(
Context.current(),
HttpServerRouteSource.CONTROLLER,
{ _, _ -> name },
Unit
)
}

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 @@ -84,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 @@ -140,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,17 +87,66 @@ class OpenTelemetryTracerTest {
}

@Test
fun `should set operation name successfully`() {
val span = currentSpyiedSpan()
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(exactly = 1) {
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 811aa17

Please sign in to comment.