Getting Started with OpenTelemetry Java Agent for Zero‑Code Tracing
Learn how the OpenTelemetry Java agent adds automatic tracing to Java apps without code changes, covering setup, a Spring Boot example, and practical limits.
02 Aug 2025, 05:42 UTC

The problem: tracing without touching code
When you add observability to a running Java service, the usual path is to sprinkle tracer calls throughout your controllers, repositories, and messaging layers. That works, but it couples your business logic to an observability SDK and requires a redeploy for every instrumentation change.
Thesis: the OpenTelemetry Java agent lets you capture traces automatically
By attaching the agent at JVM start, you get bytecode‑weaving instrumentation for popular frameworks (Spring, Servlet, JDBC, gRPC, etc.) without writing a single line of tracer code.
How the agent works
The agent JAR contains a premain method that the JVM invokes before the main class loads. Inside, it uses the OpenTelemetry SDK to configure a tracer and then rewrites the bytecode of known classes to inject span creation, context propagation, and span finishing at method entry and exit points.
Enabling and configuring the agent
- Download the latest
opentelemetry-javaagent.jarfrom the official releases. - Add the JVM argument
-javaagent:/path/to/opentelemetry-javaagent.jarto your application start command. - Set environment variables to control what is traced and where it goes:
OTEL_TRACES_EXPORTER=console– prints spans to stdout.OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4317– sends data via OTLP.OTEL_SERVICE_NAME=my‑spring‑app– logical service identifier.OTEL_PROPAGATORS=w3ctrace– ensures W3C TraceContext propagation.
Worked example: Spring Boot app with console exporter
# Start the app
java -javaagent:/opt/agent/opentelemetry-javaagent.jar \
-jar demo.jar \
-Dspring.profiles.active=dev
# In another terminal, set the variables (or export them before starting)
export OTEL_TRACES_EXPORTER=console
export OTEL_SERVICE_NAME=demo-service
Now send an HTTP request, for example:
curl http://localhost:8080/greeting
You should see output similar to:
2026-10-12T00:39:02.123Z INFO io.opentelemetry.sdk.trace.SpanProcessor - Span {name: HTTP GET /greeting, traceId: 0x4bf92f8575b22dd9, spanId: 0x16f3a7b8c9d0e1f2, ...}
The trace ID appears on every line related to that request, showing that the agent created a span for the incoming Servlet call and propagated it to any downstream JDBC or outbound HTTP calls made by the same JVM.
Trade‑offs and limitations
- Coverage gaps: The agent only instruments frameworks listed in its
instrumentation.yml. Custom libraries or obscure frameworks need manual instrumentation. - Performance: Overhead is usually low (single‑digit percent) but can rise with very high‑frequency intercepted methods, such as tight loops that call JDBC on every iteration.
- Version alignment: Using an agent built for a different JDK version may cause class‑definition errors; match the agent release to your JDK (8+).
Practical verification
- Run the application with the agent and
OTEL_TRACES_EXPORTER=console. - Make a request and confirm that a traceId and spanId appear in stdout.
- To check propagation, start a second instrumented service, call it from the first, and verify the same traceId shows up in both services’ logs.
- Inspect the agent version:
java -javaagent:/opt/agent/opentelemetry-javaagent.jar -versionprints the agent’s version string.
Actionable closing
If you need tracing today and cannot modify source code, drop the OpenTelemetry Java agent into your JVM start line, configure a few environment variables, and you’ll have automatic spans for the most common frameworks. Keep an eye on the instrumentation list and overhead for your specific workload, and remove the -javaagent flag to roll back the change.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.