@cherie-xf/nestjs-microservice-otel
TypeScript icon, indicating that this package has built-in type declarations

1.0.2-beta.1 • Public • Published

NestJS Microservice OpenTelemetry

This library provides a smimple way to automatically for collecting traces from NestJS applications with Microservice architecture. This library integrated NestJS Microservice, OpenTelemetry-js and Nodejs instrumentations

Description

Nestjs is a protocol-agnostic framework. That's why this library can able to work with different protocols like TCP,RabbitMQ, GRPC and HTTP. Also you can observe and trace Nestjs specific layers like Pipe, Guard, Controller and Provider.

Installation

npm install @/cherie-xf/nestjs-microservice-otel --save

Introduce

This is a basic configuration without any trace exporter, but includes default injectors

import { OpenTelemetryModule } from '@cherie-xf/nestjs-microservice-otel';

@Module({
  imports: [OpenTelemetryModule.forRoot()]
})
export class AppModule {}

Default Parameters

key value description
spanProcessor NoopSpanProcessor default spanProcessor inherited from NodeSDKConfiguration
serviceName String set to resource attribute : SemanticResourceAttributes.SERVICE_NAME
textMapPropagator JaegerPropagator, B3Propagator default textMapPropagator inherited from NodeSDKConfiguration

OpenTelemetryModule.forRoot() takes OpenTelemetryModuleConfig as a parameter, this type is inherited by NodeSDKConfiguration so you can use same OpenTelemetry SDK parameter.


Distributed Tracing Setup

Simple setup with Jaeger exporter, including with default trace instrumentations.

import { JaegerExporter } from '@opentelemetry/exporter-jaeger';
import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';
import { OpenTelemetryModule } from '@cherie-xf/nestjs-microservice-otel';

@Module({
  imports: [
    OpenTelemetryModule.forRoot({
      spanProcessor: new BatchSpanProcessor(
        new JaegerExporter({
          endpoint: `http://${jaeger.host}:14268/api/traces`,
        }),
      ),
      serviceName: `${myServiceName}`,
    }),
  ],
})
export class AppModule {}

After setup, your application will be instrumented, so that you can see almost every layer of application in JeagerUI, including Guards, Pipes, Controllers even global layers like this

Example trace output Example trace detail output

List of supported official exporters here.


Trace Interceptor

This library supports: rename trace span name to meaningful name for both http and rpc; propagation extract parent spanContext of RPC type context

main.ts

import { TraceInterceptor } from '@cherie-xf/nestjs-microservice-otel';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  // set up global interceptor
  app.useGlobalInterceptors(new TraceInterceptor());

  await app.listen(port);
}

bootstrap();

api.controller.ts

import {
  TraceInterceptor,
} from '@cherie-xf/nestjs-microservice-otel';

@Controller('api')
@UseInterceptors(TraceInterceptor)
export class ApiController {
  constructor(
    private readonly apiService: ApiService,
  ) {}
  @Get('get-hello')
  getHello(@Res() res): string {
    return res.status(200).send('Hello World!');
  }
}

Microserve RPC Customized ClientProxy: TraceClientProxy

This libary provide customized TraceClientProxy to automatically propagation.inject while making RPC microservice request

import { Inject, Injectable, Logger } from '@nestjs/common';
import { ClientProxy } from '@nestjs/microservices';
import { TraceClientProxy } from '@cherie-xf/nestjs-microservice-otel';

@Injectable()
export class ApiService {
  private readonly _logger = new Logger(ApiService.name);
  constructor(
    @Inject('USER_CLIENT')
    private readonly user_client: ClientProxy,
    private traceClient: TraceClientProxy,
  ) {}

  async createUser(data: any) {
    const pattern = { name: 'user', cmd: 'create.user' };
    const payload = {
      user_name: data.user_name,
      user_email: data.user_email,
    };
    return await this.traceClient.send(this.user_client, pattern, payload);
  }

Trace Decorators

This library supports auto instrumentations for Nestjs layers, but sometimes you need to define custom span for specific method blocks like providers methods. In this case @Span decorator will help you.

import { Injectable } from '@nestjs/common';
import { Span } from '@metinseylan/nestjs-opentelemetry';

@Injectable()
export class AppService {
  @Span()
  getHello(): string {
    return 'Hello World!';
  }
}

Also @Span decorator takes name field as a parameter

@Span('hello')

Trace Providers

You can use Decorators to trace Services, or you can access the native OpenTelemetry Trace api to manually handle span.

import { Injectable } from '@nestjs/common';
import { Tracer } from '@opentelemetry/sdk-trace-base';

@Injectable()
export class AppService {
  constructor(private readonly tracer: Tracer) {}

  getHello(): string {
    const span = this.tracer.startSpan('important_section_start');
    // do something important
    span.setAttributes({ userId: 1150 });
    span.end();
    return 'Hello World!';
  }
}

TraceService can access directly current span context and start new span.

import { Injectable } from '@nestjs/common';
import { TraceService } from '@metinseylan/nestjs-opentelemetry';

@Injectable()
export class AppService {
  constructor(private readonly traceService: TraceService) {}

  getHello(): string {
    const span = this.traceService.startSpan('hello');
    // do something
    span.end();
    return 'Hello World!';
  }
}

Package Sidebar

Install

npm i @cherie-xf/nestjs-microservice-otel

Weekly Downloads

0

Version

1.0.2-beta.1

License

MIT

Unpacked Size

799 kB

Total Files

125

Last publish

Collaborators

  • cherie-xf