Zero‑Code Distributed Tracing with OpenTelemetry Java Agent
Learn how OpenTelemetry’s Java auto‑instrumentation agent provides zero‑code distributed tracing for Spring Boot services, with a concrete setup example and practical limits.
01 Jan 2026, 04:23 UTC

Problem: Latency spikes hidden by incomplete tracing
In a microservice architecture, a sudden increase in request latency can be caused by a slow database call, a blocked Redis operation, or an unexpected downstream timeout. When teams rely on manual instrumentation, some services miss entry or exit points, making it impossible to see the full request‑flow in a trace backend. The result is blind spots that prolong troubleshooting.
Thesis: OpenTelemetry’s Java auto‑instrumentation agent gives end‑to‑end traces without code changes
By attaching the OpenTelemetry Java agent at JVM start‑up, widely used frameworks (Spring MVC, Servlet, JDBC, Redis clients, etc.) are instrumented via bytecode injection. The agent creates spans for each framework boundary, producing a complete trace that links HTTP requests, database queries, and cache calls.
How the Java agent works
The agent is a Java‑agent JAR that receives a callback during class loading. Using the Byte Buddy library, it rewrites the bytecode of target classes to insert span‑creation logic at method entry and exit. No application code is modified; the instrumentation is purely a JVM‑level concern.
Configuring the agent
Configuration is done through environment variables or Java system properties. The most common settings are:
OTEL_EXPORTER_OTLP_ENDPOINT– URL of the OTLP‑compatible collector (Jaeger, Tempo, etc.).OTEL_TRACES_SAMPLER– Sampling strategy (e.g.,parentbased_traceidratiowith a ratio).OTEL_SERVICE_NAME– Logical name of the service shown in the trace backend.OTEL_RESOURCE_ATTRIBUTES– Key‑value pairs such asdeployment.environment=staging.
These variables are read by the agent at start‑up; they can also be passed as -Dotel.* system properties.
Worked example: Adding the agent to a Spring Boot service
- Place the agent JAR where the JVM can read it, e.g.,
/opt/opentelemetry-javaagent.jar. Ensure the user running the service has read permission. - Export the required variables (example for a Jaeger OTLP exporter):
export OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4317 export OTEL_TRACES_SAMPLER=parentbased_traceidratio export OTEL_TRACES_SAMPLER_ARG=0.1 export OTEL_SERVICE_NAME=order-service - Start the Spring Boot jar with the agent:
java -javaagent:/opt/opentelemetry-javaagent.jar -jar order-service.jar - Check the console for agent startup messages, such as:
[otel-javaagent] Instrumenting org.springframework.web.servlet.DispatcherServlet [otel-javaagent] Instrumenting com.zaxxer.hikari.HikariDataSource [otel-javaagent] Instrumenting io.lettuce.core.RedisClient - Generate traffic (e.g., with
curl http://localhost:8080/orders) and open the Jaeger UI. You should see a trace containing:- An HTTP server span (entry point).
- A JDBC span as a child of the HTTP span (exit point).
- A Redis span as another child of the HTTP span (exit point).
Trade‑off / limitation
Automatic instrumentation captures only the framework boundaries the agent knows about. Custom business‑logic spans (e.g., marking the start of a fraud‑check algorithm) are not created, so developers must add manual spans via the OpenTelemetry API for domain‑specific events. Additionally, the agent adds measurable overhead; benchmarks typically show a 2‑5 % increase in CPU usage and a modest rise in memory consumption under load. The overhead grows with higher sampling rates and with exporters that network‑block.
Actionable close
- Deploy the agent in a staging environment first.
- Verify trace completeness by checking the agent logs and confirming that expected spans appear in Jaeger/Zipkin.
- Measure latency and resource usage with and without the agent (e.g., using a load‑testing tool) to ensure the overhead stays within your SLA.
- Promote to production once the overhead is acceptable.
- Gradually add manual spans for critical paths using the OpenTelemetry SDK where automatic coverage is insufficient.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.