nestjs-otel 6.2.0 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -10,10 +10,6 @@
10
10
 
11
11
  [OpenTelemetry](https://opentelemetry.io/) module for [Nest](https://github.com/nestjs/nest).
12
12
 
13
- ## Questions
14
-
15
- For questions and support please use the official [Discord channel](https://discord.gg/ju8C2zJgBJ).
16
-
17
13
  ## Why
18
14
 
19
15
  Setting up observability metrics with nestjs requires multiple libraries and patterns. OpenTelemetry has support for multiple exporters and types of metrics such as Prometheus Metrics.
@@ -58,7 +54,7 @@ import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';
58
54
  import { JaegerExporter } from '@opentelemetry/exporter-jaeger';
59
55
  import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
60
56
  import { JaegerPropagator } from '@opentelemetry/propagator-jaeger';
61
- import { B3InjectEncoding, B3Propagator } from '@opentelemetry/propagator-b3';
57
+ import { B3Propagator } from '@opentelemetry/propagator-b3';
62
58
  import { PrometheusExporter } from '@opentelemetry/exporter-prometheus';
63
59
  import { NodeSDK } from '@opentelemetry/sdk-node';
64
60
  import { AsyncLocalStorageContextManager } from '@opentelemetry/context-async-hooks';
@@ -76,9 +72,6 @@ const otelSDK = new NodeSDK({
76
72
  new W3CTraceContextPropagator(),
77
73
  new W3CBaggagePropagator(),
78
74
  new B3Propagator(),
79
- new B3Propagator({
80
- injectEncoding: B3InjectEncoding.MULTI_HEADER,
81
- }),
82
75
  ],
83
76
  }),
84
77
  instrumentations: [getNodeAutoInstrumentations()],
@@ -120,11 +113,13 @@ bootstrap();
120
113
 
121
114
  3. Configure nest-otel:
122
115
 
116
+ 3.1. With `forRoot`:
117
+
123
118
  ```ts
124
119
  const OpenTelemetryModuleConfig = OpenTelemetryModule.forRoot({
125
120
  metrics: {
126
121
  hostMetrics: true, // Includes Host Metrics
127
- apiMetrics: {
122
+ apiMetrics: { // @deprecated - will be removed in 8.0 - you should start using the semcov from opentelemetry metrics instead
128
123
  enable: true, // Includes api metrics
129
124
  defaultAttributes: {
130
125
  // You can set default labels for api metrics
@@ -143,17 +138,87 @@ const OpenTelemetryModuleConfig = OpenTelemetryModule.forRoot({
143
138
  export class AppModule {}
144
139
  ```
145
140
 
141
+ 3.2. With `forRootAsync`:
142
+
143
+ ```ts
144
+ OpenTelemetryModule.forRootAsync({
145
+ useClass: OtelConfigService
146
+ });
147
+ ```
148
+
149
+ ```ts
150
+ import { Injectable, Logger } from '@nestjs/common'
151
+ import { ConfigService } from '@nestjs/config'
152
+ import { OpenTelemetryOptionsFactory, OpenTelemetryModuleOptions } from 'nestjs-otel';
153
+
154
+ @Injectable()
155
+ export class OtelConfigService implements OpenTelemetryOptionsFactory {
156
+ private readonly logger = new Logger(OtelConfigService.name)
157
+
158
+ constructor(private configService: ConfigService) {}
159
+
160
+ createOpenTelemetryOptions(): Promise<OpenTelemetryModuleOptions> | OpenTelemetryModuleOptions {
161
+ const { hostMetrics, apiMetrics } = this.configService.get('otel')
162
+
163
+ return {
164
+ metrics: {
165
+ hostMetrics: hostMetrics.enabled,
166
+ apiMetrics: {
167
+ enable: apiMetrics.enabled,
168
+ },
169
+ },
170
+ };
171
+ }
172
+ }
173
+ ```
174
+
146
175
  ## Span Decorator
147
176
 
148
- If you need, you can define a custom Tracing Span for a method. It works async or sync. Span takes its name from the parameter; but by default, it is the same as the method's name
177
+ If you need, you can define a custom Tracing Span for a method. It works async or sync.
178
+
179
+ Span optionally takes one or both of the following parameters:
180
+ * `name` - explicit name of the span; if omitted, it is derived as `<class-name>.<method-name>`.
181
+ * `options` - `SpanOptions` to customize the span options.
182
+
183
+ You can also supply a function as the `options` argument. It will be called with the decorated method's arguments, so you can dynamically customize the span options.
184
+
149
185
 
150
186
  ```ts
151
187
  import { Span } from 'nestjs-otel';
152
188
 
153
- @Span('CRITICAL_SECTION')
154
- async getBooks() {
155
- return [`Harry Potter and the Philosopher's Stone`];
189
+ export class BooksService {
190
+
191
+ // span.name == 'CRITICAL_SECTION'
192
+ @Span('CRITICAL_SECTION')
193
+ async getBooks() {
194
+ return [`Harry Potter and the Philosopher's Stone`];
195
+ }
196
+
197
+ // span.name == 'BooksService.getBooksAgain'
198
+ @Span()
199
+ async getBooksAgain() {
200
+ return [`Harry Potter and the Philosopher's Stone`];
201
+ }
202
+
203
+ // explicitly set span options
204
+ @Span('getBook', { kind: SpanKind.SERVER })
205
+ async getBook(id: number) {
206
+ // ...
207
+ }
208
+
209
+ // options are set dynamically based on the id parameter
210
+ @Span('getBook', (id) => ({ attributes: { bookId: id } }))
211
+ async getBookAgain(id: number) {
212
+ // ...
213
+ }
214
+
215
+ // same as above, but span name is omitted and inferred automatically
216
+ @Span((id) => ({ attributes: { bookId: id } }))
217
+ async getBookOnceMore(id: number) {
218
+ // ...
219
+ }
156
220
  }
221
+
157
222
  ```
158
223
 
159
224
  ## Tracing Service
@@ -246,6 +311,7 @@ You have the following decorators:
246
311
  - `@OtelCounter()`
247
312
  - `@OtelUpDownCounter()`
248
313
  - `@OtelHistogram()`
314
+ - `@OtelGauge()`
249
315
  - `@OtelObservableGauge()`
250
316
  - `@OtelObservableCounter()`
251
317
  - `@OtelObservableUpDownCounter()`
@@ -269,6 +335,8 @@ export class AppController {
269
335
 
270
336
  ## API Metrics with Middleware
271
337
 
338
+ > @deprecated - this will be removed in 8.0 - you should start using the semcov from opentelemetry metrics instead
339
+
272
340
  | Impl | Otel Metric | Prometheus Metric | Description | Metric Type |
273
341
  | ---- | -------------------------------- | --------------------------------------- | ----------------------------------------- | ----------- |
274
342
  | ✅ | http.server.request.count | http_server_request_count_total | Total number of HTTP requests. | Counter |
@@ -1,24 +1,5 @@
1
- import { HttpServer } from '@nestjs/common';
2
- export declare enum ExpressVersion {
3
- V4 = "4.x",
4
- V5 = "5.x"
5
- }
6
- export declare enum FastifyVersion {
7
- V4 = "4.x",
8
- V5 = "5.x"
9
- }
10
1
  export declare enum HttpAdapterType {
11
2
  EXPRESS = "express",
12
3
  FASTIFY = "fastify"
13
4
  }
14
- type HttpExpresAdapterResponse = {
15
- adapterType: HttpAdapterType.EXPRESS;
16
- version: ExpressVersion;
17
- };
18
- type HttpFastifyAdapterResponse = {
19
- adapterType: HttpAdapterType.FASTIFY;
20
- version: FastifyVersion;
21
- };
22
- type HttpAdapterTypeAndVersion = HttpExpresAdapterResponse | HttpFastifyAdapterResponse;
23
- export declare function detectHttpAdapterTypeAndVersion(httpAdapter: HttpServer): HttpAdapterTypeAndVersion;
24
- export {};
5
+ export declare function detectHttpAdapterType(httpAdapter: any): HttpAdapterType;
@@ -1,59 +1,16 @@
1
1
  "use strict";
2
+ // Kudos to Papooch - https://github.com/Papooch/nestjs-cls/blob/2803ce67409c493601cc61a3299e7b47d3869c66/packages/core/src/lib/cls-module/feature-detection.utils.ts
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.HttpAdapterType = exports.FastifyVersion = exports.ExpressVersion = void 0;
4
- exports.detectHttpAdapterTypeAndVersion = detectHttpAdapterTypeAndVersion;
5
- var ExpressVersion;
6
- (function (ExpressVersion) {
7
- ExpressVersion["V4"] = "4.x";
8
- ExpressVersion["V5"] = "5.x";
9
- })(ExpressVersion || (exports.ExpressVersion = ExpressVersion = {}));
10
- var FastifyVersion;
11
- (function (FastifyVersion) {
12
- FastifyVersion["V4"] = "4.x";
13
- FastifyVersion["V5"] = "5.x";
14
- })(FastifyVersion || (exports.FastifyVersion = FastifyVersion = {}));
4
+ exports.HttpAdapterType = void 0;
5
+ exports.detectHttpAdapterType = detectHttpAdapterType;
15
6
  var HttpAdapterType;
16
7
  (function (HttpAdapterType) {
17
8
  HttpAdapterType["EXPRESS"] = "express";
18
9
  HttpAdapterType["FASTIFY"] = "fastify";
19
10
  })(HttpAdapterType || (exports.HttpAdapterType = HttpAdapterType = {}));
20
- function detectHttpAdapterTypeAndVersion(httpAdapter) {
21
- const adapterType = detectHttpAdapterType(httpAdapter);
22
- if (adapterType === HttpAdapterType.FASTIFY) {
23
- return {
24
- adapterType: HttpAdapterType.FASTIFY,
25
- version: detectFastifyVersion(httpAdapter.getInstance()),
26
- };
27
- }
28
- else {
29
- return {
30
- adapterType: HttpAdapterType.EXPRESS,
31
- version: detectExpressVersion(httpAdapter.getInstance()),
32
- };
33
- }
34
- }
35
11
  function detectHttpAdapterType(httpAdapter) {
36
12
  if (httpAdapter.constructor.name === 'FastifyAdapter') {
37
13
  return HttpAdapterType.FASTIFY;
38
14
  }
39
15
  return HttpAdapterType.EXPRESS;
40
16
  }
41
- function detectExpressVersion(expressApp) {
42
- // feature detection based on https://expressjs.com/en/guide/migrating-5.html
43
- if (
44
- // app.del is removed in Express 5
45
- typeof expressApp.del === 'undefined') {
46
- return ExpressVersion.V5;
47
- }
48
- return ExpressVersion.V4;
49
- }
50
- function detectFastifyVersion(fastifyApp) {
51
- // feature detection based on https://fastify.dev/docs/v5.1.x/Guides/Migration-Guide-V5/
52
- if (
53
- // these methods are removed in Fastify 5
54
- typeof fastifyApp.getDefaultRoute === 'undefined' &&
55
- typeof fastifyApp.setDefaultRoute === 'undefined') {
56
- return FastifyVersion.V5;
57
- }
58
- return FastifyVersion.V4;
59
- }
@@ -1,29 +1,53 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
19
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
20
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
21
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
22
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
23
+ };
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
2
41
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
42
  const feature_detection_utils_1 = require("./feature-detection.utils");
5
- function useNest10() {
6
- jest.mock('@nestjs/testing', () => jest.requireActual('@nestjs/testing10'));
7
- jest.mock('@nestjs/common', () => jest.requireActual('@nestjs/common10'));
8
- jest.mock('@nestjs/core', () => jest.requireActual('@nestjs/core10'));
9
- jest.mock('@nestjs/platform-express', () => jest.requireActual('@nestjs/platform-express10'));
10
- jest.mock('@nestjs/platform-fastify', () => jest.requireActual('@nestjs/platform-fastify10'));
11
- }
12
- function useNest11() {
13
- jest.unmock('@nestjs/testing');
14
- jest.unmock('@nestjs/common');
15
- jest.unmock('@nestjs/core');
16
- jest.unmock('@nestjs/platform-express');
17
- jest.unmock('@nestjs/platform-fastify');
18
- }
19
43
  describe('FeatureDetectionUtils', () => {
20
44
  describe('When using Express adapter', () => {
21
45
  async function getExpressApp() {
22
- const { Module } = await Promise.resolve().then(() => tslib_1.__importStar(require('@nestjs/common')));
23
- const { Test } = await Promise.resolve().then(() => tslib_1.__importStar(require('@nestjs/testing')));
46
+ const { Module } = await Promise.resolve().then(() => __importStar(require('@nestjs/common')));
47
+ const { Test } = await Promise.resolve().then(() => __importStar(require('@nestjs/testing')));
24
48
  let TestModule = class TestModule {
25
49
  };
26
- TestModule = tslib_1.__decorate([
50
+ TestModule = __decorate([
27
51
  Module({})
28
52
  ], TestModule);
29
53
  const module = await Test.createTestingModule({
@@ -31,33 +55,20 @@ describe('FeatureDetectionUtils', () => {
31
55
  }).compile();
32
56
  return module.createNestApplication();
33
57
  }
34
- it('should detect Express version 4 on Nest 10', async () => {
35
- useNest10();
36
- const app = await getExpressApp();
37
- const features = (0, feature_detection_utils_1.detectHttpAdapterTypeAndVersion)(app.getHttpAdapter());
38
- expect(features).toEqual({
39
- adapterType: feature_detection_utils_1.HttpAdapterType.EXPRESS,
40
- version: feature_detection_utils_1.ExpressVersion.V4,
41
- });
42
- });
43
58
  it('should detect Express version 5 on Nest 11', async () => {
44
- useNest11();
45
59
  const app = await getExpressApp();
46
- const features = (0, feature_detection_utils_1.detectHttpAdapterTypeAndVersion)(app.getHttpAdapter());
47
- expect(features).toEqual({
48
- adapterType: feature_detection_utils_1.HttpAdapterType.EXPRESS,
49
- version: feature_detection_utils_1.ExpressVersion.V5,
50
- });
60
+ const adapterType = (0, feature_detection_utils_1.detectHttpAdapterType)(app.getHttpAdapter());
61
+ expect(adapterType).toEqual(feature_detection_utils_1.HttpAdapterType.EXPRESS);
51
62
  });
52
63
  });
53
64
  describe('When using Fastify adapter', () => {
54
65
  async function getFastifyApp() {
55
- const { Module } = await Promise.resolve().then(() => tslib_1.__importStar(require('@nestjs/common')));
56
- const { Test } = await Promise.resolve().then(() => tslib_1.__importStar(require('@nestjs/testing')));
57
- const { FastifyAdapter } = await Promise.resolve().then(() => tslib_1.__importStar(require('@nestjs/platform-fastify')));
66
+ const { Module } = await Promise.resolve().then(() => __importStar(require('@nestjs/common')));
67
+ const { Test } = await Promise.resolve().then(() => __importStar(require('@nestjs/testing')));
68
+ const { FastifyAdapter } = await Promise.resolve().then(() => __importStar(require('@nestjs/platform-fastify')));
58
69
  let TestModule = class TestModule {
59
70
  };
60
- TestModule = tslib_1.__decorate([
71
+ TestModule = __decorate([
61
72
  Module({})
62
73
  ], TestModule);
63
74
  const module = await Test.createTestingModule({
@@ -65,23 +76,10 @@ describe('FeatureDetectionUtils', () => {
65
76
  }).compile();
66
77
  return module.createNestApplication(new FastifyAdapter());
67
78
  }
68
- it('should detect Fastify version 4 on Nest 10', async () => {
69
- useNest10();
70
- const app = await getFastifyApp();
71
- const features = (0, feature_detection_utils_1.detectHttpAdapterTypeAndVersion)(app.getHttpAdapter());
72
- expect(features).toEqual({
73
- adapterType: feature_detection_utils_1.HttpAdapterType.FASTIFY,
74
- version: feature_detection_utils_1.FastifyVersion.V4,
75
- });
76
- });
77
79
  it('should detect Fastify version 5 on Nest 11', async () => {
78
- useNest11();
79
80
  const app = await getFastifyApp();
80
- const features = (0, feature_detection_utils_1.detectHttpAdapterTypeAndVersion)(app.getHttpAdapter());
81
- expect(features).toEqual({
82
- adapterType: feature_detection_utils_1.HttpAdapterType.FASTIFY,
83
- version: feature_detection_utils_1.FastifyVersion.V5,
84
- });
81
+ const adapterType = (0, feature_detection_utils_1.detectHttpAdapterType)(app.getHttpAdapter());
82
+ expect(adapterType).toEqual(feature_detection_utils_1.HttpAdapterType.FASTIFY);
85
83
  });
86
84
  });
87
85
  });
package/lib/index.d.ts CHANGED
@@ -5,3 +5,4 @@ export * from './metrics/metric.service';
5
5
  export * from './metrics/injector';
6
6
  export * from './metrics/decorators';
7
7
  export * from './opentelemetry.constants';
8
+ export * from './interfaces';
package/lib/index.js CHANGED
@@ -1,10 +1,24 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
2
16
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
- tslib_1.__exportStar(require("./opentelemetry.module"), exports);
5
- tslib_1.__exportStar(require("./tracing/decorators/span"), exports);
6
- tslib_1.__exportStar(require("./tracing/trace.service"), exports);
7
- tslib_1.__exportStar(require("./metrics/metric.service"), exports);
8
- tslib_1.__exportStar(require("./metrics/injector"), exports);
9
- tslib_1.__exportStar(require("./metrics/decorators"), exports);
10
- tslib_1.__exportStar(require("./opentelemetry.constants"), exports);
17
+ __exportStar(require("./opentelemetry.module"), exports);
18
+ __exportStar(require("./tracing/decorators/span"), exports);
19
+ __exportStar(require("./tracing/trace.service"), exports);
20
+ __exportStar(require("./metrics/metric.service"), exports);
21
+ __exportStar(require("./metrics/injector"), exports);
22
+ __exportStar(require("./metrics/decorators"), exports);
23
+ __exportStar(require("./opentelemetry.constants"), exports);
24
+ __exportStar(require("./interfaces"), exports);
@@ -1 +1,2 @@
1
1
  export * from './opentelemetry-options.interface';
2
+ export * from './metric-options.interface';
@@ -1,4 +1,18 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
2
16
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
- tslib_1.__exportStar(require("./opentelemetry-options.interface"), exports);
17
+ __exportStar(require("./opentelemetry-options.interface"), exports);
18
+ __exportStar(require("./metric-options.interface"), exports);
@@ -39,6 +39,9 @@ export interface OpenTelemetryModuleAsyncOptions extends Pick<ModuleMetadata, 'i
39
39
  }
40
40
  export type OpenTelemetryMetrics = {
41
41
  hostMetrics?: boolean;
42
+ /**
43
+ * @deprecated apiMetrics is deprecated. Use semcov from opentelemetry metrics instead.
44
+ */
42
45
  apiMetrics?: {
43
46
  enable?: boolean;
44
47
  defaultAttributes?: Attributes;
@@ -21,6 +21,7 @@ const OtelInstanceCounter = (options) => (originalClass) => {
21
21
  super(...args);
22
22
  }
23
23
  };
24
+ Object.defineProperty(wrappedClass, 'name', { value: originalClass.name });
24
25
  (0, opentelemetry_utils_1.copyMetadataFromFunctionToFunction)(originalClass, wrappedClass);
25
26
  return wrappedClass;
26
27
  };
@@ -42,7 +43,11 @@ const OtelMethodCounter = (options) => (target, propertyKey, descriptor) => {
42
43
  // @ts-ignore
43
44
  return originalFunction.apply(this, args);
44
45
  };
45
- descriptor.value = wrappedFunction;
46
- (0, opentelemetry_utils_1.copyMetadataFromFunctionToFunction)(originalFunction, wrappedFunction);
46
+ descriptor.value = new Proxy(originalFunction, {
47
+ apply: (_, thisArg, args) => {
48
+ return wrappedFunction.apply(thisArg, args);
49
+ },
50
+ });
51
+ (0, opentelemetry_utils_1.copyMetadataFromFunctionToFunction)(originalFunction, descriptor.value);
47
52
  };
48
53
  exports.OtelMethodCounter = OtelMethodCounter;
@@ -1,6 +1,14 @@
1
1
  "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
2
11
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
12
  require("reflect-metadata");
5
13
  const common_1 = require("@nestjs/common");
6
14
  const common_2 = require("./common");
@@ -8,14 +16,14 @@ const TestDecoratorThatSetsMetadata = () => (0, common_1.SetMetadata)('some-meta
8
16
  let TestClass = class TestClass {
9
17
  method() { }
10
18
  };
11
- tslib_1.__decorate([
19
+ __decorate([
12
20
  TestDecoratorThatSetsMetadata(),
13
21
  (0, common_2.OtelMethodCounter)(),
14
- tslib_1.__metadata("design:type", Function),
15
- tslib_1.__metadata("design:paramtypes", []),
16
- tslib_1.__metadata("design:returntype", void 0)
22
+ __metadata("design:type", Function),
23
+ __metadata("design:paramtypes", []),
24
+ __metadata("design:returntype", void 0)
17
25
  ], TestClass.prototype, "method", null);
18
- TestClass = tslib_1.__decorate([
26
+ TestClass = __decorate([
19
27
  (0, common_2.OtelInstanceCounter)(),
20
28
  TestDecoratorThatSetsMetadata()
21
29
  ], TestClass);
@@ -27,6 +35,9 @@ describe('OtelInstanceCounter', () => {
27
35
  it('should maintain reflect metadata', async () => {
28
36
  expect(Reflect.getMetadata('some-metadata', instance.constructor)).toEqual(true);
29
37
  });
38
+ it('should preserve the original class name', async () => {
39
+ expect(instance.constructor.name).toEqual('TestClass');
40
+ });
30
41
  });
31
42
  describe('OtelMethodCounter', () => {
32
43
  let instance;
@@ -36,4 +47,7 @@ describe('OtelMethodCounter', () => {
36
47
  it('should maintain reflect metadata', async () => {
37
48
  expect(Reflect.getMetadata('some-metadata', instance.method)).toEqual(true);
38
49
  });
50
+ it('should preserve the original method name', async () => {
51
+ expect(instance.method.name).toEqual('method');
52
+ });
39
53
  });
@@ -1,5 +1,18 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
2
16
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
- tslib_1.__exportStar(require("./common"), exports);
5
- tslib_1.__exportStar(require("./param"), exports);
17
+ __exportStar(require("./common"), exports);
18
+ __exportStar(require("./param"), exports);
@@ -2,6 +2,7 @@ import { OtelMetricOptions } from '../../interfaces/metric-options.interface';
2
2
  export type MetricParamDecorator = (name: string, options?: OtelMetricOptions) => ParameterDecorator;
3
3
  export declare const OtelCounter: MetricParamDecorator;
4
4
  export declare const OtelUpDownCounter: MetricParamDecorator;
5
+ export declare const OtelGauge: MetricParamDecorator;
5
6
  export declare const OtelHistogram: MetricParamDecorator;
6
7
  export declare const OtelObservableGauge: MetricParamDecorator;
7
8
  export declare const OtelObservableCounter: MetricParamDecorator;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.OtelObservableUpDownCounter = exports.OtelObservableCounter = exports.OtelObservableGauge = exports.OtelHistogram = exports.OtelUpDownCounter = exports.OtelCounter = void 0;
3
+ exports.OtelObservableUpDownCounter = exports.OtelObservableCounter = exports.OtelObservableGauge = exports.OtelHistogram = exports.OtelGauge = exports.OtelUpDownCounter = exports.OtelCounter = void 0;
4
4
  const common_1 = require("@nestjs/common");
5
5
  const metric_data_1 = require("../metric-data");
6
6
  function createMetricParamDecorator(type, getOrCreateMetric) {
@@ -15,6 +15,7 @@ function createMetricParamDecorator(type, getOrCreateMetric) {
15
15
  }
16
16
  exports.OtelCounter = createMetricParamDecorator('OtelCounter', metric_data_1.getOrCreateCounter);
17
17
  exports.OtelUpDownCounter = createMetricParamDecorator('OtelUpDownCounter', metric_data_1.getOrCreateCounter);
18
+ exports.OtelGauge = createMetricParamDecorator('OtelGauge', metric_data_1.getOrCreateGauge);
18
19
  exports.OtelHistogram = createMetricParamDecorator('OtelHistogram', metric_data_1.getOrCreateHistogram);
19
20
  exports.OtelObservableGauge = createMetricParamDecorator('OtelObservableGauge', metric_data_1.getOrCreateObservableGauge);
20
21
  exports.OtelObservableCounter = createMetricParamDecorator('OtelObservableCounter', metric_data_1.getOrCreateObservableCounter);
@@ -1,10 +1,11 @@
1
- import { Counter, UpDownCounter, Histogram, ObservableGauge, ObservableCounter, ObservableUpDownCounter } from '@opentelemetry/api';
1
+ import { Gauge, Counter, UpDownCounter, Histogram, ObservableGauge, ObservableCounter, ObservableUpDownCounter } from '@opentelemetry/api';
2
2
  import { OtelMetricOptions } from '../interfaces/metric-options.interface';
3
- export type GenericMetric = Counter | UpDownCounter | Histogram | ObservableGauge | ObservableCounter | ObservableUpDownCounter;
3
+ export type GenericMetric = Counter | UpDownCounter | Histogram | Gauge | ObservableGauge | ObservableCounter | ObservableUpDownCounter;
4
4
  export declare enum MetricType {
5
5
  'Counter' = "Counter",
6
6
  'UpDownCounter' = "UpDownCounter",
7
7
  'Histogram' = "Histogram",
8
+ 'Gauge' = "Gauge",
8
9
  'ObservableGauge' = "ObservableGauge",
9
10
  'ObservableCounter' = "ObservableCounter",
10
11
  'ObservableUpDownCounter' = "ObservableUpDownCounter"
@@ -12,6 +13,7 @@ export declare enum MetricType {
12
13
  export declare const meterData: Map<string, GenericMetric>;
13
14
  export declare function getOrCreateHistogram(name: string, options?: OtelMetricOptions): Histogram;
14
15
  export declare function getOrCreateCounter(name: string, options?: OtelMetricOptions): Counter;
16
+ export declare function getOrCreateGauge(name: string, options?: OtelMetricOptions): Gauge;
15
17
  export declare function getOrCreateUpDownCounter(name: string, options?: OtelMetricOptions): UpDownCounter;
16
18
  export declare function getOrCreateObservableGauge(name: string, options?: OtelMetricOptions): ObservableGauge;
17
19
  export declare function getOrCreateObservableCounter(name: string, options?: OtelMetricOptions): ObservableCounter;
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.meterData = exports.MetricType = void 0;
4
4
  exports.getOrCreateHistogram = getOrCreateHistogram;
5
5
  exports.getOrCreateCounter = getOrCreateCounter;
6
+ exports.getOrCreateGauge = getOrCreateGauge;
6
7
  exports.getOrCreateUpDownCounter = getOrCreateUpDownCounter;
7
8
  exports.getOrCreateObservableGauge = getOrCreateObservableGauge;
8
9
  exports.getOrCreateObservableCounter = getOrCreateObservableCounter;
@@ -14,6 +15,7 @@ var MetricType;
14
15
  MetricType["Counter"] = "Counter";
15
16
  MetricType["UpDownCounter"] = "UpDownCounter";
16
17
  MetricType["Histogram"] = "Histogram";
18
+ MetricType["Gauge"] = "Gauge";
17
19
  MetricType["ObservableGauge"] = "ObservableGauge";
18
20
  MetricType["ObservableCounter"] = "ObservableCounter";
19
21
  MetricType["ObservableUpDownCounter"] = "ObservableUpDownCounter";
@@ -35,6 +37,9 @@ function getOrCreateHistogram(name, options = {}) {
35
37
  function getOrCreateCounter(name, options = {}) {
36
38
  return getOrCreate(name, options, MetricType.Counter);
37
39
  }
40
+ function getOrCreateGauge(name, options = {}) {
41
+ return getOrCreate(name, options, MetricType.Gauge);
42
+ }
38
43
  function getOrCreateUpDownCounter(name, options = {}) {
39
44
  return getOrCreate(name, options, MetricType.UpDownCounter);
40
45
  }
@@ -3,6 +3,7 @@ export declare class MetricService {
3
3
  getCounter(name: string, options?: OtelMetricOptions): import("@opentelemetry/api").Counter<import("@opentelemetry/api").Attributes>;
4
4
  getUpDownCounter(name: string, options?: OtelMetricOptions): import("@opentelemetry/api").UpDownCounter<import("@opentelemetry/api").Attributes>;
5
5
  getHistogram(name: string, options?: OtelMetricOptions): import("@opentelemetry/api").Histogram<import("@opentelemetry/api").Attributes>;
6
+ getGauge(name: string, options?: OtelMetricOptions): import("@opentelemetry/api").Gauge<import("@opentelemetry/api").Attributes>;
6
7
  getObservableCounter(name: string, options?: OtelMetricOptions): import("@opentelemetry/api").ObservableCounter;
7
8
  getObservableGauge(name: string, options?: OtelMetricOptions): import("@opentelemetry/api").ObservableGauge;
8
9
  getObservableUpDownCounter(name: string, options?: OtelMetricOptions): import("@opentelemetry/api").ObservableUpDownCounter;
@@ -1,7 +1,12 @@
1
1
  "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
2
8
  Object.defineProperty(exports, "__esModule", { value: true });
3
9
  exports.MetricService = void 0;
4
- const tslib_1 = require("tslib");
5
10
  const common_1 = require("@nestjs/common");
6
11
  const metric_data_1 = require("./metric-data");
7
12
  let MetricService = class MetricService {
@@ -14,6 +19,9 @@ let MetricService = class MetricService {
14
19
  getHistogram(name, options) {
15
20
  return (0, metric_data_1.getOrCreateHistogram)(name, options);
16
21
  }
22
+ getGauge(name, options) {
23
+ return (0, metric_data_1.getOrCreateGauge)(name, options);
24
+ }
17
25
  getObservableCounter(name, options) {
18
26
  return (0, metric_data_1.getOrCreateObservableCounter)(name, options);
19
27
  }
@@ -25,6 +33,6 @@ let MetricService = class MetricService {
25
33
  }
26
34
  };
27
35
  exports.MetricService = MetricService;
28
- exports.MetricService = MetricService = tslib_1.__decorate([
36
+ exports.MetricService = MetricService = __decorate([
29
37
  (0, common_1.Injectable)()
30
38
  ], MetricService);
@@ -4,16 +4,16 @@ import { MetricService } from '../metrics/metric.service';
4
4
  export declare class ApiMetricsMiddleware implements NestMiddleware {
5
5
  private readonly metricService;
6
6
  private readonly options;
7
- private defaultAttributes;
8
- private httpServerRequestCount;
9
- private httpServerResponseCount;
10
- private httpServerDuration;
11
- private httpServerRequestSize;
12
- private httpServerResponseSize;
13
- private httpServerResponseSuccessCount;
14
- private httpServerResponseErrorCount;
15
- private httpClientRequestErrorCount;
16
- private httpServerAbortCount;
7
+ private readonly defaultAttributes;
8
+ private readonly httpServerRequestCount;
9
+ private readonly httpServerResponseCount;
10
+ private readonly httpServerDuration;
11
+ private readonly httpServerRequestSize;
12
+ private readonly httpServerResponseSize;
13
+ private readonly httpServerResponseSuccessCount;
14
+ private readonly httpServerResponseErrorCount;
15
+ private readonly httpClientRequestErrorCount;
16
+ private readonly httpServerAbortCount;
17
17
  private readonly ignoreUndefinedRoutes;
18
18
  constructor(metricService: MetricService, options?: OpenTelemetryModuleOptions);
19
19
  use(req: any, res: any, next: any): void;
@@ -1,13 +1,73 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
19
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
20
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
21
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
22
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
23
+ };
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ var __metadata = (this && this.__metadata) || function (k, v) {
42
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
43
+ };
44
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
45
+ return function (target, key) { decorator(target, key, paramIndex); }
46
+ };
47
+ var __importDefault = (this && this.__importDefault) || function (mod) {
48
+ return (mod && mod.__esModule) ? mod : { "default": mod };
49
+ };
2
50
  Object.defineProperty(exports, "__esModule", { value: true });
3
51
  exports.ApiMetricsMiddleware = void 0;
4
- const tslib_1 = require("tslib");
5
52
  const common_1 = require("@nestjs/common");
6
- const response_time_1 = tslib_1.__importDefault(require("response-time"));
7
- const urlParser = tslib_1.__importStar(require("url"));
53
+ const response_time_1 = __importDefault(require("response-time"));
54
+ const urlParser = __importStar(require("url"));
8
55
  const metric_service_1 = require("../metrics/metric.service");
9
56
  const opentelemetry_constants_1 = require("../opentelemetry.constants");
10
57
  let ApiMetricsMiddleware = class ApiMetricsMiddleware {
58
+ metricService;
59
+ options;
60
+ defaultAttributes;
61
+ httpServerRequestCount;
62
+ httpServerResponseCount;
63
+ httpServerDuration;
64
+ httpServerRequestSize;
65
+ httpServerResponseSize;
66
+ httpServerResponseSuccessCount;
67
+ httpServerResponseErrorCount;
68
+ httpClientRequestErrorCount;
69
+ httpServerAbortCount;
70
+ ignoreUndefinedRoutes;
11
71
  constructor(metricService, options = {}) {
12
72
  this.metricService = metricService;
13
73
  this.options = options;
@@ -123,9 +183,9 @@ let ApiMetricsMiddleware = class ApiMetricsMiddleware {
123
183
  }
124
184
  };
125
185
  exports.ApiMetricsMiddleware = ApiMetricsMiddleware;
126
- exports.ApiMetricsMiddleware = ApiMetricsMiddleware = tslib_1.__decorate([
186
+ exports.ApiMetricsMiddleware = ApiMetricsMiddleware = __decorate([
127
187
  (0, common_1.Injectable)(),
128
- tslib_1.__param(0, (0, common_1.Inject)(metric_service_1.MetricService)),
129
- tslib_1.__param(1, (0, common_1.Inject)(opentelemetry_constants_1.OPENTELEMETRY_MODULE_OPTIONS)),
130
- tslib_1.__metadata("design:paramtypes", [metric_service_1.MetricService, Object])
188
+ __param(0, (0, common_1.Inject)(metric_service_1.MetricService)),
189
+ __param(1, (0, common_1.Inject)(opentelemetry_constants_1.OPENTELEMETRY_MODULE_OPTIONS)),
190
+ __metadata("design:paramtypes", [metric_service_1.MetricService, Object])
131
191
  ], ApiMetricsMiddleware);
@@ -1,4 +1,17 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
2
16
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
- tslib_1.__exportStar(require("./api-metrics.middleware"), exports);
17
+ __exportStar(require("./api-metrics.middleware"), exports);
@@ -3,21 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getMiddlewareMountPoint = getMiddlewareMountPoint;
4
4
  const feature_detection_utils_1 = require("./feature-detection.utils");
5
5
  const MOUNT_POINT_EXPRESS_5 = '/';
6
- const MOUNT_POINT_EXPRESS_4 = '*';
7
6
  const MOUNT_POINT_FASTIFY_5 = '{*path}';
8
- const MOUNT_POINT_FASTIFY_4 = '(.*)';
9
7
  function getMiddlewareMountPoint(adapter) {
10
- const features = (0, feature_detection_utils_1.detectHttpAdapterTypeAndVersion)(adapter);
11
- if (features.adapterType === feature_detection_utils_1.HttpAdapterType.FASTIFY) {
12
- if (features.version === feature_detection_utils_1.FastifyVersion.V5) {
13
- return MOUNT_POINT_FASTIFY_5;
14
- }
15
- return MOUNT_POINT_FASTIFY_4;
8
+ const httpAdapterType = (0, feature_detection_utils_1.detectHttpAdapterType)(adapter);
9
+ if (httpAdapterType === feature_detection_utils_1.HttpAdapterType.FASTIFY) {
10
+ return MOUNT_POINT_FASTIFY_5;
16
11
  }
17
12
  else {
18
- if (features.version === feature_detection_utils_1.ExpressVersion.V5) {
19
- return MOUNT_POINT_EXPRESS_5;
20
- }
21
- return MOUNT_POINT_EXPRESS_4;
13
+ return MOUNT_POINT_EXPRESS_5;
22
14
  }
23
15
  }
@@ -1,8 +1,19 @@
1
1
  "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
2
14
  var OpenTelemetryCoreModule_1;
3
15
  Object.defineProperty(exports, "__esModule", { value: true });
4
16
  exports.OpenTelemetryCoreModule = void 0;
5
- const tslib_1 = require("tslib");
6
17
  const common_1 = require("@nestjs/common");
7
18
  const host_metrics_1 = require("@opentelemetry/host-metrics");
8
19
  const api_1 = require("@opentelemetry/api");
@@ -19,10 +30,12 @@ const middleware_utils_1 = require("./middleware.utils");
19
30
  * @internal
20
31
  */
21
32
  let OpenTelemetryCoreModule = OpenTelemetryCoreModule_1 = class OpenTelemetryCoreModule {
33
+ options;
34
+ adapterHost;
35
+ logger = new common_1.Logger('OpenTelemetryModule');
22
36
  constructor(options = {}, adapterHost) {
23
37
  this.options = options;
24
38
  this.adapterHost = adapterHost;
25
- this.logger = new common_1.Logger('OpenTelemetryModule');
26
39
  }
27
40
  /**
28
41
  * Bootstraps the internal OpenTelemetry Module with the given options
@@ -127,9 +140,9 @@ let OpenTelemetryCoreModule = OpenTelemetryCoreModule_1 = class OpenTelemetryCor
127
140
  }
128
141
  };
129
142
  exports.OpenTelemetryCoreModule = OpenTelemetryCoreModule;
130
- exports.OpenTelemetryCoreModule = OpenTelemetryCoreModule = OpenTelemetryCoreModule_1 = tslib_1.__decorate([
143
+ exports.OpenTelemetryCoreModule = OpenTelemetryCoreModule = OpenTelemetryCoreModule_1 = __decorate([
131
144
  (0, common_1.Global)(),
132
145
  (0, common_1.Module)({}),
133
- tslib_1.__param(0, (0, common_1.Inject)(opentelemetry_constants_1.OPENTELEMETRY_MODULE_OPTIONS)),
134
- tslib_1.__metadata("design:paramtypes", [Object, core_1.HttpAdapterHost])
146
+ __param(0, (0, common_1.Inject)(opentelemetry_constants_1.OPENTELEMETRY_MODULE_OPTIONS)),
147
+ __metadata("design:paramtypes", [Object, core_1.HttpAdapterHost])
135
148
  ], OpenTelemetryCoreModule);
@@ -1,8 +1,13 @@
1
1
  "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
2
8
  var OpenTelemetryModule_1;
3
9
  Object.defineProperty(exports, "__esModule", { value: true });
4
10
  exports.OpenTelemetryModule = void 0;
5
- const tslib_1 = require("tslib");
6
11
  const common_1 = require("@nestjs/common");
7
12
  const opentelemetry_core_module_1 = require("./opentelemetry-core.module");
8
13
  /**
@@ -34,6 +39,6 @@ let OpenTelemetryModule = OpenTelemetryModule_1 = class OpenTelemetryModule {
34
39
  }
35
40
  };
36
41
  exports.OpenTelemetryModule = OpenTelemetryModule;
37
- exports.OpenTelemetryModule = OpenTelemetryModule = OpenTelemetryModule_1 = tslib_1.__decorate([
42
+ exports.OpenTelemetryModule = OpenTelemetryModule = OpenTelemetryModule_1 = __decorate([
38
43
  (0, common_1.Module)({})
39
44
  ], OpenTelemetryModule);
@@ -1,2 +1,5 @@
1
1
  import { SpanOptions } from '@opentelemetry/api';
2
- export declare function Span(name?: string, options?: SpanOptions): (target: any, propertyKey: PropertyKey, propertyDescriptor: PropertyDescriptor) => void;
2
+ type SpanDecoratorOptions<T extends any[]> = SpanOptions | ((...args: T) => SpanOptions);
3
+ export declare function Span<T extends any[]>(options?: SpanDecoratorOptions<T>): (target: any, propertyKey: PropertyKey, propertyDescriptor: TypedPropertyDescriptor<(...args: T) => any>) => void;
4
+ export declare function Span<T extends any[]>(name?: string, options?: SpanDecoratorOptions<T>): (target: any, propertyKey: PropertyKey, propertyDescriptor: TypedPropertyDescriptor<(...args: T) => any>) => void;
5
+ export {};
@@ -7,29 +7,39 @@ const recordException = (span, error) => {
7
7
  span.recordException(error);
8
8
  span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: error.message });
9
9
  };
10
- function Span(name, options = {}) {
10
+ function Span(nameOrOptions, maybeOptions) {
11
11
  return (target, propertyKey, propertyDescriptor) => {
12
+ let name;
13
+ let options;
14
+ if (typeof nameOrOptions === 'string') {
15
+ name = nameOrOptions;
16
+ options = maybeOptions ?? {};
17
+ }
18
+ else {
19
+ name = `${target.constructor.name}.${String(propertyKey)}`;
20
+ options = nameOrOptions ?? {};
21
+ }
12
22
  const originalFunction = propertyDescriptor.value;
23
+ if (typeof originalFunction !== 'function') {
24
+ throw new Error(`The @Span decorator can be only used on functions, but ${propertyKey.toString()} is not a function.`);
25
+ }
13
26
  const wrappedFunction = function PropertyDescriptor(...args) {
14
27
  const tracer = api_1.trace.getTracer('default');
15
- const spanName = name || `${target.constructor.name}.${String(propertyKey)}`;
16
- return tracer.startActiveSpan(spanName, options, span => {
28
+ const spanOptions = typeof options === 'function' ? options(...args) : options;
29
+ return tracer.startActiveSpan(name, spanOptions, span => {
17
30
  if (originalFunction.constructor.name === 'AsyncFunction') {
18
- return (originalFunction
19
- // @ts-ignore
31
+ return originalFunction
20
32
  .apply(this, args)
21
- // @ts-ignore
22
- .catch(error => {
33
+ .catch((error) => {
23
34
  recordException(span, error);
24
35
  // Throw error to propagate it further
25
36
  throw error;
26
37
  })
27
38
  .finally(() => {
28
39
  span.end();
29
- }));
40
+ });
30
41
  }
31
42
  try {
32
- // @ts-ignore
33
43
  return originalFunction.apply(this, args);
34
44
  }
35
45
  catch (error) {
@@ -42,7 +52,14 @@ function Span(name, options = {}) {
42
52
  }
43
53
  });
44
54
  };
45
- propertyDescriptor.value = wrappedFunction;
46
- (0, opentelemetry_utils_1.copyMetadataFromFunctionToFunction)(originalFunction, wrappedFunction);
55
+ // Wrap the original function in a proxy to ensure that the function name is preserved.
56
+ // This should also preserve parameters for OpenAPI and other libraries
57
+ // that rely on the function name as metadata key.
58
+ propertyDescriptor.value = new Proxy(originalFunction, {
59
+ apply: (_, thisArg, args) => {
60
+ return wrappedFunction.apply(thisArg, args);
61
+ },
62
+ });
63
+ (0, opentelemetry_utils_1.copyMetadataFromFunctionToFunction)(originalFunction, propertyDescriptor.value);
47
64
  };
48
65
  }
@@ -1,7 +1,15 @@
1
1
  "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
2
11
  var _a;
3
12
  Object.defineProperty(exports, "__esModule", { value: true });
4
- const tslib_1 = require("tslib");
5
13
  require("reflect-metadata");
6
14
  const api_1 = require("@opentelemetry/api");
7
15
  const sdk_trace_node_1 = require("@opentelemetry/sdk-trace-node");
@@ -15,48 +23,69 @@ class TestSpan {
15
23
  return this.singleSpan();
16
24
  }
17
25
  fooProducerSpan() { }
26
+ argsInOptions(a, b) { }
27
+ implicitSpanNameWithOptions() { }
28
+ argsInOptionsWithImplicitName(a, b) { }
18
29
  error() {
19
30
  throw new Error('hello world');
20
31
  }
21
32
  metadata() { }
22
33
  [_a = symbol]() { }
23
34
  }
24
- tslib_1.__decorate([
35
+ __decorate([
25
36
  (0, span_1.Span)(),
26
- tslib_1.__metadata("design:type", Function),
27
- tslib_1.__metadata("design:paramtypes", []),
28
- tslib_1.__metadata("design:returntype", void 0)
37
+ __metadata("design:type", Function),
38
+ __metadata("design:paramtypes", []),
39
+ __metadata("design:returntype", void 0)
29
40
  ], TestSpan.prototype, "singleSpan", null);
30
- tslib_1.__decorate([
41
+ __decorate([
31
42
  (0, span_1.Span)(),
32
- tslib_1.__metadata("design:type", Function),
33
- tslib_1.__metadata("design:paramtypes", []),
34
- tslib_1.__metadata("design:returntype", void 0)
43
+ __metadata("design:type", Function),
44
+ __metadata("design:paramtypes", []),
45
+ __metadata("design:returntype", void 0)
35
46
  ], TestSpan.prototype, "doubleSpan", null);
36
- tslib_1.__decorate([
47
+ __decorate([
37
48
  (0, span_1.Span)('foo', { kind: api_1.SpanKind.PRODUCER }),
38
- tslib_1.__metadata("design:type", Function),
39
- tslib_1.__metadata("design:paramtypes", []),
40
- tslib_1.__metadata("design:returntype", void 0)
49
+ __metadata("design:type", Function),
50
+ __metadata("design:paramtypes", []),
51
+ __metadata("design:returntype", void 0)
41
52
  ], TestSpan.prototype, "fooProducerSpan", null);
42
- tslib_1.__decorate([
53
+ __decorate([
54
+ (0, span_1.Span)('bar', (a, b) => ({ attributes: { a, b } })),
55
+ __metadata("design:type", Function),
56
+ __metadata("design:paramtypes", [Number, String]),
57
+ __metadata("design:returntype", void 0)
58
+ ], TestSpan.prototype, "argsInOptions", null);
59
+ __decorate([
60
+ (0, span_1.Span)({ kind: api_1.SpanKind.PRODUCER }),
61
+ __metadata("design:type", Function),
62
+ __metadata("design:paramtypes", []),
63
+ __metadata("design:returntype", void 0)
64
+ ], TestSpan.prototype, "implicitSpanNameWithOptions", null);
65
+ __decorate([
66
+ (0, span_1.Span)((a, b) => ({ attributes: { a, b } })),
67
+ __metadata("design:type", Function),
68
+ __metadata("design:paramtypes", [Number, String]),
69
+ __metadata("design:returntype", void 0)
70
+ ], TestSpan.prototype, "argsInOptionsWithImplicitName", null);
71
+ __decorate([
43
72
  (0, span_1.Span)(),
44
- tslib_1.__metadata("design:type", Function),
45
- tslib_1.__metadata("design:paramtypes", []),
46
- tslib_1.__metadata("design:returntype", void 0)
73
+ __metadata("design:type", Function),
74
+ __metadata("design:paramtypes", []),
75
+ __metadata("design:returntype", void 0)
47
76
  ], TestSpan.prototype, "error", null);
48
- tslib_1.__decorate([
77
+ __decorate([
49
78
  (0, span_1.Span)(),
50
79
  TestDecoratorThatSetsMetadata(),
51
- tslib_1.__metadata("design:type", Function),
52
- tslib_1.__metadata("design:paramtypes", []),
53
- tslib_1.__metadata("design:returntype", void 0)
80
+ __metadata("design:type", Function),
81
+ __metadata("design:paramtypes", []),
82
+ __metadata("design:returntype", void 0)
54
83
  ], TestSpan.prototype, "metadata", null);
55
- tslib_1.__decorate([
84
+ __decorate([
56
85
  (0, span_1.Span)(),
57
- tslib_1.__metadata("design:type", Function),
58
- tslib_1.__metadata("design:paramtypes", []),
59
- tslib_1.__metadata("design:returntype", void 0)
86
+ __metadata("design:type", Function),
87
+ __metadata("design:paramtypes", []),
88
+ __metadata("design:returntype", void 0)
60
89
  ], TestSpan.prototype, _a, null);
61
90
  describe('Span', () => {
62
91
  let instance;
@@ -67,8 +96,9 @@ describe('Span', () => {
67
96
  instance = new TestSpan();
68
97
  traceExporter = new sdk_trace_node_1.InMemorySpanExporter();
69
98
  spanProcessor = new sdk_trace_node_1.SimpleSpanProcessor(traceExporter);
70
- provider = new sdk_trace_node_1.NodeTracerProvider();
71
- provider.addSpanProcessor(spanProcessor);
99
+ provider = new sdk_trace_node_1.NodeTracerProvider({
100
+ spanProcessors: [spanProcessor],
101
+ });
72
102
  provider.register();
73
103
  });
74
104
  afterEach(async () => {
@@ -81,6 +111,10 @@ describe('Span', () => {
81
111
  it('should maintain reflect metadataa', async () => {
82
112
  expect(Reflect.getMetadata('some-metadata', instance.metadata)).toEqual(true);
83
113
  });
114
+ it('should preserve the original method name', () => {
115
+ const originalFunctionName = instance.singleSpan.name;
116
+ expect(originalFunctionName).toEqual('singleSpan');
117
+ });
84
118
  it('should set correct span', async () => {
85
119
  instance.singleSpan();
86
120
  const spans = traceExporter.getFinishedSpans();
@@ -93,6 +127,25 @@ describe('Span', () => {
93
127
  expect(spans).toHaveLength(1);
94
128
  expect(spans.map(span => span.kind)).toEqual([api_1.SpanKind.PRODUCER]);
95
129
  });
130
+ it('should set correct span options with implicit span name', async () => {
131
+ instance.implicitSpanNameWithOptions();
132
+ const spans = traceExporter.getFinishedSpans();
133
+ expect(spans).toHaveLength(1);
134
+ expect(spans[0].name).toEqual('TestSpan.implicitSpanNameWithOptions');
135
+ expect(spans[0].kind).toEqual(api_1.SpanKind.PRODUCER);
136
+ });
137
+ it('should set correct span options based on method params', async () => {
138
+ instance.argsInOptions(10, 'bar');
139
+ const spans = traceExporter.getFinishedSpans();
140
+ expect(spans).toHaveLength(1);
141
+ expect(spans[0].attributes).toEqual({ a: 10, b: 'bar' });
142
+ });
143
+ it('should set correct span options based on method params with implicit span name', async () => {
144
+ instance.argsInOptionsWithImplicitName(10, 'bar');
145
+ const spans = traceExporter.getFinishedSpans();
146
+ expect(spans).toHaveLength(1);
147
+ expect(spans[0].attributes).toEqual({ a: 10, b: 'bar' });
148
+ });
96
149
  it('should set correct span even when calling other method with Span decorator', async () => {
97
150
  instance.doubleSpan();
98
151
  const spans = traceExporter.getFinishedSpans();
@@ -1,7 +1,12 @@
1
1
  "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
2
8
  Object.defineProperty(exports, "__esModule", { value: true });
3
9
  exports.TraceService = void 0;
4
- const tslib_1 = require("tslib");
5
10
  const api_1 = require("@opentelemetry/api");
6
11
  const common_1 = require("@nestjs/common");
7
12
  let TraceService = class TraceService {
@@ -16,6 +21,6 @@ let TraceService = class TraceService {
16
21
  }
17
22
  };
18
23
  exports.TraceService = TraceService;
19
- exports.TraceService = TraceService = tslib_1.__decorate([
24
+ exports.TraceService = TraceService = __decorate([
20
25
  (0, common_1.Injectable)()
21
26
  ], TraceService);
package/package.json CHANGED
@@ -1,9 +1,12 @@
1
1
  {
2
2
  "name": "nestjs-otel",
3
- "version": "6.2.0",
3
+ "version": "7.0.0",
4
4
  "description": "NestJS OpenTelemetry Library",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index",
7
+ "engines": {
8
+ "node": ">= 20"
9
+ },
7
10
  "scripts": {
8
11
  "prebuild": "rimraf lib",
9
12
  "build": "tsc",
@@ -11,7 +14,7 @@
11
14
  "format": "prettier --write ./**/*.{js,json,ts}",
12
15
  "test": "npm run test:unit && npm run test:e2e",
13
16
  "test:coverage": "jest --coverage",
14
- "test:unit": "jest --passWithNoTests",
17
+ "test:unit": "jest",
15
18
  "test:watch": "jest --watch",
16
19
  "test:e2e": "jest --config ./tests/jest-e2e.json --runInBand --forceExit",
17
20
  "test:e2e:watch": "jest --config ./tests/jest-e2e.json --runInBand --watch",
@@ -26,8 +29,7 @@
26
29
  "opentelemetry",
27
30
  "otel",
28
31
  "tracing",
29
- "observability",
30
- "prometheus"
32
+ "observability"
31
33
  ],
32
34
  "author": "pragmaticivan@gmail.com",
33
35
  "license": "Apache-2.0",
@@ -37,43 +39,38 @@
37
39
  "homepage": "https://github.com/pragmaticivan/nestjs-otel#readme",
38
40
  "dependencies": {
39
41
  "@opentelemetry/api": "^1.9.0",
40
- "@opentelemetry/host-metrics": "^0.35.5",
42
+ "@opentelemetry/host-metrics": "^0.36.0",
41
43
  "response-time": "^2.3.3"
42
44
  },
43
45
  "devDependencies": {
44
- "@commitlint/cli": "^19.7.1",
45
- "@commitlint/config-conventional": "^19.7.1",
46
- "@nestjs/common": "^11.0.11",
47
- "@nestjs/common10": "npm:@nestjs/common@10",
48
- "@nestjs/core": "^11.0.11",
49
- "@nestjs/core10": "npm:@nestjs/core@10",
50
- "@nestjs/platform-express": "^11.0.11",
51
- "@nestjs/platform-express10": "npm:@nestjs/platform-express@10",
52
- "@nestjs/platform-fastify": "^11.0.11",
53
- "@nestjs/platform-fastify10": "npm:@nestjs/platform-fastify@10",
54
- "@nestjs/testing": "^11.0.11",
55
- "@nestjs/testing10": "npm:@nestjs/testing@10",
56
- "@opentelemetry/exporter-prometheus": "^0.57.2",
57
- "@opentelemetry/sdk-metrics": "^1.30.1",
58
- "@opentelemetry/sdk-trace-node": "^1.30.1",
46
+ "@commitlint/cli": "^19.8.1",
47
+ "@commitlint/config-conventional": "^19.8.1",
48
+ "@nestjs/common": "^11.1.1",
49
+ "@nestjs/core": "^11.1.1",
50
+ "@nestjs/platform-express": "^11.1.1",
51
+ "@nestjs/platform-fastify": "^11.1.1",
52
+ "@nestjs/testing": "^11.1.1",
53
+ "@opentelemetry/exporter-prometheus": "^0.201.1",
54
+ "@opentelemetry/sdk-metrics": "^2.0.0",
55
+ "@opentelemetry/sdk-trace-node": "^2.0.0",
59
56
  "@types/jest": "^29.5.14",
60
- "@types/node": "^22.13.8",
57
+ "@types/node": "^22.15.18",
61
58
  "@types/response-time": "^2.3.8",
62
- "@types/supertest": "^6.0.2",
59
+ "@types/supertest": "^6.0.3",
63
60
  "husky": "^9.1.7",
64
61
  "jest": "^29.7.0",
65
- "lint-staged": "^15.4.3",
66
- "prettier": "^3.5.2",
62
+ "lint-staged": "^16.0.0",
63
+ "prettier": "^3.5.3",
67
64
  "reflect-metadata": "^0.2.2",
68
65
  "rimraf": "^6.0.1",
69
66
  "rxjs": "^7.8.2",
70
- "supertest": "^7.0.0",
71
- "ts-jest": "^29.2.6",
72
- "typescript": "5.8.2"
67
+ "supertest": "^7.1.1",
68
+ "ts-jest": "^29.3.3",
69
+ "typescript": "5.8.3"
73
70
  },
74
71
  "peerDependencies": {
75
- "@nestjs/common": ">= 10 < 12",
76
- "@nestjs/core": ">= 10 < 12"
72
+ "@nestjs/common": ">= 11 < 12",
73
+ "@nestjs/core": ">= 11 < 12"
77
74
  },
78
75
  "jest": {
79
76
  "moduleFileExtensions": [