No manual instrumentation — use the OpenTelemetry Java Agent to collect traces and metrics automatically, correlate logs by trace_id, and finish onboarding in ten minutes.
Manual instrumentation means adding span start/end calls to every method and passing context around by hand. It's invasive, easy to miss, and every change requires a redeploy. The OpenTelemetry Java Agent uses bytecode instrumentation to intercept mainstream frameworks automatically — Spring MVC, HTTP clients, JDBC, message queues — and produces complete traces and metrics with zero changes to business code.
For a team that wants to get onto an observability platform fast, the Agent is the highest-leverage starting point: collect automatically first, then add manual spans to a few critical methods once you know where they are. The rule of thumb is simple — automate what you can, and save your manual-instrumentation effort for the core paths that genuinely need fine-grained spans.
One caveat worth knowing: the Agent only covers the frameworks it knows about. If you have a homegrown RPC library or a custom thread pool that isn't on the supported list, those calls won't show up as spans until you upgrade the Agent or add manual instrumentation there. Keep an eye on the OpenTelemetry instrumentation matrix for what each version covers.
Download opentelemetry-javaagent.jar from the official OpenTelemetry releases and put it in a fixed directory on the app server, then add these JVM options to the launch command:
java -javaagent:/opt/otel/opentelemetry-javaagent.jar -Dotel.service.name=order-service -Dotel.exporter.otlp.endpoint=https://ob.example.com/otlp -Dotel.exporter.otlp.headers=Authorization=Bearer <your-ingestion-token> -Dotel.metrics.exporter=otlp -Dotel.traces.sampler=parentbased_always_on -jar app.jar
Key options: service.name is the service name shown in the platform; exporter.otlp.endpoint is Observe's OTLP ingestion address; metrics.exporter=otlp turns on metric export. The token travels in a request header, so no code changes are needed. The traces.sampler line is optional but useful during onboarding — it samples every request so nothing hides while you verify; swap it for a probabilistic sampler later if volume becomes a concern.
If you run containers, put these lines into the JAVA_TOOL_OPTIONS environment variable and you won't even need to rebuild the image. That also decouples the Agent version from your app release cycle, which makes upgrades a one-line change. One more note on security: the token is a credential, so keep it in a secret manager or environment variable rather than committing it to a repo alongside the launch script.
The Agent automatically injects trace_id and span_id into the log MDC. Print them in your logback or log4j2 pattern:
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} [%X{trace_id}] - %msg%n</pattern>
Now every log line carries a trace_id. In Observe, the log detail view links straight to the corresponding trace, and every span in a trace can pull up its associated logs. This is the single most valuable step for debugging slow calls and errors — don't skip it. When teams onboard and later say "I have traces but troubleshooting still feels slow," the missing step is almost always this one.
Two small details to get right. First, make sure the pattern change actually reaches production — a log config that only exists in a developer's local logback.xml helps nobody. Second, if you also emit structured JSON logs, include trace_id and span_id as top-level fields, not buried in the message text, so the platform can index them as first-class fields.
Start the app, fire a few requests, then confirm three things in the console:
Common issues:
Bearer <token>%X{trace_id} is in the pattern and logs are emitted after the Agent initializesmetrics.exporter=otlp and that the ingestion address supports OTLP/HTTP metricsOnce it works, turn these launch options into a standard team template so every new service copies them instead of re-deriving them from scratch. When you're comfortable with automatic instrumentation, the natural next step is a few manual spans on your most important business methods — the Agent gives you a complete baseline, and targeted manual spans add the business-level detail (order ids, customer tiers, batch numbers) that actually matters when someone is on call at 3am trying to answer "did this one order succeed?".