Skip to main content

Java

This guide provides detailed instructions on how to instrument a Java or Spring Boot application using the OpenTelemetry Java Agent. By the end of this guide, you will be able to automatically capture metrics from your application and send them to CtrlB, enabling deep visibility into request flows, performance issues, and error hotspots.

OpenTelemetry SDK status (mid-2026): Java metrics instrumentation is Stable. See the OpenTelemetry language status table.


Prerequisites


Why Instrument with the OpenTelemetry Java Agent?

The OpenTelemetry Java agent enables zero-code instrumentation, meaning:

  • You don’t need to modify your application code.
  • The agent automatically detects frameworks such as Spring Boot, JDBC, HTTP clients, gRPC, Kafka, Redis, etc.
  • It emits metrics for HTTP servers and clients, database connection pools, messaging throughput, and the JVM runtime.
  • The data is exported using OTLP to CtrlB.

This makes it the easiest way to start collecting metrics for any Java application.


Step 1. Download the OpenTelemetry Java Agent

Download the latest Java agent JAR file from GitHub:

wget https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar

This file acts as a small "layer" around your application. When your app starts, the JVM loads this agent and instruments major libraries automatically.


Step 2. Configure OpenTelemetry Instrumentation

Instrumentation works only when the JVM is started with the agent:

OTEL_EXPORTER=otlp \
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf \
OTEL_SERVICE_NAME=<service_name> \
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=https://<INGESTION_HOST>/api/default/v1/metrics \
OTEL_TRACES_EXPORTER=none \
OTEL_LOGS_EXPORTER=none \
OTEL_EXPORTER_OTLP_HEADERS="Authorization=Basic <API_TOKEN>,stream-name=<STREAM_NAME>" \
java -javaagent:$PWD/opentelemetry-javaagent.jar -jar <my-app>.jar

<service_name> is the name of your service as it should appear in CtrlB.
<my-app>.jar is the name of your application jar file.
In case you download opentelemetry-javaagent.jar file in different directory than that of the project, replace $PWD with the path of the otel jar file.
OTEL requires headers to be in comma-separated 'key=value' format as shown in the command above.

Instrument all telemetry together

The block above sends metrics only. To export traces, metrics, and logs from the same application, use the shared OTLP endpoint and headers instead of the signal-specific endpoint above:

OTEL_EXPORTER_OTLP_ENDPOINT=https://<INGESTION_HOST>/api/default \
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=https://<INGESTION_HOST>/api/default/<STREAM_NAME>/_otel/v1/logs \
OTEL_EXPORTER_OTLP_HEADERS="Authorization=Basic <API_TOKEN>,stream-name=<STREAM_NAME>"

How the Java Agent Works

When the JVM starts with:

-javaagent:opentelemetry-javaagent.jar

the agent:

  1. Hooks into the JVM bytecode instrumentation layer (ByteBuddy) to automatically wrap supported libraries.

  2. Records metrics for:

    • HTTP server and client request duration and counts
    • JDBC and connection-pool usage
    • Messaging (Kafka, RabbitMQ) throughput
    • Cache calls (Redis)
    • JVM runtime — memory, garbage collection, threads, CPU, and class loading
  3. Exports the collected telemetry to CtrlB via OTLP.

You don’t write a single line of instrumentation code.

JVM runtime metrics out of the box. The agent's runtime-telemetry module is enabled by default and reports JVM heap and non-heap memory, garbage-collection activity, thread counts, CPU utilization, and class loading. Alongside these, supported libraries emit their own metrics — for example HTTP server and client request-duration histograms — so you get both infrastructure and request-level metrics with no code changes.


Advanced Agent Configuration

The OpenTelemetry Java agent provides extensive configuration options to fine-tune instrumentation behavior, control data collection, and optimize performance for your specific use case.

Complete configuration reference: https://opentelemetry.io/docs/zero-code/java/agent/configuration/

How to Apply Configuration Options

All agent configurations can be passed as JVM system properties using the -D flag:

java -javaagent:opentelemetry-javaagent.jar \
-Dotel.javaagent.debug=true \
-Dotel.resource.attributes=deployment.environment=production \
-jar my-app.jar

Alternatively, use environment variables (replace . with _ and uppercase):

export OTEL_JAVAAGENT_DEBUG=true
export OTEL_RESOURCE_ATTRIBUTES=deployment.environment=production
java -javaagent:opentelemetry-javaagent.jar -jar my-app.jar

Common Configuration Options

ConfigurationPurposeExample ValueUse Case
otel.javaagent.debugEnable detailed instrumentation logs during startuptrueTroubleshooting: verify which libraries are being instrumented
otel.resource.attributesAdd custom metadata to all telemetry (environment, version, etc.)deployment.env=prod,version=1.2.3Filter and group metrics by deployment environment or app version
otel.traces.samplerControl sampling strategy to reduce trace volumeparentbased_traceidratioHigh-traffic services: sample a percentage of traces to reduce costs
otel.traces.sampler.argSampling ratio (0.0 to 1.0)0.1 (10%)Collect 10% of traces while maintaining statistical representativeness
otel.instrumentation.[name].enabledEnable/disable specific instrumentation librariesfalseDisable noisy or low-quality instrumentations (e.g., legacy Dropwizard metric bridges)

Instrumentations Disabled by Default

Some instrumentations are intentionally disabled in the Java agent when their metrics output is low quality or does not align with OpenTelemetry conventions. You can enable them if needed for your specific use case.

InstrumentationWhy DisabledWhen to EnableHow to Enable
dropwizard-metricsDropwizard's metrics API lacks label/tag support, resulting in low-cardinality, low-quality metrics that don't align with OpenTelemetry standardsLegacy apps heavily invested in Dropwizard metrics that need bridging to OTEL-Dotel.instrumentation.dropwizard-metrics.enabled=true

Example: Enabling Disabled Instrumentations

java -javaagent:opentelemetry-javaagent.jar \
-Dotel.instrumentation.dropwizard-metrics.enabled=true \
-jar my-app.jar

Step 3. Use OpenTelemetry Collector (Optional)

For production setups, it’s recommended to send metrics through an OpenTelemetry Collector before CtrlB. This enables buffering, batching, retries, and multi-sink routing.

See OpenTelemetry for Metrics for configuration details.


Troubleshooting

Make sure to set OTEL_SERVICE_NAME before starting the JVM. The -javaagent:opentelemetry-javaagent.jar argument must come before -jar <your-app>.jar.