Stop wiring a separate SDK into every app. This guide shows how to use the OpenTelemetry Collector for unified collection, transformation and export, with a copy-paste config that ships logs, metrics and traces to Observe in one shot.
Many teams integrate with an observability platform the hard way: Logback appenders for logs, Micrometer for metrics, the OTel SDK for traces — each wired separately. Once the service count grows, these three configurations become a maintenance burden, and changing one ingestion endpoint means touching dozens of services. Worse, each path applies its own sampling, buffering and retry logic, so the three signals drift out of sync and become hard to correlate during an incident.
The OpenTelemetry Collector collapses all of that into a single point. Applications only send telemetry to the Collector, which handles filtering, redaction, routing and export uniformly. To switch backends, you change the Collector once. Beyond consolidation, the Collector gives you one place to enforce sampling, redaction and rate limiting — policies that would otherwise be re-implemented, slightly differently, in every single service.
The Collector is organized around four concepts, and understanding them makes the config file far less intimidating:
That layering is why one Collector can serve logs, metrics and traces at once, each with different processors.
Run a single instance in agent mode — a binary or container on the same host (or Pod) as your services — so telemetry is gathered locally before export:
docker run -d --name otelcol \
-v ./otelcol-config.yaml:/etc/otelcol/config.yaml \
otel/opentelemetry-collector-contrib:0.95.0
Here is a skeleton that ships all three signal types to Observe:
receivers:
otlp:
protocols:
grpc: { endpoint: 0.0.0.0:4317 }
http: { endpoint: 0.0.0.0:4318 }
filelog:
include: [/var/log/app/*.log]
operators:
- type: regex_parser
regex: '^(?P<ts>[^ ]+) (?P<level>\w+) (?P<msg>.*)$'
processors:
batch:
timeout: 5s
send_batch_size: 1024
memory_limiter:
check_interval: 1s
limit_mib: 512
exporters:
otlphttp:
endpoint: https://ob.example.com/otlp
headers:
Authorization: "Bearer ${OBSERVE_TOKEN}"
service:
pipelines:
traces: { receivers: [otlp], processors: [memory_limiter, batch], exporters: [otlphttp] }
metrics: { receivers: [otlp], processors: [memory_limiter, batch], exporters: [otlphttp] }
logs: { receivers: [otlp, filelog], processors: [memory_limiter, batch], exporters: [otlphttp] }
Three pipelines share one otlphttp exporter, so logs, metrics and traces are configured in a single pass. For larger fleets, add a second Collector in gateway mode to aggregate several agents before forwarding to Observe — but start with agent mode.
Applications no longer talk to the platform directly; they point at the local Collector on port 4317:
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
export OTEL_SERVICE_NAME=order-service
java -javaagent:opentelemetry-javaagent.jar -jar app.jar
Java, Go and Python all ship agents or SDKs; once attached, logs, metrics and traces flow over OTLP automatically. If an app cannot add a dependency, the filelog receiver above can still tail log files and forward them as structured records.
The Collector is the best place for unified data governance. Production logs are full of phone numbers and ID card numbers, so add a redaction or transform processor to strip sensitive fields before they leave the machine — not after the data is already in the platform:
processors:
redaction:
allow_all_keys: false
blocked_values: ["\d{11}", "\d{18}"]
Doing this at the edge means a misconfiguration never leaks raw sensitive values into the platform or its backups.
After the app starts, confirm each signal shows up in Observe:
SELECT * FROM logs WHERE service = 'order-service' ORDER BY ts DESC LIMIT 10
Then open a recent request in the trace list and confirm the spans nest correctly. If logs arrive but traces do not, the trace pipeline is usually missing its receiver, or the exporter is misconfigured.
curl http://localhost:4318/v1/traces to confirm the Collector is up.Authorization header token matches the one in the platform's Service Management.