npm package: @loongsuite/cms_trace
Description: ## 简介
Latest version: 1.0.0

# @loongsuite/cms_trace

## 简介

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

## 特性

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

## 安装

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

# 或使用 npm
npm install @loongsuite/cms_trace
```

## 核心概念

### 追踪器管理器 (TracerManager)

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

### 追踪器 (Tracer)

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

### Span

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

### 采样器 (Sampler)

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

### Span 处理器 (SpanProcessor)

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

## 主要导出

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

## 使用示例

### 基础追踪

```typescript
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

```typescript
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);
```

### 采样器配置

```typescript
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();
```

### 资源检测

```typescript
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 处理器

```typescript
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())
  ]
});
```

### 错误处理和异常记录

```typescript
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);
});
```

### 与上下文管理器集成

```typescript
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 配置

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

### BatchSpanProcessor 配置

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

## 性能优化

### 采样策略

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

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

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

### 批量处理优化

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

## 与 NodeSDK 集成

```typescript
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. **内存泄漏**: 确保正确关闭追踪器管理器

### 调试技巧

```typescript
// 启用详细日志
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