How do I line up Grafana Loki logs with Prometheus metrics for one service?
Tares lines up Loki 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 Prometheus source and a Loki source, label both by service, and open the service in Explore or read it from a connected agent.
How it works
Tares builds one timeline per entity key. The key is the source’s primary label, and any sources that share it are merged by time.
- The Prometheus connector polls the metrics you pick and turns each series into a metric event on every poll tick. The numeric value is stored as a number-typed
valuelabel. - The Loki connector polls log lines selected with a LogQL query, every 5 seconds by default. It works with Grafana Cloud too, and it takes the keys
url,query,bearer_token,username,password,tenant_id,match,dropandkey. - Both sources use the same label name,
service, marked primary, and the same service values. That shared key is what puts a service’s logs and metrics on one timeline.
Tares also keeps the metric value as a number, so a trigger can aggregate it later. This is the same per-service pattern the AI SRE guide uses, where metrics, logs and alerts are all keyed by service.
Set it up
- Install Tares and start it locally.
uv tool install tares # or: brew install glassflow/tap/tares
tares up- Add the Prometheus source in the console under Sources, Add source, Prometheus. Enter the Prometheus
url, use Discover, and pick the metrics for your service by name or by label. Tares generates the config and proposes the labels. Make the primary labelservice, read from the metric label that names your service. The generated config looks like this:
- 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-
Add the Loki source from Sources, Add source. Set its
urlto your Loki instance, and setqueryto a LogQL selector for the same service’s logs. Addusername,passwordorbearer_tokenif your Loki needs them. For Grafana Cloud, addtenant_idif it applies to your setup. -
Give the Loki source a label named
service, marked primary, with the same service value your metrics use. Labels take the keysname,field,const,primaryandtype. If one Loki query covers a single service, aconstlabel with that service name is the simplest choice. The value must match the metric side exactly, for exampleapi-serveron both. -
Check the result. In Explore, pick the service. You see Loki log lines and Prometheus metric events merged by time. Recent events on each source shows its own events, and Fields shows the labels.
-
To read the same timeline from an agent, start the MCP endpoint in a second shell and ask about the service.
tares mcpWhat you get
- One timeline per service, with log lines and metric values in time order, so you can see the error burst next to the latency climb that came with it.
- The same read for people and agents. Explore shows it in the console, and a connected MCP client gets it by asking about the service.
- Numeric metric values that triggers can aggregate with
max,avgorsum, filtered byevent_type. - A base you can extend. Add alert or deploy sources with the same
servicelabel and they land on the same timeline.
When something else fits
- If your logs come from a Docker container rather than Loki, the
docker_logsconnector tails them directly, and the same sharedservicelabel applies. - If you want a derived metric such as a p99 instead of raw series, the Prometheus connector accepts a computed series with an explicit
event_typeandfield.