How do I line up logs from Docker containers with OpenTelemetry metric series for one service?
Tares lines them up when both sources carry the same primary service label. Give the docker_logs source a constant service value, make sure your OpenTelemetry exporter sets service.name to that same value, and one read of the service returns the log lines and the metric values on one clock. The otlp source takes its service label from service.name, so you only need to match the Docker side to it.
How it works
Tares correlates events by label. Every source declares labels, and one of them is marked primary. Sources that share the same primary key and value land on one timeline for that service.
- The Docker logs connector tails a running container’s logs, one event per line. You set the
servicelabel as a constant in the source config, for exampleapi-server. - The OpenTelemetry connector receives OTLP logs, traces and metrics. One
otlpsource ingests every service. Resource attributes such asservice.namebecome labels, and theservicelabel is read fromservice.name. - When both carry
serviceas the primary label with the same value, the container’s log lines and the metric points sit together on that service’s timeline, merged on one clock.
The value is what ties them together. If the container label says api-server and the exporter sends service.name as checkout, you get two separate timelines. Pick one name and use it on both sides.
This is the same per-service pattern the AI SRE guide builds on: sources keyed by one service label, read as a single timeline by you or by an agent.
Set it up
- Start Tares locally and open the console.
tares up- Add the Docker logs source. Go to Sources → Add source → docker_logs, or ask a connected agent to find your containers and ingest the logs. Set
containerto the container name fromdocker ps, and give it a constantservicelabel marked primary. Tares needs access to the Docker daemon: runtaresdon the host, or mount the Docker socket and include the Docker CLI in the image.
- name: logs
connector: docker_logs
poll: 5s
config:
container: tares-demo-api-server # the container name (docker ps)
labels:
- { name: service, const: api-server, primary: true }- Add the OpenTelemetry source. Go to Sources → Add source → otlp. It has no required config. The
servicelabel, read fromservice.name, is the key, and you mark it primary.
- name: otel
connector: otlp
config:
labels:
- { name: service, field: service, primary: true }- Point your exporter at Tares and set the service name to the value you used in the Docker source. Here the endpoint is OTLP/HTTP, and the gRPC alternative needs the
otlp-grpcextra.
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:8787 # OTLP/HTTP → /v1/{logs,traces,metrics}
# or gRPC (otlp-grpc extra): OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317In your app or Collector, make service.name equal api-server, matching the constant in step 2. If Tares runs with auth on, the exporter sends a Bearer Authorization header holding an ingest-scoped API key. Without auth, no header is needed.
-
Check both sides. Open each source in the console and look at Recent events: the Docker source shows lines on the next poll, and the OTLP source shows metric points as they arrive. If the Docker source stays empty, check that
taresdcan rundocker logson the container. -
Read the service. In Explore, the services are listed under the
servicekey. Pickapi-serverand you see log lines and metric values merged on one clock. A connected MCP client gets the same view when it callsreadfor that service.
What you get
- One timeline per service that holds the container’s log lines and the OpenTelemetry metric points together, ordered on one clock.
- A single read for an agent or for you. You do not query the log source and the metric source separately and line up timestamps by hand.
- No per-service setup on the OpenTelemetry side. The one
otlpsource takes every service your exporters send, and each new service shows up under theservicekey as soon as it exports. - A Docker side you can tune without touching the correlation:
matchkeeps only lines that match a regex, such asERROR|WARN, anddropskips noisy lines such as access logs. Theservicelabel stays the same. - A base for triggers and agents. Because the sources are keyed by
service, a trigger or an agent in the AI SRE flow works from the same correlated timeline.
When something else fits
- If the metrics live in a Prometheus server rather than arriving as OTLP, use the Prometheus connector and give it the same primary
servicelabel. The correlation works the same way. - If your logs already reach Tares through OpenTelemetry, you do not need
docker_logs. Theotlpsource takes logs and metrics together and keys both byservice.name. - If the container name or service name differs between the two worlds and you cannot change it, set the constant in the
docker_logslabel to whateverservice.namethe exporter sends.