This workflow corresponds to n8n.io template #7021 — we link there as the canonical source.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"id": "ikJVgTYkNi4QGQSa",
"name": "Loki-logs-slack",
"tags": [],
"nodes": [
{
"id": "b8d9c924-e6d2-456d-a4cb-b3a86ddd5b63",
"name": "\ud83d\udce5 Query Loki for Error Logs",
"type": "n8n-nodes-base.httpRequest",
"position": [
-20,
180
],
"parameters": {
"url": "http://loki-gateway.monitoring.svc.cluster.local:8080/loki/api/v1/query_range",
"options": {},
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "query",
"value": "{namespace=\"monitoring\"} |= \"error\""
},
{
"name": "start",
"value": "={{ (Date.now() - 10 * 60 * 1000) * 1000000 }}"
},
{
"name": "end",
"value": "={{ Date.now() * 1000000 }}"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "119d2d65-1ea5-4f10-bdcc-2b96078e62c3",
"name": "\ud83d\udd52 Every 5 Min Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-320,
180
],
"parameters": {
"rule": {
"interval": [
{
"field": "minutes"
}
]
}
},
"typeVersion": 1.2
},
{
"id": "645bbb13-b417-4752-9bee-12571e9b8127",
"name": "\ud83e\uddf9 Extract Log Fields",
"type": "n8n-nodes-base.code",
"position": [
260,
180
],
"parameters": {
"jsCode": "const results = $json.data.result || [];\nconst output = [];\n\nfor (const entry of results) {\n const stream = entry.stream;\n const logs = entry.values;\n\n for (const [timestampNs, logLine] of logs) {\n let extractedLog = null;\n\n // Try to extract `content:` from inside extracteddata=\"map[...]\"\n const extractedMatch = logLine.match(/extracteddata=\".*?content:(.*?)(?:\\s\\w+:|]\")/s);\n if (extractedMatch && extractedMatch[1]) {\n extractedLog = extractedMatch[1]\n .replace(/\\\\\"/g, '\"')\n .replace(/\\\\\\\\/g, '\\\\')\n .trim();\n }\n\n // If not extracted, fall back to raw logLine if it looks usable\n if (!extractedLog && logLine.includes(\"level=\")) {\n extractedLog = logLine.trim();\n }\n\n // Filter out unwanted log levels\n if (extractedLog && /level=(debug|info)/i.test(extractedLog)) {\n continue; // Skip this log\n }\n\n output.push({\n json: {\n log: extractedLog || null,\n pod: stream.pod || \"unknown\",\n node: stream.node || \"unknown\",\n namespace: stream.namespace || \"unknown\",\n container: stream.container || \"unknown\",\n timestamp: new Date(Number(timestampNs) / 1e6).toISOString()\n }\n });\n }\n}\n\nreturn output;\n"
},
"typeVersion": 2
},
{
"id": "e14bd03a-0fe9-4cc9-9a5b-0a88efd29f98",
"name": "\ud83e\udde0 Remove Duplicate Alerts",
"type": "n8n-nodes-base.code",
"position": [
580,
180
],
"parameters": {
"jsCode": "const seen = new Set();\nconst output = [];\n\nfunction normalizeLog(log) {\n return log\n .replace(/ts=\\S+/g, '') // Remove 'ts=...' timestamps\n .replace(/\\d+(\\.\\d+)?/g, '#') // Replace all numbers with #\n .replace(/'[^']*'/g, '\\'X\\'') // Mask quoted strings\n .replace(/\\\"[^\\\"]*\\\"/g, '\"X\"') // Mask quoted strings\n .toLowerCase()\n .trim();\n}\n\nfor (const item of items) {\n const pod = item.json.pod || 'unknown';\n const log = item.json.log || '';\n\n const normalized = normalizeLog(log);\n const dedupKey = `${pod}::${normalized}`;\n\n if (!seen.has(dedupKey)) {\n seen.add(dedupKey);\n output.push(item);\n }\n}\n\nreturn output;\n"
},
"typeVersion": 2
},
{
"id": "9542d315-ca20-4430-8510-342e70940b1e",
"name": "\ud83d\udce4 Send Alerts to Slack",
"type": "n8n-nodes-base.httpRequest",
"position": [
860,
180
],
"parameters": {
"url": "https://slack.com/api/chat.postMessage",
"method": "POST",
"options": {},
"sendBody": true,
"sendHeaders": true,
"authentication": "genericCredentialType",
"bodyParameters": {
"parameters": [
{
"name": "channel",
"value": "#k8s-alerts"
},
{
"name": "text",
"value": "=\ud83d\udea8 *Kubernetes Error Detected* *Pod:* {{$json[\"pod\"]}} *Namespace:* {{$json[\"namespace\"]}} *Container:* {{$json[\"container\"]}} *Node:* {{$json[\"node\"]}} *Timestamp:* {{$json[\"timestamp\"]}} *Log:* ```{{$json[\"log\"]}}```"
}
]
},
"genericAuthType": "httpBearerAuth",
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"credentials": {
"httpBearerAuth": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "a4e2ab3e-c6db-45eb-926b-ea92da23a8cb",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-480,
-280
],
"parameters": {
"width": 280,
"height": 400,
"content": "## \ud83d\udd14 Loki Error Logs to Slack (Deduplicated)\n\nThis workflow monitors Kubernetes logs via Loki and sends only **unique** errors to Slack every 5 minutes.\n\n### What It Does:\n- Queries Loki logs for error patterns\n- Filters & parses relevant logs\n- Removes duplicate alerts\n- Sends clean Slack messages\n\n\ud83d\udccc Customize this by editing the regex in the Loki node or modifying deduplication logic.\n\n"
},
"typeVersion": 1
},
{
"id": "42637755-742c-43a1-b37b-376830460397",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-400,
380
],
"parameters": {
"color": 7,
"height": 320,
"content": "### \ud83d\udd52 Trigger\n\nRuns every 5 minutes.\nYou can adjust this interval as needed.\n"
},
"typeVersion": 1
},
{
"id": "a5800428-c913-4ea9-b74a-23ff21825bd9",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-100,
380
],
"parameters": {
"color": 7,
"height": 320,
"content": "### \ud83d\udce5 Loki Log Query\n\nSends an HTTP request to Loki with:\n- Time range: last 10 minutes\n- Regex match: error, failed, timeout, oom, etc.\n- Namespaces can be customized\n\nEdit the regex to customize which logs you want.\n"
},
"typeVersion": 1
},
{
"id": "dbde5ffe-f631-4732-a2f0-8d6c697e203f",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
220,
380
],
"parameters": {
"color": 7,
"height": 320,
"content": "### \ud83e\uddf9 Log Parsing\n\nParses log entries from Loki response.\nExtracts:\n- Pod\n- Namespace\n- Container\n- Node\n- Timestamp\n- Log content\n\nSkips null/empty logs automatically.\n"
},
"typeVersion": 1
},
{
"id": "83a18658-0b88-4c96-bd5e-0c8b55515758",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
520,
380
],
"parameters": {
"color": 7,
"height": 320,
"content": "### \ud83e\udde0 Deduplication\n\nThis removes repeated alerts (same log content) in the current batch.\nUseful to avoid Slack spam during repeated errors.\n"
},
"typeVersion": 1
},
{
"id": "247c5a22-8520-42f0-a895-14b732d3896f",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
820,
380
],
"parameters": {
"color": 7,
"height": 320,
"content": "### \ud83d\udce4 Slack Notification\n\nPosts each alert to a Slack channel using Slack API.\nThe message includes:\n- \ud83d\udea8 Emoji\n- Pod metadata\n- Log message (wrapped in triple backticks)\n\nEnsure you\u2019ve set your Slack token + channel name.\n"
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "f9fd9ad5-0f02-42dc-9807-e5fa007dec5d",
"connections": {
"\ud83e\uddf9 Extract Log Fields": {
"main": [
[
{
"node": "\ud83e\udde0 Remove Duplicate Alerts",
"type": "main",
"index": 0
}
]
]
},
"\ud83d\udd52 Every 5 Min Trigger": {
"main": [
[
{
"node": "\ud83d\udce5 Query Loki for Error Logs",
"type": "main",
"index": 0
}
]
]
},
"\ud83e\udde0 Remove Duplicate Alerts": {
"main": [
[
{
"node": "\ud83d\udce4 Send Alerts to Slack",
"type": "main",
"index": 0
}
]
]
},
"\ud83d\udce5 Query Loki for Error Logs": {
"main": [
[
{
"node": "\ud83e\uddf9 Extract Log Fields",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
httpBearerAuth
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Efficiently monitor Kubernetes environments by sending only unique error logs from Grafana Loki to Slack. Reduces alert fatigue while keeping your team informed about critical log events. DevOps or SRE engineers running EKS/GKE/AKS Anyone using Grafana Loki and Promtail for…
Source: https://n8n.io/workflows/7021/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This workflow is an automated employee time tracking and reporting system that monitors weekly work hours via TMetric, then delivers personalized summaries directly to each team member on Slack. It co
Import Productboard Notes Companies And Features Into Snowflake. Uses stickyNote, httpRequest, splitOut, snowflake. Scheduled trigger; 35 nodes.
Import Productboard Notes, Companies and Features into Snowflake. Uses stickyNote, httpRequest, splitOut, snowflake. Scheduled trigger; 35 nodes.
This workflow imports Productboard data into Snowflake, automating data extraction, mapping, and updates for features, companies, and notes. It supports scheduled weekly updates, data cleansing, and S
Elevate your shopping experience with an AI-driven personal assistant that lives right in your WhatsApp. This template automates the entire lifecycle of a shopping list—from intelligent intake and liv