Skip to main content
This topic documents how to get started with the LaunchDarkly observability plugin for the Java SDK. The Java SDK supports the observability plugin for error monitoring, logging, metrics, and tracing.
This LaunchDarkly observability plugin is available for early accessThis LaunchDarkly observability plugin is currently available in Early Access, and APIs are subject to change until a 1.x version is released.
SDK quick linksLaunchDarkly SDKs are open source. In addition to this reference guide, we provide source, a sample application, and a published module:
ResourceLocation
GitHub repository@launchdarkly/observability-java
Sample applicationSpring Boot web backend
Published moduleMaven Central

Prerequisites and dependencies

This reference guide assumes that you are somewhat familiar with the LaunchDarkly Java SDK. The observability plugin has the following requirements:
  • The Java SDK, version 7.10.1 or later. This is the first version that supports plugins. The observability plugin does not include the SDK as a dependency. You must declare it yourself.
  • Java 11 or later.
  • The OpenTelemetry Java SDK, version 1.38.0 or later, on your application’s runtime classpath. The plugin is built against version 1.51.0.
The plugin depends only on OpenTelemetry artifacts. It sends OpenTelemetry Protocol (OTLP) data over HTTP using the built-in java.net.http.HttpClient. It does not add OkHttp, Okio, the Kotlin standard library, or a JSON library to your classpath. It records flag evaluations with its own hook. You do not need the launchdarkly-java-server-sdk-otel package.

OpenTelemetry versions

Dependency management bills of materials (BOMs), such as the one Spring Boot provides, override the OpenTelemetry version that the plugin requests. If your build resolves an OpenTelemetry version older than 1.38.0, the plugin logs an error and does not start. Your LaunchDarkly client and application continue to run. To check which version your build resolves, run ./gradlew dependencies --configuration runtimeClasspath or mvn dependency:tree -Dincludes=io.opentelemetry. This table lists the OpenTelemetry version that each Spring Boot release manages:
Spring BootOpenTelemetry versionCompatible with plugin
3.21.31.0No. Override the OpenTelemetry version.
3.31.38.0Yes
3.41.43.0Yes
3.51.49.0Yes
4.11.62.0Yes
To override the OpenTelemetry version that Spring Boot manages, set the opentelemetry.version property. Here’s how:
Keep every io.opentelemetry artifact on the same version. If you add OpenTelemetry instrumentation libraries, such as the Logback appender, choose the release that is built on the same core version, or override opentelemetry.version to match it. For example, OpenTelemetry instrumentation 2.17.x is built on OpenTelemetry 1.51.0. Mixing versions causes AbstractMethodError or NoSuchMethodError exceptions at runtime.

Get started

Follow these steps to get started:

Install the plugin

LaunchDarkly uses a plugin to the Java SDK to provide observability. The first step is to make both the SDK and the observability plugin available as dependencies. The plugin does not include the SDK, so declare both. Here’s how:
The plugin declares io.opentelemetry:opentelemetry-api as a compile-scoped dependency, because its public methods take OpenTelemetry API types such as Attributes and Severity. You do not need to declare it yourself. Then, import the SDK and the plugin in your application code:

Initialize the client

Next, initialize the SDK and the plugin. To initialize, you need your LaunchDarkly environment’s SDK key. This authorizes your application to connect to a particular environment within LaunchDarkly. To learn more, read Initialize the client in the Java SDK reference guide. Here’s how to initialize the SDK and plugin:
After you initialize the client, the plugin does the following:
  • Sets up OpenTelemetry tracer, logger, and meter providers that export to LaunchDarkly over OTLP/HTTP.
  • Registers a hook that records a span for each flag evaluation and adds a feature_flag event to the current span. LaunchDarkly uses these events for guarded rollouts and observability.
  • Fetches sampling configuration from LaunchDarkly to control the volume of telemetry it exports.
On startup, the plugin logs one line that includes the endpoint it exports to and its service name. It logs a warning if you do not set a service name. If the plugin cannot start, for example because of a malformed endpoint or an OpenTelemetry version that is too old, it logs the cause as an error and does nothing else. Your LaunchDarkly client and application continue to run. Flag evaluation spans are children of the span that is current when you evaluate the flag. The plugin does not create HTTP request spans itself. In a web service, connect your HTTP instrumentation to the plugin, or each flag evaluation becomes its own trace. To learn how, read Use the plugin with Spring Boot and Use the plugin with other OpenTelemetry setups.
Network requirementsThe observability plugin sends data to LaunchDarkly using port 4318 by default. If your network restricts outbound traffic to port 443, read Network requirements to override the OTLP endpoint.

Configure the plugin options

You can configure options for the observability plugin when you initialize the SDK. The plugin constructor takes an ObservabilityOptions object with the configuration details. Here is an example:
For more information on plugin options, read Configuration for server-side observability.

Use the plugin with Spring Boot

In a Spring Boot application, build one LDClient bean that includes the plugin, and let Spring close it. Spring Boot shuts down from its own Java Virtual Machine (JVM) shutdown hook, after it drains in-flight requests. Turn off the plugin’s shutdown hook with shutdownHook(false), and shut down the plugin from a bean instead. Otherwise, the plugin may stop before Spring finishes draining requests, and you lose telemetry from those requests. Here’s how:

Export request spans and errors

Spring Boot’s Micrometer tracing creates a span for each HTTP request and records unhandled exceptions on it. To export these request spans to LaunchDarkly, add the Micrometer OpenTelemetry bridge and provide the plugin’s OpenTelemetry instance as a bean. Spring Boot then exports request spans with flag evaluation spans as their children, feature_flag events on the request span, and exceptions as error events. First, add the dependencies:
Then, define an OpenTelemetry bean that returns the plugin’s instance. The LDClient parameter makes Spring start the plugin first:
The plugin’s tracer provider records every span. The management.tracing.sampling.probability setting does not apply. The sampling rules you configure in LaunchDarkly determine which spans the plugin exports.

Export application logs

LDObserve.recordLog exports a single log record. To learn more, read Sending logs. To export the logs you already write through SLF4J and Logback, add the OpenTelemetry Logback appender and install it on the plugin’s OpenTelemetry instance. Choose the appender version that matches your OpenTelemetry version. To learn more, read OpenTelemetry versions. First, add the dependency:
Next, add the appender to your Logback configuration:
Finally, install the appender when you create the OpenTelemetry bean:
Log records that your application writes during a request include that request’s trace ID. The logsApiLevel option still applies to these records. If you use Log4j 2 through spring-boot-starter-log4j2, use the io.opentelemetry.instrumentation:opentelemetry-log4j-appender-2.17 appender instead. Add <OpenTelemetry name="OpenTelemetryAppender"/> to the appenders in log4j2-spring.xml, add packages="io.opentelemetry.instrumentation.log4j.appender.v2_17" to the <Configuration> element, and reference the appender from the root logger. Then call io.opentelemetry.instrumentation.log4j.appender.v2_17.OpenTelemetryAppender.install(openTelemetry) in the bean.

Use the plugin with other OpenTelemetry setups

The plugin registers its OpenTelemetry SDK as GlobalOpenTelemetry when it can. If another component has already registered the global instance, the plugin keeps its own providers. Examples include the OpenTelemetry Java agent, your own OpenTelemetry SDK, or a library that called GlobalOpenTelemetry.get() first. In either case, the plugin sends flag evaluation spans and all data you record through LDObserve to LaunchDarkly. The plugin adds the feature_flag event to whichever span is current. The component that owns that span exports the event. To send data from other instrumentation to LaunchDarkly through the plugin, pass it the instance that LDObserve.getOpenTelemetry() returns. This method returns the plugin’s OpenTelemetry instance whether or not it is the global instance. Call it after you build the LDClient. Before the plugin starts, the instance provides no-op tracers, meters, and loggers, and anything you create from them in that window stays a no-op.

Use the OpenTelemetry Java agent

When you attach the OpenTelemetry Java agent, the agent owns the global instance, creates the request spans, and exports them to its own endpoint. The plugin’s flag evaluation spans reference those request spans as parents. To review complete traces in LaunchDarkly, configure the agent to send its data to LaunchDarkly as well. Here’s how:
The highlight.project_id resource attribute is the attribute that the plugin itself sets to your SDK key. The agent also captures Logback and Log4j records and exports them the same way.

Shut down the plugin

The plugin’s OpenTelemetry providers are process-wide. Closing an LDClient does not stop them. Call LDObserve.shutdown() when your application stops, for example after you close the client. This flushes any pending telemetry and stops the providers. By default, the plugin also registers a JVM shutdown hook that does the same thing. To turn off the hook, call shutdownHook(false) when you build the plugin options. We recommend turning it off when you use a framework that manages shutdown, such as Spring Boot. To learn more, read Use the plugin with Spring Boot. Here’s how:

Use multiple clients

The first LDClient that registers the plugin starts the providers, and its SDK key identifies the LaunchDarkly project for all exported data. Another LDClient with the same SDK key shares the providers. If you register the plugin on an LDClient with a different SDK key, the plugin logs a warning and does not start anything for that client. The plugin still records that client’s flag evaluations, under the first client’s SDK key.

Explore supported features

The observability plugin supports the following features. After the SDK and plugin are initialized, you can access these from within your application:

Review observability data in LaunchDarkly

After you initialize the SDK and observability plugin, your application automatically starts sending observability data back to LaunchDarkly in the form of custom events. You can review this information in the LaunchDarkly user interface. To learn how, read Observability and OpenTelemetry autogenerated metrics.