webman需手动接入sentry才能捕获生产环境异常,因默认仅打印日志不上报;必须在onworkerstart阶段初始化sentry并覆盖set_exception_handler,且catch中需显式调用captureexception并配合configurescope添加上下文。

Webman 默认不带错误监控能力,直接部署到生产环境后,try/catch 漏掉的异常、未捕获的 Promise 拒绝、框架底层抛出的致命错误,都会静默丢失。必须手动接入 Sentry 才能拿到可定位的堆栈和上下文。
Webman 的错误捕获机制与 Sentry 冲突点
Webman 基于 Workerman,运行在 CLI 环境,没有浏览器的 window.onerror 或 unhandledrejection 事件。它依赖 PHP 的 set_exception_handler 和 set_error_handler 捕获全局异常与错误,但默认只打印到控制台或日志文件,不支持上报。
Sentry 的 @sentry/php SDK 正是为这类 CLI 场景设计的,但它不会自动 hook Webman 的异常处理器——你得显式接管。
- Webman 的
onWorkerStart阶段是初始化 Sentry 的唯一安全时机(避免多进程重复 init) - 不能在
config/bootstrap.php中直接调用Sentry\init(),否则每个 worker 进程都会新建 client,造成连接泄漏 -
set_exception_handler必须在 Sentry 初始化之后再注册,否则 Sentry 的 handler 不会被触发
安装与初始化 @sentry/php SDK
先通过 Composer 安装:
composer require sentry/sentry
然后在 config/bootstrap.php 末尾添加初始化逻辑(注意判断是否主进程):
if (Worker::$pid === Worker::$masterPid) {
\Sentry\init([
'dsn' => 'https://your-key@o123456.ingest.sentry.io/123456',
'environment' => env('APP_ENV', 'production'),
'release' => env('APP_VERSION', 'unknown'),
'traces_sample_rate' => 0.1,
'before_send' => function (\Sentry\Event $event): ?\Sentry\Event {
// 过滤调试用的测试异常
if (str_contains($event->getException()->getMessage(), 'test')) {
return null;
}
return $event;
},
]);
}
<p>接着在 <code>start.php</code> 中注册异常处理器(确保 Sentry 已 init):</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/gongju/2262" title="Webman 2.2.0"><img
src="https://img.php.cn/upload/manual/001/589/237/6a0e8a8df01ff947.jpg" alt="Webman 2.2.0" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/gongju/2262" title="Webman 2.2.0" class="overflowclass">Webman 2.2.0</a>
<p class="overflowclass">Webman 2.2.0版本强化了 TCP/UDP 服务支持,优化路由组管理,并增强异步任务处理能力。结合协程与连接池技术,Webman 能轻松应对高并发场景,适用于网站、接口服务、即时通讯、物联网及游戏开发,兼具高性能、灵活扩展与稳定可靠,是多场景 PHP 服务开发的理想选择。</p>
</div>
<a rel="nofollow" href="/xiazai/gongju/2262" title="Webman 2.2.0" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
<pre class="brush:php;toolbar:false;">set_exception_handler(function (\Throwable $e) {
\Sentry\captureException($e);
});
这个 handler 覆盖了所有未被捕获的 Exception 和 Error,包括 FatalError(PHP 7+)。
手动捕获业务逻辑异常
自动捕获只覆盖“逃逸”到顶层的异常。你在 Controller、Service 或 Event 中主动 throw 的异常,如果被 try/catch 吞掉又没处理,Sentry 就收不到。
这时候需要显式上报:
try {
$result = $this->paymentService->charge($order);
} catch (\Exception $e) {
\Sentry\captureException($e);
// 或带额外上下文
\Sentry\configureScope(function (\Sentry\State\Scope $scope) use ($order) {
$scope->setTag('order_id', $order->id);
$scope->setExtra('payment_method', $order->method);
});
\Sentry\captureException($e);
throw $e; // 仍需 re-throw,保持原有错误流
}
- 不要在
catch块里只调captureException就完事——这会让错误消失,上游无法感知 -
configureScope必须在captureException之前调用,否则上下文不生效 - Webman 的
Request对象可通过request()->getRealIP()、request()->getUri()提取关键字段,建议统一封装进 scope
Source Map 不适用,但需开启 PHP debug 符号
Webman 是 PHP 项目,没有 JavaScript 的压缩代码问题,所以不需要上传 Source Map。但你必须确保:
- 生产环境 PHP 配置中
display_errors = Off,但log_errors = On,且 error_log 指向有效路径(Sentry 不依赖它,但可作兜底) - PHP 编译时启用
--enable-debug(非必须,但开启后堆栈中的函数参数和变量名更完整) - 若使用 OPcache,确认
opcache.save_comments = 1和opcache.enable_file_override = 0,否则反射获取的类名可能为空
最常被忽略的是:Sentry 报告里的堆栈行号,依赖 PHP 的 debug_backtrace() 输出。而 Webman 的异步回调、协程切换可能导致部分帧丢失——这不是 Sentry 的问题,是 Workerman 底层调度特性决定的。遇到关键路径堆栈不全,优先检查是否在 go 或 defer 中抛出了异常。









