How do I line up logs from Docker containers with Prometheus metrics for one service?
Tares lines up Docker logs and Prometheus metrics when both sources carry the same primary service label. One read of that service then returns the log lines and the metric values merged on one clock. You add a docker_logs source and a prometheus source, and give each a primary service label with the same value.
How it works
Every source in Tares can declare labels, and one label is marked primary. The primary label is the entity key. Events from different sources that share the same primary value land on the same timeline for that entity.
- The Docker logs connector tails a running container and stores one event per log line. You set the primary
servicelabel with a constant, for exampleapi-server. - The Prometheus connector turns each series you pick into a metric event on every poll tick. You set the primary
servicelabel from the metric’s ownservicelabel, which appears asmetric.service. - The metric value is stored as a number-typed
valuelabel, so triggers can aggregate it withmax,avgorsum.
Because both sources key on service with the same value, a read of api-server returns log lines and metric values together, ordered by time. The same read is what an agent works from in the AI SRE guide.
Set it up
-
Install Tares and start it locally.
uv tool install tares # or: brew install glassflow/tap/tares tares up -
Add the logs source under Sources, Add source, docker_logs. Set
containerto the container name fromdocker ps, and give it a primaryservicelabel. Tares needs access to the Docker daemon, so runtaresdon the host or mount the Docker socket. If the container runs under Compose, setcompose_fileso the tail follows restarts.- 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 metrics source under Sources, Add source, Prometheus. Enter the
url, choose Discover, and pick the metrics by name or by label. There is no PromQL to write. Tares proposes the labels from a sample. Make sure the primaryservicelabel reads from the metric’sservicelabel and that its values match the constant you used for the logs, hereapi-server.- name: metrics connector: prometheus poll: 10s config: url: http://localhost:9090 queries: - promql: '{__name__=~"(pg_stat_database_xact_commit|pg_up)"}' # generated from your picks by_name: true labels: - { name: service, field: metric.service, primary: true } - { name: value, field: value, type: number } # the metric value, aggregate it in triggers -
Verify each source. Open it in the console. Recent events shows lines or series on the next poll. For metrics, Fields shows
metric.serviceand the numericvalue. If no logs arrive, check thattaresdcan rundocker logsfor that container. -
Read the service. Open Explore and pick
api-serverto see logs and metrics merged on one clock. To read it from an agent, start the MCP endpoint in a second shell and ask your client about the service.tares mcp
You can also ask a connected agent to do steps 2 and 3. It uses discovery to find the container and the metrics, tests the source with a dry run, then creates it.
What you get
- One timeline per service. Log lines from the container and metric values from Prometheus sit side by side, ordered by time, so you see an error burst next to the metric that moved.
- Metric values you can act on. Because
valueis number-typed, a trigger can filter to one metric byevent_typeand aggregatevalueper service. - The same view for agents. An MCP client reading the service gets the correlated evidence in one call instead of querying each system separately.
- A pattern that extends. Any further source you key by the same
servicelabel, such as alerts fromprometheus_alerts, joins the same timeline.
When something else fits
- If your logs come from an OpenTelemetry pipeline rather than a container on the local Docker daemon, use the OTLP connector for logs and keep the same
servicelabel on the Prometheus source. - If you want to compute a derived series such as a p99 or a rate, the Prometheus connector accepts a single PromQL expression with an explicit
event_typeandfield. Use that only when raw metrics are not enough.