sentry.init()必须在main()最开头调用,以确保panic捕获、http中间件和goroutine错误均被上报;需配合httpintegration补全请求上下文,并区分recover()兜底panic与captureexception()主动上报error。

必须在 Gin 启动前完成 sentry.Init(),否则中间件里 panic 不会上报;HTTP 请求上下文默认不带路径、用户 ID 或 header,得手动补。
为什么 sentry.Init() 要放在 main() 最开头
Go 的 panic 捕获依赖全局 handler 注册时机。Gin 的 router.Run() 会起 goroutine 处理请求,如果 sentry.Init() 在它之后调用,那些已启动的 goroutine 中发生的 panic 就不会被 Sentry 捕获——现象是本地测试能报错,上线后 404 或 panic 完全静默。
-
sentry.Init()必须早于日志库初始化、数据库连接、甚至gin.New() - 务必检查返回值:
if err := sentry.Init(...); err != nil { log.Fatal(err) } - DSN 必须是完整 URL:
https://xxx@o123.ingest.sentry.io/456,漏协议或路径会导致静默失败 - 开发环境加
Environment: "development",避免和生产数据混在一起
如何让 Gin 中间件自动带上请求上下文
默认的 sentry-go 不解析 *http.Request,所有错误都显示为 GET /,根本无法定位接口。要用 sentry.HTTPIntegration 补基础字段,再手动塞关键信息。
- 注册时启用
sentry.HTTPIntegration:它能自动附加method、url、status_code - 在 Gin 中间件里调用
sentry.ConfigureScope(),例如:sentry.SetTag("user_id", c.GetHeader("X-User-ID")) - 避免写敏感字段:
Authorization、Cookie等 header 不要直接塞进 scope - 若用 JWT,建议在中间件里解析 token 后取
sub或uid写成 tag,别传原始 token
怎么写 Sentry Gin 中间件捕获 handler panic
Gin 默认不 recover panic,错误会直接 500 返回且不上报。你得自己加 defer,但不能简单套 sentry.Recover()——它只处理当前 goroutine 的 panic,且不带 HTTP 上下文。
- 中间件里用
defer sentry.Recover(),它会自动捕获当前 goroutine panic 并上报 - 必须配合
AttachStacktrace: true(Init 时配置),否则堆栈只有 runtime.Callers,看不到业务代码行号 - 不要在每个 handler 里重复写 defer,统一注册中间件即可:
r.Use(sentrygin.New())(需引入github.com/getsentry/sentry-go/gin) - 注意:这个中间件只捕获未被 handler 内部 recover 的 panic;已 recover 的 error 需主动调
sentry.CaptureException(err)
普通 error 怎么上报,而不是等 panic
90% 的业务异常(如 DB timeout、第三方 API 404、参数校验失败)都不是 panic,Sentry 默认完全不感知。这类错误必须显式上报,否则监控面板永远空着。
- 遇到
if err != nil,立刻sentry.CaptureException(err),别等 panic - 高频低价值 error(如用户输入非法)要过滤,否则 quota 很快耗尽
- 上报时可加 context:
sentry.CaptureException(err, sentry.WithTag("feature", "payment")) - 进程退出前必须
sentry.Flush(2 * time.Second),否则缓冲区里的事件全丢
最易被忽略的是:Sentry 不是“开箱即用”的监控,它默认只管 panic;HTTP 上下文、业务 error、goroutine 崩溃、进程优雅退出——每一块都要手动补,漏掉任何一环,线上就等于没接。











