Adopt distributed tracing without touching business code using OpenTelemetry auto-instrumentation, with full Java and Python config, production sampling, containerized deployment, and troubleshooting of common pitfalls.
The biggest blocker to distributed tracing isn't technical — it's the cost of instrumentation. Adding spans by hand means code changes, reviews and regressions, and plenty of teams give up at exactly this step. OpenTelemetry's auto-instrumentation gets you there without touching a single line of code.
Auto-instrumentation works by injecting at runtime: Java rewrites bytecode at class-load time through an Agent, Python monkey-patches the standard library and framework entry points. It intercepts the boundaries of middleware and clients rather than your business logic, so it's zero-intrusion while still carrying the cross-process trace context.
This guide assumes you already have an OBSERVE endpoint and token. If not, create a project in the console's onboarding wizard first.
Auto-instrumentation for Java works through a Java Agent. Download the OTel Java Agent jar and add one line to your startup command:
java -javaagent:/opt/otel/opentelemetry-javaagent.jar -Dotel.service.name=order-service -Dotel.traces.exporter=otlp -Dotel.exporter.otlp.endpoint=https://otlp.jjhub.cn:4317 -Dotel.exporter.otlp.headers="Authorization=Bearer <token>" -jar app.jar
Four parameters do the work: service.name groups the service in the topology; traces.exporter picks the exporter; otlp.endpoint points at OBSERVE's OTLP receiver; headers carry the auth. The agent intercepts Spring MVC, the MySQL driver, Redis, Kafka, HTTP clients and other common components, generating spans automatically.
The mechanism is the same, only the carrier differs:
For Python:
pip install opentelemetry-distro opentelemetry-exporter-otlp
opentelemetry-bootstrap -a install
OTEL_SERVICE_NAME=user-service OTEL_EXPORTER_OTLP_ENDPOINT=https://otlp.jjhub.cn:4317 opentelemetry-instrument python app.py
Auto-instrumentation collects everything by default, which brings two costs in production: span volume explodes and storage bills rise, and high-frequency components (like a span per DB query) can slow requests down. Do these two things together:
Tune sampling. Add to the Agent flags:
-Dotel.traces.sampler=parentbased_traceidratio -Dotel.traces.sampler.arg=0.1
This keeps 10% of traces. When a parent span is sampled, the whole trace is kept, so you never get a half trace.
Containerize the Agent. On Kubernetes, mount the Agent jar into the Pod via an initContainer rather than baking it into the image, so Agent upgrades don't require rebuilding images. The key is a shared volume that mounts the agent directory into the main container's /opt/otel. Alternatively, run a per-node OTel Collector as a DaemonSet and point every Agent at it — that centralizes batching and lets you rotate tokens in one place instead of across every workload.
Once tracing works, push logs and metrics over OTLP as well, so you don't run three separate collectors for three signals. For the Java Agent, add two flags:
-Dotel.logs.exporter=otlp -Dotel.metrics.exporter=otlp
Now one Agent reports all three signals with a consistent service.name. In OBSERVE you can click from a span straight to the matching log lines and metric dashboards, instead of jumping between three tools during an incident.
Connected doesn't mean working. Verify in three steps:
Four frequent issues. First, an exporter/protocol mismatch throws unimplemented — try swapping the endpoint from 4318 (HTTP) to 4317 (gRPC) or vice versa. Second, forgetting to open the OTLP port in the firewall or security group inside containers. Third, leaving service.name unset, which dumps every service under unknown_service and crams the topology into one blob. Fourth, hosts with unsynchronized clocks make cross-service spans look inverted — tracing is sensitive to clock skew, so run NTP on every host.
For private protocols or in-house RPC that auto-instrumentation can't see, fill the gaps with manual spans. Auto first, manual second — that order gets you a complete trace map on day one.