
法兰克福的一位购物者点击支付后观看了一秒钟的加载旋转器,十秒后放弃。你的APM仪表板在此期间一直是绿色的。没有异常抛出,也没有捕获堆栈跟踪,因为你的代码中没有失败。支付提供商的脚本卡住了,页面从未完成渲染,订单因此流失。你的后端甚至从未接收到最终结账请求,所以没有失败的交易可供检查:从应用程序的角度来看,什么都没发生。但从用户的角度看,唯一重要的步骤失败了。
这就是本文所说的盲点。堆栈跟踪监控在其所做的事情上确实非常出色:当代码抛出异常时,它会向开发人员提供文件、行号以及导致异常的调用链。问题是它结构性地无法看到的部分。存在一整类用户面对的失败发生在请求到达你的代码之前、你的响应离开后,或者根本没有任何错误抛出的情况下。
以下内容将介绍堆栈跟踪监控能捕获的情况,用户体验测量中存在的五个空白,以及合成真实浏览器监控如何覆盖它无法触及的领域。
什么是堆栈跟踪监控?
堆栈跟踪是在错误发生时调用栈的快照:显示哪些函数正在执行,在哪些文件中,行号是多少,以及调用顺序。如果你曾看到控制台错误列出一连串方法和文件路径,就是在看堆栈跟踪。
作为应用性能监控(APM)工具的一部分,堆栈跟踪监控会自动捕获这些跟踪,进行分组,并跟踪每个异常的发生频率。当NullPointerException开始在结账服务中频繁出现时,APM平台会告诉开发者准确的位置和问题的广泛程度。否则会淹没在日志文件中的异常变成了可排序、可追踪、可分配的工作。
注意触发条件,因为本文之后所有内容均基于此:堆栈跟踪只有在代码执行并抛出错误时才存在。条件的两个部分都很重要。如果代码未运行,或者运行时未抛出异常,则无跟踪,无论用户刚刚经历了什么。
一个实际的记忆方法:代码运行并抛出了异常,你就得到堆栈跟踪。代码运行缓慢但未抛出异常,则无跟踪。浏览器在到达你的代码前失败,则无跟踪。你的响应发出后,某些代码外的因素阻塞过程,则无跟踪。四种状态中只有一种会产生证据,而用户则可能处于这四种状态中任何一种。
堆栈跟踪监控捕获得好的内容
以下内容绝不是反对APM。对于由代码引发的失败,堆栈跟踪是从症状到解决最快捷的方法:
- 快速根本原因识别。 堆栈跟踪指向失败的代码行及其调用路径,减少手动调试的大量猜测工作。
- 深入的错误上下文。 优秀的堆栈跟踪包含方法参数、变量状态和请求元数据,让开发者不光知道代码在哪儿崩溃,还知道其崩溃时的条件。
- 工程团队的共享语言。 堆栈跟踪精确且可复现。将跟踪粘贴到工单里,传达的信息往往胜过数段描述文字。
- 代码质量趋势。 跟踪哪些异常重复出现及其位置,揭示脆弱模块和坏的代码模式,便于重新构建,防止造成故障。
请继续使用你的APM工具。问题不在于堆栈跟踪是否有用,而在于它们是否描述了你的用户体验。它们没有做到,而这些空白大致可以分为五类。
空白:堆栈跟踪未覆盖的用户体验方面
这五个空白并非随机的盲点,而是边界问题:第三方代码、应用前基础设施、浏览器执行、地域和时间。堆栈跟踪在应用边界内非常强大,但在用户旅程跨出应用边界的地方则薄弱。

第三方脚本和外部API
当今典型网页会从其他公司服务器引入支付组件、标签管理器、聊天、分析和广告脚本。依赖中的某一环卡住或变慢,页面就会在用户端停滞,但失败的代码不是你的,于是你的监控未能捕获任何异常。通常没有明确的异常出现:第三方端点响应了,只是响应过慢阻塞了页面渲染。第三方内容是经典案例,用户苦苦挣扎而内部仪表盘却始终绿灯。
DNS、TLS和CDN故障
请求到达你的应用之前,必须完成域名解析,进行TLS握手,且通常需经过CDN边缘节点。DNS记录配置错误、证书过期或边缘节点失败会阻断用户访问。你的代码不会为这些用户执行,因而这些失败无法产生堆栈跟踪。从基础设施内部看,最明显的症状是无声无息:流量突然下降,却没有任何解释。DNS、TCP、TLS和HTTP层的失败只有外部监测才能察觉。
前端渲染和UI故障
服务器端APM确认后端按时返回了有效响应,却无法说明浏览器如何处理这些响应。JavaScript包在某浏览器版本中崩溃,移动端布局崩塌,按钮点击处理程序未绑定:用户看着破损页面,却见服务器日志显示了正常的200成功状态。客户端异常可单独收集,但缓慢渲染、布局偏移和无响应控件多数不抛异常,只是悄悄失去用户。Next.js应用中的水合失败是现代典型:服务器发送完整的200响应和HTML,客户端JavaScript失败,用户看到页面正常但无法操作。值得监控的事件不是JavaScript是否抛错,而是关键阶段是否完成:按钮是否可点击,表单是否提交,确认是否显示。堆栈跟踪记录异常,用户体验的是缺失的关键步骤。
区域性停机
监控工具嵌入在你的基础设施内,报告的是汇总数据。如果某运营商路径在某区域降级,或某CDN节点在该区域故障,用户会遇到超时,但平均数据几乎无变化。堆栈跟踪无视用户位置,只知代码执行位置。区域故障按其本质对代码中心监测来说是不可见的。
慢不等于异常
最隐晦的空白:性能下降不会抛异常。页面加载时间从两秒上涨到八秒,不会产生错误,却会持续驱逐用户。通常是市场团队最先察觉转化率下降,远早于工程师的预警电话,因为代码角度看并无故障。堆栈跟踪监控设计上也是被动的,只有在错误发生后报告,且其输出仅限懂代码的人阅读。堆栈跟踪不追踪响应时间、页面加载速度或用户侧性能指标。应用可能慢到无法使用,但从堆栈跟踪看完全健康。
| 故障 | 用户体验 | 堆栈跟踪APM显示 |
|---|---|---|
| 第三方脚本卡顿 | 页面加载中断,结账被阻塞 | 绿色——代码无异常 |
| A/B测试脚本失效 | 一半用户获得破损页面版本 | 绿色——实验非代码问题 |
| DNS记录配置错误 | 网站无法访问 | 绿色——请求未到达 |
| TLS证书过期 | 浏览器安全警告,用户离开 | 绿色——握手失败,代码未执行 |
| 某浏览器中JS包崩溃 | 按钮失效,布局破损 | 服务器端显示正常的200 |
| 某区域CDN节点降级 | 该区域加载时间长达十秒 | 响应时间聚合正常 |
| 性能逐渐恶化 | 页面变慢,用户流失增加 | 无错误,无报告 |
合成监控如何弥补空白
合成监控从相反方向切入问题。它不监控你的代码并等待异常,而是从世界各地的真实浏览器运行计划好的脚本检查,测量用户在特定时间和地点的真实体验。此反转直接覆盖每个空白:
- 它加载整个页面,不仅是你的代码。真实浏览器检查会执行页面上的所有第三方脚本。如果标签管理器卡顿或支付组件拖慢加载,检查便捕捉到,并通过瀑布图显示哪个资源停滞以及持续了多久。
- 它从用户起点开始。每次检查都会从外部解析DNS、协商TLS并穿越CDN。过期证书或失效的边缘节点在一次监测周期内导致检查失败,而不是数小时后无故流量下降才显现。
- 它在真实浏览器中渲染。因为检查驱动的是实际的浏览器引擎,脚本出错、元素无响应及渲染失败会表现为失败步骤,而非隐形客户端问题。
- 它从多个地理位置运行。来自全球网络节点的检查能隔离区域故障:当法兰克福失败而达拉斯通过时,你已知晓问题范围,先于用户在社交媒体抱怨。
- 每次运行都测量速度,无论是否出错。每次检查都记录加载和各步骤时间,因此八秒加载的页面会在你设置的阈值触发警报,远早于出现技术错误。
由此产生的分诊规则是:如果第一次字节之前检查失败,则指向DNS、TLS或CDN责任。瀑布图在第三方域停滞则该供应商将首当其冲,而非应用团队。脚本步骤抵达后端同时APM显示异常则交给工程,同时附带堆栈跟踪。
多步骤流程同理。使用EveryStep脚本,检查可定时登录、搜索、添加购物车和支付,实现全天候验证真实收入路径,确保它们的健康性不被假设。
须明确的是合成监控并不洞察内部代码。当检查因后端异常失败时,堆栈跟踪而非浏览器告知开发者应修复哪一行代码。这正是两者应结合使用的原因。
APM与合成监控:更佳的组合
这非非此即彼的选择,将其视为单选最终会让团队措手不及。带堆栈跟踪的APM从内部向外监控,回答“代码为何失败?”;合成监控从外部向内观察,回答“用户现处位置能否实际进行关键操作?”两者相辅相成,填补彼此盲区。
最危险的失败是单一工具无法发现的:APM未察觉的供应商脚本阻塞结账;合成检测漏掉的罕见输入引发异常。两者并行使用,无一类失败被遗漏。
实践中,两者形成链条。法兰克福合成检查扣押一个结账流程失败,瀑布图锁定失败层级:DNS、CDN、第三方调用或你的后端。若终点是应用,APM内的堆栈跟踪定位具体异常函数。从外检测,内诊断,仪表盘与用户体验无缝连接。也终于打破了众响应者熟悉的僵局:一队说APM显示绿色,另一队说用户在抱怨。单靠APM监控好比监控室内的安全摄像机齐备,外门却无人看守,事发后清楚盗贼是谁,却也是空柜才发现被盗。
Dotcom-Monitor处于合成监控端。它不是APM平台,也不取代New Relic或Datadog这类工具;而是通过全球节点的真实浏览器合成监控补充它们,提供每步时序、瀑布详情,并在流程变慢或失败时发出警报。
总结
堆栈跟踪监控确实有价值:当你的代码抛出异常时,它是让开发者最快定位到故障行的工具。但其触发条件——代码执行并错误,限定了它永远无法展示的内容。第三方脚本、DNS和CDN故障、前端渲染崩溃、区域停机以及无错误的性能下降,虽然影响用户,但文字意义上的“堆栈跟踪”完全找不到任何踪迹。
合成真实浏览器监控弥补这些空白,监测用户走过的完整路径,分布于你关心的各个地理位置,以计划任务的形式在问题出现前发现它们。保留堆栈跟踪用于诊断,增加外向内的监测以便探测。用户经历的是整条路径,你的监控也应覆盖整条路径。