{
  "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"
}
