sentry.init()必须在beego.run()前调用,否则启动过程中的panic无法被捕获;dsn需为完整url;beego.controller中的error需显式上报;goroutine panic需手动recover;进程退出前须调用sentry.flush()。

beego.Run()前必须调用sentry.Init()
beego 是基于 Go 的 Web 框架,启动流程由 beego.Run() 控制,而 Sentry 的全局 panic 捕获器依赖 sentry.Init() 在 runtime 初始化阶段注册。如果在 beego.Run() 之后才调用 sentry.Init(),那么框架启动过程中(如路由注册、配置加载)发生的 panic 就完全逃逸出 Sentry 监控范围。
常见错误是把 sentry.Init() 放在 main() 末尾、或封装进某个初始化函数里延迟执行。正确做法是:在 main() 函数最开头,紧挨着 import 块之后 就初始化:
func main() {
if err := sentry.Init(sentry.ClientOptions{
DSN: "https://abc123@o123.ingest.sentry.io/456",
Environment: beego.AppConfig.String("runmode"),
Release: beego.AppConfig.String("appversion"),
Debug: beego.AppConfig.String("runmode") == "dev",
}); err != nil {
log.Fatal("sentry init failed:", err)
}
defer sentry.Flush(2 * time.Second)
<pre class="brush:php;toolbar:false;">beego.Run()}
-
DSN必须是完整 URL(含https://和路径),漏掉协议或结尾数字 ID 都会导致静默失败 -
Environment推荐直接复用 beego 的runmode配置项,避免手动写死字符串 -
Release字段不能为空——它用于版本归因,建议从配置读取或构建时注入,否则所有错误都归到unknown -
Debug: true在开发环境开启,能在终端看到[Sentry] Initializing client...等日志,比盲等上报快得多
beego.Controller 中的 error 要显式上报
beego 不会自动捕获 if err != nil 类型的业务错误,比如数据库查询失败、HTTP 客户端超时、JSON 解析异常等。这些 error 只有被 sentry.CaptureException() 主动提交,才会进入 Sentry 控制台并参与聚类。
不要在每个 action 方法里重复写 sentry.CaptureException(err),推荐封装一个带上下文的辅助方法:
func (c *BaseController) CaptureError(err error, tags map[string]string) {
event := sentry.NewEvent()
event.Level = sentry.LevelError
event.Tags = tags
event.Extra = map[string]interface{}{
"controller": c.CtrlName(),
"action": c.ActionName(),
"request_id": c.GetString("X-Request-ID"),
}
sentry.CaptureEvent(event)
}
- 在具体 controller 里调用:
c.CaptureError(err, map[string]string{"feature": "user_login"}) - 避免对参数校验类错误(如
"invalid email format")全量上报,它们高频低价值,容易刷爆 quota - 如果用了 beego 的
Abort()或Abort500(),记得在 abort 前先上报,否则错误就丢了
goroutine panic 不会上报,需手动 recover
beego 的异步操作(如 beego.BeeLogger.AsyncWrite)、定时任务(time.AfterFunc)、或你自己起的 goroutine,一旦 panic,Sentry 默认监听器完全收不到——因为 Go 的 panic 不跨 goroutine 传播,而 sentry.Init() 注册的是主线程的全局 handler。
典型现象是:日志里出现 panic: runtime error: index out of range,但 Sentry issues 页面空空如也。
- 对自定义 goroutine,统一用
defer sentry.Recover()包裹入口函数 - 不要给 beego 内部的 goroutine(如
beego.Task启动的任务)盲目加 recover——它已有自己的错误兜底逻辑,强行加可能掩盖真实问题 - 如果用了
beego.RunWithMiddleWares()自定义中间件,确保中间件函数本身也做 recover,否则中间件 panic 会绕过 Sentry
进程退出前不 flush,错误就永远丢失
Sentry 默认异步发送事件,数据先进入内存缓冲区。beego 应用收到 SIGTERM(如 k8s rolling update)或调用 os.Exit() 时,若没显式 flush,缓冲区里的待上报事件就直接丢弃,不会重试也不会落盘。
除了 main() 开头的 defer sentry.Flush(2 * time.Second),你还得在信号处理器里补一手:
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGTERM, syscall.SIGINT)
go func() {
-
sentry.Flush()是阻塞调用,超时时间建议设为 2 秒以上,太短可能截断慢网络下的事件 - 如果应用用了 beego 的热重载(
bee run),Flush()不会触发——但开发阶段本就不依赖 Sentry 上报,重点保障生产环境即可 - 注意:
sentry.Flush()不能放在beego.Run()之后的代码里,因为beego.Run()是阻塞的,后面代码根本不会执行
实际最难的不是集成,而是区分哪些错误值得上报。比如 beego 的 404 not found 日志、浏览器扩展注入的 JS 错误、已知的第三方 SDK 报错——它们高频且无修复价值,却会稀释真正需要关注的崩溃。过滤逻辑必须写在 beforeSend 钩子或业务层判断中,而不是靠 Sentry 后台规则“事后打捞”。











