这个WooCommerce站点跑着Divi、LearnDash、一堆营销自动化插件,之前出问题时,会员的抱怨总要过好几天才能传到我这,而且永远说不清到底是哪个页面崩了、报了什么错。周三下午我花了20分钟把Sentry接上去,没想到第一个真正的Bug在一小时内就跳了出来——一个在每次REST请求里悄悄循环的错误,用户侧完全无感知,如果没有追踪系统,它大概能藏到明年。

为什么不用官方PHP片段,而是选了wp-sentry插件

打开网易新闻 查看精彩图片

进Sentry后台建项目时,引导页会给你一段\Sentry\init()的PHP代码和一个浏览器loader脚本。别往WordPress里粘。wp-sentry-integration这个插件把PHP和浏览器的官方SDK都打包好了,还做了几件你自己手搓会很费劲的事:在WordPress启动足够早的阶段初始化PHP SDK,保证捕获到其他插件的致命错误;把PHP错误、异常和致命错误全挂上钩子;在前端自动入队浏览器SDK并打通Tracing和Session Replay;每次事件都附上WordPress上下文——当前登录用户、运行环境、release版本、所有活动插件和主题的元数据。

刚开始有个地方让我懵了一下:设置页上的复选框一个都勾不动。不是bug,设计如此——插件不在UI里保存任何配置,全靠wp-config.php里写常量。那个设置页其实是个只读仪表盘,列出它检测到的所有常量,打勾说明常量存在且值有效。你对着它们点一天也是白点。想了下这反而更合理:错误追踪配置落在代码里,不受插件升级影响,不会因为wp-admin里的操作被意外改坏;就算后台账号被人拿走,也没法偷偷把错误流导向别人的DSN——和DISABLE_WP_CRON一个道理。

配置就两步
先把PHP和浏览器拆成两个Sentry项目。在这种挂满扩展、浏览器端各种第三方脚本乱飞的环境里,合在一起的结果就是浏览器噪音把服务端错误淹没掉。分开以后各管各的报警规则,排查清爽得多。

然后打开wp-config.php,在/* That's all, stop editing! */线上方的位置把下面这些常量写进去:

—— WP_SENTRY_PHP_DSN 和 WP_SENTRY_BROWSER_DSN 分别填两个项目的入口地址;
—— WP_SENTRY_ENV 标上 production;
—— WP_SENTRY_SEND_DEFAULT_PII 设为 true 可以把当前登录用户ID、用户名和邮箱一起送到事件里,方便回溯是谁触发的;
—— 顺便把采样率和Tracing的开销之类也按需要定好,保持轻量。

一小时内抓到的第一个“隐形”Bug

配置敲完不到一个钟头,Sentry的Feed里就弹出一条错误:某个REST API端点每次被命中都会扔出一个PHP Warning,紧接着又触发自身的错误处理,形成循环。这个过程对前端零影响,管理员后台也看不到,如果不是因为性能面板上偶尔出现几毫秒的不明抖动,根本不可能有人注意到。

之前的情况是,用户只会丢一句“最近网站有点慢”,我翻遍日志也未必能找到这条循环,因为它根本不会写进Nginx的access log里作为失败请求,WordPress自己的debug log里又可能因为级别被过滤掉。而现在Sentry不仅把所有调用栈和发生频率给了出来,还附带了当时操作的用户信息,一眼就定位到是某个已停用会员角色的遗留权限检查在作怪。

修掉之后,整个站点的REST响应时间平均降了大约80毫秒,对登录会员的页面加载速度有肉眼可见的改善。虽然绝对数值不大,但这类藏在基础设施角落里的“无害”错误长期叠加起来,对数据库连接和PHP-FPM进程的消耗远比你估得高。

几点事后才明白的经验
1. 别把前端和后端错误混在一个项目里。浏览器端的各种扩展报错、旧设备兼容性问题、第三方脚本的异常,量级远超你想象,混在一起只会让真正需要处理的服务端错误变得不显眼。
2. 启用用户身份追踪。很多问题只有特定会员角色或者某个用户才会触发,有了用户ID就能马上圈定影响面。
3. 只看UI不用碰配置的做法,对错误追踪反而是好事。所有设置固化成常量,等于给你的监控系统加了一层物理隔离,任何后台层面的异常都改不掉它。
4. Sentry不只是崩了才报警。那些从未成为可见故障的静默错误,才是侵蚀性能和稳定性的主要来源,早一天抓出来就少一天带病运行。