Skip to main content
Technical Preview

Overview

A client-mode connector for the Grafana Loki HTTP API. Use it to ship broker events (alarms, state changes, machine messages) into Loki as log lines labelled with their MQTT topic, so they sit next to your other logs in Grafana, and to pull LogQL results (error counts per line, the last alarms on a machine) back onto MQTT. Set BASE_ADDRESS to your Loki URL with no trailing slash, for example http://loki.plant.local:3100 (keep USE_SSL "false" for plain HTTP) or https://logs-prod-XXX.grafana.net for Grafana Cloud (set USE_SSL "true"). Topics use analytics/loki/<object>/<verb>; replies land on <topic>/response. See the base guide: REST API Connectors.
Tenant and auth: every /loki/api/v1 event sends X-Scope-OrgID: {value.json.tenant}. Multi-tenant Loki (auth_enabled: true) rejects calls without it (401 no org id) and keeps each tenant’s data separate. Single-tenant Loki ignores the header. Loki OSS has no built-in authentication, so put it behind a gateway or reverse proxy. Grafana Cloud Logs uses Basic auth with your numeric Loki user id and a Cloud access policy token (logs:write, logs:read); set them on the connector with WITH USERNAME and WITH PASSWORD GET SECRET "GRAFANA_CLOUD_LOKI_TOKEN" so the token stays in Hub secrets and out of MQTT payloads. Never commit tokens.

Basic Syntax

MQTT examples

Push broker messages as log lines. Publish to analytics/loki/push:
Each stream is one label set; values holds [timestamp, line] pairs, where the timestamp is Unix time in nanoseconds as a string. An optional third element adds structured metadata (high-cardinality fields such as a machine or order id) without creating new streams. Loki answers 204 with an empty body. Keep labels few and low-cardinality (site, line, topic, level) and put values in the line or in structured metadata. Read recent lines. Publish to analytics/loki/query_range:
Reply (tested on Loki 3.7.8):
Structured metadata (machine) comes back as extra keys in stream, and stats (trimmed here) carries query statistics. Loki 3.x also adds service_name (set to unknown_service when the stream has no service label) and detected_level on ingest. Count alarms per level. Publish a metric query to analytics/loki/query (instant vector) or analytics/loki/query_range (matrix):
List the MQTT topics Loki has seen. Publish to analytics/loki/labels/values:
Labels takes {"tenant","since"} and Series takes {"tenant","match","since"}, where match is a stream selector such as {source="coreflux"}.

Notes

  • Query events send application/x-www-form-urlencoded bodies, so LogQL braces, quotes and |= work as written. A query that contains &, + or % must be percent-encoded by whoever builds the payload.
  • since accepts Loki durations (5m, 1h, 24h). Instead of since you can edit the template to send start and end (Unix nanoseconds or RFC 3339).
  • Loki rejects lines older than reject_old_samples_max_age (one week by default) and, per stream, lines far out of order; send current timestamps.
  • Errors: bad LogQL returns 400 with the parse error; a malformed push returns 400; a missing tenant on multi-tenant Loki returns 401 no org id. Grafana Cloud returns 401 for a wrong user id or token.
  • Not covered: the protobuf/snappy push format, OTLP ingest (/otlp/v1/logs), tail over WebSocket, index stats and volume, log deletion, and ruler / alerting APIs.
  • Suggested branches: feat/rest-api-route-grafana-loki, feat/docs-rest-api-grafana-loki (Hugo pushes).
Last modified on October 21, 2026