Tracing | Context propagation
OpenTelemetry Java SDK and otel4s rely on different context manipulation approaches, which aren't interoperable out of the box. Java SDK utilizes ThreadLocal variables to share tracing information, otel4s, on the other hand, uses Local.
Cats Effect 3.6.0 introduced a new method of fiber context tracking, which can be integrated almost seamlessly with the OpenTelemetry Java SDK.
Getting started
Add settings to the build.sbt
:
libraryDependencies ++= Seq(
"org.typelevel" %% "otel4s-oteljava" % "0.12.0-RC2", // <1>
"org.typelevel" %% "otel4s-oteljava-context-storage" % "0.12.0-RC2", // <2>
)
javaOptions += "-Dcats.effect.trackFiberContext=true" // <3>
Add directives to the *.scala
file:
//> using dep "org.typelevel::otel4s-oteljava:0.12.0-RC2" // <1>
//> using dep "org.typelevel::otel4s-oteljava-context-storage:0.12.0-RC2" // <2>
//> using `java-opt` "-Dcats.effect.trackFiberContext=true" // <3>
- Add the
otel4s-oteljava
library - Add the
otel4s-oteljava-context-storage
library - Enable Cats Effect fiber context tracking
Configuration
You need to use IOLocalContextStorage.localProvider[IO]
to provide the global context storage, backed by IOLocal
:
import cats.effect.IO
import cats.effect.IOApp
import io.opentelemetry.api.trace.{Span => JSpan}
import org.typelevel.otel4s.context.LocalProvider
import org.typelevel.otel4s.oteljava.OtelJava
import org.typelevel.otel4s.oteljava.context.Context
import org.typelevel.otel4s.oteljava.context.IOLocalContextStorage
import org.typelevel.otel4s.trace.Tracer
object Main extends IOApp.Simple {
def program(tracer: Tracer[IO]): IO[Unit] =
tracer.span("test").use { span => // start 'test' span using otel4s
println(s"jctx: ${JSpan.current().getSpanContext}") // get a span from a ThreadLocal
IO.println(s"otel4s: ${span.context}")
}
def run: IO[Unit] = {
implicit val provider: LocalProvider[IO, Context] =
IOLocalContextStorage.localProvider[IO]
OtelJava.autoConfigured[IO]().use { otelJava =>
otelJava.tracerProvider.tracer("com.service").get.flatMap { tracer =>
program(tracer)
}
}
}
}
According to the output, the context is the same:
jctx : SpanContext{traceId=58b8ed50a558ca53fcc64a0d80b5e662, spanId=fc25fe2c9fb41905, ...}
otel4s: SpanContext{traceId=58b8ed50a558ca53fcc64a0d80b5e662, spanId=fc25fe2c9fb41905, ...}
Limitations
The IOLocalContextStorageProvider
doesn't work with OpenTelemetry Java Agent.