直接用Composer安装官方SDK最稳妥:composer require sentry/sentry;Laravel项目优先选sentry/sentry-laravel,Symfony则用sentry/sentry-symfony,均支持自动集成与异常捕获。

PHP项目中怎么装Sentry SDK
直接用 Composer 装官方 SDK 是最稳的路径,别手写 autoload 或手动下载 ZIP。Sentry 官方维护的 sentry/sentry 包已原生支持 PHP 7.2+ 和 PSR-14(事件分发),不需要额外配 Monolog 中间层,除非你已有复杂日志管道。
执行命令:
composer require sentry/sentry
- 如果项目用了 Laravel,优先装
sentry/sentry-laravel,它自动注册服务、捕获 Artisan 命令异常、兼容 Horizon,比手动集成少踩三类配置坑 - 若用 Symfony,
sentry/sentry-symfony提供了 Bundle,能 hook 到 Kernel.terminate,避免请求未结束就上报失败 - 不建议在
require_once后手动 new Client——SDK 初始化必须早于任何可能抛异常的代码,否则首次 500 就漏报
如何让未捕获异常自动上报到 Sentry
核心是设置全局异常处理器,但 PHP 的 set_exception_handler 和 set_error_handler 行为不同:前者只管未 catch 的 Exception/Throwable,后者才管 E_WARNING 这类错误。Sentry 默认只接 Exception,E_ERROR 类错误需显式开启。
初始化时加这两个开关:
$client = new \Sentry\Client([
'dsn' => 'https://xxx@o123.ingest.sentry.io/456',
'enable_compression' => true,
'environment' => $_SERVER['APP_ENV'] ?? 'production',
'error_types' => E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED, // 关键:控制哪些错误会上报
]);
-
error_types不设默认值,意味着E_NOTICE这类低级别错误不会进 Sentry——不是 SDK 漏报,是故意过滤 - 若想捕获
ParseError(如语法错导致的致命错误),得在index.php最开头调用set_error_handler并转成 Throwable 再交由 Sentry 处理,PHP 7.4+ 才能稳定做到 - CLI 场景(如 cron)下,记得调用
\Sentry\flush()在脚本退出前清空队列,否则进程结束可能丢数据
怎么给 Sentry 上报自定义上下文和业务数据
单纯报错堆栈没用,关键是要带 request ID、用户 ID、订单号这类可关联业务的信息。Sentry 的 scope 机制就是干这个的,但它不是全局单例——每次请求都该新建 scope,且不能复用上一个请求的 scope。
立即学习“PHP免费学习笔记(深入)”;
常见写法:
\Sentry\configure_scope(function (\Sentry\State\Scope $scope): void {
$scope->setTag('route', $_SERVER['REQUEST_URI'] ?? 'cli');
$scope->setUser(['id' => $uid, 'email' => $email]);
$scope->setExtra('order_id', $orderId);
});
-
setTag()适合筛选(如按route查所有 /api/pay 接口错误),但值长度不能超 200 字符,超长会被截断且不报错 -
setUser()的id字段必须是字符串,传 int 会导致整个 user 结构被 Sentry 后端忽略 - 不要在中间件里反复调用
configure_scope——它会覆盖之前设置,应集中放在请求入口或统一的 RequestHandler 中
为什么本地开发时 Sentry 总是收不到测试异常
大概率是 DSN 配错了,或者环境过滤生效了。Sentry 默认对 localhost、127.0.0.1、dev 环境静默丢弃事件,不是 SDK 坏了。
检查三处:
// 1. DSN 是否含 oXXX.ingest.sentry.io?旧版 sentry.io 域名已停用 // 2. 'environment' 配置是否等于你当前 APP_ENV(大小写敏感) // 3. 是否启用了 'before_send' 回调并 return null?
- 本地验证最简单方法:临时删掉
environment配置项,再抛个throw new RuntimeException('test');,看 Sentry 控制台是否立刻出现 - Chrome 开发者工具 Network 标签页搜
store,能看到 SDK 实际发出的 POST 请求,响应 200 但没数据?说明后端过滤了;直接失败?基本是 DSN 或网络问题 - 某些共享主机禁用
curl_exec,此时 SDK 会 fallback 到 file transport,但默认不启用——得手动加'transport' => new \Sentry\Transport\NullTransport()来确认是否卡在 HTTP 层
真正难调试的是异步任务里的上报:Worker 进程常驻,scope 和 client 实例容易复用,一次异常污染后续所有上报的 user 数据。这种场景必须每个 job 单独 new Client 或重置 scope。



















