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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@loongsuite/cms_trace

v1.0.0

Published

## 简介

Downloads

15

Readme

@loongsuite/cms_trace

简介

CMS Trace 是 CMS 可观测性 SDK 的核心追踪实现包,提供完整的分布式追踪功能。包括追踪器管理器、追踪器、Span、采样器、Span 处理器等核心组件,是实现分布式追踪的基础设施。

特性

  • 🎯 完整追踪: 提供完整的分布式追踪实现
  • 📊 多种采样器: 支持多种采样策略
  • 🔄 批量处理: 高效的 Span 批量处理
  • 高性能: 优化的追踪性能
  • 🔧 灵活配置: 可配置的追踪参数
  • 📈 资源检测: 自动资源信息检测

安装

# 使用 anpm (推荐)
anpm add @loongsuite/cms_trace

# 或使用 npm
npm install @loongsuite/cms_trace

核心概念

追踪器管理器 (TracerManager)

追踪器管理器是追踪系统的核心,负责管理追踪器实例和 Span 处理。

追踪器 (Tracer)

追踪器用于创建和管理 Span,是追踪数据的主要入口。

Span

Span 表示追踪中的一个操作单元,包含操作名称、时间戳、属性等信息。

采样器 (Sampler)

采样器决定哪些 Span 需要被记录和导出。

Span 处理器 (SpanProcessor)

Span 处理器负责处理 Span 的生命周期事件。

主要导出

import {
  TracerManager,
  Tracer,
  Span,
  SpanProcessor,
  BatchSpanProcessor,
  SimpleSpanProcessor,
  Sampler,
  TraceIdRatioBasedSampler,
  AlwaysOnSampler,
  AlwaysOffSampler,
  ParentBasedSampler,
  ResourceDetector,
  EnvResourceDetector,
  ProcessResourceDetector,
  HostResourceDetector
} from '@loongsuite/cms_trace';

使用示例

基础追踪

import { TracerManager, BatchSpanProcessor } from '@loongsuite/cms_trace';
import { ConsoleSpanExporter } from '@loongsuite/cms_exporters';

// 创建追踪器管理器
const tracerManager = new TracerManager({
  spanProcessors: [
    new BatchSpanProcessor(new ConsoleSpanExporter(), {
      scheduledDelayMillis: 200,
      maxExportBatchSize: 100,
      maxQueueSize: 1000
    })
  ]
});

// 获取追踪器
const tracer = tracerManager.getTracer('my-service', '1.0.0');

// 创建 Span
const span = tracer.startSpan('user-operation', {
  kind: 1, // SERVER
  attributes: {
    'user.id': '12345',
    'operation.type': 'login'
  }
});

// 执行业务逻辑
try {
  // 模拟业务操作
  await new Promise(resolve => setTimeout(resolve, 100));
  
  // 添加事件
  span.addEvent('user-authenticated', {
    'auth.method': 'password',
    'auth.success': true
  });
  
  // 设置状态
  span.setStatus({ code: 1, message: 'Success' });
  
} catch (error) {
  // 记录错误
  span.setStatus({ code: 2, message: error.message });
  span.recordException(error);
} finally {
  // 结束 Span
  span.end();
}

// 关闭追踪器管理器
await tracerManager.shutdown();

嵌套 Span

import { TracerManager, BatchSpanProcessor } from '@loongsuite/cms_trace';
import { ConsoleSpanExporter } from '@loongsuite/cms_exporters';

const tracerManager = new TracerManager({
  spanProcessors: [new BatchSpanProcessor(new ConsoleSpanExporter())]
});

const tracer = tracerManager.getTracer('nested-service');

// 创建父 Span
const parentSpan = tracer.startSpan('http-request', {
  kind: 1, // SERVER
  attributes: {
    'http.method': 'POST',
    'http.url': '/api/users',
    'http.status_code': 200
  }
});

// 在父 Span 上下文中创建子 Span
const childSpan = tracer.startSpan('database-query', {
  kind: 2, // CLIENT
  attributes: {
    'db.system': 'postgresql',
    'db.operation': 'INSERT',
    'db.table': 'users'
  }
});

// 模拟数据库操作
setTimeout(() => {
  childSpan.setStatus({ code: 1 });
  childSpan.end();
  
  // 创建另一个子 Span
  const anotherChildSpan = tracer.startSpan('cache-update', {
    kind: 2, // CLIENT
    attributes: {
      'cache.operation': 'SET',
      'cache.key': 'user:12345'
    }
  });
  
  setTimeout(() => {
    anotherChildSpan.setStatus({ code: 1 });
    anotherChildSpan.end();
    
    parentSpan.setStatus({ code: 1 });
    parentSpan.end();
  }, 50);
}, 100);

采样器配置

import { 
  TracerManager, 
  BatchSpanProcessor,
  TraceIdRatioBasedSampler,
  AlwaysOnSampler,
  AlwaysOffSampler,
  ParentBasedSampler
} from '@loongsuite/cms_trace';
import { ConsoleSpanExporter } from '@loongsuite/cms_exporters';

// 1. 基于比例的采样器(采样 50% 的请求)
const ratioSampler = new TraceIdRatioBasedSampler(0.5);

// 2. 总是采样
const alwaysOnSampler = new AlwaysOnSampler();

// 3. 从不采样
const alwaysOffSampler = new AlwaysOffSampler();

// 4. 基于父 Span 的采样器
const parentBasedSampler = new ParentBasedSampler({
  root: new TraceIdRatioBasedSampler(0.1), // 根 Span 采样 10%
  remoteParentSampled: new AlwaysOnSampler(), // 远程父 Span 已采样则采样
  remoteParentNotSampled: new AlwaysOffSampler(), // 远程父 Span 未采样则不采样
  localParentSampled: new AlwaysOnSampler(), // 本地父 Span 已采样则采样
  localParentNotSampled: new AlwaysOffSampler() // 本地父 Span 未采样则不采样
});

const tracerManager = new TracerManager({
  sampler: parentBasedSampler,
  spanProcessors: [new BatchSpanProcessor(new ConsoleSpanExporter())]
});

const tracer = tracerManager.getTracer('sampled-service');

// 创建 Span(会根据采样器决定是否记录)
const span = tracer.startSpan('sampled-operation');
span.end();

资源检测

import { 
  TracerManager, 
  BatchSpanProcessor,
  EnvResourceDetector,
  ProcessResourceDetector,
  HostResourceDetector
} from '@loongsuite/cms_trace';
import { ConsoleSpanExporter } from '@loongsuite/cms_exporters';

// 创建资源检测器
const resourceDetectors = [
  new EnvResourceDetector(),    // 环境变量检测
  new ProcessResourceDetector(), // 进程信息检测
  new HostResourceDetector()     // 主机信息检测
];

const tracerManager = new TracerManager({
  resourceDetectors,
  spanProcessors: [new BatchSpanProcessor(new ConsoleSpanExporter())]
});

const tracer = tracerManager.getTracer('resource-service');

// 创建 Span(会自动包含资源信息)
const span = tracer.startSpan('resource-operation');
span.end();

自定义 Span 处理器

import { SpanProcessor, ReadableSpan } from '@loongsuite/cms_trace';

class CustomSpanProcessor implements SpanProcessor {
  onStart(span: ReadableSpan): void {
    console.log('Span started:', span.name);
    
    // 添加自定义属性
    span.setAttributes({
      'custom.processor': 'custom-span-processor',
      'custom.timestamp': Date.now()
    });
  }

  onEnd(span: ReadableSpan): void {
    console.log('Span ended:', span.name, 'Duration:', span.duration);
    
    // 自定义处理逻辑
    if (span.duration > 1000) {
      console.warn('Slow operation detected:', span.name);
    }
  }

  shutdown(): Promise<void> {
    console.log('Custom span processor shutting down');
    return Promise.resolve();
  }

  forceFlush(): Promise<void> {
    console.log('Custom span processor force flush');
    return Promise.resolve();
  }
}

const tracerManager = new TracerManager({
  spanProcessors: [
    new CustomSpanProcessor(),
    new BatchSpanProcessor(new ConsoleSpanExporter())
  ]
});

错误处理和异常记录

import { TracerManager, BatchSpanProcessor } from '@loongsuite/cms_trace';
import { ConsoleSpanExporter } from '@loongsuite/cms_exporters';

const tracerManager = new TracerManager({
  spanProcessors: [new BatchSpanProcessor(new ConsoleSpanExporter())]
});

const tracer = tracerManager.getTracer('error-service');

async function riskyOperation() {
  const span = tracer.startSpan('risky-operation');
  
  try {
    // 可能失败的操作
    await new Promise((resolve, reject) => {
      setTimeout(() => {
        if (Math.random() > 0.5) {
          reject(new Error('Random failure'));
        } else {
          resolve('Success');
        }
      }, 100);
    });
    
    span.setStatus({ code: 1, message: 'Success' });
    
  } catch (error) {
    // 记录异常
    span.recordException(error);
    span.setStatus({ 
      code: 2, 
      message: error.message 
    });
    
    // 添加错误相关属性
    span.setAttributes({
      'error.type': error.constructor.name,
      'error.message': error.message,
      'error.stack': error.stack
    });
    
    throw error;
  } finally {
    span.end();
  }
}

// 使用示例
riskyOperation().catch(error => {
  console.error('Operation failed:', error.message);
});

与上下文管理器集成

import { TracerManager, BatchSpanProcessor } from '@loongsuite/cms_trace';
import { ConsoleSpanExporter } from '@loongsuite/cms_exporters';
import { AsyncLocalStorageContextManager } from '@loongsuite/cms_context';

const contextManager = new AsyncLocalStorageContextManager();
const tracerManager = new TracerManager({
  contextManager,
  spanProcessors: [new BatchSpanProcessor(new ConsoleSpanExporter())]
});

const tracer = tracerManager.getTracer('context-service');

// 在上下文中创建 Span
const span = tracer.startSpan('contextual-operation');
const contextWithSpan = tracerManager.setSpan(contextManager.active(), span);

contextManager.with(contextWithSpan, () => {
  // 在此上下文中,可以获取当前 Span
  const currentSpan = tracerManager.getActiveSpan(contextManager.active());
  console.log('Current span:', currentSpan?.name);
  
  // 异步操作也会保持上下文
  setTimeout(() => {
    const asyncSpan = tracerManager.getActiveSpan(contextManager.active());
    console.log('Async span:', asyncSpan?.name); // 仍然是同一个 span
  }, 100);
});

span.end();

配置选项

TracerManager 配置

interface TracerManagerConfig {
  contextManager?: IContextManager;
  sampler?: Sampler;
  spanProcessors?: SpanProcessor[];
  resourceDetectors?: ResourceDetector[];
  resource?: Resource;
}

BatchSpanProcessor 配置

interface BatchSpanProcessorConfig {
  scheduledDelayMillis?: number;    // 批量导出间隔,默认 5000
  maxExportBatchSize?: number;       // 每批最大数量,默认 512
  maxQueueSize?: number;              // 队列最大大小,默认 2048
  exportTimeoutMillis?: number;      // 导出超时时间,默认 30000
}

性能优化

采样策略

// 生产环境:低采样率
const productionSampler = new TraceIdRatioBasedSampler(0.01); // 1%

// 开发环境:高采样率
const developmentSampler = new TraceIdRatioBasedSampler(1.0); // 100%

// 根据环境动态配置
const sampler = process.env.NODE_ENV === 'production' 
  ? productionSampler 
  : developmentSampler;

批量处理优化

const batchProcessor = new BatchSpanProcessor(exporter, {
  scheduledDelayMillis: 1000,  // 更频繁的导出
  maxExportBatchSize: 256,     // 更小的批次
  maxQueueSize: 1024,          // 更小的队列
  exportTimeoutMillis: 5000    // 更短的超时
});

与 NodeSDK 集成

import { NodeSDK } from '@loongsuite/cms_node_sdk';
import { BatchSpanProcessor, TraceIdRatioBasedSampler } from '@loongsuite/cms_trace';
import { ConsoleSpanExporter } from '@loongsuite/cms_exporters';

const sdk = new NodeSDK({
  serviceName: 'my-service',
  spanProcessors: [
    new BatchSpanProcessor(new ConsoleSpanExporter())
  ],
  // 其他配置会自动使用默认的 TracerManager
});

sdk.start();

// 获取追踪器管理器
const tracerManager = sdk.getTracerManager();
const tracer = tracerManager.getTracer('my-service');

故障排除

常见问题

  1. Span 未导出: 检查 Span 是否正确结束
  2. 性能问题: 调整采样率和批量处理参数
  3. 内存泄漏: 确保正确关闭追踪器管理器

调试技巧

// 启用详细日志
const tracerManager = new TracerManager({
  spanProcessors: [
    new BatchSpanProcessor(new ConsoleSpanExporter(), {
      scheduledDelayMillis: 100 // 更频繁的导出用于调试
    })
  ]
});

// 添加调试信息
const span = tracer.startSpan('debug-operation');
span.setAttributes({
  'debug.timestamp': Date.now(),
  'debug.process.pid': process.pid,
  'debug.memory.usage': process.memoryUsage().heapUsed
});
span.end();

依赖

  • @loongsuite/cms_core: 核心类型和接口定义
  • @loongsuite/cms_context: 上下文管理器实现

许可证

MIT License