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

Onboarding OpenTelemetry in 30 Minutes: Collector to JJWhale OBSERVE

A step-by-step guide to shipping traces, metrics, and logs into JJWhale OBSERVE via the OpenTelemetry Collector, with a complete config file, multi-language instrumentation examples, and verification commands.

Onboarding OpenTelemetry in 30 Minutes: Collector to JJWhale OBSERVE

OpenTelemetry has become a de facto standard, but plenty of teams still get stuck on how to ship all three signal types into a backend. This guide uses a minimal setup to get traces, metrics, and logs flowing into JJWhale OBSERVE in about half an hour.

Step 1: Deploy the Collector

Run a local Collector from the official Docker image rather than piling config into your business processes. Keeping the Collector as a separate sidecar means your apps only need to speak OTLP to localhost, and you can change backends without touching application code:

docker run -d --name otel-col \
  -v $(pwd)/otel-collector.yaml:/etc/otel/config.yaml \
  otel/opentelemetry-collector-contrib:0.110.0 \
  --config=/etc/otel/config.yaml

Use the contrib build, which ships with a wider set of receivers and exporters. Make sure your workloads can reach ports 4317 (gRPC) and 4318 (HTTP) on the Collector.

Step 2: Write the Config

The otel-collector.yaml below accepts OTLP data and forwards it to JJWhale OBSERVE:

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: 5s
    limit_mib: 512
exporters:
  otlphttp:
    endpoint: https://ob.jjhub.cn/otel/v1
    headers:
      Authorization: Bearer <your 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]

Each pipeline handles one signal type. The batch processor buffers scattered data before sending, which substantially reduces backend load, while memory_limiter stops the Collector's own memory from blowing up. Generate the token on the "Ingest Config" page of the JJWhale OBSERVE console.

Step 3: Instrument Your Code

For Java, the opentelemetry-javaagent gives you automatic instrumentation with no code changes:

java -javaagent:opentelemetry-javaagent.jar \
  -Dotel.exporter.otlp.endpoint=http://localhost:4317 \
  -Dotel.service.name=order-api \
  -jar order-api.jar

You get request traces and basic metrics out of the box. The same pattern works across languages — a Go service imports the SDK and registers the OTLP exporter, while a Python service can use opentelemetry-instrument to auto-instrument common frameworks. When you need business semantics such as "place order" or "deduct stock", add spans manually and attach them to the existing trace, so business actions become visible inside the full call chain.

Step 4: Verify Data Has Arrived

Wait about a minute, then check three places in JJWhale OBSERVE: search order-api on the tracing page to see individual traces, open the metrics page for JVM and HTTP metrics, and check the logs page for forwarded entries. If all three show data, you are done. To debug the pipeline itself, run docker logs otel-col and look for export errors — the Collector logs every failed batch with the exporter that rejected it and the HTTP status, which usually points straight at the token or the endpoint URL.

How the Pieces Fit Together

It's worth being clear about what the Collector is actually doing, because it explains most troubleshooting. Your application sends OTLP to the receiver on ports 4317 or 4318. The data then flows through the processors in the order listed — memory_limiter first to protect the process, then batch to group spans, metrics, and logs before sending. Finally, the otlphttp exporter forwards each batch to JJWhale OBSERVE over HTTPS with your token. Every stage logs failures, so when data goes missing, docker logs otel-col is the first place to look, and a rejected batch names the exact exporter responsible.

Sizing and Going Further

For a small fleet, a single Collector with 512 MiB is enough. As volume grows, run one Collector per cluster or availability zone and keep it close to your workloads to cut network hops. You can add more receivers (Prometheus scrape, file tailing) and processors (resource detection, redaction) later without changing the exporters, because the Collector keeps signal handling and delivery cleanly separated. In production, front the OTLP endpoints with mTLS or a network policy so only your own workloads can push data — the receiver itself does no authentication.

Common Pitfalls

  • 401 errors: check that the token in the Authorization header is valid and has no stray spaces.
  • Intermittent data: verify the batch timeout and network connectivity to the backend.
  • Mismatched metrics: keep service.name consistent across processes, otherwise traces and metrics for the same service won't line up.