全链路追踪中异步错误源头标记的关键是建立可继承、透传、还原的执行上下文,而非简单打标签;需用weakmap+任务id模拟asynclocalstorage,在每个异步起点创建/延续上下文并注入traceid等字段,错误捕获时实时提取上下文并上报。

在全链路追踪中标记异步错误源头,核心不是“打上一个标签”,而是让每次异步操作都携带可继承、可透传、可还原的执行上下文。错误发生时,这个上下文必须能被准确提取并注入上报数据中。
用轻量上下文管理器替代全局变量
AsyncLocalStorage 在浏览器端不可用,需用 WeakMap + 当前任务标识(如 Promise ID 或 requestAnimationFrame ID)模拟。关键点是:每个异步起点(fetch、setTimeout、Promise 构造、路由跳转)都要创建或延续上下文对象,并绑定 traceId、requestId、入口行为(如点击按钮的 data-id)、时间戳等字段。
- 不手动在每个 fetch 参数里塞 traceId,而是在封装的请求函数中自动读取当前活跃上下文
- 对 setTimeout/setInterval 包一层 wrapper,在执行回调前恢复上下文
- Vue/React 中,避免依赖组件实例生命周期去存 traceId;改用 hook 或 composable 统一获取上下文
错误捕获时主动注入上下文,而非事后补
window.addEventListener('unhandledrejection') 和 window.onerror 触发时,原始 error 对象里没有 traceId。此时不能 fallback 到 localStorage 或全局变量查——它们可能已被覆盖或失效。必须在错误被捕获的瞬间,从当前执行上下文中实时提取。
- 在 unhandledrejection 回调里调用 event.preventDefault() 后,立即执行 context.get() 获取 traceId
- 对 event.reason 做类型判断:若为字符串,尝试用 new Error(event.reason).stack 补充堆栈;若为 Error 实例,直接合并上下文字段
- 上报 payload 中必须包含 traceId、errorId(用 error.stack + timestamp 生成)、触发位置(如 currentRoute、activeElement?.dataset?.id)
资源加载类异步错误要提前埋点
img/script/link 的加载失败不会触发 unhandledrejection,也不会带上下文。解决方案是在插入 DOM 前打标:
- 动态创建 script 标签时,设置 data-trace-id 属性,值来自当前上下文
- 监听 error 事件时,从 event.target.dataset.traceId 提取,而不是靠堆栈反推
- 对 performance.getEntriesByType('resource') 中的失败项,过滤出 name 匹配当前页面资源路径的条目,再关联最近一次的 traceId
确保异步堆栈可追溯,不止于 traceId
traceId 是关联线索,但定位源头还需调用链快照。可在关键异步入口处记录轻量栈信息:
- 发起 fetch 前执行 const entryStack = new Error().stack.split('\n').slice(0, 4).join(' | '),存入上下文
- 错误上报时,把 entryStack 作为 extra 字段,和 traceId 一起发送
- 避免 console.trace()(影响性能),也不依赖 DevTools 异步堆栈(线上不可用)
不复杂但容易忽略:异步错误源头标记成败,取决于上下文是否在第一个异步动作开始时就建立,且能在任意嵌套层级、任意事件循环阶段被稳定读取。不是加个 traceId 就算完成,而是让整个异步生命周期都活在同一个“上下文容器”里。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











