前端追踪技术:使用OpenTelemetry实现全栈可观测性

本文详细介绍了如何在前端应用中使用OpenTelemetry实现分布式追踪,包括浏览器设置、用户事件记录、前后端连接等核心技术,帮助开发者获得全栈可观测性,快速定位性能瓶颈。

前端追踪技术:使用OpenTelemetry实现全栈可观测性

为什么前端需要追踪

前端系统有其独特的复杂性,这些在后端日志中往往不可见:

  • 用户交互延迟 - 当用户点击按钮感觉"慢"时,是React重渲染过多?JS包太大?还是API慢?没有追踪,我们无从得知
  • 异步复杂性 - 单页应用可能同时有多个请求、渲染任务和状态转换
  • 本地差异 - 后端日志不知道用户是否在使用受限的3G连接、CPU使用情况或浏览器异常行为

前端追踪将这些信息整合,让我们能够:

  • 将用户操作与触发的网络请求关联
  • 跟踪请求通过后端服务的全过程
  • 比较感知延迟与系统延迟

快速回顾:追踪工作原理

  • Trace(追踪):完整的执行路径,如"用户点击结账"
  • Span(跨度):追踪中的较小工作单元(UI渲染、API调用、数据库查询)

每个追踪都有唯一的ID,通过系统边界传播(通过traceparent等头部)。

示例流程:

  1. 用户在React应用中点击"立即购买" → 前端span开始
  2. 点击向/checkout发起fetch请求 → OTel自动创建网络span
  3. 请求发送时携带包含追踪ID的头部
  4. 后端继续追踪,为订单处理、数据库写入等创建span
  5. Jaeger、Tempo或Datadog等工具显示端到端的完整追踪

在浏览器中设置OpenTelemetry

步骤1:安装依赖

1
npm install @opentelemetry/sdk-trace-web @opentelemetry/instrumentation-fetch @opentelemetry/exporter-trace-otlp-http

步骤2:在应用中引导

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import { WebTracerProvider } from '@opentelemetry/sdk-trace-web';
import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { registerInstrumentations } from '@opentelemetry/instrumentation';
import { FetchInstrumentation } from '@opentelemetry/instrumentation-fetch';

const provider = new WebTracerProvider();
const exporter = new OTLPTraceExporter({
  url: 'http://localhost:4318/v1/traces',
});

provider.addSpanProcessor(new BatchSpanProcessor(exporter));
provider.register();

registerInstrumentations({
  instrumentations: [new FetchInstrumentation()],
});

console.log('OpenTelemetry bootstrapped');

这意味着:

  • 每个fetch或XHR调用都被追踪
  • span发送到追踪收集器(OTLP、Jaeger、Datadog等)
  • 上下文自动向下游传播

记录用户事件

网络请求很有用,但能捕获用户事件时追踪价值更大:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import { trace } from '@opentelemetry/api';

const tracer = trace.getTracer('ui-tracer');

document.getElementById('checkout-btn')?.addEventListener('click', () => {
  const span = tracer.startSpan('user.click.checkout');
  
  setTimeout(() => {
    span.end();
  }, 200);
});

“用户点击结账” → 触发的API调用 → 后端订单服务 → 数据库查询

可以将这些封装在React的hooks或高阶组件中,确保追踪在整个应用中保持一致。

连接前端和后端

这是魔法发生的地方,当span跨越边界时:

  • OTel自动注入traceparent头部
  • 后端服务接收请求时继续追踪
  • 追踪查看器将所有内容拼接成统一时间线

Jaeger中的示例追踪:

1
2
3
4
user.click.checkout (前端, 50ms)
 └── fetch /checkout (前端, 20ms)
       └── OrderService.processOrder (后端, 120ms)
            └── Database query (数据库, 80ms)

通过这种视图,可以清楚看到请求变慢发生在客户端、API还是更深层的数据库。

实际调试和监控

调试难以复现的错误

当用户说"结账很慢"但无法复现时,通过追踪可以发现:

  • JavaScript包解析时间较慢
  • API调用缓慢
  • 后端数据库问题

性能监控

追踪显示:

  • 渲染时间 vs 后端处理时间
  • 阻塞交互性的长任务
  • 前端测量(可交互时间)与后端API延迟的关联

可靠性洞察

随时间采样的追踪可以显示:

  • 仅在特定UI路径下失败的不可靠API
  • 仅限于特定浏览器的减速
  • 设备特定的性能问题

超越OpenTelemetry:其他工具

OpenTelemetry是广泛使用的开放标准,还有其他供应商特定工具:

  • Sentry Performance - 设置简单的性能工具,具有事务追踪功能
  • Datadog RUM - 将真实用户监控与后端追踪结合的工具

其他供应商工具可能比OpenTelemetry更易使用和实现;OpenTelemetry可以提供未来的可移植性。

前端可观测性最佳实践

  • 明智采样 - 不需要追踪每次点击。建议使用概率采样,在可管理开销下找到合适的可见度水平
  • 不捕获敏感数据 - 永远不要捕获原始按键、密码或个人信​​息。确保清理span
  • 跨技术栈沟通策略 - 只有前端和后端团队有一定程度的一致性,可观测性才能工作
  • 为可视化提供上下文 - 如果无法将用户体验指标与后端span关联,火焰图意义不大

结论:黑盒已被打开

前端性能在可观测性中长期被忽视。但用户不关心单独的API响应时间,他们只体验端到端的完整旅程。

前端追踪(如使用OpenTelemetry)最终将在UI层面给予我们后端风格的可观测性。

这意味着:

  • 将用户交互与后端请求连接
  • 整体调试分布式系统
  • 提供更好、可预测的用户体验

换句话说,追踪不仅是可观测性的附加价值,而是实现全栈可观测性的缺失环节。

常见问题解答

Q1:追踪对前端应用来说是否太重?

通过采样,绝对不会。不需要每个追踪,只需要足够的追踪来识别模式。

Q2:前端追踪需要修改后端吗?

理想情况下需要。为了拼接追踪,后端也需要有OTel或兼容的东西。

Q3:追踪会替代日志和指标吗?

不会。追踪不是替代日志和指标。日志提供所有细节,指标提供趋势,追踪提供跨系统的故事。

Q4:如果团队已经在使用Sentry或Datadog怎么办?

没问题!许多供应商工具都自带开箱即用的追踪功能。你仍然可以引入OTel以避免未来的供应商锁定。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计