使用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记