在開發專案時,我們經常使用 Sentry 這類錯誤監控服務來即時捕捉線上環境發生的問題。Sentry 的一大優點是可以在錯誤發生時,立即通知開發團隊。然而,若想直接將通知整合到 Discord,需要升級到付費的「Team Plan」方案
但別擔心!今天我們將利用自動化工具 n8n,繞個彎路,實作一個免費且高效的解決方案:當 Sentry 寄出錯誤通知信時,自動解析信件內容,並將精美的通知訊息發送到指定的 Discord 頻道
來到儀表板,新增一個流程「Create Workflow」
初始節點選擇「GMAIL」的「On message received」
同樣要設定憑證,之前有介紹過就不重複惹
「Filters」選擇「Sender」並設定為「sentry」
由於 Sentry 寄來的 Email 是 HTML 格式,我們需要從中提取有用的資訊
下個節點選擇「HTML」的「Extract HTML Content」
「JSON Property」設定為「html」,並使用「Add Value」來新增變數資料
Key:errorTitle
Key:errorUrl
CSS Selector:.btn.view-on-sentry
Return Value:Attribute
Attribute:href
Key:exceptionDetails
下個節點選擇「Edit Fields」來組合要傳遞給 Discord 的變數資料
點選「Add Field」來新增變數
Name: projectName
{{ $('Gmail Trigger').item.json.headers['x-sentry-project'].split(': ')[1] }}
Name: environment
{{ $('Gmail Trigger').item.json.text.match(/environment = (.*)/)[1] }}
Name: level
{{ $('Gmail').item.json.text.match(/level = (.*)/)[1] }}
下個節點選擇「Discord」的「Send a message」來傳送訊息
「Connection Type」選擇「Webhook」,憑證的串接在之前的文章有撰寫過,這邊就不重複惹
可以在「Embeds」選擇「Raw JSON」來傳送具有樣式的訊息
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() }}"
}
接著點選「Execute step」來試跑,看到「true」代表傳送成功囉
看起來的訊息會長得像這樣
畫布上的流程如下
恭喜,現在已經擁有一個自動化、免費且客製化的 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
}
}