全链路追踪需确保所有数据在统一请求上下文中可关联,核心是异步操作的上下文透传与错误/性能/资源等信息的 traceid 注入;须用 asynclocalstorage 或轻量模拟方案维持上下文,错误捕获时主动注入 traceid,navigation 性能数据需对齐服务端 trace,unhandledrejection 需 preventdefault 以保障日志可见性,离线场景下须持久化完整上下文字段并复用 traceid。

全链路追踪不是加个 traceId 就完事的;它要求错误、性能、资源、用户行为等所有数据在同一个请求上下文里可关联,否则 traceId 只是个装饰。核心难点在于:如何让异步操作(Promise、setTimeout、fetch、路由跳转)都继承并透传上下文,且不破坏原有逻辑。
怎么让错误堆栈带上 traceId 和 request_id
错误本身不带链路信息,必须在捕获时主动注入。不能只靠全局 window.onerror 或 unhandledrejection 拿到原始 error 对象就上报——这时候 traceId 早就丢了。
- 所有错误上报前,必须从当前活跃的“执行上下文”中取
traceId和requestId;这个上下文要能跨 Promise 链、跨事件循环、跨 React/Vue 组件生命周期存活 - 推荐用
AsyncLocalStorage(Node.js 端)或前端模拟方案(如基于WeakMap+ 当前任务 ID 的轻量上下文管理器),避免污染全局变量或手动透传 - Vue/React 框架错误(
app.config.errorHandler、ErrorBoundary)要优先读取组件实例或 hook 内部绑定的上下文,而不是 fallback 到全局 trace - 资源加载错误(
img/script)无法自动携带 trace,需在插入 DOM 前打上自定义属性(如data-trace-id),再通过event.target提取
performance.getEntriesByType('navigation') 怎么对齐后端 trace
performance.getEntriesByType('navigation') 返回的是浏览器原生导航记录,不含任何服务端 trace 字段。直接上报等于断链。
前端设计与 UI/UX 全方位优化专家。覆盖视觉层次、排版系统、色彩理论、响应式布局、交互体验、动画动效、无障碍访问、性能优化八大维度,帮助开发者将普通页面升级为高品质产品级界面。前端设计与 UI/UX 全方位优化专家。覆盖视觉层次、排版系统、色彩理论、响应式布局、交互体验、动画动效、无障碍访问、性能优化八大维度,帮助开发者将普通页面升级为高品质产品级界面。
- 必须在 HTML 模板或首屏 JS 注入阶段,从服务端响应头(如
traceparent)或内联 script 中提取初始 trace 上下文,并挂载到全局对象(如window.__TRACE__) - 后续所有 fetch 请求必须在
headers中带上traceparent,且与 navigation 的startTime对齐——即用performance.timeOrigin + entry.startTime计算绝对时间戳,和服务端对齐毫秒级偏差 - 不要依赖
performance.now()单独计时,它不保证和服务端时钟同步;所有关键时间点(TTFB、FCP、LCP)都要映射回timeOrigin基准
为什么 unhandledrejection 必须 preventDefault
默认情况下,未捕获的 Promise 拒绝会被浏览器静默丢弃,连控制台都不报——你监听到了,但用户根本不知道发生了什么,更别说触发 trace 关联。
- 调用
event.preventDefault()是唯一能让浏览器强制输出该错误到 console 的方式,这对开发期调试和线上日志补全都关键 - 但注意:preventDefault 不影响你的上报逻辑,只是“唤醒”浏览器日志系统;真正上报仍要走你自己的
reportError函数 - 如果用了 Sentry 等 SDK,它们内部已做
preventDefault;但自研 SDK 容易漏掉这行,导致错误看似捕获了,实际没进任何可观测通道 - 某些低版本 iOS Safari 不支持
preventDefaultonunhandledrejection,需降级为console.error(event.reason)强制刷日志
离线场景下 traceId 如何不丢失
网络中断时,错误和性能数据会缓存在 IndexedDB,但若缓存期间页面刷新或关闭,新会话的 traceId 就变了,旧数据再也无法关联。
- 离线缓存的数据必须自带完整上下文字段:
traceId、spanId、parentSpanId、timestamp,不能只存原始 error 对象 - 每次生成新 trace 前,先检查 localStorage 是否有未上报的 traceId(比如标记为
pending_trace),优先复用而非新建 - IndexedDB 表结构要支持按
traceId聚合查询,后端接收时也得允许“分批上报同一 trace”的语义,否则聚合链路会断裂 - 最易忽略的一点:service worker 缓存的资源,其 fetch 请求若失败,错误事件发生在 SW 线程,无法访问页面主线程的
AsyncLocalStorage——这类错误必须由 SW 主动注入 trace 上下文再 postMessage 回来
真正卡住全链路的,往往不是 traceId 生成,而是异步边界处的上下文泄漏。每个 setTimeout、每个 addEventListener、每个 new Promise,都是潜在的断点。别指望框架自动帮你透传——得在每层调度入口做显式绑定。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










