OpenTelemetry 根Span创建
介绍
在分布式系统中,Span是OpenTelemetry的核心概念之一,代表一个独立的工作单元(如API请求或数据库调用)。**根Span(Root Span)**是追踪链路的起点,没有父Span,通常由服务的入口点(如HTTP请求处理器)创建。理解根Span的创建是构建完整分布式追踪的基础。
核心概念
- Span上下文:包含Trace ID(唯一标识追踪链路)、Span ID(当前Span的唯一标识)和父Span ID(根Span的父ID为空)。
- TracerProvider:用于创建
Tracer
实例的工厂。 - Tracer:实际创建Span的工具。
创建根Span的步骤
1. 初始化OpenTelemetry
首先需要配置TracerProvider
(通常全局唯一):
javascript
const { NodeTracerProvider } = require('@opentelemetry/sdk-trace-node');
const provider = new NodeTracerProvider();
provider.register(); // 注册为全局TracerProvider
2. 创建Tracer实例
通过TracerProvider
获取Tracer
:
javascript
const { trace } = require('@opentelemetry/api');
const tracer = trace.getTracer('my-service-tracer');
3. 创建根Span
使用tracer.startSpan()
创建根Span(不传递上下文时自动成为根Span):
javascript
const rootSpan = tracer.startSpan('HTTP GET /users');
// ...执行业务逻辑
rootSpan.end(); // 必须显式结束Span
实际案例:Express.js中的根Span
以下是在Express中间件中创建根Span的完整示例:
javascript
const express = require('express');
const app = express();
app.use((req, res, next) => {
// 创建根Span(HTTP请求作为追踪起点)
const span = tracer.startSpan(`HTTP ${req.method} ${req.path}`, {
attributes: {
'http.method': req.method,
'http.path': req.path
}
});
// 将Span上下文注入请求对象
req.context = trace.setSpan(trace.contextActive(), span);
res.on('finish', () => {
span.setAttribute('http.status_code', res.statusCode);
span.end(); // 请求结束时完成Span
});
next();
});
可视化追踪链路
常见问题
注意
- 忘记结束Span:会导致内存泄漏和追踪数据不完整。
- 错误的上下文传播:手动创建子Span时需确保传递正确的父上下文。
总结
根Span是分布式追踪的起点,通过tracer.startSpan()
创建且不指定父上下文。关键要点:
- 根Span代表整个追踪链路的初始操作
- 必须在业务逻辑完成后调用
span.end()
- 通过属性(Attributes)记录操作的元数据
扩展练习
- 尝试在Koa或Fastify框架中实现根Span创建
- 为根Span添加自定义属性(如用户ID或请求体大小)
- 使用Jaeger或Zipkin查看生成的追踪数据