nestjs-otel 7.0.1 → 8.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 +73 -30
- package/UPGRADING.md +75 -0
- package/biome.jsonc +40 -0
- package/package.json +29 -29
- package/.prettierignore +0 -0
- package/lib/feature-detection.utils.d.ts +0 -5
- package/lib/feature-detection.utils.js +0 -16
- package/lib/feature-detection.utils.spec.d.ts +0 -1
- package/lib/feature-detection.utils.spec.js +0 -85
- package/lib/index.d.ts +0 -8
- package/lib/index.js +0 -24
- package/lib/interfaces/index.d.ts +0 -2
- package/lib/interfaces/index.js +0 -18
- package/lib/interfaces/metric-options.interface.d.ts +0 -7
- package/lib/interfaces/metric-options.interface.js +0 -2
- package/lib/interfaces/opentelemetry-options.interface.d.ts +0 -52
- package/lib/interfaces/opentelemetry-options.interface.js +0 -2
- package/lib/metrics/decorators/common.d.ts +0 -15
- package/lib/metrics/decorators/common.js +0 -53
- package/lib/metrics/decorators/common.spec.d.ts +0 -1
- package/lib/metrics/decorators/common.spec.js +0 -53
- package/lib/metrics/decorators/index.d.ts +0 -2
- package/lib/metrics/decorators/index.js +0 -18
- package/lib/metrics/decorators/param.d.ts +0 -9
- package/lib/metrics/decorators/param.js +0 -22
- package/lib/metrics/injector.d.ts +0 -1
- package/lib/metrics/injector.js +0 -9
- package/lib/metrics/metric-data.d.ts +0 -20
- package/lib/metrics/metric-data.js +0 -54
- package/lib/metrics/metric.service.d.ts +0 -10
- package/lib/metrics/metric.service.js +0 -38
- package/lib/metrics/utils.d.ts +0 -4
- package/lib/metrics/utils.js +0 -9
- package/lib/metrics/utils.spec.d.ts +0 -1
- package/lib/metrics/utils.spec.js +0 -10
- package/lib/middleware/api-metrics.middleware.d.ts +0 -21
- package/lib/middleware/api-metrics.middleware.js +0 -191
- package/lib/middleware/index.d.ts +0 -1
- package/lib/middleware/index.js +0 -17
- package/lib/middleware.utils.d.ts +0 -2
- package/lib/middleware.utils.js +0 -15
- package/lib/opentelemetry-core.module.d.ts +0 -41
- package/lib/opentelemetry-core.module.js +0 -148
- package/lib/opentelemetry.constants.d.ts +0 -2
- package/lib/opentelemetry.constants.js +0 -5
- package/lib/opentelemetry.module.d.ts +0 -20
- package/lib/opentelemetry.module.js +0 -44
- package/lib/opentelemetry.utils.d.ts +0 -1
- package/lib/opentelemetry.utils.js +0 -12
- package/lib/tracing/decorators/span.d.ts +0 -5
- package/lib/tracing/decorators/span.js +0 -65
- package/lib/tracing/decorators/span.spec.d.ts +0 -1
- package/lib/tracing/decorators/span.spec.js +0 -183
- package/lib/tracing/trace.service.d.ts +0 -6
- package/lib/tracing/trace.service.js +0 -26
package/README.md
CHANGED
|
@@ -119,16 +119,6 @@ bootstrap();
|
|
|
119
119
|
const OpenTelemetryModuleConfig = OpenTelemetryModule.forRoot({
|
|
120
120
|
metrics: {
|
|
121
121
|
hostMetrics: true, // Includes Host Metrics
|
|
122
|
-
apiMetrics: { // @deprecated - will be removed in 8.0 - you should start using the semcov from opentelemetry metrics instead
|
|
123
|
-
enable: true, // Includes api metrics
|
|
124
|
-
defaultAttributes: {
|
|
125
|
-
// You can set default labels for api metrics
|
|
126
|
-
custom: 'label',
|
|
127
|
-
},
|
|
128
|
-
ignoreRoutes: ['/favicon.ico'], // You can ignore specific routes (See https://docs.nestjs.com/middleware#excluding-routes for options)
|
|
129
|
-
ignoreUndefinedRoutes: false, //Records metrics for all URLs, even undefined ones
|
|
130
|
-
prefix: 'my_prefix', // Add a custom prefix to all API metrics
|
|
131
|
-
},
|
|
132
122
|
},
|
|
133
123
|
});
|
|
134
124
|
|
|
@@ -158,14 +148,11 @@ export class OtelConfigService implements OpenTelemetryOptionsFactory {
|
|
|
158
148
|
constructor(private configService: ConfigService) {}
|
|
159
149
|
|
|
160
150
|
createOpenTelemetryOptions(): Promise<OpenTelemetryModuleOptions> | OpenTelemetryModuleOptions {
|
|
161
|
-
const { hostMetrics
|
|
151
|
+
const { hostMetrics } = this.configService.get('otel')
|
|
162
152
|
|
|
163
153
|
return {
|
|
164
154
|
metrics: {
|
|
165
155
|
hostMetrics: hostMetrics.enabled,
|
|
166
|
-
apiMetrics: {
|
|
167
|
-
enable: apiMetrics.enabled,
|
|
168
|
-
},
|
|
169
156
|
},
|
|
170
157
|
};
|
|
171
158
|
}
|
|
@@ -217,8 +204,80 @@ export class BooksService {
|
|
|
217
204
|
async getBookOnceMore(id: number) {
|
|
218
205
|
// ...
|
|
219
206
|
}
|
|
207
|
+
|
|
208
|
+
// Capture return value as attribute
|
|
209
|
+
// Note: Explicitly type the result to ensure type safety
|
|
210
|
+
@Span({
|
|
211
|
+
onResult: (result: string[]) => ({ attributes: { 'book.count': result.length } }),
|
|
212
|
+
})
|
|
213
|
+
async getBooks() {
|
|
214
|
+
return ['Book 1', 'Book 2'];
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Traceable Decorator
|
|
221
|
+
|
|
222
|
+
If you want to trace all methods in a class, you can use the `@Traceable` decorator.
|
|
223
|
+
|
|
224
|
+
```ts
|
|
225
|
+
import { Traceable } from 'nestjs-otel';
|
|
226
|
+
|
|
227
|
+
@Injectable()
|
|
228
|
+
@Traceable()
|
|
229
|
+
export class UsersService {
|
|
230
|
+
findAll() {
|
|
231
|
+
// This method will be automatically traced
|
|
232
|
+
return [];
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
findOne(id: string) {
|
|
236
|
+
// This method will also be automatically traced
|
|
237
|
+
return {};
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
## Current Span Decorator
|
|
243
|
+
|
|
244
|
+
You can access the current span in your controllers using the `@CurrentSpan` decorator.
|
|
245
|
+
|
|
246
|
+
> **Note:** This decorator only works in Controllers, Resolvers, and Gateways where NestJS handles argument injection. It does **not** work in standard service-to-service calls.
|
|
247
|
+
|
|
248
|
+
```ts
|
|
249
|
+
import { Controller, Get } from '@nestjs/common';
|
|
250
|
+
import { Span } from '@opentelemetry/api';
|
|
251
|
+
import { CurrentSpan } from 'nestjs-otel';
|
|
252
|
+
|
|
253
|
+
@Controller('cats')
|
|
254
|
+
export class CatsController {
|
|
255
|
+
@Get()
|
|
256
|
+
findAll(@CurrentSpan() span: Span) {
|
|
257
|
+
if (span) {
|
|
258
|
+
span.setAttribute('custom.attribute', 'value');
|
|
259
|
+
}
|
|
260
|
+
return 'This action returns all cats';
|
|
261
|
+
}
|
|
220
262
|
}
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## Baggage Decorator
|
|
266
|
+
|
|
267
|
+
You can access the OpenTelemetry Baggage (Distributed Context) in your controllers using the `@Baggage` decorator.
|
|
268
|
+
|
|
269
|
+
```ts
|
|
270
|
+
import { Controller, Get } from '@nestjs/common';
|
|
271
|
+
import { Baggage } from 'nestjs-otel';
|
|
221
272
|
|
|
273
|
+
@Controller('cats')
|
|
274
|
+
export class CatsController {
|
|
275
|
+
@Get()
|
|
276
|
+
findAll(@Baggage('tenant-id') tenantId: string) {
|
|
277
|
+
console.log('Tenant ID:', tenantId);
|
|
278
|
+
return 'This action returns all cats';
|
|
279
|
+
}
|
|
280
|
+
}
|
|
222
281
|
```
|
|
223
282
|
|
|
224
283
|
## Tracing Service
|
|
@@ -333,22 +392,6 @@ export class AppController {
|
|
|
333
392
|
}
|
|
334
393
|
```
|
|
335
394
|
|
|
336
|
-
## API Metrics with Middleware
|
|
337
|
-
|
|
338
|
-
> @deprecated - this will be removed in 8.0 - you should start using the semcov from opentelemetry metrics instead
|
|
339
|
-
|
|
340
|
-
| Impl | Otel Metric | Prometheus Metric | Description | Metric Type |
|
|
341
|
-
| ---- | -------------------------------- | --------------------------------------- | ----------------------------------------- | ----------- |
|
|
342
|
-
| ✅ | http.server.request.count | http_server_request_count_total | Total number of HTTP requests. | Counter |
|
|
343
|
-
| ✅ | http.server.response.count | http_server_response_count_total | Total number of HTTP responses. | Counter |
|
|
344
|
-
| ✅ | http.server.abort.count | http_server_abort_count_total | Total number of data transfers aborted. | Counter |
|
|
345
|
-
| ✅ | http.server.duration | http_server_duration | The duration of the inbound HTTP request. | Histogram |
|
|
346
|
-
| ✅ | http.server.request.size | http_server_request_size | Size of incoming bytes. | Histogram |
|
|
347
|
-
| ✅ | http.server.response.size | http_server_response_size | Size of outgoing bytes. | Histogram |
|
|
348
|
-
| ✅ | http.server.response.success.count | http_server_response_success_count_total | Total number of all successful responses. | Counter |
|
|
349
|
-
| ✅ | http.server.response.error.count | http_server_response_error_count_total | Total number of server error responses. | Counter |
|
|
350
|
-
| ✅ | http.client.request.error.count | http_client_request_error_count_total | Total number of client error requests. | Counter |
|
|
351
|
-
|
|
352
395
|
## Prometheus Metrics
|
|
353
396
|
|
|
354
397
|
When `metricExporter` is defined in otel SDK with a `PrometheusExporter`it will start a new process on port `8081` (default port) and metrics will be available at `http://localhost:8081/metrics`.
|
package/UPGRADING.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Upgrading from v7 to v8
|
|
2
|
+
|
|
3
|
+
This guide provides instructions for upgrading `nestjs-otel` from version 7.x to version 8.x.
|
|
4
|
+
|
|
5
|
+
## Breaking Changes
|
|
6
|
+
|
|
7
|
+
### Metric Naming Convention
|
|
8
|
+
|
|
9
|
+
The default naming convention for metrics generated by decorators has changed to follow OpenTelemetry standards (using dots `.` instead of underscores `_` as separators).
|
|
10
|
+
|
|
11
|
+
**Previous Behavior (v7):**
|
|
12
|
+
- Instance Counter: `app_ClassName_instances_total`
|
|
13
|
+
- Method Counter: `app_ClassName_methodName_calls_total`
|
|
14
|
+
|
|
15
|
+
**New Behavior (v8):**
|
|
16
|
+
- Instance Counter: `app.ClassName.instances.total`
|
|
17
|
+
- Method Counter: `app.ClassName.methodName.calls.total`
|
|
18
|
+
|
|
19
|
+
**Action Required:**
|
|
20
|
+
If you are using default metric names in your dashboards (e.g., Grafana) or alerts, you will need to update the metric names to match the new dot-notation format.
|
|
21
|
+
|
|
22
|
+
If you were manually specifying names in the decorators (e.g., `@OtelMethodCounter({ name: 'my_custom_name' })`), no change is required as your custom names are preserved.
|
|
23
|
+
|
|
24
|
+
### Deprecated API Middleware and Configuration Removed
|
|
25
|
+
|
|
26
|
+
The deprecated API middleware and its associated configuration have been removed.
|
|
27
|
+
|
|
28
|
+
- The `apiMetrics` option in `OpenTelemetryModuleOptions` is no longer available.
|
|
29
|
+
- The `ApiMetricsMiddleware` class has been removed.
|
|
30
|
+
|
|
31
|
+
If you were relying on this middleware for request tracing, please ensure you are using the OpenTelemetry SDK's auto-instrumentation or the provided decorators.
|
|
32
|
+
|
|
33
|
+
## New Features
|
|
34
|
+
|
|
35
|
+
### New Decorators
|
|
36
|
+
|
|
37
|
+
v8 introduces several new decorators to improve the developer experience:
|
|
38
|
+
|
|
39
|
+
- **`@Traceable()`**: A class-level decorator that automatically applies tracing to all methods in a class.
|
|
40
|
+
```typescript
|
|
41
|
+
@Traceable()
|
|
42
|
+
@Injectable()
|
|
43
|
+
export class MyService {
|
|
44
|
+
// All methods are now traced automatically
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
- **`@CurrentSpan()`**: A parameter decorator to inject the current OpenTelemetry Span into your controller methods.
|
|
49
|
+
```typescript
|
|
50
|
+
@Get()
|
|
51
|
+
findAll(@CurrentSpan() span: Span) {
|
|
52
|
+
span.setAttribute('custom.attr', 'value');
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
- **`@Baggage(key)`**: A parameter decorator to extract OpenTelemetry Baggage values.
|
|
57
|
+
```typescript
|
|
58
|
+
@Get()
|
|
59
|
+
findAll(@Baggage('tenant-id') tenantId: string) {
|
|
60
|
+
// ...
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Span Decorator Enhancements
|
|
65
|
+
|
|
66
|
+
The `@Span` decorator now supports capturing the return value of a method using the `onResult` callback.
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
@Span({
|
|
70
|
+
onResult: (result) => ({ attributes: { 'item.count': result.length } }),
|
|
71
|
+
})
|
|
72
|
+
async getItems() {
|
|
73
|
+
return [1, 2, 3];
|
|
74
|
+
}
|
|
75
|
+
```
|
package/biome.jsonc
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
|
|
3
|
+
"extends": ["ultracite/core"],
|
|
4
|
+
"javascript": {
|
|
5
|
+
"parser": {
|
|
6
|
+
"unsafeParameterDecoratorsEnabled": true
|
|
7
|
+
},
|
|
8
|
+
"globals": ["jest"]
|
|
9
|
+
},
|
|
10
|
+
"linter": {
|
|
11
|
+
"rules": {
|
|
12
|
+
"performance": {
|
|
13
|
+
"noBarrelFile": "off",
|
|
14
|
+
"useTopLevelRegex": "off",
|
|
15
|
+
"noNamespaceImport": "off"
|
|
16
|
+
},
|
|
17
|
+
"suspicious": {
|
|
18
|
+
"noExplicitAny": "off",
|
|
19
|
+
"useAwait": "off",
|
|
20
|
+
"noEmptyBlockStatements": "off",
|
|
21
|
+
"noImplicitAnyLet": "off",
|
|
22
|
+
"noEvolvingTypes": "off",
|
|
23
|
+
"noSkippedTests": "off"
|
|
24
|
+
},
|
|
25
|
+
"style": {
|
|
26
|
+
"useConsistentMemberAccessibility": "off",
|
|
27
|
+
"noDoneCallback": "off",
|
|
28
|
+
"noParameterProperties": "off",
|
|
29
|
+
"noEnum": "off"
|
|
30
|
+
},
|
|
31
|
+
"complexity": {
|
|
32
|
+
"noStaticOnlyClass": "off",
|
|
33
|
+
"noBannedTypes": "off"
|
|
34
|
+
},
|
|
35
|
+
"nursery": {
|
|
36
|
+
"noShadow": "off"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
package/package.json
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nestjs-otel",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.0.0",
|
|
4
4
|
"description": "NestJS OpenTelemetry Library",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"typings": "lib/index",
|
|
7
7
|
"engines": {
|
|
8
|
-
"node": ">=
|
|
8
|
+
"node": ">= 22"
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
11
|
"prebuild": "rimraf lib",
|
|
12
12
|
"build": "tsc",
|
|
13
|
-
"lint": "
|
|
14
|
-
"format": "
|
|
13
|
+
"lint": "ultracite check",
|
|
14
|
+
"format": "ultracite fix",
|
|
15
15
|
"test": "npm run test:unit && npm run test:e2e",
|
|
16
16
|
"test:coverage": "jest --coverage",
|
|
17
17
|
"test:unit": "jest",
|
|
18
18
|
"test:watch": "jest --watch",
|
|
19
|
-
"test:e2e": "jest --config ./tests/jest-e2e.json --runInBand --forceExit",
|
|
19
|
+
"test:e2e": "jest --config ./tests/jest-e2e.json --runInBand --forceExit --detectOpenHandles",
|
|
20
20
|
"test:e2e:watch": "jest --config ./tests/jest-e2e.json --runInBand --watch",
|
|
21
21
|
"prepare": "husky"
|
|
22
22
|
},
|
|
@@ -39,34 +39,34 @@
|
|
|
39
39
|
"homepage": "https://github.com/pragmaticivan/nestjs-otel#readme",
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"@opentelemetry/api": "^1.9.0",
|
|
42
|
-
"@opentelemetry/host-metrics": "^0.
|
|
43
|
-
"response-time": "^2.3.3"
|
|
42
|
+
"@opentelemetry/host-metrics": "^0.37.0"
|
|
44
43
|
},
|
|
45
44
|
"devDependencies": {
|
|
46
|
-
"@
|
|
47
|
-
"@commitlint/
|
|
48
|
-
"@
|
|
49
|
-
"@nestjs/
|
|
50
|
-
"@nestjs/
|
|
51
|
-
"@nestjs/platform-
|
|
52
|
-
"@nestjs/
|
|
53
|
-
"@
|
|
54
|
-
"@opentelemetry/
|
|
55
|
-
"@opentelemetry/sdk-
|
|
56
|
-
"@
|
|
57
|
-
"@types/
|
|
58
|
-
"@types/
|
|
45
|
+
"@biomejs/biome": "^2.3.8",
|
|
46
|
+
"@commitlint/cli": "^20.2.0",
|
|
47
|
+
"@commitlint/config-conventional": "^20.2.0",
|
|
48
|
+
"@nestjs/common": "^11.1.9",
|
|
49
|
+
"@nestjs/core": "^11.1.9",
|
|
50
|
+
"@nestjs/platform-express": "^11.1.9",
|
|
51
|
+
"@nestjs/platform-fastify": "^11.1.9",
|
|
52
|
+
"@nestjs/testing": "^11.1.9",
|
|
53
|
+
"@opentelemetry/exporter-prometheus": "^0.208.0",
|
|
54
|
+
"@opentelemetry/sdk-metrics": "^2.2.0",
|
|
55
|
+
"@opentelemetry/sdk-trace-node": "^2.2.0",
|
|
56
|
+
"@types/express": "^5.0.6",
|
|
57
|
+
"@types/jest": "^30.0.0",
|
|
58
|
+
"@types/node": "^24.10.1",
|
|
59
59
|
"@types/supertest": "^6.0.3",
|
|
60
60
|
"husky": "^9.1.7",
|
|
61
|
-
"jest": "^
|
|
62
|
-
"lint-staged": "^16.
|
|
63
|
-
"prettier": "^3.5.3",
|
|
61
|
+
"jest": "^30.2.0",
|
|
62
|
+
"lint-staged": "^16.2.7",
|
|
64
63
|
"reflect-metadata": "^0.2.2",
|
|
65
|
-
"rimraf": "^6.
|
|
64
|
+
"rimraf": "^6.1.2",
|
|
66
65
|
"rxjs": "^7.8.2",
|
|
67
|
-
"supertest": "^7.1.
|
|
68
|
-
"ts-jest": "^29.
|
|
69
|
-
"typescript": "5.
|
|
66
|
+
"supertest": "^7.1.4",
|
|
67
|
+
"ts-jest": "^29.4.6",
|
|
68
|
+
"typescript": "5.9.3",
|
|
69
|
+
"ultracite": "^6.3.10"
|
|
70
70
|
},
|
|
71
71
|
"peerDependencies": {
|
|
72
72
|
"@nestjs/common": ">= 11 < 12",
|
|
@@ -91,8 +91,8 @@
|
|
|
91
91
|
"testEnvironment": "node"
|
|
92
92
|
},
|
|
93
93
|
"lint-staged": {
|
|
94
|
-
"
|
|
95
|
-
"
|
|
94
|
+
"*.{js,jsx,ts,tsx,json,jsonc,css,scss,md,mdx}": [
|
|
95
|
+
"npx ultracite fix"
|
|
96
96
|
]
|
|
97
97
|
}
|
|
98
98
|
}
|
package/.prettierignore
DELETED
|
File without changes
|
|
@@ -1,16 +0,0 @@
|
|
|
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
|
|
3
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.HttpAdapterType = void 0;
|
|
5
|
-
exports.detectHttpAdapterType = detectHttpAdapterType;
|
|
6
|
-
var HttpAdapterType;
|
|
7
|
-
(function (HttpAdapterType) {
|
|
8
|
-
HttpAdapterType["EXPRESS"] = "express";
|
|
9
|
-
HttpAdapterType["FASTIFY"] = "fastify";
|
|
10
|
-
})(HttpAdapterType || (exports.HttpAdapterType = HttpAdapterType = {}));
|
|
11
|
-
function detectHttpAdapterType(httpAdapter) {
|
|
12
|
-
if (httpAdapter.constructor.name === 'FastifyAdapter') {
|
|
13
|
-
return HttpAdapterType.FASTIFY;
|
|
14
|
-
}
|
|
15
|
-
return HttpAdapterType.EXPRESS;
|
|
16
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,85 +0,0 @@
|
|
|
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
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
-
const feature_detection_utils_1 = require("./feature-detection.utils");
|
|
43
|
-
describe('FeatureDetectionUtils', () => {
|
|
44
|
-
describe('When using Express adapter', () => {
|
|
45
|
-
async function getExpressApp() {
|
|
46
|
-
const { Module } = await Promise.resolve().then(() => __importStar(require('@nestjs/common')));
|
|
47
|
-
const { Test } = await Promise.resolve().then(() => __importStar(require('@nestjs/testing')));
|
|
48
|
-
let TestModule = class TestModule {
|
|
49
|
-
};
|
|
50
|
-
TestModule = __decorate([
|
|
51
|
-
Module({})
|
|
52
|
-
], TestModule);
|
|
53
|
-
const module = await Test.createTestingModule({
|
|
54
|
-
imports: [TestModule],
|
|
55
|
-
}).compile();
|
|
56
|
-
return module.createNestApplication();
|
|
57
|
-
}
|
|
58
|
-
it('should detect Express version 5 on Nest 11', async () => {
|
|
59
|
-
const app = await getExpressApp();
|
|
60
|
-
const adapterType = (0, feature_detection_utils_1.detectHttpAdapterType)(app.getHttpAdapter());
|
|
61
|
-
expect(adapterType).toEqual(feature_detection_utils_1.HttpAdapterType.EXPRESS);
|
|
62
|
-
});
|
|
63
|
-
});
|
|
64
|
-
describe('When using Fastify adapter', () => {
|
|
65
|
-
async function getFastifyApp() {
|
|
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')));
|
|
69
|
-
let TestModule = class TestModule {
|
|
70
|
-
};
|
|
71
|
-
TestModule = __decorate([
|
|
72
|
-
Module({})
|
|
73
|
-
], TestModule);
|
|
74
|
-
const module = await Test.createTestingModule({
|
|
75
|
-
imports: [TestModule],
|
|
76
|
-
}).compile();
|
|
77
|
-
return module.createNestApplication(new FastifyAdapter());
|
|
78
|
-
}
|
|
79
|
-
it('should detect Fastify version 5 on Nest 11', async () => {
|
|
80
|
-
const app = await getFastifyApp();
|
|
81
|
-
const adapterType = (0, feature_detection_utils_1.detectHttpAdapterType)(app.getHttpAdapter());
|
|
82
|
-
expect(adapterType).toEqual(feature_detection_utils_1.HttpAdapterType.FASTIFY);
|
|
83
|
-
});
|
|
84
|
-
});
|
|
85
|
-
});
|
package/lib/index.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export * from './opentelemetry.module';
|
|
2
|
-
export * from './tracing/decorators/span';
|
|
3
|
-
export * from './tracing/trace.service';
|
|
4
|
-
export * from './metrics/metric.service';
|
|
5
|
-
export * from './metrics/injector';
|
|
6
|
-
export * from './metrics/decorators';
|
|
7
|
-
export * from './opentelemetry.constants';
|
|
8
|
-
export * from './interfaces';
|
package/lib/index.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
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
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
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);
|
package/lib/interfaces/index.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
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
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./opentelemetry-options.interface"), exports);
|
|
18
|
-
__exportStar(require("./metric-options.interface"), exports);
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { ModuleMetadata, Type, Abstract } from '@nestjs/common';
|
|
2
|
-
import { Attributes } from '@opentelemetry/api';
|
|
3
|
-
import { RouteInfo } from '@nestjs/common/interfaces';
|
|
4
|
-
export type OpenTelemetryModuleOptions = {
|
|
5
|
-
/**
|
|
6
|
-
* OpenTelemetry Metrics Setup
|
|
7
|
-
*/
|
|
8
|
-
metrics?: OpenTelemetryMetrics;
|
|
9
|
-
};
|
|
10
|
-
export interface OpenTelemetryOptionsFactory {
|
|
11
|
-
createOpenTelemetryOptions(): Promise<OpenTelemetryModuleOptions> | OpenTelemetryModuleOptions;
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* The options for the asynchronous Terminus module creation
|
|
15
|
-
*
|
|
16
|
-
* @publicApi
|
|
17
|
-
*/
|
|
18
|
-
export interface OpenTelemetryModuleAsyncOptions extends Pick<ModuleMetadata, 'imports'> {
|
|
19
|
-
/**
|
|
20
|
-
* The name of the module
|
|
21
|
-
*/
|
|
22
|
-
name?: string;
|
|
23
|
-
/**
|
|
24
|
-
* The class which should be used to provide the Terminus options
|
|
25
|
-
*/
|
|
26
|
-
useClass?: Type<OpenTelemetryOptionsFactory>;
|
|
27
|
-
/**
|
|
28
|
-
* Import existing providers from other module
|
|
29
|
-
*/
|
|
30
|
-
useExisting?: Type<OpenTelemetryOptionsFactory>;
|
|
31
|
-
/**
|
|
32
|
-
* The factory which should be used to provide the Terminus options
|
|
33
|
-
*/
|
|
34
|
-
useFactory?: (...args: any[]) => Promise<OpenTelemetryModuleOptions> | OpenTelemetryModuleOptions;
|
|
35
|
-
/**
|
|
36
|
-
* The providers which should get injected
|
|
37
|
-
*/
|
|
38
|
-
inject?: (string | symbol | Function | Type<any> | Abstract<any>)[];
|
|
39
|
-
}
|
|
40
|
-
export type OpenTelemetryMetrics = {
|
|
41
|
-
hostMetrics?: boolean;
|
|
42
|
-
/**
|
|
43
|
-
* @deprecated apiMetrics is deprecated. Use semcov from opentelemetry metrics instead.
|
|
44
|
-
*/
|
|
45
|
-
apiMetrics?: {
|
|
46
|
-
enable?: boolean;
|
|
47
|
-
defaultAttributes?: Attributes;
|
|
48
|
-
ignoreRoutes?: (string | RouteInfo)[];
|
|
49
|
-
ignoreUndefinedRoutes?: boolean;
|
|
50
|
-
prefix?: string;
|
|
51
|
-
};
|
|
52
|
-
};
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { OtelMetricOptions } from '../../interfaces/metric-options.interface';
|
|
2
|
-
/**
|
|
3
|
-
* Create and increment a counter when a new instance is created
|
|
4
|
-
*
|
|
5
|
-
* @param originalClass
|
|
6
|
-
*/
|
|
7
|
-
export declare const OtelInstanceCounter: (options?: OtelMetricOptions) => <T extends {
|
|
8
|
-
new (...args: any[]): {};
|
|
9
|
-
}>(originalClass: T) => {
|
|
10
|
-
new (...args: any[]): {};
|
|
11
|
-
} & T;
|
|
12
|
-
/**
|
|
13
|
-
* Create and increment a counter when the method is called
|
|
14
|
-
*/
|
|
15
|
-
export declare const OtelMethodCounter: (options?: OtelMetricOptions) => (target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<(...args: any[]) => any>) => void;
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.OtelMethodCounter = exports.OtelInstanceCounter = void 0;
|
|
4
|
-
const opentelemetry_utils_1 = require("../../opentelemetry.utils");
|
|
5
|
-
const metric_data_1 = require("../metric-data");
|
|
6
|
-
/**
|
|
7
|
-
* Create and increment a counter when a new instance is created
|
|
8
|
-
*
|
|
9
|
-
* @param originalClass
|
|
10
|
-
*/
|
|
11
|
-
const OtelInstanceCounter = (options) => (originalClass) => {
|
|
12
|
-
const name = `app_${originalClass.name}_instances_total`;
|
|
13
|
-
const description = `app_${originalClass.name} object instances total`;
|
|
14
|
-
let counterMetric;
|
|
15
|
-
const wrappedClass = class extends originalClass {
|
|
16
|
-
constructor(...args) {
|
|
17
|
-
if (!counterMetric) {
|
|
18
|
-
counterMetric = (0, metric_data_1.getOrCreateCounter)(name, { description, ...options });
|
|
19
|
-
}
|
|
20
|
-
counterMetric.add(1);
|
|
21
|
-
super(...args);
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
Object.defineProperty(wrappedClass, 'name', { value: originalClass.name });
|
|
25
|
-
(0, opentelemetry_utils_1.copyMetadataFromFunctionToFunction)(originalClass, wrappedClass);
|
|
26
|
-
return wrappedClass;
|
|
27
|
-
};
|
|
28
|
-
exports.OtelInstanceCounter = OtelInstanceCounter;
|
|
29
|
-
/**
|
|
30
|
-
* Create and increment a counter when the method is called
|
|
31
|
-
*/
|
|
32
|
-
const OtelMethodCounter = (options) => (target, propertyKey, descriptor) => {
|
|
33
|
-
const className = target.constructor.name;
|
|
34
|
-
const name = `app_${className}_${propertyKey.toString()}_calls_total`;
|
|
35
|
-
const description = `app_${className}#${propertyKey.toString()} called total`;
|
|
36
|
-
let counterMetric;
|
|
37
|
-
const originalFunction = descriptor.value ?? (() => { });
|
|
38
|
-
const wrappedFunction = function PropertyDescriptor(...args) {
|
|
39
|
-
if (!counterMetric) {
|
|
40
|
-
counterMetric = (0, metric_data_1.getOrCreateCounter)(name, { description, ...options });
|
|
41
|
-
}
|
|
42
|
-
counterMetric.add(1);
|
|
43
|
-
// @ts-ignore
|
|
44
|
-
return originalFunction.apply(this, args);
|
|
45
|
-
};
|
|
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);
|
|
52
|
-
};
|
|
53
|
-
exports.OtelMethodCounter = OtelMethodCounter;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import 'reflect-metadata';
|