{"id":14978640,"url":"https://github.com/metinseylan/nestjs-opentelemetry","last_synced_at":"2025-05-16T06:07:47.590Z","repository":{"id":38949870,"uuid":"310828120","full_name":"MetinSeylan/Nestjs-OpenTelemetry","owner":"MetinSeylan","description":"🔭  Deeply Integrated and Auto Instrumented OpenTelemetry module for NestJS ","archived":false,"fork":false,"pushed_at":"2023-06-15T16:20:24.000Z","size":1505,"stargazers_count":380,"open_issues_count":22,"forks_count":44,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-05-16T06:07:36.727Z","etag":null,"topics":["distributed-tracing","jeager","metrics","nest","nestjs","nestjs-best-practices","nestjs-library","nestjs-logger","nestjs-module","opentracing","prometheus","telemetry","tracing","typescript","zipkin"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MetinSeylan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2020-11-07T11:21:59.000Z","updated_at":"2025-05-12T13:55:23.000Z","dependencies_parsed_at":"2023-12-26T06:33:26.427Z","dependency_job_id":"3577cc9b-b446-4961-b68b-118bc1ae4630","html_url":"https://github.com/MetinSeylan/Nestjs-OpenTelemetry","commit_stats":{"total_commits":38,"total_committers":9,"mean_commits":4.222222222222222,"dds":0.5263157894736843,"last_synced_commit":"992b38228940922935716cdbe013d8fe6c41006f"},"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MetinSeylan%2FNestjs-OpenTelemetry","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MetinSeylan%2FNestjs-OpenTelemetry/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MetinSeylan%2FNestjs-OpenTelemetry/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MetinSeylan%2FNestjs-OpenTelemetry/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MetinSeylan","download_url":"https://codeload.github.com/MetinSeylan/Nestjs-OpenTelemetry/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254478193,"owners_count":22077676,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["distributed-tracing","jeager","metrics","nest","nestjs","nestjs-best-practices","nestjs-library","nestjs-logger","nestjs-module","opentracing","prometheus","telemetry","tracing","typescript","zipkin"],"created_at":"2024-09-24T13:58:05.610Z","updated_at":"2025-05-16T06:07:42.580Z","avatar_url":"https://github.com/MetinSeylan.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg width=\"450\" alt=\"NestJS OpenTelemetry logo\" src=\"https://raw.githubusercontent.com/MetinSeylan/Nestjs-OpenTelemetry/main/docs/logo.png\"/\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eNestJS OpenTelemetry\u003c/h1\u003e\n\u003cp align=\"center\"\u003e\n\u003ca href=\"https://www.npmjs.com/package/@metinseylan/nestjs-opentelemetry\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/@metinseylan/nestjs-opentelemetry.svg\"/\u003e \u003cimg src=\"https://img.shields.io/npm/dt/@metinseylan/nestjs-opentelemetry.svg\"/\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/MetinSeylan/Nestjs-OpenTelemetry\"\u003e\u003cimg src=\"https://img.shields.io/npm/l/@metinseylan/nestjs-opentelemetry.svg\"/\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/MetinSeylan/Nestjs-OpenTelemetry\"\u003e\u003cimg src=\"https://img.shields.io/github/stars/MetinSeylan/nestjs-opentelemetry.svg\"/\u003e\u003c/a\u003e\n\u003c/p\u003e\n\nThis library provides deeply integrated protocol-agnostic Nestjs [OpenTelemetry](https://opentelemetry.io/) instrumentations, metrics and SDK.\n\n### Description\n\nNestjs 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](https://docs.nestjs.com/pipes), [Guard](https://docs.nestjs.com/guards), [Controller](https://docs.nestjs.com/controllers) and [Provider](https://docs.nestjs.com/providers).\n\nIt also includes auto trace and metric instrumentations for some popular Nestjs libraries.\n\n- #### Distributed Tracing\n  - [Setup](#distributed-tracing-1)\n  - [Decorators](#trace-decorators)\n  - [Trace Providers](#trace-providers)\n  - [Auto Trace Instrumentations](#auto-trace-instrumentations)\n  - [Distributed Logging with Trace ID](#distributed-logging-with-trace-id)\n- #### Metrics\n  - [Setup](#metrics-1)\n  - ~~[Decorators](#metric-decorators)~~\n  - ~~[Metric Providers](#metric-providers)~~\n  - ~~[Auto Metric Observers](#auto-metric-observers)~~\n\nOpenTelemetry 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.\n\nCompetability table for Nestjs versions.\n\n| Nestjs | Nestjs-OpenTelemetry |\n|--------|----------------------|\n| 9.x    | 3.x.x                |\n| 8.x    | 2.x.x                |\n\n\n### Installation \n``` bash\nnpm install @metinseylan/nestjs-opentelemetry --save\n```\n***\n### Configuration\nThis is a basic configuration without any trace and metric exporter, but includes default metrics and injectors\n```ts\nimport { OpenTelemetryModule } from '@metinseylan/nestjs-opentelemetry';\n\n@Module({\n  imports: [\n    OpenTelemetryModule.forRoot({\n      serviceName: 'nestjs-opentelemetry-example',\n    })\n  ]\n})\nexport class AppModule {}\n```\n\nAsync configuration example\n```ts\nimport { OpenTelemetryModule } from '@metinseylan/nestjs-opentelemetry';\nimport {ConfigModule, ConfigService} from '@nestjs/config';\n\n@Module({\n  imports: [\n    OpenTelemetryModule.forRootAsync({\n      imports: [ConfigModule],\n      useFactory: async (configService: ConfigService) =\u003e ({\n        serviceName: configService.get('SERVICE_NAME'),\n      }),\n      inject: [ConfigService]\n    })\n  ]\n})\nexport class AppModule {}\n```\n#### Default Parameters\n| key                 | value                                                                                                                                                                                                                    | description                                                                                                                                                                                                                                                               |\n|---------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| traceAutoInjectors  | ControllerInjector, GuardInjector, EventEmitterInjector, ScheduleInjector, PipeInjector, LoggerInjector                                                                                                                  | default auto trace instrumentations                                                                                                                                                                                                                                       |\n| metricAutoObservers | ResourceMetric, ProcessStartTimeMetric, ProcessOpenFdsMetric, ProcessMaxFdsMetric, ActiveHandlesMetric, ActiveHandlesTotalMetric, HttpRequestDurationSeconds, GrpcRequestDurationSeconds, RabbitMqRequestDurationSeconds | default auto metric collectors                                                                                                                                                                                                                                            |                                                                                                                                                                                                                 | inherited from \u003ca href=\"https://github.com/open-telemetry/opentelemetry-js/blob/745bd5c34d3961dc73873190adc763747e5e026d/experimental/packages/opentelemetry-sdk-node/src/types.ts#:~:text=NodeSDKConfiguration\"\u003eNodeSDKConfiguration\u003c/a\u003e                                 |\n| contextManager      | AsyncLocalStorageContextManager                                                                                                                                                                                          | default trace context manager inherited from \u003ca href=\"https://github.com/open-telemetry/opentelemetry-js/blob/745bd5c34d3961dc73873190adc763747e5e026d/experimental/packages/opentelemetry-sdk-node/src/types.ts#:~:text=NodeSDKConfiguration\"\u003e NodeSDKConfiguration \u003c/a\u003e |\n| instrumentations    | AutoInstrumentations                                                                                                                                                                                                     | default instrumentations inherited from \u003ca href=\"https://github.com/open-telemetry/opentelemetry-js/blob/745bd5c34d3961dc73873190adc763747e5e026d/experimental/packages/opentelemetry-sdk-node/src/types.ts#:~:text=NodeSDKConfiguration\"\u003e NodeSDKConfiguration \u003c/a\u003e      |\n| spanProcessor       | NoopSpanProcessor                                                                                                                                                                                                        | default spanProcessor inherited from  \u003ca href=\"https://github.com/open-telemetry/opentelemetry-js/blob/745bd5c34d3961dc73873190adc763747e5e026d/experimental/packages/opentelemetry-sdk-node/src/types.ts#:~:text=NodeSDKConfiguration\"\u003e NodeSDKConfiguration \u003c/a\u003e        |\n| textMapPropagator   | JaegerPropagator, B3Propagator                                                                                                                                                                                           | default textMapPropagator inherited from \u003ca href=\"https://github.com/open-telemetry/opentelemetry-js/blob/745bd5c34d3961dc73873190adc763747e5e026d/experimental/packages/opentelemetry-sdk-node/src/types.ts#:~:text=NodeSDKConfiguration\"\u003e NodeSDKConfiguration \u003c/a\u003e     |\n\n`OpenTelemetryModule.forRoot()` takes [OpenTelemetryModuleConfig](https://github.com/MetinSeylan/Nestjs-OpenTelemetry/blob/main/src/OpenTelemetryModuleConfig.ts#L25) as a parameter, this type is inherited by [NodeSDKConfiguration](https://github.com/open-telemetry/opentelemetry-js/blob/745bd5c34d3961dc73873190adc763747e5e026d/experimental/packages/opentelemetry-sdk-node/src/types.ts#:~:text=NodeSDKConfiguration) so you can use same OpenTelemetry SDK parameter.\n***\n### Distributed Tracing\nSimple setup with Zipkin exporter, including with default trace instrumentations.\n```ts\nimport { OpenTelemetryModule } from '@metinseylan/nestjs-opentelemetry';\nimport { ZipkinExporter } from '@opentelemetry/exporter-zipkin';\nimport { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base';\n\n@Module({\n  imports: [\n    OpenTelemetryModule.forRoot({\n      spanProcessor: new SimpleSpanProcessor(\n        new ZipkinExporter({\n          url: 'your-zipkin-url',\n        })\n      ),\n    }),\n  ],\n})\nexport class AppModule {}\n```\nAfter 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\n\n![Example trace output](./docs/trace-flow.jpeg)\n\nList of supported official exporters [here](https://opentelemetry.io/docs/js/exporters/).\n***\n#### Trace Decorators\nThis 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.\n```ts\nimport { Injectable } from '@nestjs/common';\nimport { Span } from '@metinseylan/nestjs-opentelemetry';\n\n@Injectable()\nexport class AppService {\n  @Span()\n  getHello(): string {\n    return 'Hello World!';\n  }\n}\n```\nAlso `@Span` decorator takes `name` field as a parameter \n```ts\n@Span('hello')\n```\n***\n#### Trace Providers\nIn an advanced usage case, you need to access the native OpenTelemetry Trace provider to access them from Nestjs application context.\n```ts\nimport { Injectable } from '@nestjs/common';\nimport { Tracer } from '@opentelemetry/sdk-trace-base';\n\n@Injectable()\nexport class AppService {\n  constructor(private readonly tracer: Tracer) {}\n\n  getHello(): string {\n    const span = this.tracer.startSpan('important_section_start');\n    // do something important\n    span.setAttributes({ userId: 1150 });\n    span.end();\n    return 'Hello World!';\n  }\n}\n```\n`TraceService` can access directly current span context and start new span.\n```ts\nimport { Injectable } from '@nestjs/common';\nimport { TraceService } from '@metinseylan/nestjs-opentelemetry';\n\n@Injectable()\nexport class AppService {\n  constructor(private readonly traceService: TraceService) {}\n\n  getHello(): string {\n    const span = this.traceService.startSpan('hello');\n    // do something\n    span.end();\n    return 'Hello World!';\n  }\n}\n```\n***\n#### Auto Trace Instrumentations\nThe 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.\n```ts\nimport { Module } from '@nestjs/common';\nimport {\n  OpenTelemetryModule,\n  ControllerInjector,\n  EventEmitterInjector,\n  GuardInjector,\n  LoggerInjector,\n  PipeInjector,\n  ScheduleInjector,\n} from '@metinseylan/nestjs-opentelemetry';\nimport { ZipkinExporter } from '@opentelemetry/exporter-zipkin';\nimport { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base';\n\n@Module({\n  imports: [\n    OpenTelemetryModule.forRoot({\n      traceAutoInjectors: [\n        ControllerInjector,\n        GuardInjector,\n        EventEmitterInjector,\n        ScheduleInjector,\n        PipeInjector,\n        LoggerInjector,\n      ],\n      spanProcessor: new SimpleSpanProcessor(\n        new ZipkinExporter({\n          url: 'your-zipkin-url',\n        }),\n      ),\n    }),\n  ]\n})\nexport class AppModule {}\n```\n\n#### List of Trace Injectors\n| Instance               | Description                                                         |\n|------------------------|---------------------------------------------------------------------|\n| `ControllerInjector`   | Auto trace all of module controllers                                |\n| `GuardInjector`        | Auto trace all of module guards including global guards             |\n| `PipeInjector`         | Auto trace all of module pipes including global pipes               |\n| `EventEmitterInjector` | Auto trace for [@nestjs/event-emitter](https://docs.nestjs.com/techniques/events) library, supports all features |\n| `ScheduleInjector`     | Auto trace for [@nestjs/schedule](https://docs.nestjs.com/techniques/task-scheduling) library, supports all features      |\n| `LoggerInjector`       | [ConsoleLogger](https://docs.nestjs.com/techniques/logger#extend-built-in-logger) and [Logger](https://docs.nestjs.com/techniques/logger#using-the-logger-for-application-logging) class tracer, logs with traceId            |\n***\n#### Distributed Logging with Trace ID\nWhen you set up your environment with the `LoggerInjector` class or default configuration, you can see trace id with every log.\n\n![Example trace output](./docs/log.png)\n\n***\n### Metrics\nSimple setup with Prometheus exporter, you need install [@opentelemetry/exporter-prometheus](https://www.npmjs.com/package/@opentelemetry/exporter-prometheus)  \n```ts\nimport { OpenTelemetryModule } from '@metinseylan/nestjs-opentelemetry';\nimport { PrometheusExporter } from '@opentelemetry/exporter-prometheus';\n\n@Module({\n  imports: [OpenTelemetryModule.forRoot({\n    serviceName: 'nestjs-opentelemetry-example',\n    metricReader: new PrometheusExporter({\n      endpoint: 'metrics',\n      port: 9464,\n    })\n  })]\n})\nexport class AppModule {}\n```\nNow you can access Prometheus exporter with auto collected metrics [http://localhost:9464/metrics](http://localhost:9464/metrics).\nAlso, you can find different exporters [here](https://opentelemetry.io/docs/js/exporters/)\n***\n### Metric Decorators (Deprecated)\nIf you need to observe simple block of function, you can use some basic decorators like `@Counter` and `@Observer`\n\n#### Counter\n```ts\nimport { Injectable } from '@nestjs/common';\nimport { Counter } from '@metinseylan/nestjs-opentelemetry';\n\n@Injectable()\nexport class AppService {\n  @Counter()\n  getHello(): string {\n    return 'Hello World!';\n  }\n}\n```\n`@Counter` decorator is uses OpenTelemetry `Counter` metric, If you check prometheus exporter you will see metric `appservice_gethello_total`\n```ts\n@Counter('call_me_mr_fahrenheit', {\n  description: 'important function call counting here.'\n})\n```\nAnd of course, you can configure your decorator metric, the first parameter is \"name\" and the second one is [MetricOptions](https://github.com/open-telemetry/opentelemetry-js/blob/357ec92e95e03b4d2309c65ffb17d06105985628/experimental/packages/opentelemetry-api-metrics/src/types/Metric.ts#L29)\n\n#### Observer (Deprecated)\n```ts\nimport {Injectable} from '@nestjs/common';\nimport {Observer} from \"./Observer\";\n\n@Injectable()\nexport class AppService {\n  @Observer('nice_one_observer', {\n    description: 'some description here.',\n    boundaries: [10, 20, 30],\n  })\n  getHello(): string {\n    return 'Hello World!';\n  }\n}\n```\n`@Observer` decorator uses OpenTelemetry `ValueRecorder` metric. If you check Prometheus exporter, you will see metric and configuration parameters same as `@Counter`.\n***\n### Metric Providers (Deprecated)\nIn advanced usage cases, you need to access the native OpenTelemetry Metric provider to access them from the Nestjs application context.\n\n```ts\nimport { Injectable } from '@nestjs/common';\nimport { Meter } from '@opentelemetry/sdk-metrics-base';\nimport { Counter } from '@opentelemetry/api-metrics';\n\n@Injectable()\nexport class AppService {\n  private readonly counter: Counter;\n\n  constructor(private readonly meter: Meter) {\n    this.counter = this.meter.createCounter('handsome_counter');\n  }\n\n  getHello(): string {\n    this.counter.add(1);\n    return 'Hello World!';\n  }\n}\n```\n***\n### Auto Metric Observers (Deprecated)\nThis library has extendable resource and protocol-specific Auto Observers. All of them come with default module configuration, which you can extend and configure.\n```ts\nimport { Module } from '@nestjs/common';\nimport { PrometheusExporter } from '@opentelemetry/exporter-prometheus';\nimport {\n  ActiveHandlesMetric,\n  HttpRequestDurationSeconds,\n  OpenTelemetryModule,\n} from '@metinseylan/nestjs-opentelemetry';\n\n@Module({\n  imports: [\n    OpenTelemetryModule.forRoot({\n      serviceName: 'nestjs-opentelemetry-example',\n      metricAutoObservers: [\n        HttpRequestDurationSeconds.build({\n          boundaries: [20, 30, 100],\n        }),\n        ActiveHandlesMetric,\n      ],\n      metricReader: new PrometheusExporter({\n        endpoint: 'metrics',\n        port: 9464,\n      }),\n    }),\n  ],\n})\nexport class AppModule {}\n```\n`.build` function takes [MetricOptions](https://github.com/open-telemetry/opentelemetry-js/blob/357ec92e95e03b4d2309c65ffb17d06105985628/experimental/packages/opentelemetry-api-metrics/src/types/Metric.ts#L29) as a parameter.\n\n#### List Of Auto Observers (Deprecated)\n\n| Metric Observer Provider         | Description                                                                                 | Configurable |\n|----------------------------------|---------------------------------------------------------------------------------------------|--------------|\n| `HttpRequestDurationSeconds`     | Observe http request duration                                                               | yes          |\n| `GrpcRequestDurationSeconds`     | Observe grpc request duration                                                               | yes          |\n| `RabbitMqRequestDurationSeconds` | Observe rabbitmq request duration                                                           | yes          |\n| `ResourceMetric`                 | Metrics of cpu, memory usage                                                                | no           |\n| `ProcessStartTimeMetric`         | Start time of the process since unix epoch in seconds.                                      | no           |\n| `ProcessOpenFdsMetric`           | Number of open file descriptors.                                                            | no           |\n| `ProcessMaxFdsMetric`            | Maximum number of open file descriptors.                                                    | no           |\n| `ActiveHandlesMetric`            | Number of active libuv handles grouped by handle type. Every handle type is C++ class name. | no           |\n| `ActiveHandlesTotalMetric`       | Total number of active handles.                                                             | no           |\n\n#### Example Output for `HttpRequestDurationSeconds`\n| Key       | Value                                                           |\n|-----------|-----------------------------------------------------------------|\n| exception | Empty string or exception instance name                         |\n| method    | GET, POST, PUT, PATCH, DELETE                                   |\n| outcome   | INFORMATIONAL, SUCCESS, REDIRECTION, CLIENT_ERROR, SERVER_ERROR |\n| status    | number of HttpStatus                                            |\n| uri       | url path                                                        |\n\n***\n\n### Let's Combine All of them\n```ts\nimport { Module } from '@nestjs/common';\nimport { PrometheusExporter } from '@opentelemetry/exporter-prometheus';\nimport { OpenTelemetryModule } from '@metinseylan/nestjs-opentelemetry';\nimport { ZipkinExporter } from '@opentelemetry/exporter-zipkin';\nimport { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base';\n\n@Module({\n  imports: [\n    OpenTelemetryModule.forRoot({\n      serviceName: 'nestjs-opentelemetry-example',\n      metricReader: new PrometheusExporter({\n        endpoint: 'metrics',\n        port: 9464,\n      }),\n      spanProcessor: new SimpleSpanProcessor(\n        new ZipkinExporter({\n          url: 'your-zipkin-url',\n        })\n      ),\n    }),\n  ],\n})\nexport class AppModule {}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmetinseylan%2Fnestjs-opentelemetry","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmetinseylan%2Fnestjs-opentelemetry","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmetinseylan%2Fnestjs-opentelemetry/lists"}