Route traces, metrics, and logs into JJH OBSERVE through an OpenTelemetry Collector. Includes a minimal collector config, a Java auto-instrumentation example, and a debug checklist for when data doesn't appear.
Three things before you start:
For local verification you can run a single-node Collector in Docker, covered below. If you already run an OpenTelemetry deployment, skip the Collector section and point your existing exporter at the platform directly.
Use an OpenTelemetry Collector as the unified egress so your applications never talk to the platform directly. It also gives you one place to batch, retry, and redact data before it leaves your network. A minimal working config:
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
processors:
batch:
timeout: 5s
send_batch_size: 512
memory_limiter:
check_interval: 1s
limit_mib: 512
exporters:
otlphttp:
endpoint: https://ob.example.com/otlp
headers:
Authorization: "Bearer <token>"
service:
pipelines:
traces:
receivers: [otlp]
processors: [memory_limiter, batch]
exporters: [otlphttp]
metrics:
receivers: [otlp]
processors: [memory_limiter, batch]
exporters: [otlphttp]
logs:
receivers: [otlp]
processors: [memory_limiter, batch]
exporters: [otlphttp]
Three things matter here:
For Java, the automatic instrumentation agent gives you traces, metrics, and logs with zero code changes:
java -javaagent:opentelemetry-javaagent.jar \
-Dotel.traces.exporter=otlp \
-Dotel.metrics.exporter=otlp \
-Dotel.logs.exporter=otlp \
-Dotel.exporter.otlp.endpoint=http://localhost:4317 \
-Dotel.service.name=order-service \
-jar order-service.jar
Two settings worth adding in production: otel.resource.attributes=service.version=<version> so you can diff latency by release, and otel.traces.sampler with a sensible ratio (start at 1.0 and lower it as volume grows).
Go and Python follow the same model but need explicit instrumentation. In Go you wrap handlers with otelhttp and add a trace provider at startup; in Python you run opentelemetry-instrument python app.py. Whatever the language, the one rule that matters is service.name: it must be globally unique and semantically clear (order-service, pay-gateway). That name is the join key for per-service aggregation and topology graphs, and renaming it later breaks your historical views.
Within about a minute, the Service Topology and Tracing pages should show data.
Before you call the integration done, run through these:
These are the settings that separate a demo from something you can leave running unattended overnight.
If nothing appears, work through this checklist in order:
To confirm end-to-end correlation, log a trace_id from your code and look it up in the platform — if the trace shows up but no logs attach to it, your logs pipeline isn't propagating trace context.
That's the whole onboarding path: one Collector, one agent flag, one token. Everything after that is tuning, which we cover in the sampling and retention guides.