← Back to blog
Guide 4 min read 炬鲸团队

Instrument with OpenTelemetry in Five Minutes: Auto-Instrumentation to Distributed Tracing

Wire up distributed tracing with OpenTelemetry auto-instrumentation and barely touch your code. This guide covers Java/Go dependencies, OTLP exporter config, sampling strategy, and the mistakes beginners hit most.

OpenTelemetry (OTel) has become the de facto standard for tracing and metrics. The vendor-specific SDKs of recent years have largely converged onto it, which means instrumenting with OTel decouples your code from any single backend. If you switch observability vendors, you change the Exporter configuration and leave your business code untouched. Jujing OBSERVE speaks the OTLP protocol natively, so wiring it in is nearly zero-effort. This guide takes you from nothing to a full trace in about five minutes.

Add the SDK and Instrument

For a Java service, add the API dependency:

<dependency>
  <groupId>io.opentelemetry</groupId>
  <artifactId>opentelemetry-api</artifactId>
  <version>1.40.0</version>
</dependency>

For Go:

go get go.opentelemetry.io/otel

The least-effort path is auto-instrumentation. For Java, attach the agent with a single JVM flag and it intercepts HTTP, database, and message-queue calls across mainstream frameworks:

java -javaagent:opentelemetry-javaagent.jar -jar app.jar

No code changes required — the agent generates spans for inbound requests, outbound calls, and database queries automatically. Python and Node.js have equivalent agents; for Python it's a one-liner:

pip install opentelemetry-distro
opentelemetry-instrument python app.py

If you need finer control, add manual spans around business-critical methods with tracer.startSpan("checkout") and set attributes for the order id or user id — those attributes are what let you search traces by business key later.

Point the Exporter at OBSERVE

In agent mode, everything is configured through environment variables:

export OTEL_EXPORTER_OTLP_ENDPOINT=https://ob.jjhub.cn/otlp
export OTEL_SERVICE_NAME=order-service
export OTEL_TRACES_SAMPLER=parentbased_traceidratio
export OTEL_TRACES_SAMPLER_ARG=0.1

OTEL_SERVICE_NAME is the identity your spans carry into the platform — keep it consistent with your service registry or you'll end up with duplicate entries for the same deployment. Start with a sampling ratio of 0.1 and adjust once traffic stabilizes. After starting the service, fire a few requests with curl, then open the tracing page in OBSERVE: you should see full call chains with per-hop latency.

Exporter Tuning for Production

Once traces are flowing, tune the exporter for real traffic. The OTLP exporter batches spans by default; in high-throughput services, raise the queue size with OTEL_BSP_MAX_QUEUE_SIZE to smooth out bursts, and lower OTEL_BSP_SCHEDULE_DELAY if you want traces closer to real time. Enable gzip compression on the exporter to cut egress bandwidth, and confirm the collector endpoint is reachable over the same network path your application uses — a silently dropped export is the most common reason traces show up only intermittently. When exports fail, the SDK retries with backoff, but if the queue overflows spans are dropped; that drop is an intentional trade-off to protect your application, so monitor exported-vs-dropped counts if completeness matters to you.

Sampling Strategy and Common Pitfalls

  • Sampling rate. Full sampling at production volume is both expensive and slow; 1% to 10% is usually enough to surface problems. Raise it per-endpoint for critical APIs rather than cranking it globally.
  • Span naming. The default span name looks like HTTP GET /user/12345; unique IDs in paths explode your cardinality and bloat the index. Normalize them to templates such as /user/{id}.
  • Propagating trace_id. Make sure your gateway and middleware forward the traceparent header, otherwise the chain breaks at the first hop and you'll only ever see single-service spans.
  • Correlating logs. Write trace_id into your application logs so you can jump between a log line and its trace during an incident — this single habit turns every error log into a tracing entry point.

Verifying Your First Trace

After the service is up, hit it a few times and open the trace detail page. Check three things: every hop you expect is present (gateway, service, database), the timing adds up roughly right, and the service name is what you set. If a hop is missing, it's almost always a traceparent header being dropped by a proxy or an SDK that wasn't loaded. Fix the propagation first, then look at sampling.

If a hop is present but has no children where you expected a database call, check that the auto-instrumentation actually covered that library — some older or less-common drivers need a manual span. Getting the first end-to-end trace usually takes under five minutes with the agent; the real work is deciding what to sample and how to name your spans.