This library provides deeply integrated protocol-agnostic Nestjs OpenTelemetry instrumentations, metrics and SDK.
Nestjs is a protocol-agnostic framework. That's why this library can able to work with different protocols like RabbitMQ, GRPC and HTTP. Also you can observe and trace Nestjs specific layers like Pipe, Guard, Controller and Provider.
It also includes auto trace and metric instrumentations for some popular Nestjs libraries.
OpenTelemetry Metrics currently experimental. So, this library doesn't support metric decorators and Auto Observers until it's stable. but if you want to use it, you can use OpenTelemetry API directly.
Only supports NestJS 9.x
npm install @easyv/nestjs-opentelemetry --save
This is a basic configuration without any trace and metric exporter, but includes default metrics and injectors
import { OpenTelemetryModule } from '@easyv/nestjs-opentelemetry'
@Module({
imports: [
OpenTelemetryModule.forRoot({
serviceName: 'nestjs-opentelemetry-example',
})
]
})
export class AppModule {}
Async configuration example (Not recommended, May cause auto instrumentations to not work)
import { OpenTelemetryModule } from '@easyv/nestjs-opentelemetry'
import { ConfigModule, ConfigService } from '@nestjs/config'
@Module({
imports: [
OpenTelemetryModule.forRootAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
serviceName: configService.get('SERVICE_NAME'),
}),
inject: [ConfigService]
})
]
})
export class AppModule {}
key | value | description |
---|---|---|
traceInjectors | DecoratorInjector, ScheduleInjector, ControllerInjector, GuardInjector, PipeInjector, InterceptorInjector, ExceptionFilterInjector, TypeormInjector, LoggerInjector, ProviderInjector, MiddlewareInjector | default auto trace instrumentations |
contextManager | AsyncLocalStorageContextManager | default trace context manager inherited from NodeSDKConfiguration |
instrumentations | AutoInstrumentations | default instrumentations inherited from NodeSDKConfiguration |
textMapPropagator | W3CTraceContextPropagator | 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.
Simple setup with Zipkin exporter, including with default trace instrumentations.
import { OpenTelemetryModule } from '@easyv/nestjs-opentelemetry'
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc'
import { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base'
@Module({
imports: [
OpenTelemetryModule.forRoot({
spanProcessor: new SimpleSpanProcessor(
new OTLPTraceExporter({
url: 'http://<collector-hostname>:<port>',
})
),
}),
],
})
export class AppModule {}
After setup, your application will be instrumented, so that you can see almost every layer of application in ZipkinUI, including Guards, Pipes, Controllers even global layers like this
List of supported official exporters here.
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 @Trace
and @TracePlain
decorator will help you.
import { Injectable } from '@nestjs/common'
import { Trace } from '@easyv/nestjs-opentelemetry'
@Injectable()
export class AppService {
@Trace()
getHello(): string {
return 'Hello World!'
}
}
Also @Trace
decorator takes name
field as a parameter
@Trace({ name: 'hello' })
In an advanced usage case, you need to access the native OpenTelemetry Trace provider to access them from Nestjs application context.
import { Injectable } from '@nestjs/common'
import { Tracer } from '@opentelemetry/sdk-trace-base'
@Injectable()
export class AppService {
constructor() {}
getHello(): string {
const span = trace.getTracer('default').startSpan('important_section_start')
// do something important
span.setAttributes({ userId: 1150 })
span.end()
return 'Hello World!'
}
}
The most helpful part of this library is that you already get all of the instrumentations by default if you set up a module without any extra configuration. If you need to avoid some of them, you can use the traceAutoInjectors
parameter.
import { Module } from '@nestjs/common'
import {
ControllerInjector,
EventEmitterInjector,
GuardInjector,
LoggerInjector,
OpenTelemetryModule,
PipeInjector,
ScheduleInjector,
} from '@easyv/nestjs-opentelemetry'
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc'
import { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base'
@Module({
imports: [
OpenTelemetryModule.forRoot({
traceInjectors: [
ControllerInjector,
GuardInjector,
EventEmitterInjector,
ScheduleInjector,
PipeInjector,
LoggerInjector,
],
spanProcessor: new SimpleSpanProcessor(
new OTLPTraceExporter({
url: 'http://<collector-hostname>:<port>',
})
),
}),
]
})
export class AppModule {}
Instance | Description |
---|---|
ControllerInjector |
Auto trace all of module controllers |
DecoratorInjector |
Auto trace all of decorator providers |
GuardInjector |
Auto trace all of module guards including global guards |
PipeInjector |
Auto trace all of module pipes including global pipes |
InterceptorInjector |
Auto trace all of module interceptors including global interceptors |
ExceptionFilterInjector |
Auto trace all of module exceptionFilters including global exceptionFilters |
MiddlewareInjector |
Auto trace all of module middlewares including global middlewares |
ProviderInjector |
Auto trace all of module providers |
ScheduleInjector |
Auto trace for @nestjs/schedule library, supports all features |
LoggerInjector |
Logger class tracer |
TypeormInjector |
Auto trace for typeorm library |