必须检查sentry.Init()返回值并配置完整DSN、Environment和Release,否则错误将静默丢失;panic需defer sentry.Recover()配合AttachStacktrace:true还原原始堆栈,普通error须用sentry.CaptureException()而非CaptureMessage()以支持聚类。

Go 服务接入 Sentry 后,错误能自动捕获、去重聚合、按环境/标签分组,并支持上下文追踪——但前提是正确初始化 SDK、区分手动上报与 panic 捕获、且避免 context 泄漏或重复初始化。
如何正确初始化 sentry-go 并避免静默失败
SDK 初始化失败时默认不报错,容易误以为已接入成功。常见原因包括 DSN 格式错误、网络不通、或在 init() 中过早调用(如依赖未就绪的配置)。
- 始终检查
sentry.Init()返回的error,哪怕只是 log.Fatal - DNS 必须是完整 Sentry 项目 DSN(含
https://xxx@o123.ingest.sentry.io/456格式),不能只填 public key 或 URL - 避免在
init()函数中初始化;应在main()开头或服务启动流程中显式调用 - 设置
Environment和Release(如v1.2.0-rc1),否则所有事件会混在production下无法按版本过滤
err := sentry.Init(sentry.ClientOptions{
Dsn: os.Getenv("SENTRY_DSN"),
Environment: os.Getenv("ENV"),
Release: os.Getenv("APP_VERSION"),
Debug: true, // 开发期开启,可看到 SDK 内部日志
})
if err != nil {
log.Fatalf("sentry init failed: %v", err)
}如何捕获 panic 并还原原始堆栈(而非 Sentry 包装后的)
默认 sentry.Recover() 会丢失原始 panic 类型和消息,且堆栈从 recover() 调用点开始,不是 panic 发生点。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 用
sentry.Flush()配合defer sentry.Recover()是基础,但不够 - 必须启用
AttachStacktrace: true,否则 HTTP handler panic 只上报错误类型,无行号 - 对关键 goroutine(如定时任务、worker)单独加
defer sentry.Recover(),主 goroutine 的 recover 不会覆盖子 goroutine panic - 若用
gin或echo,需注册中间件,而非只靠全局 recover
// gin 中间件示例
func SentryRecovery() gin.HandlerFunc {
return func(c *gin.Context) {
defer sentry.Recover()
c.Next()
}
}何时该用 sentry.CaptureException() 而非 sentry.CaptureMessage()
CaptureMessage() 仅上报字符串,不带堆栈、无法聚合为同一 issue;而 CaptureException() 自动提取 error 类型 + 堆栈 + cause 链,Sentry 才能按 error 类型聚类。
- 业务校验失败(如 “user not found”)用
CaptureMessage()+ 自定义 level(LevelWarning)更合适 - 任何
error值(含fmt.Errorf、errors.Wrap、xerrors)都应走CaptureException() - 传入前可调用
sentry.WithScope()添加 tags、user、extra,但 scope 必须在 defer 或同步调用中完成,异步上报会丢失 - 不要在 defer 中直接传
err(可能为 nil),先判空
if err != nil {
sentry.WithScope(func(scope *sentry.Scope) {
scope.SetTag("handler", "upload")
scope.SetExtra("file_size", fileSize)
sentry.CaptureException(err)
})
}为什么本地开发时看不到上报,但日志显示 “event queued”
这是 Sentry SDK 的默认行为:当 Debug: false 且无网络或 DSN 无效时,它会静默丢弃事件,只在 debug 模式下打印 “dropped event”。但即使 DSN 正确,也可能因以下原因卡住:
- 未调用
sentry.Flush(2 * time.Second)—— SDK 异步发送,进程退出前不 flush 就丢失 - 使用了
sentry.NewHub()但没绑定到全局,导致CaptureXXX()调用无效果 - Go 程序启用了
os.Exit(0)(如 CLI 工具),它绕过 defer,必须在 exit 前显式 flush - Docker 容器内 DNS 解析失败,或 Sentry 域名被防火墙拦截(可 curl 测试
https://o123.ingest.sentry.io/api/456/envelope/)
最易忽略的是:Sentry 默认采样率是 1.0,但若配置了 SampleRate: 0.1 却没意识到,90% 的错误就真的不上报了。

















