- An
otlpdrain in statehealthy, delivering into a collector. - A Loki datasource in Grafana, receiving from that collector.
- Grafana 10 or later.
The queries assume Loki 3.x with OTLP ingestion, where
service.name becomes the service_name stream label and the remaining resource and record attributes become structured metadata with every non-alphanumeric character replaced by _ — so severity_text, gen_ai_tool_name, lua_drain_backlog. If your pipeline promotes a different set of attributes to labels, change the stream selector in each panel; the filter stages after it stay as they are.What you get
An
$agent template variable over service_name scopes all four panels to one agent or to all of them.
Import it
1
Save the dashboard
Save the JSON below as
lua-grafana-dashboard.json.2
Import
In Grafana, Dashboards → New → Import, upload the file, pick your Loki datasource for the
DS_LOKI input, and Import.The dashboard’s UID is lua-log-drain, so re-importing updates it in place rather than creating a second copy.3
Check the heartbeat panel
It should read
3 within fifteen minutes of a healthy drain. DOWN in red means either no heartbeat reached Loki or the attribute name differs in your pipeline — run the panel’s query in Explore and confirm lua_drain_backlog is the structured-metadata name your Loki produced.The dashboard
lua-grafana-dashboard.json
Why these selectors
Each panel keys on a field that is unique to what it measures, which avoids depending on the OTLPeventName field reaching Loki as a queryable label:
severity_textdistinguishes the four severities directly.gen_ai_tool_nameis present only on tool calls, soseverity_text = "ERROR"plus that attribute is exactly “a tool call failed”, across skills and MCP servers.lua_drain_backlogis present only on the heartbeat record. Counting records that carry it is counting heartbeats.
lua_drain_dropped_count appears only on a drop record, and lua_truncated_lines only on a truncation record.
@lua.eventName instead, because the Datadog encoder ships the whole record as a nested object and the event name is directly addressable there. The two packs watch the same four signals from opposite ends of the schema.
Alert on it
Grafana alert rules over the same queries, if Grafana rather than the backend owns your alerting:Drain heartbeat missing — alert when IS BELOW 1 for 5m
Errors spiking — alert when IS ABOVE 5 for 5m
Records dropped — alert when IS ABOVE 0
Alerting: with no heartbeats there is no series at all, and the default of No Data would leave it silent exactly when it matters.
Next steps
OpenTelemetry Collector config
The pipeline that feeds this dashboard.
OpenTelemetry
Create the drain.
Event schema
Where these attribute names come from.
Datadog monitor pack
The same signals, in Datadog.

