使用Trapfall收集錯誤信息
最近閒暇時間都在琢磨我的個人微信小程序:

昨天在看項目訪問日誌的時候,發現了個異常。
一個新疆·喀什用戶 POST 請求 422, 哪個接口大部分時候應該是觸發 400, FastAPI 的 422 是在路由函數執行之前,由內置異常處理器拋出的,路由內部代碼還沒跑,普通日誌拿不到原始請求體。
想要專門捕獲 Pydantic 校驗失敗(422),拿到完整報錯 + 原始請求 body,或者 5xx 等錯誤,定位代碼塊,拿到請求 body 什麼的,通常需要 Sentry 等專業方案。
自己部署過 Sentry 的都知道,它不是一個簡單單體程序,整套包含非常多組件:PostgreSQL、Redis、Kafka、ZooKeeper、ClickHouse、Symbolicator 等一堆微服務容器,最低推薦 8G 內存、4 核 CPU,服務器配置要求高,後續還要持續升級、備份、排障,運維成本很高。
個人項目的丐版主機明顯資源不夠用啊,告訴 AI 我的窘迫狀況,讓它幫忙推薦類似輕量方案,且要開放源碼的。
推薦了幾個,只有下面 2 個入眼:
- PocketSentry:MIT Golang 單二進制 + SQLite <20MB ✅ ⭐⭐⭐⭐⭐
- TrapFall:Apache2.0/MIT Rust 單二進制 + SQLite 佔用極低 ✅ ⭐⭐⭐⭐
個人偏好 Rust 版的 TrapFall,帶前端面板:SvelteKit 5,靜態嵌入到二進制包裏面,不需要單獨啓動前端服務。其實看了下 PocketSentry 也不錯。留着以後再試用吧!
1. FastAPI 項目接入 TrapFall
sentry-sdk 直接複用,方便啊
1uv add sentry-sdk
僞代碼:
1import sentry_sdk
2from sentry_sdk.integrations.starlette import StarletteIntegration
3from sentry_sdk.integrations.fastapi import FastApiIntegration
4from sentry_sdk import capture_exception
5
6# ===================== SENTRY 初始化【放在最前面!】=====================
7SENTRY_DSN = "替換成你的DSN" # TrapFall
8if SENTRY_DSN:
9 sentry_sdk.init(
10 dsn=SENTRY_DSN,
11 send_default_pii=True, # 採集IP、headers,方便定位那個新疆用戶
12 traces_sample_rate=0.1, # 生產調低,避免流量爆炸,0.1=10%採樣
13 environment="production",
14 integrations=[
15 StarletteIntegration(
16 transaction_style="endpoint",
17 # 重點:把422加入上報
18 failed_request_status_codes={422, *range(500, 599)},
19 ),
20 FastApiIntegration(
21 transaction_style="endpoint",
22 failed_request_status_codes={422, *range(500, 599)},
23 ),
24 ],
25 )
26
27#略去其它業務代碼#
28
29# 測試接口,驗證sentry連通性,上線前刪掉
30@app.get("/sentry-debug")
31async def sentry_debug():
32 1/0
2. Trapfall 部署
trapfall 現在才 8 個標星,我點了個變成 9 個,我也是服了 AI 了,這都能找到。
直接採用源碼編譯的方式部署:
1# Build frontend
2cd web && npm ci && npm run build && cd ..
3
4# Build + run
5cargo run --release -p trapfalld -- --db trapfall.db serve --listen 0.0.0.0:9090
注意:我是在我個人 Arch Linux 電腦上部署好後,放到服務器上的,都是 x86 架構,不在服務器上部署污染環境!不讓部署的時候要裝個 npm 就要安裝一大堆包,對待丐版主機要溫柔。
編譯出 trapfall 二進制文件後,傳到服務器上,Rust 程序很爽的地方就是直接用 Systemd 管理就好了:
1[Unit]
2Description=TrapFall Binary Service
3After=network.target
4
5[Service]
6Type=simple
7User=www-data
8WorkingDirectory=/data/trapfall
9
10# ========== 在這裏自定義環境變量 ==========
11Environment="TRAPFALL_LISTEN=127.0.0.1:9090"
12Environment="TRAPFALL_DATABASE_URL=sqlite:/data/trapfall/trapfall.db"
13Environment="TRAPFALL_SECURE_COOKIE=true"
14Environment="TRAPFALL_CORS_ORIGINS=xxx"
15Environment="TRAPFALL_PUBLIC_URL=xxx"
16Environment="RUST_LOG=trapfall=info"
17Environment="TRAPFALL_TIMEZONE=Asia/Shanghai"
18
19ExecStart=/bin/trapfall
20Restart=on-failure
21RestartSec=5
22
23# 資源限制,防止OOM
24MemoryMax=768M
25CPUQuota=150%
26
27[Install]
28WantedBy=multi-user.target
再設置啓動:systemctl enable --now trapfall
稍微看下官方文檔,理解後使用就 ok 了,實在是懶得敲字了。
3. web 前端面板配置
web 前端面板相關設置, 我用 caddy 代理,只開放給家裏電腦訪問。
1# 類似Sentry 的替代輕量工具 Trapfall
2errors.xxx.com{
3 encode zstd br gzip
4 log {
5 output file /var/log/caddy/xxx.xxx.com.log {
6 roll_size 30mb
7 roll_keep 10
8 roll_keep_for 7d
9 }
10 }
11
12 @allowed {
13 client_ip xxx.xxx.xxx.xx # your_home_public_ip
14 }
15
16 handle @allowed {
17 reverse_proxy 127.0.0.1:9090
18 }
19
20 respond "Forbidden: Access denied👻" 403
21}
訪問後,設置用戶密碼,創建項目,讓後複製項目的 DSN,給上面的 FastApi 代碼使用。
這裏有個需要注意⚠️的點:
1SENTRY_DSN = "http://c84e5ad7-adc3-42b8-82b7-e55b9ae414bf@127.0.0.1:9090/1"
仔細看,用 http 協議,後面也是內網地址,因爲是同一臺機器的兩個服務,不用繞道外面去。
4. 觸發錯誤並驗證
部署應用錯誤收集系統的最終目的,就是爲了收集信息,方便定位處理的嘛。
- 直接在 Python REPL 測試投遞:
1import sentry_sdk
2sentry_sdk.init(
3 dsn="這裏粘貼你完整的TrapFall DSN",
4 traces_sample_rate=1.0,
5)
6try:
7 1/0
8except Exception as e:
9 sentry_sdk.capture_exception(e)
- 再用你的 sentry-debug 接口測試
1curl \
2-H "xxx: xxx" \
3-H "Referer: xxx" \
4http://你的域名/sentry-debug
你自己的服務需要什麼 Header 就都帶上,正常沒有問題的話,你就可以在 web 前端面板,看到收集信息啦。
如圖所示:

兩行分別對應上面的兩種觸發方式,相比 sentry 維護起來那麼麻煩,組件一堆,真是簡單實用啊...
5. 告警配置
老實說,一般個人項目我都是不配置告警的,這輩子被公司告警支配,賺點錢真實不容易。
但是個人項目,有業務錯誤了,都不修,那可以說毫無責任心了。比如你人在外面玩,個人項目都掛了,總得發個告警讓自己知道吧,萬一是影響賺打錢了呢?
Trapfall 默認支持 webthook 的放方式和外部交互,在其 web 面板上配置好 rules,需要填 Webhook URL
國內一般是企業微信、飛書、釘釘的,也有手機上的 bark 什麼的。這個項目的作者我看了下是個印尼人,不可能原生支持我們國內這一套的。
所以需要自己縫合下,好在現在是 AI 時代,用 AI 我自己花了幾個小時用 rust 編寫了程序,調試通了告警到飛書羣聊機器人。
本質上就是要解決 trapfall 觸發告警吐出來的東西,按照飛書 webhook 封裝下,兩套系統,需要中間程序翻一下。
整個鏈路簡單大概這樣:
TrapFall → 中間 Rust 翻譯服務(沒錯,讓 AI 用 rust 寫的) → 飛書機器人
複雜點是這樣:
TrapFall → Caddy (HTTPS) → 127.0.0.1:3000 → 你的 Rust 服務 → 飛書機器人
爲什麼是 3000,axum 框架默認監聽端口,Trapfall 就 Webhook Url 就填你這個中間服務暴露的服務地址。直接填飛書 webhook 肯定是不行的嗎,語言不通嘛。
有需要我找個程序的,可以關注我微信公衆號留言索取,懶得貼了,不又要寫一大堆文字。其實,都不用索取,AI 解決這種轉換程序,真的是小菜一碟。
最終觸發手動觸發錯誤的時候,收到的告警信息如下圖所示:

最後,這樣一通操作下來,個人業餘項目也是能正常收集致命錯誤和告警了,有問題就能及時發現並修復。也不用維護 Sentry 等重量級服務,自主可控,多項目都可以自由使用。
就這樣很完美了嗎?No,實測發現 trapfall 的 rules 相關接口還是有 bug 的,經常刪不掉😅,也沒辦法修改, 8個標星,還要什麼自行車?
遇到刪不掉,我都是直接去 sqlite 數據庫裏面刪的,rules 也不用經常改動,勉強可以接受。不然呢?提交 pr 吧......

版權申明:
- 未標註來源的內容皆為原創,未經授權請勿轉載(因轉載後排版往往錯亂、內容不可控、無法持續更新等);
- 非營利為目的,演繹本博客任何內容,請以'原文出處'或者'參考鏈接'等方式給出本站相關網頁地址(方便讀者)。
相關文章:
- 應用啓動器yofi使用配置
- 我做了第二個微信小程序
- Wayland合成器下快速連接藍牙設備
- 截圖標記工具Satty推薦
- 修復rime-ice無法彈出候選框的問題
- 開機滾動字體顯示優化
- 樹莓派上部署Vaultwarden
- 使用goaccess即時分析Caddy日誌
- 個人網站監控
- Hugo全站AVIF記