前端可观测性体系:日志、指标与链路追踪
一句话结论:建立一个由日志 (Logging)、指标 (Metrics) 和链路追踪 (Tracing) 构成的“可观测性铁三角”,是主动发现、快速定位并有效解决线上问题的基础,它能将前端从被动的“救火队”转变为主动的“领航员”。
1. 可观测性的三大支柱 (The Three Pillars)
可观测性 (Observability) 不仅仅是监控 (Monitoring)。监控告诉你“系统出错了”,而可观测性告诉你“系统为什么出错”。
| 支柱 | 角色 | 数据形态 | 核心问题 | 常用工具 |
|---|---|---|---|---|
| 日志 (Logging) | 离散事件记录 | 带有时间戳的、非结构化或结构化的文本行。 | 发生了什么? (What happened?) | Sentry, LogRocket, 自研日志库 + ELK/Loki |
| 指标 (Metrics) | 聚合数据度量 | 随时间变化的、可聚合的数值(计数器、仪表盘、直方图)。 | 系统状态如何? (How is the system doing?) | Prometheus, Datadog, Vercel Analytics |
| 链路追踪 (Tracing) | 请求生命周期 | 一个请求跨越多个服务的完整路径,由 Spans 组成的 Trace。 | 瓶颈在哪里? (Where is the bottleneck?) | OpenTelemetry, Jaeger, Datadog APM, Sentry |
这三者相辅相成:通过指标发现异常(例如,错误率飙升),通过链路定位到具体服务和操作(例如,支付 API 耗时过长),最后通过日志查看该操作的详细上下文(例如,请求参数、错误堆栈)。
2. 前端日志 (Logging)
前端日志是事后追溯问题的“黑匣子”。
A. 日志分类与分级
- 行为日志 (Behavior):记录用户的关键操作路径(点击、路由跳转、功能使用等),用于分析用户行为和复现问题。
- 错误日志 (Error):记录 JS 错误、Promise rejections、资源加载失败、API 请求失败等。这是最重要的日志类型。
- 性能日志 (Performance):记录 Core Web Vitals (LCP/INP/CLS)、API 请求耗时、组件渲染时间等。
日志分级 (Level):
error: 严重错误,必须立即处理。warn: 警告,可能存在潜在问题。info: 普通信息,用于记录业务流程。debug: 调试信息,仅在开发或特定排错场景下开启。
B. 如何采集
- 全局错误捕获:
// 捕获同步错误和资源加载错误 window.addEventListener('error', event => { // 过滤掉非脚本错误 if (event.message) { console.log('JS Error:', event.message, event.filename, event.lineno, event.colno, event.error); } else { console.log('Resource Error:', event.target.src || event.target.href); } }, true); // 使用捕获阶段以捕获资源加载错误 // 捕获未处理的 Promise 拒绝 window.addEventListener('unhandledrejection', event => { console.log('Promise Rejection:', event.reason); }); - React Error Boundary:捕获组件渲染期间的错误。
class ErrorBoundary extends React.Component { componentDidCatch(error, errorInfo) { logErrorToMyService(error, errorInfo); // 发送到日志服务 } // ... } - 封装上报函数:提供一个统一的 SDK 函数,业务代码可以手动调用来上报特定日志。该函数应自动附加用户 ID、设备信息、App 版本、页面 URL 等通用元数据。
C. 推荐方案
- Sentry:业界标杆。提供错误聚合、SourceMap 关联、版本管理、告警等一站式服务。
- LogRocket:可以录制用户会话的视频,像素级复现用户操作和 bug 现场,是排查疑难杂症的神器。
3. 前端指标 (Metrics)
指标提供了系统健康状况的宏观视图。
A. 关键指标 (Key Metrics)
- 性能指标 (Performance):Core Web Vitals (LCP, INP, CLS), FCP, TTFB。
- 可用性指标 (Availability):API 成功率、资源加载成功率。
- 流量指标 (Traffic):PV (Page View), UV (Unique Visitor)。
- 业务指标 (Business):转化率、功能使用率。
B. 如何采集与展示
- 采集:
- Core Web Vitals: 使用 Google 的
web-vitals库。 - API 成功率: 封装
fetch或axios,在拦截器中统计请求的成功与失败。
- Core Web Vitals: 使用 Google 的
- 发送:通常采用“信标”(Beacon) API (
navigator.sendBeacon) 在页面卸载前发送数据,因为它不会阻塞页面导航且能保证数据送达。 - 存储与可视化:将数据发送到 Prometheus (时序数据库) + Grafana (可视化面板) 或商业服务如 Datadog。
示例:使用 web-vitals 库
import { onLCP, onINP, onCLS } from 'web-vitals';
onLCP(console.log);
onINP(console.log);
onCLS(console.log);
4. 前端在链路追踪中的角色 (Tracing)
分布式链路追踪 (Distributed Tracing) 旨在追踪一个请求从用户发起,到经过前端、BFF、后端微服务,再到数据库,最后返回给用户的完整旅程。
前端为何关键?
前端是全链路的起点。一个完整的 Trace 如果没有前端这一环,就无法衡量用户的真实端到端体验,也无法区分问题是出在网络、CDN 还是服务器。
实现原理:Trace Context 的生成与传递
- 生成 Trace ID:当用户在前端执行一个关键操作(如页面加载或点击按钮发起 API 请求)时,前端的监控 SDK 会生成一个全局唯一的
Trace ID和一个代表当前操作的Span ID。 - 传递 Trace Context:前端在发起 API 请求时,会将这个 Trace Context(通常包含
traceparent和tracestate)注入到 HTTP 请求头中。// W3C Trace Context 标准请求头 traceparent: 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01 - 后端接收与传递:后端服务(BFF、微服务)必须配置为能够识别并解析这个请求头。当它处理完请求并调用下一个服务时,它会继续传递
Trace ID,并生成自己的Span ID。 - 聚合与可视化:所有服务都将自己的 Span 信息(包含 Trace ID, Span ID, Parent Span ID, 操作名称, 耗时等)上报给一个收集器 (Collector),最终在 Jaeger, Zipkin 或 Sentry 等工具中聚合成一个完整的调用链火焰图。
推荐方案:OpenTelemetry
OpenTelemetry (OTel) 是一个 CNCF 的开源项目,它提供了一套与供应商无关的 API、SDK 和工具,用于检测、生成、收集和导出遥测数据(指标、日志、链路)。这是未来的行业标准。
在前端集成 OTel 的基本步骤:
- 安装 OTel SDK 和相关检测库 (
@opentelemetry/sdk-trace-web,@opentelemetry/instrumentation-document-load等)。 - 配置
TracerProvider和导出器 (Exporter) 将数据发送到后端收集器。 - 自动检测库会自动为页面加载、XHR/Fetch 请求等创建 Spans。
5. 关联阅读
- OpenTelemetry 官方文档: opentelemetry.io
- Sentry 官方文档: Frontend Monitoring
- Google Web Vitals: web.dev/vitals