nestjs-otel 6.1.2 → 6.2.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/lib/feature-detection.utils.d.ts +24 -0
- package/lib/feature-detection.utils.js +59 -0
- package/lib/feature-detection.utils.spec.d.ts +1 -0
- package/lib/feature-detection.utils.spec.js +87 -0
- package/lib/middleware.utils.d.ts +2 -0
- package/lib/middleware.utils.js +23 -0
- package/lib/opentelemetry-core.module.d.ts +3 -1
- package/lib/opentelemetry-core.module.js +9 -4
- package/package.json +26 -21
|
@@ -0,0 +1,24 @@
|
|
|
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
|
+
export declare enum HttpAdapterType {
|
|
11
|
+
EXPRESS = "express",
|
|
12
|
+
FASTIFY = "fastify"
|
|
13
|
+
}
|
|
14
|
+
type HttpExpresAdapterResponse = {
|
|
15
|
+
adapterType: HttpAdapterType.EXPRESS;
|
|
16
|
+
version: ExpressVersion;
|
|
17
|
+
};
|
|
18
|
+
type HttpFastifyAdapterResponse = {
|
|
19
|
+
adapterType: HttpAdapterType.FASTIFY;
|
|
20
|
+
version: FastifyVersion;
|
|
21
|
+
};
|
|
22
|
+
type HttpAdapterTypeAndVersion = HttpExpresAdapterResponse | HttpFastifyAdapterResponse;
|
|
23
|
+
export declare function detectHttpAdapterTypeAndVersion(httpAdapter: HttpServer): HttpAdapterTypeAndVersion;
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HttpAdapterType = exports.FastifyVersion = exports.ExpressVersion = void 0;
|
|
4
|
+
exports.detectHttpAdapterTypeAndVersion = detectHttpAdapterTypeAndVersion;
|
|
5
|
+
var ExpressVersion;
|
|
6
|
+
(function (ExpressVersion) {
|
|
7
|
+
ExpressVersion["V4"] = "4.x";
|
|
8
|
+
ExpressVersion["V5"] = "5.x";
|
|
9
|
+
})(ExpressVersion || (exports.ExpressVersion = ExpressVersion = {}));
|
|
10
|
+
var FastifyVersion;
|
|
11
|
+
(function (FastifyVersion) {
|
|
12
|
+
FastifyVersion["V4"] = "4.x";
|
|
13
|
+
FastifyVersion["V5"] = "5.x";
|
|
14
|
+
})(FastifyVersion || (exports.FastifyVersion = FastifyVersion = {}));
|
|
15
|
+
var HttpAdapterType;
|
|
16
|
+
(function (HttpAdapterType) {
|
|
17
|
+
HttpAdapterType["EXPRESS"] = "express";
|
|
18
|
+
HttpAdapterType["FASTIFY"] = "fastify";
|
|
19
|
+
})(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
|
+
function detectHttpAdapterType(httpAdapter) {
|
|
36
|
+
if (httpAdapter.constructor.name === 'FastifyAdapter') {
|
|
37
|
+
return HttpAdapterType.FASTIFY;
|
|
38
|
+
}
|
|
39
|
+
return HttpAdapterType.EXPRESS;
|
|
40
|
+
}
|
|
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
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
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
|
+
describe('FeatureDetectionUtils', () => {
|
|
20
|
+
describe('When using Express adapter', () => {
|
|
21
|
+
async function getExpressApp() {
|
|
22
|
+
const { Module } = await Promise.resolve().then(() => tslib_1.__importStar(require('@nestjs/common')));
|
|
23
|
+
const { Test } = await Promise.resolve().then(() => tslib_1.__importStar(require('@nestjs/testing')));
|
|
24
|
+
let TestModule = class TestModule {
|
|
25
|
+
};
|
|
26
|
+
TestModule = tslib_1.__decorate([
|
|
27
|
+
Module({})
|
|
28
|
+
], TestModule);
|
|
29
|
+
const module = await Test.createTestingModule({
|
|
30
|
+
imports: [TestModule],
|
|
31
|
+
}).compile();
|
|
32
|
+
return module.createNestApplication();
|
|
33
|
+
}
|
|
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
|
+
it('should detect Express version 5 on Nest 11', async () => {
|
|
44
|
+
useNest11();
|
|
45
|
+
const app = await getExpressApp();
|
|
46
|
+
const features = (0, feature_detection_utils_1.detectHttpAdapterTypeAndVersion)(app.getHttpAdapter());
|
|
47
|
+
expect(features).toEqual({
|
|
48
|
+
adapterType: feature_detection_utils_1.HttpAdapterType.EXPRESS,
|
|
49
|
+
version: feature_detection_utils_1.ExpressVersion.V5,
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
describe('When using Fastify adapter', () => {
|
|
54
|
+
async function getFastifyApp() {
|
|
55
|
+
const { Module } = await Promise.resolve().then(() => tslib_1.__importStar(require('@nestjs/common')));
|
|
56
|
+
const { Test } = await Promise.resolve().then(() => tslib_1.__importStar(require('@nestjs/testing')));
|
|
57
|
+
const { FastifyAdapter } = await Promise.resolve().then(() => tslib_1.__importStar(require('@nestjs/platform-fastify')));
|
|
58
|
+
let TestModule = class TestModule {
|
|
59
|
+
};
|
|
60
|
+
TestModule = tslib_1.__decorate([
|
|
61
|
+
Module({})
|
|
62
|
+
], TestModule);
|
|
63
|
+
const module = await Test.createTestingModule({
|
|
64
|
+
imports: [TestModule],
|
|
65
|
+
}).compile();
|
|
66
|
+
return module.createNestApplication(new FastifyAdapter());
|
|
67
|
+
}
|
|
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
|
+
it('should detect Fastify version 5 on Nest 11', async () => {
|
|
78
|
+
useNest11();
|
|
79
|
+
const app = await getFastifyApp();
|
|
80
|
+
const features = (0, feature_detection_utils_1.detectHttpAdapterTypeAndVersion)(app.getHttpAdapter());
|
|
81
|
+
expect(features).toEqual({
|
|
82
|
+
adapterType: feature_detection_utils_1.HttpAdapterType.FASTIFY,
|
|
83
|
+
version: feature_detection_utils_1.FastifyVersion.V5,
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getMiddlewareMountPoint = getMiddlewareMountPoint;
|
|
4
|
+
const feature_detection_utils_1 = require("./feature-detection.utils");
|
|
5
|
+
const MOUNT_POINT_EXPRESS_5 = '/';
|
|
6
|
+
const MOUNT_POINT_EXPRESS_4 = '*';
|
|
7
|
+
const MOUNT_POINT_FASTIFY_5 = '{*path}';
|
|
8
|
+
const MOUNT_POINT_FASTIFY_4 = '(.*)';
|
|
9
|
+
function getMiddlewareMountPoint(adapter) {
|
|
10
|
+
const features = (0, feature_detection_utils_1.detectHttpAdapterTypeAndVersion)(adapter);
|
|
11
|
+
if (features.adapterType === feature_detection_utils_1.HttpAdapterType.FASTIFY) {
|
|
12
|
+
if (features.version === feature_detection_utils_1.FastifyVersion.V5) {
|
|
13
|
+
return MOUNT_POINT_FASTIFY_5;
|
|
14
|
+
}
|
|
15
|
+
return MOUNT_POINT_FASTIFY_4;
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
if (features.version === feature_detection_utils_1.ExpressVersion.V5) {
|
|
19
|
+
return MOUNT_POINT_EXPRESS_5;
|
|
20
|
+
}
|
|
21
|
+
return MOUNT_POINT_EXPRESS_4;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DynamicModule, MiddlewareConsumer, OnApplicationBootstrap } from '@nestjs/common';
|
|
2
2
|
import { OpenTelemetryModuleAsyncOptions, OpenTelemetryModuleOptions } from './interfaces';
|
|
3
|
+
import { HttpAdapterHost } from '@nestjs/core';
|
|
3
4
|
/**
|
|
4
5
|
* The internal OpenTelemetry Module which handles the integration
|
|
5
6
|
* with the third party OpenTelemetry library and Nest
|
|
@@ -8,8 +9,9 @@ import { OpenTelemetryModuleAsyncOptions, OpenTelemetryModuleOptions } from './i
|
|
|
8
9
|
*/
|
|
9
10
|
export declare class OpenTelemetryCoreModule implements OnApplicationBootstrap {
|
|
10
11
|
private readonly options;
|
|
12
|
+
private readonly adapterHost;
|
|
11
13
|
private readonly logger;
|
|
12
|
-
constructor(options
|
|
14
|
+
constructor(options: OpenTelemetryModuleOptions | undefined, adapterHost: HttpAdapterHost);
|
|
13
15
|
/**
|
|
14
16
|
* Bootstraps the internal OpenTelemetry Module with the given options
|
|
15
17
|
* synchronously and sets the correct providers
|
|
@@ -10,6 +10,8 @@ const metric_service_1 = require("./metrics/metric.service");
|
|
|
10
10
|
const middleware_1 = require("./middleware");
|
|
11
11
|
const opentelemetry_constants_1 = require("./opentelemetry.constants");
|
|
12
12
|
const trace_service_1 = require("./tracing/trace.service");
|
|
13
|
+
const core_1 = require("@nestjs/core");
|
|
14
|
+
const middleware_utils_1 = require("./middleware.utils");
|
|
13
15
|
/**
|
|
14
16
|
* The internal OpenTelemetry Module which handles the integration
|
|
15
17
|
* with the third party OpenTelemetry library and Nest
|
|
@@ -17,8 +19,9 @@ const trace_service_1 = require("./tracing/trace.service");
|
|
|
17
19
|
* @internal
|
|
18
20
|
*/
|
|
19
21
|
let OpenTelemetryCoreModule = OpenTelemetryCoreModule_1 = class OpenTelemetryCoreModule {
|
|
20
|
-
constructor(options = {}) {
|
|
22
|
+
constructor(options = {}, adapterHost) {
|
|
21
23
|
this.options = options;
|
|
24
|
+
this.adapterHost = adapterHost;
|
|
22
25
|
this.logger = new common_1.Logger('OpenTelemetryModule');
|
|
23
26
|
}
|
|
24
27
|
/**
|
|
@@ -54,14 +57,16 @@ let OpenTelemetryCoreModule = OpenTelemetryCoreModule_1 = class OpenTelemetryCor
|
|
|
54
57
|
configure(consumer) {
|
|
55
58
|
const { apiMetrics = { enable: false } } = this.options?.metrics ?? {};
|
|
56
59
|
if (apiMetrics.enable === true) {
|
|
60
|
+
const adapter = this.adapterHost.httpAdapter;
|
|
61
|
+
const mountPoint = (0, middleware_utils_1.getMiddlewareMountPoint)(adapter);
|
|
57
62
|
if (apiMetrics?.ignoreRoutes && apiMetrics?.ignoreRoutes.length > 0) {
|
|
58
63
|
consumer
|
|
59
64
|
.apply(middleware_1.ApiMetricsMiddleware)
|
|
60
65
|
.exclude(...apiMetrics.ignoreRoutes)
|
|
61
|
-
.forRoutes(
|
|
66
|
+
.forRoutes(mountPoint);
|
|
62
67
|
}
|
|
63
68
|
else {
|
|
64
|
-
consumer.apply(middleware_1.ApiMetricsMiddleware).forRoutes(
|
|
69
|
+
consumer.apply(middleware_1.ApiMetricsMiddleware).forRoutes(mountPoint);
|
|
65
70
|
}
|
|
66
71
|
}
|
|
67
72
|
}
|
|
@@ -126,5 +131,5 @@ exports.OpenTelemetryCoreModule = OpenTelemetryCoreModule = OpenTelemetryCoreMod
|
|
|
126
131
|
(0, common_1.Global)(),
|
|
127
132
|
(0, common_1.Module)({}),
|
|
128
133
|
tslib_1.__param(0, (0, common_1.Inject)(opentelemetry_constants_1.OPENTELEMETRY_MODULE_OPTIONS)),
|
|
129
|
-
tslib_1.__metadata("design:paramtypes", [Object])
|
|
134
|
+
tslib_1.__metadata("design:paramtypes", [Object, core_1.HttpAdapterHost])
|
|
130
135
|
], OpenTelemetryCoreModule);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nestjs-otel",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.2.0",
|
|
4
4
|
"description": "NestJS OpenTelemetry Library",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"typings": "lib/index",
|
|
@@ -37,38 +37,43 @@
|
|
|
37
37
|
"homepage": "https://github.com/pragmaticivan/nestjs-otel#readme",
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@opentelemetry/api": "^1.9.0",
|
|
40
|
-
"@opentelemetry/host-metrics": "^0.35.
|
|
40
|
+
"@opentelemetry/host-metrics": "^0.35.5",
|
|
41
41
|
"response-time": "^2.3.3"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"@commitlint/cli": "^19.
|
|
45
|
-
"@commitlint/config-conventional": "^19.
|
|
46
|
-
"@nestjs/common": "^
|
|
47
|
-
"@nestjs/
|
|
48
|
-
"@nestjs/
|
|
49
|
-
"@nestjs/
|
|
50
|
-
"@nestjs/
|
|
51
|
-
"@
|
|
52
|
-
"@
|
|
53
|
-
"@
|
|
44
|
+
"@commitlint/cli": "^19.7.1",
|
|
45
|
+
"@commitlint/config-conventional": "^19.7.1",
|
|
46
|
+
"@nestjs/common": "^11.0.11",
|
|
47
|
+
"@nestjs/common10": "npm:@nestjs/common@10",
|
|
48
|
+
"@nestjs/core": "^11.0.11",
|
|
49
|
+
"@nestjs/core10": "npm:@nestjs/core@10",
|
|
50
|
+
"@nestjs/platform-express": "^11.0.11",
|
|
51
|
+
"@nestjs/platform-express10": "npm:@nestjs/platform-express@10",
|
|
52
|
+
"@nestjs/platform-fastify": "^11.0.11",
|
|
53
|
+
"@nestjs/platform-fastify10": "npm:@nestjs/platform-fastify@10",
|
|
54
|
+
"@nestjs/testing": "^11.0.11",
|
|
55
|
+
"@nestjs/testing10": "npm:@nestjs/testing@10",
|
|
56
|
+
"@opentelemetry/exporter-prometheus": "^0.57.2",
|
|
57
|
+
"@opentelemetry/sdk-metrics": "^1.30.1",
|
|
58
|
+
"@opentelemetry/sdk-trace-node": "^1.30.1",
|
|
54
59
|
"@types/jest": "^29.5.14",
|
|
55
|
-
"@types/node": "^22.
|
|
60
|
+
"@types/node": "^22.13.8",
|
|
56
61
|
"@types/response-time": "^2.3.8",
|
|
57
62
|
"@types/supertest": "^6.0.2",
|
|
58
|
-
"husky": "^9.1.
|
|
63
|
+
"husky": "^9.1.7",
|
|
59
64
|
"jest": "^29.7.0",
|
|
60
|
-
"lint-staged": "^15.
|
|
61
|
-
"prettier": "^3.
|
|
65
|
+
"lint-staged": "^15.4.3",
|
|
66
|
+
"prettier": "^3.5.2",
|
|
62
67
|
"reflect-metadata": "^0.2.2",
|
|
63
68
|
"rimraf": "^6.0.1",
|
|
64
|
-
"rxjs": "^7.8.
|
|
69
|
+
"rxjs": "^7.8.2",
|
|
65
70
|
"supertest": "^7.0.0",
|
|
66
|
-
"ts-jest": "^29.2.
|
|
67
|
-
"typescript": "5.
|
|
71
|
+
"ts-jest": "^29.2.6",
|
|
72
|
+
"typescript": "5.8.2"
|
|
68
73
|
},
|
|
69
74
|
"peerDependencies": {
|
|
70
|
-
"@nestjs/common": "
|
|
71
|
-
"@nestjs/core": "
|
|
75
|
+
"@nestjs/common": ">= 10 < 12",
|
|
76
|
+
"@nestjs/core": ">= 10 < 12"
|
|
72
77
|
},
|
|
73
78
|
"jest": {
|
|
74
79
|
"moduleFileExtensions": [
|