sentry-go捕获panic需用sentry.recover()而非原生recover,因其自动提取堆栈、goroutine id等上下文;必须在同goroutine defer中调用,且init早于panic代码。

recover 本身不能直接对接 Sentry
Go 的 recover 只能在 defer 中配合 panic 使用,它返回的是 interface{} 类型的 panic 值,**不包含堆栈、goroutine 状态、时间戳等 Sentry 所需的上下文信息**。直接用 recover 捕获后调用 Sentry SDK 上报,会丢失关键诊断线索,上报的错误在 Sentry 后台几乎不可排查。
正确做法:用 Sentry 的 Hub + 自定义 panic handler
Sentry 官方 Go SDK(sentry-go)提供了 sentry.Recover() 和 sentry.RecoverWithContext(),它们才是为 panic 场景设计的封装——底层会自动提取 runtime.Stack、当前 goroutine ID、panic value,并关联 active Hub(含 tags、user、contexts 等)。你不需要手动调用 recover。
典型用法是包裹主逻辑或 HTTP handler:
func main() {
sentry.Init(sentry.ClientOptions{
Dsn: "https://xxx@o123.ingest.sentry.io/456",
})
defer sentry.Recover() // ← 这才是关键,不是自己写 recover
panic("test panic")
}
注意点:
-
sentry.Recover()必须放在panic可能发生位置的**同 goroutine 且 defer 链上游**;HTTP server 中建议在每个 handler 内部 defer - 若需传递额外 context(如 request ID),用
sentry.RecoverWithContext(ctx),其中ctx会被注入到事件中 - 不要在 defer 中混用原生
recover()和sentry.Recover(),会导致 panic 被提前吞掉,Sentry 收不到
HTTP handler 中上报 panic 并保留请求上下文
Web 服务最常见需求:panic 发生时,把 *http.Request 的 method、path、headers、body(谨慎)、remote IP 等带上。Sentry SDK 支持通过 sentry.HTTPRequestEventProcessor 自动注入。
诊断并恢复通过 SSH 隧道连接的 OpenClaw 节点。用于解决配对必需错误、隧道冲突、远程端点错误以及 SSH 目标配置错误等问题。
实操步骤:
- 初始化时注册 processor:
sentry.Init(...); sentry.ConfigureScope(func(scope *sentry.Scope) { scope.AddEventProcessor(sentry.HTTPRequestEventProcessor) }) - 在 handler 中 defer
sentry.RecoverWithContext(r.Context()),其中r是*http.Request - 如需额外标记(如用户 ID),在 defer 前调用
sentry.ConfigureScope设置 tag 或 user
示例片段:
func myHandler(w http.ResponseWriter, r *http.Request) {
sentry.ConfigureScope(func(scope *sentry.Scope) {
scope.SetTag("handler", "myHandler")
scope.SetUser(sentry.User{ID: r.Header.Get("X-User-ID")})
})
defer sentry.RecoverWithContext(r.Context())
// 可能 panic 的业务逻辑
doSomethingRisky()
}
recover + Sentry 混用时的典型陷阱
有人想“先 recover 拿到 panic 值,再手动构造 Sentry event”,这容易踩坑:
-
recover()返回值是interface{},无法直接转成error;若 panic 是字符串或 int,sentry.CaptureException()会静默失败(不报错也不上报) - 手动调用
runtime.Stack(buf, false)只能拿到当前 goroutine 的 stack,而 panic 可能发生在子 goroutine,此时 stack 是空的 - 忽略 Sentry 的采样率(
SampleRate)和BeforeSend钩子,导致高频 panic 淹没真实问题,或敏感字段(如密码)被误传 - 在 init 函数或包级变量初始化中 panic —— 此时 Sentry 尚未初始化,
sentry.Recover()不生效,必须靠外部进程监控或日志 fallback
真正需要自定义上报逻辑的场景极少,优先走 sentry.Recover* 标准路径;只有当必须拦截 panic 做清理(如关闭文件、释放锁)且同时上报时,才考虑 recover + CaptureException 组合,但务必手动补全 stack 和 context。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










