Overview
otel4s-oteljava
modules provide implementation of the API interfaces.
The implementation uses opentelemetry-java under the hood.
There are several advantages of using the otel4s-oteljava
:
- Low memory overhead
- Extensive instrumentation ecosystem
- Easy integration with Java libraries
- Well-tested implementation
It's a recommended backend to use on JVM.
Getting Started
Add settings to the build.sbt
:
libraryDependencies ++= Seq(
"org.typelevel" %% "otel4s-oteljava" % "0.11.2", // <1>
"io.opentelemetry" % "opentelemetry-exporter-otlp" % "1.45.0" % Runtime, // <2>
"io.opentelemetry" % "opentelemetry-sdk-extension-autoconfigure" % "1.45.0" % Runtime // <3>
)
javaOptions += "-Dotel.java.global-autoconfigure.enabled=true" // <4>
Add directives to the *.scala
file:
//> using lib "org.typelevel::otel4s-oteljava:0.11.2" // <1>
//> using lib "io.opentelemetry:opentelemetry-exporter-otlp:1.45.0" // <2>
//> using lib "io.opentelemetry:opentelemetry-sdk-extension-autoconfigure:1.45.0" // <3>
//> using `java-opt` "-Dotel.java.global-autoconfigure.enabled=true" // <4>
- Add the
otel4s-oteljava
library - Add an OpenTelemetry exporter. Without the exporter, the application will crash
- Add an OpenTelemetry autoconfigure extension
- Enable OpenTelemetry SDK autoconfigure mode
Creating an autoconfigured instance
You can use OtelJava.autoConfigured
to autoconfigure the SDK:
import cats.effect.{IO, IOApp}
import org.typelevel.otel4s.oteljava.OtelJava
import org.typelevel.otel4s.metrics.MeterProvider
import org.typelevel.otel4s.trace.TracerProvider
object TelemetryApp extends IOApp.Simple {
def run: IO[Unit] =
OtelJava.autoConfigured[IO]().use { otel4s =>
program(otel4s.meterProvider, otel4s.tracerProvider)
}
def program(
meterProvider: MeterProvider[IO],
tracerProvider: TracerProvider[IO]
): IO[Unit] =
???
}
The OtelJava.autoConfigured(...)
relies on the environment variables and system properties to configure the SDK.
For example, use export OTEL_SERVICE_NAME=auth-service
to configure the name of the service.
See the full set of the supported options.
OtelJava.autoConfigured
creates an isolated non-global instance.
If you create multiple instances, those instances won't interoperate (i.e. be able to see each others spans).
Accessing the global instance
There are several reasons to use the global instance:
- You are using the Java Agent
- You must reuse the global instance to interoperate with Java libraries
- You have no control over the entry point
In such a case, you can use the OtelJava.global
to use the global OpenTelemetry instance:
import cats.effect.{IO, IOApp}
import org.typelevel.otel4s.oteljava.OtelJava
import org.typelevel.otel4s.metrics.MeterProvider
import org.typelevel.otel4s.trace.TracerProvider
object TelemetryApp extends IOApp.Simple {
def run: IO[Unit] =
OtelJava.global[IO].flatMap { otel4s =>
program(otel4s.meterProvider, otel4s.tracerProvider)
}
def program(
meterProvider: MeterProvider[IO],
tracerProvider: TracerProvider[IO]
): IO[Unit] =
???
}