推荐使用 sentry/sentry-laravel,因其深度集成 Laravel 生命周期,自动捕获全场景异常;而 sentry/sentry 需手动调用且易静默失效,三大原因:DSN 格式错误、enabled 关闭、环境判断卡死。

直接说结论:用 sentry/sentry-laravel,别碰 sentry/sentry;DSN 格式错、enabled 关闭、环境判断卡死是三大静默失效原因。
为什么 sentry/sentry-laravel 是唯一推荐选项
它不是“可选插件”,而是 Laravel 异常生命周期的深度参与者。自动注册异常处理器、注入请求上下文(用户 ID、路由名、请求头)、绑定日志通道、支持队列/HTTP/命令行全场景捕获——这些能力 sentry/sentry 全都不具备,你得自己在 App\Exceptions\Handler::report() 里手动调 captureException(),漏一个地方,那块的异常就永远不上报。
常见错误现象:php artisan tinker 中执行 Sentry\captureException(new \Exception('test')) 没反应,或 Sentry 控制台空空如也。大概率是你装了 sentry/sentry 却没配 Sentry\init(),或者根本没注册到 Laravel 容器里。
- 必须执行:
composer require sentry/sentry-laravel - 不要执行:
composer require sentry/sentry(除非你明确要绕过 Laravel 生态自己造轮子) - 验证是否生效:检查
config/app.php中是否自动注册了\Sentry\Laravel\ServiceProvider::class
SENTRY_LARAVEL_DSN 必须带协议和完整路径
DSN 不是“随便填个字符串”,它本质是 Sentry 的连接 URI。格式必须是 https://xxx@o123.ingest.sentry.io/456 这种完整结构。只填 o123.ingest.sentry.io/456 或 https://xxx@o123.ingest.sentry.io 都会触发 Sentry\init() 静默跳过——不报错、不提示、不初始化客户端,监控彻底失能。
常见错误现象:本地测试时 php artisan sentry:test 报错 “No DSN provided”,但 .env 明明写了。原因往往是 .env 里写的是 SENTRY_DSN=...,而 SDK 默认读的是 SENTRY_LARAVEL_DSN。
- 确保
.env中使用SENTRY_LARAVEL_DSN=,不是SENTRY_DSN - 运行
php artisan sentry:publish --dsn=...后,检查config/sentry.php中'dsn' => env('SENTRY_LARAVEL_DSN')是否存在 - 开发阶段测试,临时把
config/sentry.php的'enabled' => true硬编码,绕过环境判断
未捕获异常才自动上报,try/catch 里的异常要手动触发
SDK 默认行为非常克制:只捕获抛到顶层、没被任何 catch 拦截的异常。这意味着以下代码不会产生 Sentry 事件:
try {
throw new \Exception('支付验签失败');
} catch (\Exception $e) {
Log::error('验签失败', ['error' => $e->getMessage()]);
// 这里不会自动上报
}
但业务上这类“预期内失败”恰恰最需要告警——比如支付回调失败、第三方 API 超时。必须显式调用:
-
app('sentry')->captureException($e)(推荐,走 Laravel 容器) -
Sentry\captureException($e)(全局函数,需确保已加载) - 队列任务中加额外上下文:
app('sentry')->captureException($e, ['extra' => ['job' => get_class($this)]])
注意:Log::error() 绑定 Sentry 日志通道后,只会把日志当 message 上报,不带堆栈、不触发 issue 创建,不能替代 captureException。
环境隔离与上下文注入最容易被忽略
本地开发时开着 Sentry,跑一次 phpunit 就可能刷爆当月事件 quota。而生产环境不传用户 ID、订单号、IP,等于白搭——你看到的全是“匿名 500 错误”,没法定位到具体用户或交易。
关键配置点:
-
config/sentry.php中'enabled' => app()->environment('production')是默认值,测试环境务必关掉 - 用户上下文必须在
AppServiceProvider::boot()中用Sentry\configureScope()注入,不能放中间件里(会污染后续请求) - 避免在
Handler::report()中重复调captureException():如果app()->bound('sentry')为真,且$this->shouldReport($e)为真,才执行;否则可能重复上报
真正难的不是装上 Sentry,而是让每条上报事件都携带足够还原现场的信息。少一个 setUser(),排查时间就翻倍;多一个没关的本地开关,账单就爆表。


















