Files
ewoooc/n8n-workflows/22-alert-deduplication.json
ogt 1b4f3a7bbe
Some checks failed
CD Pipeline / deploy (push) Failing after 59s
feat: EwoooC 初始化 — 完整專案推版至 Gitea
- 建立 Gitea Actions CD pipeline (.gitea/workflows/cd.yaml)
- 部署模式: rsync Python 檔案至 188 → docker restart (volume mount)
- Dockerfile/requirements 變動時自動重建 Docker image
- 部署通知: Telegram (開始/成功/失敗)
- 健康檢查: https://mo.wooo.work/health (最多 5 次重試)
- 同步最新 CLAUDE.md / ADR-008 / memory (2026-04-19)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 01:21:13 +08:00

122 lines
5.0 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"name": "告警去重與抑制機制",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "alert-receiver",
"options": {}
},
"id": "webhook",
"name": "告警接收器",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [240, 300]
},
{
"parameters": {
"jsCode": "const alert = $input.first().json;\nconst now = Date.now();\nconst alertKey = `${alert.environment}_${alert.alertType}_${alert.service}`;\n\n// 從 static data 讀取告警歷史\nconst alertHistory = $getWorkflowStaticData('global');\nif (!alertHistory.alerts) {\n alertHistory.alerts = {};\n}\n\nconst lastAlert = alertHistory.alerts[alertKey];\nconst cooldownMinutes = {\n 'critical': 5, // 嚴重告警5 分鐘內不重複\n 'warning': 15, // 警告15 分鐘內不重複\n 'info': 60 // 資訊1 小時內不重複\n};\n\nconst cooldown = (cooldownMinutes[alert.severity] || 15) * 60 * 1000;\nconst shouldSend = !lastAlert || (now - lastAlert.timestamp > cooldown);\n\nif (shouldSend) {\n alertHistory.alerts[alertKey] = {\n timestamp: now,\n count: (lastAlert?.count || 0) + 1\n };\n}\n\n// 清理超過 24 小時的歷史\nObject.keys(alertHistory.alerts).forEach(key => {\n if (now - alertHistory.alerts[key].timestamp > 24 * 60 * 60 * 1000) {\n delete alertHistory.alerts[key];\n }\n});\n\nreturn [{\n json: {\n ...alert,\n shouldSend,\n suppressReason: shouldSend ? null : `冷卻中 (${cooldownMinutes[alert.severity]}分鐘)`,\n repeatCount: alertHistory.alerts[alertKey]?.count || 1\n }\n}];"
},
"id": "dedup",
"name": "告警去重邏輯",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [460, 300]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "should-send",
"leftValue": "={{ $json.shouldSend }}",
"rightValue": true,
"operator": {
"type": "boolean",
"operation": "equals"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "if-send",
"name": "是否發送?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [680, 300]
},
{
"parameters": {
"jsCode": "const alert = $input.first().json;\nconst now = new Date().toLocaleString('zh-TW', { timeZone: 'Asia/Taipei' });\n\nconst severityEmoji = {\n 'critical': '🔴',\n 'warning': '🟠',\n 'info': '🔵'\n};\n\nconst envEmoji = {\n 'UAT': '🟦',\n 'GCP': '🟥'\n};\n\nlet message = `${severityEmoji[alert.severity] || '⚪'} <b>${envEmoji[alert.environment] || ''} ${alert.title}</b>\\n\\n`;\nmessage += `📍 環境: ${alert.environment}\\n`;\nmessage += `🔧 服務: ${alert.service}\\n`;\nmessage += `📝 詳情: ${alert.description}\\n`;\n\nif (alert.repeatCount > 1) {\n message += `🔄 重複次數: ${alert.repeatCount}\\n`;\n}\n\nmessage += `⏰ 時間: ${now}`;\n\nreturn [{ json: { message } }];"
},
"id": "format",
"name": "格式化訊息",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [900, 200]
},
{
"parameters": {
"url": "https://api.telegram.org/bot8075645931:AAH-EGKMo8ZC4QJs-Nc1_0s92xHrGdQvdpg/sendMessage",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"chat_id\": \"5619078117\",\n \"parse_mode\": \"HTML\",\n \"text\": \"{{ $json.message }}\"\n}",
"options": {}
},
"id": "telegram",
"name": "發送 Telegram",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [1120, 200]
},
{
"parameters": {
"jsCode": "// 記錄被抑制的告警(供分析用)\nconst alert = $input.first().json;\nconsole.log(`告警被抑制: ${alert.alertType} - ${alert.suppressReason}`);\nreturn [{ json: { suppressed: true, reason: alert.suppressReason } }];"
},
"id": "log-suppressed",
"name": "記錄抑制",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [900, 400]
}
],
"connections": {
"告警接收器": {
"main": [
[{ "node": "告警去重邏輯", "type": "main", "index": 0 }]
]
},
"告警去重邏輯": {
"main": [
[{ "node": "是否發送?", "type": "main", "index": 0 }]
]
},
"是否發送?": {
"main": [
[{ "node": "格式化訊息", "type": "main", "index": 0 }],
[{ "node": "記錄抑制", "type": "main", "index": 0 }]
]
},
"格式化訊息": {
"main": [
[{ "node": "發送 Telegram", "type": "main", "index": 0 }]
]
}
},
"settings": {
"executionOrder": "v1"
},
"staticData": null,
"tags": [],
"triggerCount": 0,
"updatedAt": "2026-02-07T17:00:00.000Z",
"versionId": "1"
}