Sentry Go SDK 默认不自动捕获HTTP上下文,需在Gin中间件中调用sentry.ConfigureScope()手动注入请求路径、方法、过滤后的Header等信息,并在每个handler或goroutine内显式使用defer sentry.Recover()捕获panic。

为什么默认 Sentry 不会自动带上请求路径和 Header
Sentry Go SDK 默认只捕获 panic 堆栈和 error 字符串,sentry.Recover() 或 sentry.CaptureException() 都不会自动注入 HTTP 上下文。Gin 的 *gin.Context 是局部变量,不随 panic 自动传播,更不会被 Sentry 主动提取。
在 Gin 中间件里手动附加 Request 信息
必须在中间件中显式调用 sentry.ConfigureScope(),把当前请求的 URL、Method、Header、Query 等塞进 Sentry 的 scope,否则所有错误都丢失上下文,排查时只能看到“某处 panic”,不知道是哪个接口、谁触发的。
- 用
c.Request.URL.Path和c.Request.Method记录请求路径与方法 -
c.Request.Header是http.Header类型,不能直接传;需遍历并过滤敏感字段(如Authorization、Cookie)后写入scope.SetExtra() - 避免在 scope 中塞完整 body —— 可能含用户隐私,且超长内容会被 Sentry 截断或拒绝
- 推荐只附加
X-Request-ID、User-Agent、Content-Type等关键 Header
示例中间件:
func SentryMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
sentry.ConfigureScope(func(scope *sentry.Scope) {
scope.SetTag("http.method", c.Request.Method)
scope.SetTag("http.path", c.Request.URL.Path)
scope.SetContext("request", map[string]interface{}{
"query": c.Request.URL.RawQuery,
"user_agent": c.Request.UserAgent(),
"ip": c.ClientIP(),
})
// 安全地附加部分 Header
headers := make(map[string]string)
for k, v := range c.Request.Header {
if len(v) > 0 && !strings.Contains(strings.ToLower(k), "auth") && k != "Cookie" {
headers[k] = v[0]
}
}
scope.SetExtra("headers", headers)
})
c.Next()
// 可选:对非 2xx 响应也上报(仅限 5xx 或明确业务错误)
if c.Writer.Status() >= 500 {
sentry.CaptureMessage(fmt.Sprintf("HTTP %d on %s", c.Writer.Status(), c.Request.URL.Path))
}
}
}
panic 捕获必须配合 defer sentry.Recover()
Gin 的 handler panic 后会返回 500,但若没调 defer sentry.Recover(),Sentry 根本收不到事件。注意:sentry.Recover() 必须放在 handler 内部或中间件末尾,不能只靠全局 init 注册——Gin 的 panic 处理链不经过标准 Go runtime。
- 在每个路由 handler 开头加
defer sentry.Recover()最稳妥 - 或者统一用中间件包裹:
c.Next()后再 recover,但此时 panic 已被 Gin 捕获,sentry.Recover()无效;正确做法是在c.Next()前 defer -
sentry.Recover()不会终止执行流,你仍需检查c.IsAborted()避免重复响应
别漏掉 goroutine 中的 panic
Gin handler 里启的 goroutine(比如异步发消息、定时清理)一旦 panic,sentry.Recover() 完全捕获不到——Go 的 goroutine panic 是隔离的。常见于 go func() { ... }() 或 time.AfterFunc。
- 不要依赖全局 recover,每个 goroutine 入口自己 defer
sentry.Recover() - 封装一个安全启动函数:
sentry.Go(func(){ ... }),内部做 recover + CaptureException - 尤其注意数据库查询、HTTP 调用、文件读写等 I/O 操作,它们常被丢进 goroutine 却忘了加监控
真正难的不是加 SDK,而是确保每条执行路径上的 panic 和 error 都被同一套上下文包裹——路径、Header、用户标识、traceID 缺一不可,否则报错堆栈再全也没法定位到具体一次 API 调用。


















