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

先说几个核心判断:用 `sentry/sentry-lara vel` 就对了,别碰那个原生的 `sentry/sentry`。一旦碰上DSN格式不对、`enabled` 被悄悄关掉、或者环境判断出岔子,监控就会神不知鬼不觉地失效——这三个问题堪称静默失败的三大元凶。
为什么 sentry/sentry-lara vel 是唯一推荐选项
它可不是什么“可选插件”,而是真正嵌入 Lara vel 异常生命周期的核心组件。它会自动注册异常处理器、帮你注入请求上下文(用户ID、路由名、请求头)、绑定日志通道,并且支持队列、HTTP、命令行这些全场景的异常捕获。这些能力,`sentry/sentry` 一个都不具备。如果你用后者,只能自己在 `App\Exceptions\Handler::report()` 里吭哧吭哧手动调 `captureException()`——只要漏掉一处,那块的异常就永远上不了报。
常见的翻车现场是什么?在 `php artisan tinker` 里执行 `Sentry\captureException(new \Exception('test'))` 没反应,或者 Sentry控制台一片空白。十有八九,你装的是 `sentry/sentry` 却没配 `Sentry\init()`,或者根本没把它注册到 Lara vel 容器里。
关键操作清单:
- 必须执行:`composer require sentry/sentry-lara vel`
- 不要执行:`composer require sentry/sentry`(除非你铁了心要绕过整个 Lara vel 生态自己造轮子)
- 验证是否生效:去 `config/app.php` 里检查一下,有没有自动注册上 `\Sentry\Lara vel\ServiceProvider::class`
SENTRY_LARA VEL_DSN 必须带协议和完整路径
DSN 这玩意儿可不是随便填个字符串就完事了。它本质上是个连接 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 文件里明明写了。原因很可能是你写的是 `SENTRY_DSN=...`,而 SDK 默认读的是 `SENTRY_LARA VEL_DSN`。
几个保命技巧:
- 确保 .env 里用的是 `SENTRY_LARA VEL_DSN=`,不是 `SENTRY_DSN`
- 跑完 `php artisan sentry:publish --dsn=...` 后,检查 `config/sentry.php` 中 `'dsn' => env('SENTRY_LARA VEL_DSN')` 是否存在
- 开发阶段测试时,可以临时把 `config/sentry.php` 里的 `'enabled' => true` 硬编码,先绕过环境判断再说
未捕获异常才自动上报,try/catch 里的异常要手动触发
SDK 的默认行为其实非常保守:它只捕获那些抛到顶层、没被任何 `catch` 拦住的异常。这意味着下面这段代码,不会产生任何 Sentry 事件:
```php
try {
throw new \Exception('支付验签失败');
} catch (\Exception $e) {
Log::error('验签失败', ['error' => $e->getMessage()]);
// 这里不会自动上报
}
```
但业务上,恰恰是这类“预期内的失败”最需要告警——比如支付回调失败、第三方 API 超时。这时候必须显式调用:
- `app('sentry')->captureException($e)`(推荐,走 Lara vel 容器)
- `Sentry\captureException($e)`(全局函数,需要确保已加载)
- 队列任务里加额外上下文:`app('sentry')->captureException($e, ['extra' => ['job' => get_class($this)]])`
注意:`Log::error()` 绑定 Sentry 日志通道后,只会把日志当普通 message 上报,不带堆栈信息、也不会触发 issue 创建,所以不能替代 `captureException`。
环境隔离与上下文注入最容易被忽略
本地开发时要是开着 Sentry,跑一次 `phpunit` 就可能把当月的上报额度刷爆。反过来,生产环境里如果不传用户 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()`,排查时间就翻一倍;多一个没关的本地开关,账单分分钟爆表。
本文转载于:https://www.php.cn/faq/2438842.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。