Java
This guide covers adding OpenTelemetry instrumentation to Java applications. Java offers a powerful auto-instrumentation agent that patches bytecode at runtime, covering hundreds of libraries with zero code changes.
Prerequisites
Section titled “Prerequisites”- Java 8+ (Java 11+ recommended)
- OTel Collector running at
localhost:4317(gRPC) orlocalhost:4318(HTTP) - Maven or Gradle for dependency management
Install dependencies
Section titled “Install dependencies”Auto-instrumentation agent
Section titled “Auto-instrumentation agent”Download the latest Java agent JAR:
curl -L -o opentelemetry-javaagent.jar \ https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jarMaven (manual instrumentation)
Section titled “Maven (manual instrumentation)”<dependencyManagement> <dependencies> <dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-bom</artifactId> <version>1.43.0</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies></dependencyManagement>
<dependencies> <dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-api</artifactId> </dependency> <dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-sdk</artifactId> </dependency> <dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-exporter-otlp</artifactId> </dependency> <dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-sdk-extension-autoconfigure</artifactId> </dependency></dependencies>Gradle (manual instrumentation)
Section titled “Gradle (manual instrumentation)”implementation platform("io.opentelemetry:opentelemetry-bom:1.43.0")implementation "io.opentelemetry:opentelemetry-api"implementation "io.opentelemetry:opentelemetry-sdk"implementation "io.opentelemetry:opentelemetry-exporter-otlp"implementation "io.opentelemetry:opentelemetry-sdk-extension-autoconfigure"Auto-instrumentation with the Java agent
Section titled “Auto-instrumentation with the Java agent”Attach the agent at JVM startup:
java -javaagent:opentelemetry-javaagent.jar \ -Dotel.service.name=my-java-service \ -Dotel.exporter.otlp.endpoint=http://localhost:4317 \ -jar my-application.jarThe agent automatically instruments:
- Servlet containers (Tomcat, Jetty, Undertow)
- Spring Boot, Spring MVC, Spring WebFlux
- JAX-RS (Jersey, RESTEasy)
- JDBC, Hibernate, JPA
- gRPC, Apache HttpClient, OkHttp
- Kafka, RabbitMQ, AWS SDK
- And 100+ more libraries
Suppress specific instrumentations
Section titled “Suppress specific instrumentations”java -javaagent:opentelemetry-javaagent.jar \ -Dotel.instrumentation.jdbc.enabled=false \ -jar my-application.jarManual SDK setup
Section titled “Manual SDK setup”For programmatic configuration without the agent:
import io.opentelemetry.api.OpenTelemetry;import io.opentelemetry.sdk.OpenTelemetrySdk;import io.opentelemetry.sdk.trace.SdkTracerProvider;import io.opentelemetry.sdk.trace.export.BatchSpanProcessor;import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;import io.opentelemetry.sdk.metrics.SdkMeterProvider;import io.opentelemetry.sdk.metrics.export.PeriodicMetricReader;import io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporter;import io.opentelemetry.sdk.resources.Resource;import io.opentelemetry.semconv.ResourceAttributes;
public class TelemetryConfig {
public static OpenTelemetry setup() { Resource resource = Resource.getDefault() .merge(Resource.create(io.opentelemetry.api.common.Attributes.of( ResourceAttributes.SERVICE_NAME, "my-java-service", ResourceAttributes.SERVICE_VERSION, "1.0.0" )));
SdkTracerProvider tracerProvider = SdkTracerProvider.builder() .setResource(resource) .addSpanProcessor(BatchSpanProcessor.builder( OtlpGrpcSpanExporter.builder() .setEndpoint("http://localhost:4317") .build() ).build()) .build();
SdkMeterProvider meterProvider = SdkMeterProvider.builder() .setResource(resource) .registerMetricReader(PeriodicMetricReader.builder( OtlpGrpcMetricExporter.builder() .setEndpoint("http://localhost:4317") .build() ).build()) .build();
return OpenTelemetrySdk.builder() .setTracerProvider(tracerProvider) .setMeterProvider(meterProvider) .buildAndRegisterGlobal(); }}Manual instrumentation
Section titled “Manual instrumentation”Creating spans
Section titled “Creating spans”import io.opentelemetry.api.trace.Tracer;import io.opentelemetry.api.trace.Span;import io.opentelemetry.api.trace.StatusCode;import io.opentelemetry.context.Scope;
Tracer tracer = openTelemetry.getTracer("com.example.orders");
public void processOrder(String orderId) { Span span = tracer.spanBuilder("process_order") .setAttribute("order.id", orderId) .startSpan();
try (Scope scope = span.makeCurrent()) { validatePayment(orderId); span.addEvent("order_processed"); } catch (Exception e) { span.recordException(e); span.setStatus(StatusCode.ERROR, e.getMessage()); throw e; } finally { span.end(); }}Recording metrics
Section titled “Recording metrics”import io.opentelemetry.api.metrics.Meter;import io.opentelemetry.api.metrics.LongCounter;import io.opentelemetry.api.metrics.DoubleHistogram;
Meter meter = openTelemetry.getMeter("com.example.orders");
LongCounter requestCounter = meter.counterBuilder("http.server.request_count") .setDescription("Number of HTTP requests") .setUnit("1") .build();
DoubleHistogram requestDuration = meter.histogramBuilder("http.server.duration") .setDescription("HTTP request duration") .setUnit("ms") .build();
public void handleRequest() { requestCounter.add(1, Attributes.of( AttributeKey.stringKey("http.method"), "GET", AttributeKey.stringKey("http.route"), "/api/orders" ));}Framework integration
Section titled “Framework integration”Spring Boot
Section titled “Spring Boot”With the Java agent, Spring Boot is auto-instrumented. For programmatic setup, add the Spring Boot starter:
<dependency> <groupId>io.opentelemetry.instrumentation</groupId> <artifactId>opentelemetry-spring-boot-starter</artifactId></dependency>Configure in application.properties:
otel.service.name=my-spring-serviceotel.exporter.otlp.endpoint=http://localhost:4317Quarkus
Section titled “Quarkus”Quarkus has built-in OTel support:
quarkus.otel.exporter.otlp.endpoint=http://localhost:4317quarkus.otel.service.name=my-quarkus-servicequarkus.otel.enabled=trueEnvironment variables
Section titled “Environment variables”| Variable | Description | Example |
|---|---|---|
OTEL_SERVICE_NAME | Service name | my-java-service |
OTEL_EXPORTER_OTLP_ENDPOINT | Collector endpoint | http://localhost:4317 |
OTEL_EXPORTER_OTLP_PROTOCOL | Export protocol | grpc |
OTEL_TRACES_SAMPLER | Sampler type | parentbased_traceidratio |
OTEL_TRACES_SAMPLER_ARG | Sampler argument | 0.1 |
OTEL_JAVAAGENT_ENABLED | Enable/disable the agent | true |
OTEL_INSTRUMENTATION_[NAME]_ENABLED | Toggle specific instrumentation | false |
JAVA_TOOL_OPTIONS | Attach agent via env var | -javaagent:opentelemetry-javaagent.jar |
Related links
Section titled “Related links”- Applications overview
- Auto-instrumentation
- Manual instrumentation
- OpenTelemetry Java documentation — Official OTel Java SDK reference
- Java instrumentation libraries — Available auto-instrumentation packages