@loongsuite/cms_propagators
v1.0.0
Published
## 简介
Readme
@loongsuite/cms_propagators
简介
CMS Propagators 提供上下文传播器和传播管理器,实现分布式追踪中的上下文信息在服务间的传递。支持 W3C Trace Context、W3C Baggage 等标准协议,以及组合传播功能。
特性
- 🌐 W3C 标准: 支持 W3C Trace Context 和 Baggage 标准
- 🔄 组合传播: 支持多种传播器的组合使用
- 🎯 灵活配置: 可配置的传播管理器
- ⚡ 高性能: 高效的上下文注入和提取
- 🔧 类型安全: 完整的 TypeScript 类型支持
- 📊 标准化: 遵循 OpenTelemetry 传播规范
安装
# 使用 anpm (推荐)
anpm add @loongsuite/cms_propagators
# 或使用 npm
npm install @loongsuite/cms_propagators核心概念
传播器 (Propagator)
传播器负责在服务间传播上下文信息,主要包括:
- W3CTraceContextPropagator: W3C Trace Context 传播器
- W3CBaggagePropagator: W3C Baggage 传播器
- CompositePropagator: 组合传播器
传播管理器 (PropagatorManager)
传播管理器统一管理传播器的注入和提取操作。
主要导出
import {
W3CTraceContextPropagator,
W3CBaggagePropagator,
PropagatorManager,
CompositePropagator
} from '@loongsuite/cms_propagators';使用示例
W3C Trace Context 传播
import { W3CTraceContextPropagator } from '@loongsuite/cms_propagators';
import { TracerManager } from '@loongsuite/cms_trace';
import { AsyncLocalStorageContextManager } from '@loongsuite/cms_context';
// 创建传播器
const tracerManager = new TracerManager({
contextManager: new AsyncLocalStorageContextManager()
});
const traceContextPropagator = new W3CTraceContextPropagator(tracerManager);
// 创建 span
const tracer = tracerManager.getTracer('my-service');
const span = tracer.startSpan('outgoing-request');
// 注入上下文到 HTTP 请求头
const headers: Record<string, string> = {};
traceContextPropagator.inject(
tracerManager.setSpan(tracerManager.getContextManager().active(), span),
headers
);
console.log('Trace Context Headers:', headers);
// 输出类似: { 'traceparent': '00-abc123...-def456...-01' }
span.end();W3C Baggage 传播
import { W3CBaggagePropagator } from '@loongsuite/cms_propagators';
import { AsyncLocalStorageContextManager } from '@loongsuite/cms_context';
// 创建 Baggage 传播器
const contextManager = new AsyncLocalStorageContextManager();
const baggagePropagator = new W3CBaggagePropagator();
// 设置 Baggage 信息
const baggageContext = {
'user-id': '12345',
'tenant-id': 'tenant-abc',
'request-source': 'mobile-app'
};
// 注入 Baggage 到请求头
const headers: Record<string, string> = {};
baggagePropagator.inject(baggageContext, headers);
console.log('Baggage Headers:', headers);
// 输出类似: { 'baggage': 'user-id=12345,tenant-id=tenant-abc,request-source=mobile-app' }组合传播器
import {
W3CTraceContextPropagator,
W3CBaggagePropagator,
CompositePropagator
} from '@loongsuite/cms_propagators';
import { TracerManager } from '@loongsuite/cms_trace';
import { AsyncLocalStorageContextManager } from '@loongsuite/cms_context';
// 创建组合传播器
const contextManager = new AsyncLocalStorageContextManager();
const tracerManager = new TracerManager({ contextManager });
const traceContextPropagator = new W3CTraceContextPropagator(tracerManager);
const baggagePropagator = new W3CBaggagePropagator();
const compositePropagator = new CompositePropagator({
propagators: [traceContextPropagator, baggagePropagator]
});
// 创建包含追踪和 Baggage 的上下文
const tracer = tracerManager.getTracer('my-service');
const span = tracer.startSpan('outgoing-request');
const contextWithSpan = tracerManager.setSpan(contextManager.active(), span);
const contextWithBaggage = {
...contextWithSpan,
baggage: {
'user-id': '12345',
'tenant-id': 'tenant-abc'
}
};
// 注入组合上下文
const headers: Record<string, string> = {};
compositePropagator.inject(contextWithBaggage, headers);
console.log('Combined Headers:', headers);
// 输出:
// {
// 'traceparent': '00-abc123...-def456...-01',
// 'baggage': 'user-id=12345,tenant-id=tenant-abc'
// }传播管理器
import {
PropagatorManager,
W3CTraceContextPropagator,
W3CBaggagePropagator,
CompositePropagator
} from '@loongsuite/cms_propagators';
import { TracerManager } from '@loongsuite/cms_trace';
import { AsyncLocalStorageContextManager } from '@loongsuite/cms_context';
// 创建传播管理器
const contextManager = new AsyncLocalStorageContextManager();
const tracerManager = new TracerManager({ contextManager });
const traceContextPropagator = new W3CTraceContextPropagator(tracerManager);
const baggagePropagator = new W3CBaggagePropagator();
const compositePropagator = new CompositePropagator({
propagators: [traceContextPropagator, baggagePropagator]
});
const propagatorManager = new PropagatorManager({
contextManager,
propagator: compositePropagator
});
// 使用传播管理器
const tracer = tracerManager.getTracer('my-service');
// 服务端:从请求头提取上下文
const incomingHeaders = {
'traceparent': '00-abc123...-def456...-01',
'baggage': 'user-id=12345,tenant-id=tenant-abc'
};
const extractedContext = propagatorManager.extract(incomingHeaders);
contextManager.with(extractedContext, () => {
const span = tracer.startSpan('incoming-request');
// 获取 Baggage 信息
const baggage = propagatorManager.getBaggage();
console.log('Extracted Baggage:', baggage);
span.end();
});
// 客户端:注入上下文到请求头
const outgoingHeaders: Record<string, string> = {};
propagatorManager.inject(outgoingHeaders);
console.log('Outgoing Headers:', outgoingHeaders);HTTP 服务示例
import {
PropagatorManager,
W3CTraceContextPropagator,
W3CBaggagePropagator,
CompositePropagator
} from '@loongsuite/cms_propagators';
import { TracerManager, BatchSpanProcessor } from '@loongsuite/cms_trace';
import { ConsoleSpanExporter } from '@loongsuite/cms_exporters';
import { AsyncLocalStorageContextManager } from '@loongsuite/cms_context';
import * as http from 'http';
// 设置传播管理器
const contextManager = new AsyncLocalStorageContextManager();
const tracerManager = new TracerManager({
contextManager,
spanProcessors: [new BatchSpanProcessor(new ConsoleSpanExporter())]
});
const traceContextPropagator = new W3CTraceContextPropagator(tracerManager);
const baggagePropagator = new W3CBaggagePropagator();
const compositePropagator = new CompositePropagator({
propagators: [traceContextPropagator, baggagePropagator]
});
const propagatorManager = new PropagatorManager({
contextManager,
propagator: compositePropagator
});
const tracer = tracerManager.getTracer('http-service');
// 创建 HTTP 服务器
const server = http.createServer((req, res) => {
// 从请求头提取上下文
const extractedContext = propagatorManager.extract(req.headers as any);
contextManager.with(extractedContext, () => {
const span = tracer.startSpan(`${req.method} ${req.url}`, {
kind: 1 // SERVER
});
try {
// 获取 Baggage 信息
const baggage = propagatorManager.getBaggage();
if (baggage) {
span.setAttributes({
'user.id': baggage.getEntry('user-id')?.value,
'tenant.id': baggage.getEntry('tenant-id')?.value
});
}
// 业务逻辑
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World');
} finally {
span.end();
}
});
});
server.listen(3000, () => {
console.log('Server running on port 3000');
});HTTP 客户端示例
import {
PropagatorManager,
W3CTraceContextPropagator,
W3CBaggagePropagator,
CompositePropagator
} from '@loongsuite/cms_propagators';
import { TracerManager, BatchSpanProcessor } from '@loongsuite/cms_trace';
import { ConsoleSpanExporter } from '@loongsuite/cms_exporters';
import { AsyncLocalStorageContextManager } from '@loongsuite/cms_context';
import * as http from 'http';
// 设置传播管理器
const contextManager = new AsyncLocalStorageContextManager();
const tracerManager = new TracerManager({
contextManager,
spanProcessors: [new BatchSpanProcessor(new ConsoleSpanExporter())]
});
const traceContextPropagator = new W3CTraceContextPropagator(tracerManager);
const baggagePropagator = new W3CBaggagePropagator();
const compositePropagator = new CompositePropagator({
propagators: [traceContextPropagator, baggagePropagator]
});
const propagatorManager = new PropagatorManager({
contextManager,
propagator: compositePropagator
});
const tracer = tracerManager.getTracer('http-client');
// 创建 HTTP 请求
function makeHttpRequest(url: string, options: http.RequestOptions = {}) {
const span = tracer.startSpan(`HTTP ${options.method || 'GET'}`, {
kind: 2 // CLIENT
});
try {
// 设置 Baggage
propagatorManager.setBaggage({
'request-source': 'client-app',
'user-id': '12345'
});
// 注入上下文到请求头
const headers = { ...options.headers };
propagatorManager.inject(headers);
// 发送请求
const req = http.request(url, {
...options,
headers
}, (res) => {
span.setAttributes({
'http.status_code': res.statusCode,
'http.response_size': res.headers['content-length']
});
res.on('end', () => {
span.end();
});
});
req.on('error', (error) => {
span.setStatus({ code: 2, message: error.message });
span.end();
});
req.end();
} catch (error) {
span.setStatus({ code: 2, message: error.message });
span.end();
}
}
// 使用示例
makeHttpRequest('http://localhost:3000/api/users', {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
});配置选项
CompositePropagator 配置
interface CompositePropagatorConfig {
propagators: TextMapPropagator[];
}PropagatorManager 配置
interface PropagatorManagerConfig {
contextManager: IContextManager;
propagator: TextMapPropagator;
}性能考虑
传播器选择
- W3CTraceContextPropagator: 标准追踪上下文传播,性能最佳
- W3CBaggagePropagator: Baggage 信息传播,适合元数据传递
- CompositePropagator: 组合传播,功能最全但性能稍差
最佳实践
// 好的做法:按需使用传播器
const propagators = [traceContextPropagator];
if (needBaggage) {
propagators.push(baggagePropagator);
}
const compositePropagator = new CompositePropagator({ propagators });
// 避免:不必要的传播器
const allPropagators = new CompositePropagator({
propagators: [traceContextPropagator, baggagePropagator, customPropagator]
});与 NodeSDK 集成
import { NodeSDK } from '@loongsuite/cms_node_sdk';
import {
PropagatorManager,
W3CTraceContextPropagator,
W3CBaggagePropagator,
CompositePropagator
} from '@loongsuite/cms_propagators';
const sdk = new NodeSDK({
serviceName: 'my-service',
// 传播管理器会自动配置
});
sdk.start();
// 获取传播管理器
const propagatorManager = sdk.getPropagatorManager();
console.log(propagatorManager instanceof PropagatorManager); // true故障排除
常见问题
- 上下文丢失: 确保正确使用传播管理器
- Baggage 不生效: 检查 Baggage 传播器是否正确配置
- 性能问题: 避免使用不必要的传播器
调试技巧
// 调试传播过程
const debugPropagator = {
inject: (context: Context, carrier: Carrier) => {
console.log('Injecting context:', context);
console.log('Into carrier:', carrier);
compositePropagator.inject(context, carrier);
console.log('Result carrier:', carrier);
},
extract: (context: Context, carrier: Carrier) => {
console.log('Extracting from carrier:', carrier);
const result = compositePropagator.extract(context, carrier);
console.log('Extracted context:', result);
return result;
}
};依赖
@loongsuite/cms_core: 核心类型和接口定义
许可证
MIT License
