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 +81 -13
- package/lib/feature-detection.utils.d.ts +1 -20
- package/lib/feature-detection.utils.js +3 -46
- package/lib/feature-detection.utils.spec.js +50 -52
- package/lib/index.d.ts +1 -0
- package/lib/index.js +22 -8
- package/lib/interfaces/index.d.ts +1 -0
- package/lib/interfaces/index.js +16 -2
- package/lib/interfaces/opentelemetry-options.interface.d.ts +3 -0
- package/lib/metrics/decorators/common.js +7 -2
- package/lib/metrics/decorators/common.spec.js +20 -6
- package/lib/metrics/decorators/index.js +16 -3
- package/lib/metrics/decorators/param.d.ts +1 -0
- package/lib/metrics/decorators/param.js +2 -1
- package/lib/metrics/metric-data.d.ts +4 -2
- package/lib/metrics/metric-data.js +5 -0
- package/lib/metrics/metric.service.d.ts +1 -0
- package/lib/metrics/metric.service.js +10 -2
- package/lib/middleware/api-metrics.middleware.d.ts +10 -10
- package/lib/middleware/api-metrics.middleware.js +67 -7
- package/lib/middleware/index.js +15 -2
- package/lib/middleware.utils.js +4 -12
- package/lib/opentelemetry-core.module.js +18 -5
- package/lib/opentelemetry.module.js +7 -2
- package/lib/tracing/decorators/span.d.ts +4 -1
- package/lib/tracing/decorators/span.js +28 -11
- package/lib/tracing/decorators/span.spec.js +80 -27
- package/lib/tracing/trace.service.js +7 -2
- package/package.json +26 -29
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 {
|
|
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.
|
|
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
|
-
|
|
154
|
-
|
|
155
|
-
|
|
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
|
-
|
|
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 =
|
|
4
|
-
exports.
|
|
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(() =>
|
|
23
|
-
const { Test } = await Promise.resolve().then(() =>
|
|
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 =
|
|
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
|
|
47
|
-
expect(
|
|
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(() =>
|
|
56
|
-
const { Test } = await Promise.resolve().then(() =>
|
|
57
|
-
const { FastifyAdapter } = await Promise.resolve().then(() =>
|
|
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 =
|
|
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
|
|
81
|
-
expect(
|
|
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
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
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
CHANGED
|
@@ -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
|
-
|
|
4
|
-
|
|
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 =
|
|
46
|
-
|
|
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
|
-
|
|
19
|
+
__decorate([
|
|
12
20
|
TestDecoratorThatSetsMetadata(),
|
|
13
21
|
(0, common_2.OtelMethodCounter)(),
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
22
|
+
__metadata("design:type", Function),
|
|
23
|
+
__metadata("design:paramtypes", []),
|
|
24
|
+
__metadata("design:returntype", void 0)
|
|
17
25
|
], TestClass.prototype, "method", null);
|
|
18
|
-
TestClass =
|
|
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
|
-
|
|
4
|
-
|
|
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 =
|
|
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 =
|
|
7
|
-
const urlParser =
|
|
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 =
|
|
186
|
+
exports.ApiMetricsMiddleware = ApiMetricsMiddleware = __decorate([
|
|
127
187
|
(0, common_1.Injectable)(),
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
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);
|
package/lib/middleware/index.js
CHANGED
|
@@ -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
|
-
|
|
4
|
-
tslib_1.__exportStar(require("./api-metrics.middleware"), exports);
|
|
17
|
+
__exportStar(require("./api-metrics.middleware"), exports);
|
package/lib/middleware.utils.js
CHANGED
|
@@ -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
|
|
11
|
-
if (
|
|
12
|
-
|
|
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
|
-
|
|
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 =
|
|
143
|
+
exports.OpenTelemetryCoreModule = OpenTelemetryCoreModule = OpenTelemetryCoreModule_1 = __decorate([
|
|
131
144
|
(0, common_1.Global)(),
|
|
132
145
|
(0, common_1.Module)({}),
|
|
133
|
-
|
|
134
|
-
|
|
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 =
|
|
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
|
-
|
|
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(
|
|
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
|
|
16
|
-
return tracer.startActiveSpan(
|
|
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
|
|
19
|
-
// @ts-ignore
|
|
31
|
+
return originalFunction
|
|
20
32
|
.apply(this, args)
|
|
21
|
-
|
|
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
|
-
|
|
46
|
-
|
|
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
|
-
|
|
35
|
+
__decorate([
|
|
25
36
|
(0, span_1.Span)(),
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
37
|
+
__metadata("design:type", Function),
|
|
38
|
+
__metadata("design:paramtypes", []),
|
|
39
|
+
__metadata("design:returntype", void 0)
|
|
29
40
|
], TestSpan.prototype, "singleSpan", null);
|
|
30
|
-
|
|
41
|
+
__decorate([
|
|
31
42
|
(0, span_1.Span)(),
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
43
|
+
__metadata("design:type", Function),
|
|
44
|
+
__metadata("design:paramtypes", []),
|
|
45
|
+
__metadata("design:returntype", void 0)
|
|
35
46
|
], TestSpan.prototype, "doubleSpan", null);
|
|
36
|
-
|
|
47
|
+
__decorate([
|
|
37
48
|
(0, span_1.Span)('foo', { kind: api_1.SpanKind.PRODUCER }),
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
49
|
+
__metadata("design:type", Function),
|
|
50
|
+
__metadata("design:paramtypes", []),
|
|
51
|
+
__metadata("design:returntype", void 0)
|
|
41
52
|
], TestSpan.prototype, "fooProducerSpan", null);
|
|
42
|
-
|
|
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
|
-
|
|
45
|
-
|
|
46
|
-
|
|
73
|
+
__metadata("design:type", Function),
|
|
74
|
+
__metadata("design:paramtypes", []),
|
|
75
|
+
__metadata("design:returntype", void 0)
|
|
47
76
|
], TestSpan.prototype, "error", null);
|
|
48
|
-
|
|
77
|
+
__decorate([
|
|
49
78
|
(0, span_1.Span)(),
|
|
50
79
|
TestDecoratorThatSetsMetadata(),
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
80
|
+
__metadata("design:type", Function),
|
|
81
|
+
__metadata("design:paramtypes", []),
|
|
82
|
+
__metadata("design:returntype", void 0)
|
|
54
83
|
], TestSpan.prototype, "metadata", null);
|
|
55
|
-
|
|
84
|
+
__decorate([
|
|
56
85
|
(0, span_1.Span)(),
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
-
|
|
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 =
|
|
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": "
|
|
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
|
|
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.
|
|
42
|
+
"@opentelemetry/host-metrics": "^0.36.0",
|
|
41
43
|
"response-time": "^2.3.3"
|
|
42
44
|
},
|
|
43
45
|
"devDependencies": {
|
|
44
|
-
"@commitlint/cli": "^19.
|
|
45
|
-
"@commitlint/config-conventional": "^19.
|
|
46
|
-
"@nestjs/common": "^11.
|
|
47
|
-
"@nestjs/
|
|
48
|
-
"@nestjs/
|
|
49
|
-
"@nestjs/
|
|
50
|
-
"@nestjs/
|
|
51
|
-
"@
|
|
52
|
-
"@
|
|
53
|
-
"@
|
|
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.
|
|
57
|
+
"@types/node": "^22.15.18",
|
|
61
58
|
"@types/response-time": "^2.3.8",
|
|
62
|
-
"@types/supertest": "^6.0.
|
|
59
|
+
"@types/supertest": "^6.0.3",
|
|
63
60
|
"husky": "^9.1.7",
|
|
64
61
|
"jest": "^29.7.0",
|
|
65
|
-
"lint-staged": "^
|
|
66
|
-
"prettier": "^3.5.
|
|
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.
|
|
71
|
-
"ts-jest": "^29.
|
|
72
|
-
"typescript": "5.8.
|
|
67
|
+
"supertest": "^7.1.1",
|
|
68
|
+
"ts-jest": "^29.3.3",
|
|
69
|
+
"typescript": "5.8.3"
|
|
73
70
|
},
|
|
74
71
|
"peerDependencies": {
|
|
75
|
-
"@nestjs/common": ">=
|
|
76
|
-
"@nestjs/core": ">=
|
|
72
|
+
"@nestjs/common": ">= 11 < 12",
|
|
73
|
+
"@nestjs/core": ">= 11 < 12"
|
|
77
74
|
},
|
|
78
75
|
"jest": {
|
|
79
76
|
"moduleFileExtensions": [
|