iT邦幫忙

2025 iThome 鐵人賽

DAY 14
0

在開發專案時,我們經常使用 Sentry 這類錯誤監控服務來即時捕捉線上環境發生的問題。Sentry 的一大優點是可以在錯誤發生時,立即通知開發團隊。然而,若想直接將通知整合到 Discord,需要升級到付費的「Team Plan」方案

但別擔心!今天我們將利用自動化工具 n8n,繞個彎路,實作一個免費且高效的解決方案:當 Sentry 寄出錯誤通知信時,自動解析信件內容,並將精美的通知訊息發送到指定的 Discord 頻道

image 0.png

workflow

1. 建立 Gmail 觸發節點

  • 來到儀表板,新增一個流程「Create Workflow」

    image 1.png

  • 初始節點選擇「GMAIL」的「On message received」

    image 2.png

  • 同樣要設定憑證,之前有介紹過就不重複惹

    image 3.png

  • 「Filters」選擇「Sender」並設定為「sentry」

    • 然後再增加一個「Search」並設定為「”error”」

    image 4.png

2. 解析 Email 內容

由於 Sentry 寄來的 Email 是 HTML 格式,我們需要從中提取有用的資訊

  • 下個節點選擇「HTML」的「Extract HTML Content」

    image 5.png

  • 「JSON Property」設定為「html」,並使用「Add Value」來新增變數資料

    • Key:errorTitle

      • CSS Selector:.event-type.error small
    • Key:errorUrl

      • CSS Selector:.btn.view-on-sentry

      • Return Value:Attribute

      • Attribute:href

    • Key:exceptionDetails

      • CSS Selector:div.interface > pre

    image 6.png

3. 組合與編輯欄位

  • 下個節點選擇「Edit Fields」來組合要傳遞給 Discord 的變數資料

    image 7.png

  • 點選「Add Field」來新增變數

    • Name: projectName

      • Value: {{ $('Gmail Trigger').item.json.headers['x-sentry-project'].split(': ')[1] }}
    • Name: environment

      • Value: {{ $('Gmail Trigger').item.json.text.match(/environment = (.*)/)[1] }}
    • Name: level

      • Value: {{ $('Gmail').item.json.text.match(/level = (.*)/)[1] }}

    image 8.png

4. 發送 Discord 通知

  • 下個節點選擇「Discord」的「Send a message」來傳送訊息

    image 9.png

  • 「Connection Type」選擇「Webhook」,憑證的串接在之前的文章有撰寫過,這邊就不重複惹

    image 10.png

  • 可以在「Embeds」選擇「Raw JSON」來傳送具有樣式的訊息

    image 11.png

  • JSON 內容如下

    {
      "title": "🚨 Sentry 錯誤通知 (來自 Gmail)",
      "color": 15548997,
      "url": "{{ $('HTML').item.json.errorUrl }}",
      "description": "**錯誤訊息:**\\n{{ $('HTML').item.json.errorTitle.replace(/"/g, '\\"').replace(/\n/g, '\\n') }}\\n\\n**詳細堆疊資訊:**\\n```\\n{{ $('HTML').item.json.exceptionDetails.slice(0, 1500).replace(/"/g, '\\"').replace(/\n/g, '\\n') }}\\n```",
      "fields": [
        {
          "name": "專案",
          "value": "{{ $json.projectName.replace(/"/g, '\\"') }}",
          "inline": true
        },
        {
          "name": "環境",
          "value": "{{ $json.environment.replace(/"/g, '\\"') }}",
          "inline": true
        },
        {
          "name": "等級",
          "value": "`{{ $json.level }}`",
          "inline": true
        }
      ],
      "footer": {
        "text": "由 n8n 轉發"
      },
      "timestamp": "{{ new Date().toISOString() }}"
    }
    

    image 12.png

  • 接著點選「Execute step」來試跑,看到「true」代表傳送成功囉

    image 13.png

  • 看起來的訊息會長得像這樣

    image 14.png

  • 畫布上的流程如下

    image 15.png

恭喜,現在已經擁有一個自動化、免費且客製化的 Sentry 錯誤通知系統了

  • 最後也附上流程的 JSON 內容

    {
      "nodes": [
        {
          "parameters": {
            "pollTimes": {
              "item": [
                {
                  "mode": "everyMinute"
                }
              ]
            },
            "simple": false,
            "filters": {
              "q": "\"error\"",
              "sender": "sentry"
            },
            "options": {}
          },
          "type": "n8n-nodes-base.gmailTrigger",
          "typeVersion": 1.2,
          "position": [0, 0],
          "id": "f23db1a9-bf57-442f-a12a-bf1daa5fc38b",
          "name": "Gmail Trigger"
        },
        {
          "parameters": {
            "operation": "extractHtmlContent",
            "dataPropertyName": "html",
            "extractionValues": {
              "values": [
                {
                  "key": "errorTitle",
                  "cssSelector": ".event-type.error small"
                },
                {
                  "key": "errorUrl",
                  "cssSelector": ".btn.view-on-sentry",
                  "returnValue": "attribute",
                  "attribute": "href"
                },
                {
                  "key": "exceptionDetails",
                  "cssSelector": "div.interface > pre"
                }
              ]
            },
            "options": {}
          },
          "type": "n8n-nodes-base.html",
          "typeVersion": 1.2,
          "position": [220, 0],
          "id": "612bef6a-3072-4d2e-a8d9-59e9c9b413df",
          "name": "HTML"
        },
        {
          "parameters": {
            "assignments": {
              "assignments": [
                {
                  "id": "b94bbf0a-e651-4495-87d2-6f3cdc995a96",
                  "name": "projectName",
                  "value": "={{ $('Gmail Trigger').item.json.headers['x-sentry-project'].split(': ')[1] }}",
                  "type": "string"
                },
                {
                  "id": "c841e270-89e2-4274-af3c-9c6ce79d75a0",
                  "name": "environment",
                  "value": "={{ $('Gmail Trigger').item.json.text.match(/environment = (.*)/)[1] }}",
                  "type": "string"
                },
                {
                  "id": "c02b409a-8ed4-4c59-ba31-38a7c794bce9",
                  "name": "level",
                  "value": "={{ $('Gmail Trigger').item.json.text.match(/level = (.*)/)[1] }}",
                  "type": "string"
                }
              ]
            },
            "options": {}
          },
          "type": "n8n-nodes-base.set",
          "typeVersion": 3.4,
          "position": [440, 0],
          "id": "fe591d12-d3b7-4b7a-b43e-73a35610d80d",
          "name": "Edit Fields"
        },
        {
          "parameters": {
            "authentication": "webhook",
            "options": {},
            "embeds": {
              "values": [
                {
                  "inputMethod": "json",
                  "json": "={\n  \"title\": \"🚨 Sentry 錯誤通知 (來自 Gmail)\",\n  \"color\": 15548997,\n  \"url\": \"{{ $('HTML').item.json.errorUrl }}\",\n  \"description\": \"**錯誤訊息:**\\\\n{{ $('HTML').item.json.errorTitle.replace(/\"/g, '\\\\\"').replace(/\\n/g, '\\\\n') }}\\\\n\\\\n**詳細堆疊資訊:**\\\\n```\\\\n{{ $('HTML').item.json.exceptionDetails.slice(0, 1500).replace(/\"/g, '\\\\\"').replace(/\\n/g, '\\\\n') }}\\\\n```\",\n  \"fields\": [\n    {\n      \"name\": \"專案\",\n      \"value\": \"{{ $json.projectName.replace(/\"/g, '\\\\\"') }}\",\n      \"inline\": true\n    },\n    {\n      \"name\": \"環境\",\n      \"value\": \"{{ $json.environment.replace(/\"/g, '\\\\\"') }}\",\n      \"inline\": true\n    },\n    {\n      \"name\": \"等級\",\n      \"value\": \"`{{ $json.level }}`\",\n      \"inline\": true\n    }\n  ],\n  \"footer\": {\n    \"text\": \"由 n8n 轉發\"\n  },\n  \"timestamp\": \"{{ new Date().toISOString() }}\"\n}"
                }
              ]
            }
          },
          "type": "n8n-nodes-base.discord",
          "typeVersion": 2,
          "position": [660, 0],
          "id": "e9639ccc-9f8d-46eb-b0a2-8f5238452e3a",
          "name": "Discord"
        }
      ],
      "connections": {
        "Gmail Trigger": {
          "main": [
            [
              {
                "node": "HTML",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "HTML": {
          "main": [
            [
              {
                "node": "Edit Fields",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "Edit Fields": {
          "main": [
            [
              {
                "node": "Discord",
                "type": "main",
                "index": 0
              }
            ]
          ]
        }
      },
      "pinData": {},
      "meta": {
        "templateCredsSetupCompleted": true
      }
    }
    

上一篇
[Day13]_LeetCode 每週複習
下一篇
[Day15]_新功能部署廣播器
系列文
告別重複瑣事: n8n workflow 自動化工作實踐17
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言