Nestjs教程使用OpenTelemetry进行分布式追踪

我正在学习使用Nestjs和OpenTelemetry实现分布式追踪,但在实践中遇到了一些问题:

  1. 如何正确地在Nestjs项目中集成OpenTelemetry?官方文档看起来有点分散,有没有具体的配置示例?

  2. 在微服务架构中,如何确保跨服务的trace能够正确关联?特别是当使用不同技术栈的服务时,该如何处理?

  3. OpenTelemetry的采样率设置有什么最佳实践吗?在高并发生产环境中应该如何配置?

  4. 有没有推荐的可视化工具来查看这些分布式追踪数据?除了Jaeger和Zipkin之外,还有其他选择吗?

  5. 在Nestjs中,如何为特定的业务逻辑添加自定义span?比如想追踪某个复杂计算过程的耗时。

希望能得到有实际经验的朋友的指导,谢谢!


3 回复

NestJS 结合 OpenTelemetry 实现分布式追踪的步骤如下:

  1. 安装依赖
    首先需要安装 NestJS 的 OpenTelemetry 支持包和相关的 tracer:

    npm install [@opentelemetry](/user/opentelemetry)/api [@opentelemetry](/user/opentelemetry)/sdk-trace-web [@opentelemetry](/user/opentelemetry)/exporter-jaeger [@nestjs](/user/nestjs)/telemetry
    
  2. 配置 OpenTelemetry
    创建一个全局的 TracerProvider 配置文件(如 tracer.provider.ts):

    import { registerAs } from '[@nestjs](/user/nestjs)/config';
    import { NodeTracerProvider } from '[@opentelemetry](/user/opentelemetry)/sdk-trace-node';
    import { JaegerExporter } from '[@opentelemetry](/user/opentelemetry)/exporter-jaeger';
    
    export const tracerProviderConfig = registerAs('opentelemetry', () => {
      const provider = new NodeTracerProvider();
      const exporter = new JaegerExporter({
        endpoint: 'http://localhost:14268/api/traces',
      });
      provider.addExporter(exporter);
      provider.register();
      return {
        isActive: true,
      };
    });
    
  3. 集成到 NestJS
    app.module.ts 中引入 OpenTelemetry 提供器:

    import { Module } from '[@nestjs](/user/nestjs)/common';
    import { APP_INTERCEPTOR } from '[@nestjs](/user/nestjs)/core';
    import { TracingInterceptor } from '[@nestjs](/user/nestjs)/telemetry';
    import { tracerProviderConfig } from './tracer.provider';
    
    [@Module](/user/Module)({
      imports: [],
      providers: [
        {
          provide: APP_INTERCEPTOR,
          useClass: TracingInterceptor,
        },
      ],
    })
    export class AppModule {}
    
  4. 启动 Jaeger 服务
    使用 Docker 启动 Jaeger:

    docker run -d --name jaeger \
      -e COLLECTOR_ZIPKIN_HTTP_PORT=9411 \
      -p 5775:5775/udp \
      -p 6831:6831/udp \
      -p 6832:6832/udp \
      -p 5778:5778 \
      -p 16686:16686 \
      -p 14268:14268 \
      -p 14250:14250 \
      -p 9411:9411 \
      jaegertracing/all-in-one:latest
    
  5. 验证追踪
    启动 NestJS 应用后,Jaeger UI 将显示应用的调用链路。访问 http://localhost:16686 查看 Trace 数据。

这样就完成了 NestJS 的分布式追踪配置。


以下是一个简单的NestJS项目结合OpenTelemetry实现分布式追踪的步骤:

  1. 初始化NestJS项目:
npm i -g @nestjs/cli
nest new my-app
cd my-app
  1. 安装OpenTelemetry相关依赖:
npm install --save @opentelemetry/api @opentelemetry/sdk-trace-web @opentelemetry/exporter-jaeger
  1. 配置OpenTelemetry: 创建src/trace.ts文件:
import { registerAs } from '@nestjs/config';
import * as opentelemetry from '@opentelemetry/api';

export const traceConfig = registerAs('trace', () => ({
  serviceName: 'my-nest-app',
}));

export function setupOpenTelemetry() {
  const tracerProvider = new opentelemetry.NodeTracerProvider();
  
  // 设置导出器(这里以Jaeger为例)
  const jaegerExporter = new opentelemetry.exporter.JaegerExporter({
    endpoint: 'http://localhost:14268/api/traces',
  });
  
  tracerProvider.addSpanProcessor(new opentelemetry.SimpleSpanProcessor(jaegerExporter));
  tracerProvider.register();
}
  1. 在主模块中初始化: 在main.ts中添加:
import { setupOpenTelemetry } from './trace';

async function bootstrap() {
  setupOpenTelemetry(); // 初始化OpenTelemetry
  const app = await NestFactory.create(AppModule);
  await app.listen(3000);
}
bootstrap();
  1. 创建服务并生成Trace: 例如,在src/app.service.ts中:
import { Injectable, Trace } from '@nestjs/common';
import { tracer } from '@opentelemetry/api';

@Injectable()
export class AppService {
  getHello(): string {
    const span = tracer.trace('app.service.getHello');
    span.setAttribute('key', 'value');
    span.end();
    return 'Hello World!';
  }
}
  1. 启动Jaeger:
docker run -d --name jaeger \
  -e COLLECTOR_ZIPKIN_HTTP_PORT=9411 \
  -p 5775:5775/udp \
  -p 6831:6831/udp \
  -p 6832:6832/udp \
  -p 5778:5778 \
  -p 16686:16686 \
  -p 14268:14268 \
  -p 14250:14250 \
  -p 9411:9411 \
  jaegertracing/all-in-one:latest
  1. 访问http://localhost:16686查看分布式追踪数据。

NestJS 使用 OpenTelemetry 进行分布式追踪指南

OpenTelemetry 是一个开源的可观测性框架,用于生成、收集和导出分布式追踪数据。在 NestJS 中使用 OpenTelemetry 可以帮助你监控微服务架构中的请求流程。

基本设置步骤

  1. 安装必要依赖
npm install @opentelemetry/sdk-node
npm install @opentelemetry/auto-instrumentations-node
npm install @opentelemetry/exporter-trace-otlp-grpc
  1. 创建 tracing.ts 配置文件
import { NodeSDK } from '@opentelemetry/sdk-node';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc';

const sdk = new NodeSDK({
  traceExporter: new OTLPTraceExporter({
    url: 'your-collector-endpoint' // 例如: 'http://localhost:4317'
  }),
  instrumentations: [getNodeAutoInstrumentations()]
});

sdk.start();
  1. 在 main.ts 中导入
import './tracing';
import { NestFactory } from '@nestjs/core';
// ...其余应用代码

自定义追踪

你可以创建自定义的跨度来追踪特定业务逻辑:

import { trace } from '@opentelemetry/api';

async function myBusinessLogic() {
  const tracer = trace.getTracer('my-service');
  
  return tracer.startActiveSpan('business-logic', async (span) => {
    try {
      // 你的业务逻辑
      span.setAttribute('custom.attribute', 'value');
      return result;
    } finally {
      span.end();
    }
  });
}

与Jaeger/Zipkin集成

如果你使用Jaeger或Zipkin作为后端:

// 使用Jaeger exporter
import { JaegerExporter } from '@opentelemetry/exporter-jaeger';

const sdk = new NodeSDK({
  traceExporter: new JaegerExporter({
    endpoint: 'http://localhost:14268/api/traces'
  }),
  // ...其他配置
});

最佳实践

  1. 确保在微服务环境中传递追踪上下文(通过HTTP头或消息属性)
  2. 为关键业务操作添加自定义跨度
  3. 合理设置采样率以平衡性能和可观测性
  4. 使用语义约定的属性名称

记得根据你的实际环境和需求调整配置,特别是收集器地址和采样策略。

回到顶部