Dashboard: - Dark theme by default (zinc-950 background, high-contrast status colors) - Layout: sticky header with live status, hero HealthBanner, FailuresPanel, AnomaliesPanel, 2-col grid (Workflows + Activity), StatsStrip footer - Auto-detected anomalies: stale active workflows, 100% fail rate, stuck running - Click any failure/activity row → links to n8n execution view (VITE_N8N_URL) - VITE_N8N_URL env var threaded through Dockerfile + compose Poller (poller.n8n.json): - Fetch n8n Executions: includeData false → true (now includes execution data) - Create/Update Execution Record: extract error_message from data.resultData.error using a safe IIFE that JSON.parses the data field Also: - Added vite-env.d.ts so VITE_* env vars are typed - docker-compose.yml: VITE_N8N_URL added to build args - .env.example: documented VITE_N8N_URL at root and dashboard level
571 lines
No EOL
15 KiB
JSON
571 lines
No EOL
15 KiB
JSON
{
|
|
"name": "n8n Monitoring Dashboard - Poller",
|
|
"nodes": [
|
|
{
|
|
"parameters": {
|
|
"content": "## Setup\n1. Create an \"HTTP Header Auth\" credential named \"n8n API Key\" (header X-N8N-API-KEY = your n8n API key).\n2. Create an \"HTTP Header Auth\" credential named \"PocketBase Admin\" (header Authorization = \"Bearer <your PocketBase admin token>\").\n3. PocketBase base URL is pre-set to http://pocketbase-fftm1vu8twxfixup17v82xwe.169.239.180.130.sslip.io \u2014 no change needed.\n4. Collections already created in PocketBase.\n5. Activate this workflow when ready.",
|
|
"height": 200,
|
|
"width": 300,
|
|
"color": 4
|
|
},
|
|
"id": "ec8c99c4-8f93-4a84-af5b-8e64d74d553e",
|
|
"name": "Sticky Note 67b8b148",
|
|
"type": "n8n-nodes-base.stickyNote",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
-256,
|
|
256
|
|
]
|
|
},
|
|
{
|
|
"parameters": {
|
|
"rule": {
|
|
"interval": [
|
|
{
|
|
"field": "minutes"
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"id": "0b884dbe-36c1-420b-be75-671c93187ba5",
|
|
"name": "Every 5 Minutes",
|
|
"type": "n8n-nodes-base.scheduleTrigger",
|
|
"typeVersion": 1.3,
|
|
"position": [
|
|
-192,
|
|
304
|
|
]
|
|
},
|
|
{
|
|
"parameters": {
|
|
"url": "https://wfdash.n8n.apphub.co.za/api/v1/workflows",
|
|
"authentication": "genericCredentialType",
|
|
"genericAuthType": "httpHeaderAuth",
|
|
"options": {}
|
|
},
|
|
"id": "aa3f8fb7-e934-422b-ae7b-0684f40fcbc1",
|
|
"name": "Fetch n8n Workflows",
|
|
"type": "n8n-nodes-base.httpRequest",
|
|
"typeVersion": 4.3,
|
|
"position": [
|
|
112,
|
|
160
|
|
]
|
|
},
|
|
{
|
|
"parameters": {
|
|
"fieldToSplitOut": "data",
|
|
"options": {}
|
|
},
|
|
"id": "eea0d135-d067-46b3-9314-1e24787c603f",
|
|
"name": "Split Workflows Array",
|
|
"type": "n8n-nodes-base.splitOut",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
400,
|
|
160
|
|
]
|
|
},
|
|
{
|
|
"parameters": {},
|
|
"id": "53071f8d-f8be-4c41-aa85-4d6b87928c5a",
|
|
"name": "Workflows Sync Done",
|
|
"type": "n8n-nodes-base.noOp",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
1904,
|
|
160
|
|
]
|
|
},
|
|
{
|
|
"parameters": {
|
|
"url": "http://pocketbase-fftm1vu8twxfixup17v82xwe.169.239.180.130.sslip.io/api/collections/workflows/records",
|
|
"authentication": "genericCredentialType",
|
|
"genericAuthType": "httpHeaderAuth",
|
|
"sendQuery": true,
|
|
"queryParameters": {
|
|
"parameters": [
|
|
{
|
|
"name": "filter",
|
|
"value": "=(n8n_id=\"{{ $json.id }}\")"
|
|
}
|
|
]
|
|
},
|
|
"options": {}
|
|
},
|
|
"id": "262ec577-9f0f-4914-80ec-23bde9ec37e5",
|
|
"name": "Check Workflow Record Exists",
|
|
"type": "n8n-nodes-base.httpRequest",
|
|
"typeVersion": 4.3,
|
|
"position": [
|
|
1008,
|
|
160
|
|
]
|
|
},
|
|
{
|
|
"parameters": {
|
|
"conditions": {
|
|
"options": {
|
|
"caseSensitive": true,
|
|
"leftValue": "",
|
|
"typeValidation": "loose",
|
|
"version": 1
|
|
},
|
|
"conditions": [
|
|
{
|
|
"leftValue": "={{ $json.totalItems }}",
|
|
"operator": {
|
|
"type": "number",
|
|
"operation": "gt"
|
|
},
|
|
"rightValue": 0
|
|
}
|
|
],
|
|
"combinator": "and"
|
|
},
|
|
"options": {}
|
|
},
|
|
"id": "8a5df769-640f-4f57-889a-9d92ab304b69",
|
|
"name": "Workflow Record Exists?",
|
|
"type": "n8n-nodes-base.if",
|
|
"typeVersion": 2.2,
|
|
"position": [
|
|
1312,
|
|
160
|
|
]
|
|
},
|
|
{
|
|
"parameters": {
|
|
"method": "PATCH",
|
|
"url": "={{ \"http://pocketbase-fftm1vu8twxfixup17v82xwe.169.239.180.130.sslip.io/api/collections/workflows/records/\" + $json.items[0].id }}",
|
|
"authentication": "genericCredentialType",
|
|
"genericAuthType": "httpHeaderAuth",
|
|
"sendBody": true,
|
|
"specifyBody": "json",
|
|
"jsonBody": "={{ { \"name\": $(\"Split Workflows Array\").item.json.name, \"active\": $(\"Split Workflows Array\").item.json.active, \"n8n_updated_at\": $(\"Split Workflows Array\").item.json.updatedAt } }}",
|
|
"options": {}
|
|
},
|
|
"id": "49ab8e98-0e47-48a4-8e78-1d7fb959f286",
|
|
"name": "Update Workflow Record",
|
|
"type": "n8n-nodes-base.httpRequest",
|
|
"typeVersion": 4.3,
|
|
"position": [
|
|
1600,
|
|
64
|
|
]
|
|
},
|
|
{
|
|
"parameters": {
|
|
"options": {}
|
|
},
|
|
"id": "a5290a91-9b2d-45e8-8851-2d702b406b5d",
|
|
"name": "Workflows: One At A Time",
|
|
"type": "n8n-nodes-base.splitInBatches",
|
|
"typeVersion": 3,
|
|
"position": [
|
|
704,
|
|
160
|
|
]
|
|
},
|
|
{
|
|
"parameters": {
|
|
"method": "POST",
|
|
"url": "http://pocketbase-fftm1vu8twxfixup17v82xwe.169.239.180.130.sslip.io/api/collections/workflows/records",
|
|
"authentication": "genericCredentialType",
|
|
"genericAuthType": "httpHeaderAuth",
|
|
"sendBody": true,
|
|
"specifyBody": "json",
|
|
"jsonBody": "={{ { \"n8n_id\": $(\"Split Workflows Array\").item.json.id, \"name\": $(\"Split Workflows Array\").item.json.name, \"active\": $(\"Split Workflows Array\").item.json.active, \"n8n_updated_at\": $(\"Split Workflows Array\").item.json.updatedAt } }}",
|
|
"options": {}
|
|
},
|
|
"id": "ac8f44a6-03e4-48c1-9536-5adfa6295427",
|
|
"name": "Create Workflow Record",
|
|
"type": "n8n-nodes-base.httpRequest",
|
|
"typeVersion": 4.3,
|
|
"position": [
|
|
1600,
|
|
256
|
|
]
|
|
},
|
|
{
|
|
"parameters": {
|
|
"url": "https://wfdash.n8n.apphub.co.za/api/v1/executions",
|
|
"authentication": "genericCredentialType",
|
|
"genericAuthType": "httpHeaderAuth",
|
|
"sendQuery": true,
|
|
"queryParameters": {
|
|
"parameters": [
|
|
{
|
|
"name": "limit",
|
|
"value": "50"
|
|
},
|
|
{
|
|
"name": "includeData",
|
|
"value": "true"
|
|
}
|
|
]
|
|
},
|
|
"options": {}
|
|
},
|
|
"id": "18ae2824-df7d-46f6-8606-8487306e8616",
|
|
"name": "Fetch n8n Executions",
|
|
"type": "n8n-nodes-base.httpRequest",
|
|
"typeVersion": 4.3,
|
|
"position": [
|
|
112,
|
|
560
|
|
]
|
|
},
|
|
{
|
|
"parameters": {
|
|
"fieldToSplitOut": "data",
|
|
"options": {}
|
|
},
|
|
"id": "7c79adc6-7b7b-43e2-9b2c-b6d914bcbeab",
|
|
"name": "Split Executions Array",
|
|
"type": "n8n-nodes-base.splitOut",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
400,
|
|
560
|
|
]
|
|
},
|
|
{
|
|
"parameters": {},
|
|
"id": "c3af8ab7-2976-47b8-87b4-9abc5e54a379",
|
|
"name": "Executions Sync Done",
|
|
"type": "n8n-nodes-base.noOp",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
1904,
|
|
560
|
|
]
|
|
},
|
|
{
|
|
"parameters": {
|
|
"url": "http://pocketbase-fftm1vu8twxfixup17v82xwe.169.239.180.130.sslip.io/api/collections/executions/records",
|
|
"authentication": "genericCredentialType",
|
|
"genericAuthType": "httpHeaderAuth",
|
|
"sendQuery": true,
|
|
"queryParameters": {
|
|
"parameters": [
|
|
{
|
|
"name": "filter",
|
|
"value": "=(n8n_execution_id=\"{{ $json.id }}\")"
|
|
}
|
|
]
|
|
},
|
|
"options": {}
|
|
},
|
|
"id": "bd057afd-4ac4-4834-8bde-f1e1824d42a4",
|
|
"name": "Check Execution Record Exists",
|
|
"type": "n8n-nodes-base.httpRequest",
|
|
"typeVersion": 4.3,
|
|
"position": [
|
|
1008,
|
|
560
|
|
]
|
|
},
|
|
{
|
|
"parameters": {
|
|
"conditions": {
|
|
"options": {
|
|
"caseSensitive": true,
|
|
"leftValue": "",
|
|
"typeValidation": "loose",
|
|
"version": 1
|
|
},
|
|
"conditions": [
|
|
{
|
|
"leftValue": "={{ $json.totalItems }}",
|
|
"operator": {
|
|
"type": "number",
|
|
"operation": "gt"
|
|
},
|
|
"rightValue": 0
|
|
}
|
|
],
|
|
"combinator": "and"
|
|
},
|
|
"options": {}
|
|
},
|
|
"id": "79569deb-1551-4823-9488-de30c81392fe",
|
|
"name": "Execution Record Exists?",
|
|
"type": "n8n-nodes-base.if",
|
|
"typeVersion": 2.2,
|
|
"position": [
|
|
1312,
|
|
560
|
|
]
|
|
},
|
|
{
|
|
"parameters": {
|
|
"method": "PATCH",
|
|
"url": "={{ \"http://pocketbase-fftm1vu8twxfixup17v82xwe.169.239.180.130.sslip.io/api/collections/executions/records/\" + $json.items[0].id }}",
|
|
"authentication": "genericCredentialType",
|
|
"genericAuthType": "httpHeaderAuth",
|
|
"sendBody": true,
|
|
"specifyBody": "json",
|
|
"jsonBody": "={{ { \"status\": $(\"Split Executions Array\").item.json.status, \"started_at\": $(\"Split Executions Array\").item.json.startedAt, \"stopped_at\": $(\"Split Executions Array\").item.json.stoppedAt, \"workflow_n8n_id\": $(\"Split Executions Array\").item.json.workflowId, \"error_message\": ((() => { try { return JSON.parse($('Split Executions Array').item.json.data || '{}')?.resultData?.error?.message || ''; } catch { return ''; } })()) } }}",
|
|
"options": {}
|
|
},
|
|
"id": "15dc5e8c-9d0f-4583-a0ce-dc43ea1b609c",
|
|
"name": "Update Execution Record",
|
|
"type": "n8n-nodes-base.httpRequest",
|
|
"typeVersion": 4.3,
|
|
"position": [
|
|
1600,
|
|
464
|
|
]
|
|
},
|
|
{
|
|
"parameters": {
|
|
"options": {}
|
|
},
|
|
"id": "71fa9479-a294-42bc-93f6-80c6d6885105",
|
|
"name": "Executions: One At A Time",
|
|
"type": "n8n-nodes-base.splitInBatches",
|
|
"typeVersion": 3,
|
|
"position": [
|
|
704,
|
|
560
|
|
]
|
|
},
|
|
{
|
|
"parameters": {
|
|
"method": "POST",
|
|
"url": "http://pocketbase-fftm1vu8twxfixup17v82xwe.169.239.180.130.sslip.io/api/collections/executions/records",
|
|
"authentication": "genericCredentialType",
|
|
"genericAuthType": "httpHeaderAuth",
|
|
"sendBody": true,
|
|
"specifyBody": "json",
|
|
"jsonBody": "={{ { \"n8n_execution_id\": $(\"Split Executions Array\").item.json.id, \"workflow_n8n_id\": $(\"Split Executions Array\").item.json.workflowId, \"status\": $(\"Split Executions Array\").item.json.status, \"started_at\": $(\"Split Executions Array\").item.json.startedAt, \"stopped_at\": $(\"Split Executions Array\").item.json.stoppedAt, \"error_message\": ((() => { try { return JSON.parse($('Split Executions Array').item.json.data || '{}')?.resultData?.error?.message || ''; } catch { return ''; } })()) } }}",
|
|
"options": {}
|
|
},
|
|
"id": "acd3d95a-1e95-4312-88f2-16ba8978c7e2",
|
|
"name": "Create Execution Record",
|
|
"type": "n8n-nodes-base.httpRequest",
|
|
"typeVersion": 4.3,
|
|
"position": [
|
|
1600,
|
|
656
|
|
]
|
|
}
|
|
],
|
|
"pinData": {},
|
|
"connections": {
|
|
"Every 5 Minutes": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Fetch n8n Workflows",
|
|
"type": "main",
|
|
"index": 0
|
|
},
|
|
{
|
|
"node": "Fetch n8n Executions",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Fetch n8n Workflows": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Split Workflows Array",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Split Workflows Array": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Workflows: One At A Time",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Check Workflow Record Exists": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Workflow Record Exists?",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Workflow Record Exists?": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Update Workflow Record",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
],
|
|
[
|
|
{
|
|
"node": "Create Workflow Record",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Update Workflow Record": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Workflows: One At A Time",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Workflows: One At A Time": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Workflows Sync Done",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
],
|
|
[
|
|
{
|
|
"node": "Check Workflow Record Exists",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Create Workflow Record": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Workflows: One At A Time",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Fetch n8n Executions": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Split Executions Array",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Split Executions Array": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Executions: One At A Time",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Check Execution Record Exists": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Execution Record Exists?",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Execution Record Exists?": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Update Execution Record",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
],
|
|
[
|
|
{
|
|
"node": "Create Execution Record",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Update Execution Record": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Executions: One At A Time",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Executions: One At A Time": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Executions Sync Done",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
],
|
|
[
|
|
{
|
|
"node": "Check Execution Record Exists",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Create Execution Record": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Executions: One At A Time",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
}
|
|
},
|
|
"active": false,
|
|
"settings": {
|
|
"executionOrder": "v1",
|
|
"binaryMode": "separate",
|
|
"availableInMCP": true
|
|
},
|
|
"versionId": "6c005d1b-a2e9-4f00-94f9-a1dadedb1532",
|
|
"meta": {
|
|
"aiBuilderAssisted": true,
|
|
"builderVariant": "mcp",
|
|
"instanceId": "05bcfa3b50919141d3600718ff4b7b2b52a3883525b05573a27ba5ef437ac7fb"
|
|
},
|
|
"nodeGroups": [],
|
|
"id": "cM8YciHiEwpslh1y",
|
|
"tags": []
|
|
} |