@artus-engineering/n8n-nodes-loki
v1.1.2
Published
n8n community node to write log lines to Grafana Loki.
Readme
Table of Contents
- Features
- Installation
- Credential
- Node reference
- Automatic n8n context
- Workflow-level logging toggle
- Usage
- Loki push payload
- Troubleshooting
- Development
- Releases
Features
- Auto-detected Loki URL — Enter a base URL (
https://loki.example.com) or the full push endpoint (.../loki/api/v1/push); both work - Optional authentication — None, Basic Auth, Bearer Token, or a custom header — configured once on a reusable credential
- Custom headers & multi-tenant support — Arbitrary headers plus a dedicated
X-Scope-OrgIDtenant field - Plain text or JSON messages — Free-form JSON, or build a JSON object from typed key/value fields, no manual
JSON.stringifyneeded - Automatic n8n context — Every entry gets
job,workflowandworkflow_idstream labels plus the execution ID as structured metadata - Labels & structured metadata — Set additional Loki stream labels and per-entry structured metadata from the node UI
- Workflow-level mute — A
Set Workflow Loggingoperation on one Loki node turns logging off for every Loki node downstream, sub-workflows included, without disabling each one - Batching — Send all input items in a single push request (grouped into streams by label set), or one request per item
- Zero runtime dependencies — Uses n8n's built-in HTTP helpers only, per n8n's community node requirements
- Full TypeScript support — Written in strict TypeScript against
n8n-workflow's types
Installation
From the n8n GUI (recommended)
In n8n, go to Settings → Community Nodes → Install, and enter:
@artus-engineering/n8n-nodes-lokiSelf-hosted, via npm
npm install @artus-engineering/n8n-nodes-lokiSee n8n's community nodes installation guide for details (including instructions for npm-restricted or Docker deployments).
Credential
Create a Loki API credential and configure:
| Field | Description |
| --- | --- |
| Loki URL | Base URL or full push endpoint, e.g. https://loki.example.com or https://loki.example.com/loki/api/v1/push — both work |
| Authentication | None (default), Basic Auth, Bearer Token, or Header Auth |
| Username / Password | Shown for Basic Auth |
| Token | Shown for Bearer Token |
| Header Name / Header Secret | Shown for Header Auth, e.g. an X-Api-Key header |
| Tenant ID (X-Scope-OrgID) | Sent as X-Scope-OrgID for multi-tenant Loki setups. Leave empty otherwise |
| Custom Headers | Arbitrary name/value headers sent with every request |
| Ignore SSL Issues (Insecure) | Accept self-signed or otherwise invalid TLS certificates |
Use Test on the credential to verify connectivity (calls GET /loki/api/v1/labels).
Node reference
| Parameter | Description |
| --- | --- |
| Operation | Send Log — pushes one or more log lines to Loki. Set Workflow Logging — a pass-through switch that later Loki nodes read to mute or allow logging |
| Logging Enabled | Shown for Set Workflow Logging. Defaults to on. Turn off to mute every Loki node further down this workflow |
| Labels | Extra Loki stream labels (name/value pairs, Edit Fields–style). Shown for both operations: on Send Log they apply to this entry; on Set Workflow Logging they are added to every downstream Loki node. A same-name label on Send Log overrides the workflow default. job (n8n), workflow and workflow_id are added automatically. In workflow JSON this is { "assignments": [{ "name": "env", "value": "prod", "type": "string" }] } |
| Log Format | Text or JSON |
| Message | The plain-text log line (shown for Text) |
| JSON Input Mode | JSON (a raw JSON value) or Fields Below (build an object from typed fields) — shown for JSON |
| JSON | The raw JSON log line — shown for JSON Input Mode JSON |
| Fields | Name/Value/Type rows assembled into the JSON log line — shown for JSON Input Mode Fields Below. Same assignments JSON shape as Labels |
Options
| Option | Description |
| --- | --- |
| Timestamp | ISO-8601 or epoch (seconds/ms/µs/ns auto-detected). Defaults to now. Do not also add a timestamp label or JSON field — Loki already indexes this value on the entry |
| Structured Metadata | Extra per-entry structured metadata (indexed but not part of the stream labels). The execution ID is always added as execution_id. Also available on Set Workflow Logging as a default for downstream nodes |
| Send All Items in One Request | Default on. Groups all input items into one push request (still split into separate streams per distinct label set); disable to send one request per item. Send Log only |
| Additional Headers | Extra headers for this request, layered on top of the credential's. Also available on Set Workflow Logging as a default for downstream nodes |
| Timeout | Request timeout in ms (default 10000). Also available on Set Workflow Logging as a default for downstream nodes |
| Propagate to Sub-Workflows | Set Workflow Logging only, default on. Writes the resolved settings onto every item as _lokiLogging so sub-workflows inherit them |
Automatic n8n context
Every log entry is tagged with the current workflow without extra fields on the node:
| Field | Where it lands | Why |
| --- | --- | --- |
| job | Stream label | Fixed to n8n so every log from this node is queryable as one job |
| workflow | Stream label | Low cardinality — bounded by how many workflows you have |
| workflow_id | Stream label | Survives a rename; same cardinality as workflow |
| execution_id | Structured metadata | High cardinality — a new value every run, so it must not become a stream label |
| Entry timestamp | Loki value tuple ([ts, line]) | Already produced automatically. Do not add a timestamp label or JSON field |
A user-defined label or metadata key of the same name wins over the injected value. Structured metadata requires Loki 3.0+ with a TSDB schema v13.
Workflow-level logging toggle
n8n has no per-workflow setting a community node can register, so the mute switch lives on a Loki node itself.
- Drop a Loki node immediately after the trigger (or anywhere that is an ancestor of every Loki node you want to gate).
- Set Operation to
Set Workflow Logging. - Leave Logging Enabled on (the default) or turn it off to mute Loki for the rest of this workflow.
- Optionally add Labels and, under Options, Additional Headers, Structured Metadata, or Timeout. Those become defaults for every downstream
Send Lognode.
How later Send Log nodes resolve the switch and defaults:
- No control node upstream, or
Logging Enabledleft at its default / unset → logging stays on - Any enabled upstream control node resolving to off disables logging ("off wins")
- A control node that is itself disabled on the canvas is ignored, so disabling that node is the quick way to restore logging
- The control node can use an expression (
={{ $vars.LOKI_ENABLED }}). Expressions on a control node in the same workflow are evaluated in the reading Loki node's context;Logging Enabled,TimeoutandAdditional Headersare resolved once against the first input item,LabelsandStructured Metadataper item - An expression that resolves to something other than
false(including an unset variable) leaves logging on — the switch fails open - When logging is off, each
Send Lognode passes its input items through unchanged and does not call Loki - Workflow labels / headers / metadata are merged under the automatic n8n context; a same-name field on the Send Log node overrides the workflow default
- Workflow Timeout is used when the Send Log node has not added Timeout itself; a local Timeout always wins
- Several enabled control nodes merge nearest-last, so the control node closest to the Send Log node wins on colliding keys
The control operation does not require a Loki credential. Also skip Send All Items in One Request and Timestamp on the control node — those stay per Send Log node.
Sub-workflows
Nothing about a running workflow is visible from a sub-workflow, so the settings travel with the data: a control node writes them onto every item it passes through, under _lokiLogging. Execute Sub-workflow hands those items to the sub-workflow, where Loki nodes pick them up again — from their own input item, or from the Execute Sub-workflow Trigger if nodes in between rebuilt the items.
- Off stays off: a sub-workflow cannot re-enable logging its caller muted. A control node inside the sub-workflow can add labels, headers, metadata and a timeout on top, and merges the inherited settings into what it propagates further down, so nesting works to any depth
- The
Execute Sub-workflow Triggermust accept the extra field. With Input data mode set toDefine using fields below, n8n drops everything outside the declared schema — including_lokiLogging— so useAccept all data, or declare a_lokiLoggingfield - Turn the
Propagate to Sub-Workflowsoption off to leave the items untouched; the switch then applies inside the current workflow only - A Loki node used as an AI tool is not connected into the main flow and receives no items from it, so the switch does not reach it — mute those nodes on the canvas instead
Usage
Plain text
Set Log Format to Text and enter a message. job, workflow and workflow_id are added automatically:
Message: Workflow "Order Sync" completed successfullyFree-form JSON
Set Log Format to JSON, JSON Input Mode to JSON:
{
"event": "order.synced",
"orderId": "{{ $json.orderId }}",
"durationMs": 842
}Key/value JSON (no manual stringify)
Set JSON Input Mode to Fields Below and add typed fields:
| Name | Value | Type |
| --- | --- | --- |
| event | order.synced | String |
| orderId | {{ $json.orderId }} | String |
| durationMs | 842 | Number |
| success | true | Boolean |
Multiple items in one stream
With Send All Items in One Request enabled (default), feeding the node multiple input items with the same labels sends one push request containing one stream with all entries, sorted by timestamp — the efficient way to log a batch.
Loki push payload
The node builds a standard Loki push API request. For the plain-text example above, it sends:
{
"streams": [
{
"stream": { "job": "n8n", "workflow": "Order Sync", "workflow_id": "wCmWqkUNVuNhbIU0" },
"values": [
["1717000000000000000", "Workflow \"Order Sync\" completed successfully", { "execution_id": "1234" }]
]
}
]
}Troubleshooting
| Problem | Cause |
| --- | --- |
| 400 Bad Request mentioning a label | Label names must match [a-zA-Z_][a-zA-Z0-9_]* — no hyphens or leading digits |
| 400 — entry out of order / too far behind | Loki requires non-decreasing timestamps per stream; check the Timestamp option and clock skew |
| 401 / 403 | Check the credential's authentication settings and, for multi-tenant Loki, the Tenant ID (X-Scope-OrgID) field |
| ECONNREFUSED / TLS errors | Verify the Loki URL, and enable Ignore SSL Issues for self-signed certificates on self-hosted Loki |
Development
Clone the repository and install dependencies:
pnpm install
pnpm run dev # launches n8n on :5678 with this node hot-linkedRun the full check suite before opening a pull request:
pnpm run lint # biome
pnpm run lint:n8n # n8n node/credential structural rules
pnpm run typecheck
pnpm run build
pnpm run testSee AGENTS.md for contributor conventions.
Releases
Packages are published to npm when a GitHub Release is published.
- Ensure
mainis green. - Create a GitHub Release with a semver tag, e.g.
v0.2.0. - The publish workflow runs lint, type checks, builds, tests, and publishes to npm via Trusted Publishing with npm provenance (no npm token required).
The release tag (without the leading v) becomes the package version.
Maintained by Artus Engineering GmbH.
