npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@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)

传播器负责在服务间传播上下文信息,主要包括:

  1. W3CTraceContextPropagator: W3C Trace Context 传播器
  2. W3CBaggagePropagator: W3C Baggage 传播器
  3. 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

故障排除

常见问题

  1. 上下文丢失: 确保正确使用传播管理器
  2. Baggage 不生效: 检查 Baggage 传播器是否正确配置
  3. 性能问题: 避免使用不必要的传播器

调试技巧

// 调试传播过程
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