nestjs-otel 5.1.4 → 6.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/.prettierignore +0 -0
- package/README.md +10 -8
- package/lib/index.js +8 -21
- package/lib/interfaces/index.js +2 -15
- package/lib/interfaces/opentelemetry-options.interface.d.ts +25 -2
- package/lib/metrics/decorators/common.d.ts +8 -0
- package/lib/metrics/decorators/common.js +9 -0
- package/lib/metrics/decorators/common.spec.js +6 -14
- package/lib/metrics/decorators/index.js +5 -18
- package/lib/metrics/metric-data.js +1 -1
- package/lib/metrics/metric.service.js +3 -8
- package/lib/metrics/utils.d.ts +3 -0
- package/lib/metrics/utils.js +3 -0
- package/lib/middleware/api-metrics.middleware.d.ts +1 -1
- package/lib/middleware/api-metrics.middleware.js +19 -24
- package/lib/middleware/index.js +2 -15
- package/lib/opentelemetry-core.module.d.ts +26 -0
- package/lib/opentelemetry-core.module.js +42 -38
- package/lib/opentelemetry.module.d.ts +14 -0
- package/lib/opentelemetry.module.js +17 -8
- package/lib/opentelemetry.utils.js +3 -0
- package/lib/tracing/decorators/span.d.ts +1 -1
- package/lib/tracing/decorators/span.js +8 -3
- package/lib/tracing/decorators/span.spec.js +37 -29
- package/lib/tracing/trace.service.js +3 -8
- package/package.json +32 -34
package/.prettierignore
ADDED
|
File without changes
|
package/README.md
CHANGED
|
@@ -25,10 +25,18 @@ Please read this [comprehensive whitepaper](https://github.com/cncf/tag-observab
|
|
|
25
25
|
|
|
26
26
|

|
|
27
27
|
|
|
28
|
+
|
|
29
|
+
## Examples
|
|
30
|
+
|
|
31
|
+
A full working examples are available. This includes a nestjs application fully integrated with prometheus, grafana, loki and tempo:
|
|
32
|
+
|
|
33
|
+
- [nestjs-otel-prom-grafana-tempo](https://github.com/pragmaticivan/nestjs-otel-prom-grafana-tempo )
|
|
34
|
+
|
|
35
|
+
|
|
28
36
|
## Installation
|
|
29
37
|
|
|
30
38
|
```bash
|
|
31
|
-
|
|
39
|
+
npm i nestjs-otel @opentelemetry/sdk-node --save
|
|
32
40
|
```
|
|
33
41
|
|
|
34
42
|
## Setup
|
|
@@ -58,10 +66,9 @@ import { AsyncLocalStorageContextManager } from '@opentelemetry/context-async-ho
|
|
|
58
66
|
import * as process from 'process';
|
|
59
67
|
|
|
60
68
|
const otelSDK = new NodeSDK({
|
|
61
|
-
|
|
69
|
+
metricReader: new PrometheusExporter({
|
|
62
70
|
port: 8081,
|
|
63
71
|
}),
|
|
64
|
-
metricInterval: 1000,
|
|
65
72
|
spanProcessor: new BatchSpanProcessor(new JaegerExporter()),
|
|
66
73
|
contextManager: new AsyncLocalStorageContextManager(),
|
|
67
74
|
textMapPropagator: new CompositePropagator({
|
|
@@ -315,11 +322,6 @@ export const loggerOptions: LoggerOptions = {
|
|
|
315
322
|
export const logger: Logger = Pino(loggerOptions);
|
|
316
323
|
```
|
|
317
324
|
|
|
318
|
-
## Examples
|
|
319
|
-
|
|
320
|
-
A full working examples are available. This includes a nestjs application fully integrated with prometheus, grafana, loki and tempo:
|
|
321
|
-
|
|
322
|
-
* [nestjs-otel-prom-grafana-tempo](https://github.com/pragmaticivan/nestjs-otel-prom-grafana-tempo )
|
|
323
325
|
## Stargazers over time
|
|
324
326
|
|
|
325
327
|
[](https://starchart.cc/pragmaticivan/nestjs-otel)
|
package/lib/index.js
CHANGED
|
@@ -1,23 +1,10 @@
|
|
|
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
|
-
};
|
|
16
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
|
|
18
|
-
__exportStar(require("./
|
|
19
|
-
__exportStar(require("./tracing/
|
|
20
|
-
__exportStar(require("./
|
|
21
|
-
__exportStar(require("./metrics/
|
|
22
|
-
__exportStar(require("./metrics/
|
|
23
|
-
__exportStar(require("./
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
tslib_1.__exportStar(require("./opentelemetry.module"), exports);
|
|
5
|
+
tslib_1.__exportStar(require("./tracing/decorators/span"), exports);
|
|
6
|
+
tslib_1.__exportStar(require("./tracing/trace.service"), exports);
|
|
7
|
+
tslib_1.__exportStar(require("./metrics/metric.service"), exports);
|
|
8
|
+
tslib_1.__exportStar(require("./metrics/injector"), exports);
|
|
9
|
+
tslib_1.__exportStar(require("./metrics/decorators"), exports);
|
|
10
|
+
tslib_1.__exportStar(require("./opentelemetry.constants"), exports);
|
package/lib/interfaces/index.js
CHANGED
|
@@ -1,17 +1,4 @@
|
|
|
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
|
-
};
|
|
16
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
tslib_1.__exportStar(require("./opentelemetry-options.interface"), exports);
|
|
@@ -1,24 +1,47 @@
|
|
|
1
1
|
import { ModuleMetadata, Type, Abstract } from '@nestjs/common';
|
|
2
|
-
import {
|
|
2
|
+
import { Attributes } from '@opentelemetry/api';
|
|
3
3
|
import { RouteInfo } from '@nestjs/common/interfaces';
|
|
4
4
|
export type OpenTelemetryModuleOptions = {
|
|
5
|
+
/**
|
|
6
|
+
* OpenTelemetry Metrics Setup
|
|
7
|
+
*/
|
|
5
8
|
metrics?: OpenTelemetryMetrics;
|
|
6
9
|
};
|
|
7
10
|
export interface OpenTelemetryOptionsFactory {
|
|
8
11
|
createOpenTelemetryOptions(): Promise<OpenTelemetryModuleOptions> | OpenTelemetryModuleOptions;
|
|
9
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* The options for the asynchronous Terminus module creation
|
|
15
|
+
*
|
|
16
|
+
* @publicApi
|
|
17
|
+
*/
|
|
10
18
|
export interface OpenTelemetryModuleAsyncOptions extends Pick<ModuleMetadata, 'imports'> {
|
|
19
|
+
/**
|
|
20
|
+
* The name of the module
|
|
21
|
+
*/
|
|
11
22
|
name?: string;
|
|
23
|
+
/**
|
|
24
|
+
* The class which should be used to provide the Terminus options
|
|
25
|
+
*/
|
|
12
26
|
useClass?: Type<OpenTelemetryOptionsFactory>;
|
|
27
|
+
/**
|
|
28
|
+
* Import existing providers from other module
|
|
29
|
+
*/
|
|
13
30
|
useExisting?: Type<OpenTelemetryOptionsFactory>;
|
|
31
|
+
/**
|
|
32
|
+
* The factory which should be used to provide the Terminus options
|
|
33
|
+
*/
|
|
14
34
|
useFactory?: (...args: any[]) => Promise<OpenTelemetryModuleOptions> | OpenTelemetryModuleOptions;
|
|
35
|
+
/**
|
|
36
|
+
* The providers which should get injected
|
|
37
|
+
*/
|
|
15
38
|
inject?: (string | symbol | Function | Type<any> | Abstract<any>)[];
|
|
16
39
|
}
|
|
17
40
|
export type OpenTelemetryMetrics = {
|
|
18
41
|
hostMetrics?: boolean;
|
|
19
42
|
apiMetrics?: {
|
|
20
43
|
enable?: boolean;
|
|
21
|
-
defaultAttributes?:
|
|
44
|
+
defaultAttributes?: Attributes;
|
|
22
45
|
ignoreRoutes?: (string | RouteInfo)[];
|
|
23
46
|
ignoreUndefinedRoutes?: boolean;
|
|
24
47
|
};
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { MetricOptions } from '@opentelemetry/api';
|
|
2
|
+
/**
|
|
3
|
+
* Create and increment a counter when a new instance is created
|
|
4
|
+
*
|
|
5
|
+
* @param originalClass
|
|
6
|
+
*/
|
|
2
7
|
export declare const OtelInstanceCounter: (options?: MetricOptions) => <T extends new (...args: any[]) => {}>(originalClass: T) => {
|
|
3
8
|
new (...args: any[]): {};
|
|
4
9
|
} & T;
|
|
10
|
+
/**
|
|
11
|
+
* Create and increment a counter when the method is called
|
|
12
|
+
*/
|
|
5
13
|
export declare const OtelMethodCounter: (options?: MetricOptions) => (target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<(...args: any[]) => any>) => void;
|
|
@@ -3,6 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.OtelMethodCounter = exports.OtelInstanceCounter = void 0;
|
|
4
4
|
const opentelemetry_utils_1 = require("../../opentelemetry.utils");
|
|
5
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
|
+
*/
|
|
6
11
|
const OtelInstanceCounter = (options) => (originalClass) => {
|
|
7
12
|
const name = `app_${originalClass.name}_instances_total`;
|
|
8
13
|
const description = `app_${originalClass.name} object instances total`;
|
|
@@ -20,6 +25,9 @@ const OtelInstanceCounter = (options) => (originalClass) => {
|
|
|
20
25
|
return wrappedClass;
|
|
21
26
|
};
|
|
22
27
|
exports.OtelInstanceCounter = OtelInstanceCounter;
|
|
28
|
+
/**
|
|
29
|
+
* Create and increment a counter when the method is called
|
|
30
|
+
*/
|
|
23
31
|
const OtelMethodCounter = (options) => (target, propertyKey, descriptor) => {
|
|
24
32
|
const className = target.constructor.name;
|
|
25
33
|
const name = `app_${className}_${propertyKey.toString()}_calls_total`;
|
|
@@ -31,6 +39,7 @@ const OtelMethodCounter = (options) => (target, propertyKey, descriptor) => {
|
|
|
31
39
|
counterMetric = (0, metric_data_1.getOrCreateCounter)(name, { description, ...options });
|
|
32
40
|
}
|
|
33
41
|
counterMetric.add(1);
|
|
42
|
+
// @ts-ignore
|
|
34
43
|
return originalFunction.apply(this, args);
|
|
35
44
|
};
|
|
36
45
|
descriptor.value = wrappedFunction;
|
|
@@ -1,14 +1,6 @@
|
|
|
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
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
12
4
|
require("reflect-metadata");
|
|
13
5
|
const common_1 = require("@nestjs/common");
|
|
14
6
|
const common_2 = require("./common");
|
|
@@ -16,14 +8,14 @@ const TestDecoratorThatSetsMetadata = () => (0, common_1.SetMetadata)('some-meta
|
|
|
16
8
|
let TestClass = class TestClass {
|
|
17
9
|
method() { }
|
|
18
10
|
};
|
|
19
|
-
__decorate([
|
|
11
|
+
tslib_1.__decorate([
|
|
20
12
|
TestDecoratorThatSetsMetadata(),
|
|
21
13
|
(0, common_2.OtelMethodCounter)(),
|
|
22
|
-
__metadata("design:type", Function),
|
|
23
|
-
__metadata("design:paramtypes", []),
|
|
24
|
-
__metadata("design:returntype", void 0)
|
|
14
|
+
tslib_1.__metadata("design:type", Function),
|
|
15
|
+
tslib_1.__metadata("design:paramtypes", []),
|
|
16
|
+
tslib_1.__metadata("design:returntype", void 0)
|
|
25
17
|
], TestClass.prototype, "method", null);
|
|
26
|
-
TestClass = __decorate([
|
|
18
|
+
TestClass = tslib_1.__decorate([
|
|
27
19
|
(0, common_2.OtelInstanceCounter)(),
|
|
28
20
|
TestDecoratorThatSetsMetadata()
|
|
29
21
|
], TestClass);
|
|
@@ -1,20 +1,7 @@
|
|
|
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
|
-
};
|
|
16
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
|
|
18
|
-
__exportStar(require("./
|
|
19
|
-
__exportStar(require("./
|
|
20
|
-
__exportStar(require("./
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
tslib_1.__exportStar(require("./common"), exports);
|
|
5
|
+
tslib_1.__exportStar(require("./counter"), exports);
|
|
6
|
+
tslib_1.__exportStar(require("./histogram"), exports);
|
|
7
|
+
tslib_1.__exportStar(require("./observable"), exports);
|
|
@@ -11,7 +11,7 @@ var MetricType;
|
|
|
11
11
|
MetricType["ObservableGauge"] = "ObservableGauge";
|
|
12
12
|
MetricType["ObservableCounter"] = "ObservableCounter";
|
|
13
13
|
MetricType["ObservableUpDownCounter"] = "ObservableUpDownCounter";
|
|
14
|
-
})(MetricType
|
|
14
|
+
})(MetricType || (exports.MetricType = MetricType = {}));
|
|
15
15
|
exports.meterData = new Map();
|
|
16
16
|
function getOrCreateHistogram(name, options = {}) {
|
|
17
17
|
if (exports.meterData.has(name)) {
|
|
@@ -1,12 +1,7 @@
|
|
|
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
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
3
|
exports.MetricService = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
10
5
|
const common_1 = require("@nestjs/common");
|
|
11
6
|
const metric_data_1 = require("./metric-data");
|
|
12
7
|
let MetricService = class MetricService {
|
|
@@ -29,7 +24,7 @@ let MetricService = class MetricService {
|
|
|
29
24
|
return (0, metric_data_1.getOrCreateObservableUpDownCounter)(name, options);
|
|
30
25
|
}
|
|
31
26
|
};
|
|
32
|
-
MetricService =
|
|
27
|
+
exports.MetricService = MetricService;
|
|
28
|
+
exports.MetricService = MetricService = tslib_1.__decorate([
|
|
33
29
|
(0, common_1.Injectable)()
|
|
34
30
|
], MetricService);
|
|
35
|
-
exports.MetricService = MetricService;
|
package/lib/metrics/utils.d.ts
CHANGED
package/lib/metrics/utils.js
CHANGED
|
@@ -4,7 +4,7 @@ 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
|
|
7
|
+
private defaultAttributes;
|
|
8
8
|
private httpServerRequestCount;
|
|
9
9
|
private httpServerResponseCount;
|
|
10
10
|
private httpServerDuration;
|
|
@@ -1,30 +1,20 @@
|
|
|
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
|
-
};
|
|
14
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
3
|
exports.ApiMetricsMiddleware = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
16
5
|
const common_1 = require("@nestjs/common");
|
|
17
|
-
const
|
|
18
|
-
const urlParser = require("url");
|
|
6
|
+
const response_time_1 = tslib_1.__importDefault(require("response-time"));
|
|
7
|
+
const urlParser = tslib_1.__importStar(require("url"));
|
|
19
8
|
const metric_service_1 = require("../metrics/metric.service");
|
|
20
9
|
const opentelemetry_constants_1 = require("../opentelemetry.constants");
|
|
21
10
|
let ApiMetricsMiddleware = class ApiMetricsMiddleware {
|
|
22
11
|
constructor(metricService, options = {}) {
|
|
23
12
|
this.metricService = metricService;
|
|
24
13
|
this.options = options;
|
|
25
|
-
const { defaultAttributes = {}, ignoreUndefinedRoutes = false
|
|
26
|
-
this.
|
|
14
|
+
const { defaultAttributes = {}, ignoreUndefinedRoutes = false } = options?.metrics?.apiMetrics ?? {};
|
|
15
|
+
this.defaultAttributes = defaultAttributes;
|
|
27
16
|
this.ignoreUndefinedRoutes = ignoreUndefinedRoutes;
|
|
17
|
+
// Semantic Convention
|
|
28
18
|
this.httpServerRequestCount = this.metricService.getCounter('http.server.request.count', {
|
|
29
19
|
description: 'Total number of HTTP requests',
|
|
30
20
|
unit: 'requests',
|
|
@@ -49,6 +39,7 @@ let ApiMetricsMiddleware = class ApiMetricsMiddleware {
|
|
|
49
39
|
description: 'Size of outgoing bytes',
|
|
50
40
|
unit: 'By',
|
|
51
41
|
});
|
|
42
|
+
// Helpers
|
|
52
43
|
this.httpServerResponseSuccessCount = this.metricService.getCounter('http.server.response.success.count', {
|
|
53
44
|
description: 'Total number of all successful responses',
|
|
54
45
|
unit: 'responses',
|
|
@@ -61,7 +52,7 @@ let ApiMetricsMiddleware = class ApiMetricsMiddleware {
|
|
|
61
52
|
});
|
|
62
53
|
}
|
|
63
54
|
use(req, res, next) {
|
|
64
|
-
|
|
55
|
+
(0, response_time_1.default)((req, res, time) => {
|
|
65
56
|
const { route, url, method } = req;
|
|
66
57
|
let path;
|
|
67
58
|
if (route) {
|
|
@@ -78,18 +69,22 @@ let ApiMetricsMiddleware = class ApiMetricsMiddleware {
|
|
|
78
69
|
const responseLength = parseInt(res.getHeader('Content-Length'), 10) || 0;
|
|
79
70
|
const status = res.statusCode || 500;
|
|
80
71
|
const attributes = {
|
|
81
|
-
method,
|
|
72
|
+
method,
|
|
73
|
+
status,
|
|
74
|
+
path,
|
|
75
|
+
...this.defaultAttributes,
|
|
82
76
|
};
|
|
83
77
|
this.httpServerRequestSize.record(requestLength, attributes);
|
|
84
78
|
this.httpServerResponseSize.record(responseLength, attributes);
|
|
85
79
|
this.httpServerResponseCount.add(1, attributes);
|
|
86
|
-
this.httpServerDuration.record(time
|
|
80
|
+
this.httpServerDuration.record(time, attributes);
|
|
87
81
|
const codeClass = this.getStatusCodeClass(status);
|
|
88
82
|
switch (codeClass) {
|
|
89
83
|
case 'success':
|
|
90
84
|
this.httpServerResponseSuccessCount.add(1);
|
|
91
85
|
break;
|
|
92
86
|
case 'redirect':
|
|
87
|
+
// TODO: Review what should be appropriate for redirects.
|
|
93
88
|
this.httpServerResponseSuccessCount.add(1);
|
|
94
89
|
break;
|
|
95
90
|
case 'client_error':
|
|
@@ -118,10 +113,10 @@ let ApiMetricsMiddleware = class ApiMetricsMiddleware {
|
|
|
118
113
|
return 'server_error';
|
|
119
114
|
}
|
|
120
115
|
};
|
|
121
|
-
ApiMetricsMiddleware =
|
|
116
|
+
exports.ApiMetricsMiddleware = ApiMetricsMiddleware;
|
|
117
|
+
exports.ApiMetricsMiddleware = ApiMetricsMiddleware = tslib_1.__decorate([
|
|
122
118
|
(0, common_1.Injectable)(),
|
|
123
|
-
__param(0, (0, common_1.Inject)(metric_service_1.MetricService)),
|
|
124
|
-
__param(1, (0, common_1.Inject)(opentelemetry_constants_1.OPENTELEMETRY_MODULE_OPTIONS)),
|
|
125
|
-
__metadata("design:paramtypes", [metric_service_1.MetricService, Object])
|
|
119
|
+
tslib_1.__param(0, (0, common_1.Inject)(metric_service_1.MetricService)),
|
|
120
|
+
tslib_1.__param(1, (0, common_1.Inject)(opentelemetry_constants_1.OPENTELEMETRY_MODULE_OPTIONS)),
|
|
121
|
+
tslib_1.__metadata("design:paramtypes", [metric_service_1.MetricService, Object])
|
|
126
122
|
], ApiMetricsMiddleware);
|
|
127
|
-
exports.ApiMetricsMiddleware = ApiMetricsMiddleware;
|
package/lib/middleware/index.js
CHANGED
|
@@ -1,17 +1,4 @@
|
|
|
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
|
-
};
|
|
16
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
tslib_1.__exportStar(require("./api-metrics.middleware"), exports);
|
|
@@ -1,13 +1,39 @@
|
|
|
1
1
|
import { DynamicModule, MiddlewareConsumer, OnApplicationBootstrap } from '@nestjs/common';
|
|
2
2
|
import { OpenTelemetryModuleAsyncOptions, OpenTelemetryModuleOptions } from './interfaces';
|
|
3
|
+
/**
|
|
4
|
+
* The internal OpenTelemetry Module which handles the integration
|
|
5
|
+
* with the third party OpenTelemetry library and Nest
|
|
6
|
+
*
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
3
9
|
export declare class OpenTelemetryCoreModule implements OnApplicationBootstrap {
|
|
4
10
|
private readonly options;
|
|
5
11
|
private readonly logger;
|
|
6
12
|
constructor(options?: OpenTelemetryModuleOptions);
|
|
13
|
+
/**
|
|
14
|
+
* Bootstraps the internal OpenTelemetry Module with the given options
|
|
15
|
+
* synchronously and sets the correct providers
|
|
16
|
+
* @param options The options to bootstrap the module synchronously
|
|
17
|
+
*/
|
|
7
18
|
static forRoot(options?: OpenTelemetryModuleOptions): DynamicModule;
|
|
19
|
+
/**
|
|
20
|
+
* Bootstraps the internal OpenTelemetry Module with the given
|
|
21
|
+
* options asynchronously and sets the correct providers
|
|
22
|
+
* @param options The options to bootstrap the module
|
|
23
|
+
*/
|
|
8
24
|
static forRootAsync(options: OpenTelemetryModuleAsyncOptions): DynamicModule;
|
|
9
25
|
configure(consumer: MiddlewareConsumer): void;
|
|
10
26
|
onApplicationBootstrap(): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* Returns the asynchrnous OpenTelemetry options providers depending on the
|
|
29
|
+
* given module options
|
|
30
|
+
* @param options Options for the asynchrnous OpenTelemetry module
|
|
31
|
+
*/
|
|
11
32
|
private static createAsyncOptionsProvider;
|
|
33
|
+
/**
|
|
34
|
+
* Returns the asynchrnous providers depending on the given module
|
|
35
|
+
* options
|
|
36
|
+
* @param options Options for the asynchrnous OpenTelemetry module
|
|
37
|
+
*/
|
|
12
38
|
private static createAsyncProviders;
|
|
13
39
|
}
|
|
@@ -1,19 +1,8 @@
|
|
|
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
|
-
};
|
|
14
2
|
var OpenTelemetryCoreModule_1;
|
|
15
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
4
|
exports.OpenTelemetryCoreModule = void 0;
|
|
5
|
+
const tslib_1 = require("tslib");
|
|
17
6
|
const common_1 = require("@nestjs/common");
|
|
18
7
|
const host_metrics_1 = require("@opentelemetry/host-metrics");
|
|
19
8
|
const api_1 = require("@opentelemetry/api");
|
|
@@ -21,11 +10,22 @@ const metric_service_1 = require("./metrics/metric.service");
|
|
|
21
10
|
const middleware_1 = require("./middleware");
|
|
22
11
|
const opentelemetry_constants_1 = require("./opentelemetry.constants");
|
|
23
12
|
const trace_service_1 = require("./tracing/trace.service");
|
|
13
|
+
/**
|
|
14
|
+
* The internal OpenTelemetry Module which handles the integration
|
|
15
|
+
* with the third party OpenTelemetry library and Nest
|
|
16
|
+
*
|
|
17
|
+
* @internal
|
|
18
|
+
*/
|
|
24
19
|
let OpenTelemetryCoreModule = OpenTelemetryCoreModule_1 = class OpenTelemetryCoreModule {
|
|
25
20
|
constructor(options = {}) {
|
|
26
21
|
this.options = options;
|
|
27
22
|
this.logger = new common_1.Logger('OpenTelemetryModule');
|
|
28
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* Bootstraps the internal OpenTelemetry Module with the given options
|
|
26
|
+
* synchronously and sets the correct providers
|
|
27
|
+
* @param options The options to bootstrap the module synchronously
|
|
28
|
+
*/
|
|
29
29
|
static forRoot(options = {}) {
|
|
30
30
|
const openTelemetryModuleOptions = {
|
|
31
31
|
provide: opentelemetry_constants_1.OPENTELEMETRY_MODULE_OPTIONS,
|
|
@@ -33,38 +33,32 @@ let OpenTelemetryCoreModule = OpenTelemetryCoreModule_1 = class OpenTelemetryCor
|
|
|
33
33
|
};
|
|
34
34
|
return {
|
|
35
35
|
module: OpenTelemetryCoreModule_1,
|
|
36
|
-
providers: [
|
|
37
|
-
|
|
38
|
-
trace_service_1.TraceService,
|
|
39
|
-
metric_service_1.MetricService,
|
|
40
|
-
],
|
|
41
|
-
exports: [
|
|
42
|
-
trace_service_1.TraceService,
|
|
43
|
-
metric_service_1.MetricService,
|
|
44
|
-
],
|
|
36
|
+
providers: [openTelemetryModuleOptions, trace_service_1.TraceService, metric_service_1.MetricService],
|
|
37
|
+
exports: [trace_service_1.TraceService, metric_service_1.MetricService],
|
|
45
38
|
};
|
|
46
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Bootstraps the internal OpenTelemetry Module with the given
|
|
42
|
+
* options asynchronously and sets the correct providers
|
|
43
|
+
* @param options The options to bootstrap the module
|
|
44
|
+
*/
|
|
47
45
|
static forRootAsync(options) {
|
|
48
46
|
const asyncProviders = this.createAsyncProviders(options);
|
|
49
47
|
return {
|
|
50
48
|
module: OpenTelemetryCoreModule_1,
|
|
51
49
|
imports: [...(options.imports || [])],
|
|
52
|
-
providers: [
|
|
53
|
-
|
|
54
|
-
trace_service_1.TraceService,
|
|
55
|
-
metric_service_1.MetricService,
|
|
56
|
-
],
|
|
57
|
-
exports: [
|
|
58
|
-
trace_service_1.TraceService,
|
|
59
|
-
metric_service_1.MetricService,
|
|
60
|
-
],
|
|
50
|
+
providers: [...asyncProviders, trace_service_1.TraceService, metric_service_1.MetricService],
|
|
51
|
+
exports: [trace_service_1.TraceService, metric_service_1.MetricService],
|
|
61
52
|
};
|
|
62
53
|
}
|
|
63
54
|
configure(consumer) {
|
|
64
|
-
const { apiMetrics = { enable: false }
|
|
55
|
+
const { apiMetrics = { enable: false } } = this.options?.metrics ?? {};
|
|
65
56
|
if (apiMetrics.enable === true) {
|
|
66
57
|
if (apiMetrics?.ignoreRoutes && apiMetrics?.ignoreRoutes.length > 0) {
|
|
67
|
-
consumer
|
|
58
|
+
consumer
|
|
59
|
+
.apply(middleware_1.ApiMetricsMiddleware)
|
|
60
|
+
.exclude(...apiMetrics.ignoreRoutes)
|
|
61
|
+
.forRoutes('*');
|
|
68
62
|
}
|
|
69
63
|
else {
|
|
70
64
|
consumer.apply(middleware_1.ApiMetricsMiddleware).forRoutes('*');
|
|
@@ -74,8 +68,8 @@ let OpenTelemetryCoreModule = OpenTelemetryCoreModule_1 = class OpenTelemetryCor
|
|
|
74
68
|
async onApplicationBootstrap() {
|
|
75
69
|
let hostMetrics = false;
|
|
76
70
|
if (this.options?.metrics) {
|
|
77
|
-
hostMetrics =
|
|
78
|
-
!== undefined ? this.options.metrics.hostMetrics : false;
|
|
71
|
+
hostMetrics =
|
|
72
|
+
this.options.metrics.hostMetrics !== undefined ? this.options.metrics.hostMetrics : false;
|
|
79
73
|
}
|
|
80
74
|
const meterProvider = api_1.metrics.getMeterProvider();
|
|
81
75
|
if (hostMetrics) {
|
|
@@ -83,6 +77,11 @@ let OpenTelemetryCoreModule = OpenTelemetryCoreModule_1 = class OpenTelemetryCor
|
|
|
83
77
|
host.start();
|
|
84
78
|
}
|
|
85
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* Returns the asynchrnous OpenTelemetry options providers depending on the
|
|
82
|
+
* given module options
|
|
83
|
+
* @param options Options for the asynchrnous OpenTelemetry module
|
|
84
|
+
*/
|
|
86
85
|
static createAsyncOptionsProvider(options) {
|
|
87
86
|
if (options.useFactory) {
|
|
88
87
|
return {
|
|
@@ -103,6 +102,11 @@ let OpenTelemetryCoreModule = OpenTelemetryCoreModule_1 = class OpenTelemetryCor
|
|
|
103
102
|
}
|
|
104
103
|
throw new Error();
|
|
105
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* Returns the asynchrnous providers depending on the given module
|
|
107
|
+
* options
|
|
108
|
+
* @param options Options for the asynchrnous OpenTelemetry module
|
|
109
|
+
*/
|
|
106
110
|
static createAsyncProviders(options) {
|
|
107
111
|
if (options.useFactory || options.useExisting) {
|
|
108
112
|
return [this.createAsyncOptionsProvider(options)];
|
|
@@ -117,10 +121,10 @@ let OpenTelemetryCoreModule = OpenTelemetryCoreModule_1 = class OpenTelemetryCor
|
|
|
117
121
|
];
|
|
118
122
|
}
|
|
119
123
|
};
|
|
120
|
-
OpenTelemetryCoreModule =
|
|
124
|
+
exports.OpenTelemetryCoreModule = OpenTelemetryCoreModule;
|
|
125
|
+
exports.OpenTelemetryCoreModule = OpenTelemetryCoreModule = OpenTelemetryCoreModule_1 = tslib_1.__decorate([
|
|
121
126
|
(0, common_1.Global)(),
|
|
122
127
|
(0, common_1.Module)({}),
|
|
123
|
-
__param(0, (0, common_1.Inject)(opentelemetry_constants_1.OPENTELEMETRY_MODULE_OPTIONS)),
|
|
124
|
-
__metadata("design:paramtypes", [Object])
|
|
128
|
+
tslib_1.__param(0, (0, common_1.Inject)(opentelemetry_constants_1.OPENTELEMETRY_MODULE_OPTIONS)),
|
|
129
|
+
tslib_1.__metadata("design:paramtypes", [Object])
|
|
125
130
|
], OpenTelemetryCoreModule);
|
|
126
|
-
exports.OpenTelemetryCoreModule = OpenTelemetryCoreModule;
|
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
import { DynamicModule } from '@nestjs/common';
|
|
2
2
|
import { OpenTelemetryModuleAsyncOptions, OpenTelemetryModuleOptions } from './interfaces';
|
|
3
|
+
/**
|
|
4
|
+
* The NestJS module for OpenTelemetry
|
|
5
|
+
*
|
|
6
|
+
* @publicApi
|
|
7
|
+
*/
|
|
3
8
|
export declare class OpenTelemetryModule {
|
|
9
|
+
/**
|
|
10
|
+
* Bootstraps the OpenTelemetry Module synchronously
|
|
11
|
+
* @param options The options for the OpenTelemetry Module
|
|
12
|
+
*/
|
|
4
13
|
static forRoot(options?: OpenTelemetryModuleOptions): DynamicModule;
|
|
14
|
+
/**
|
|
15
|
+
* Bootstrap the OpenTelemetry Module asynchronously
|
|
16
|
+
* @see https://dev.to/nestjs/advanced-nestjs-how-to-build-completely-dynamic-nestjs-modules-1370
|
|
17
|
+
* @param options The options for the OpenTelemetry module
|
|
18
|
+
*/
|
|
5
19
|
static forRootAsync(options: OpenTelemetryModuleAsyncOptions): DynamicModule;
|
|
6
20
|
}
|
|
@@ -1,22 +1,31 @@
|
|
|
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
2
|
var OpenTelemetryModule_1;
|
|
9
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
4
|
exports.OpenTelemetryModule = void 0;
|
|
5
|
+
const tslib_1 = require("tslib");
|
|
11
6
|
const common_1 = require("@nestjs/common");
|
|
12
7
|
const opentelemetry_core_module_1 = require("./opentelemetry-core.module");
|
|
8
|
+
/**
|
|
9
|
+
* The NestJS module for OpenTelemetry
|
|
10
|
+
*
|
|
11
|
+
* @publicApi
|
|
12
|
+
*/
|
|
13
13
|
let OpenTelemetryModule = OpenTelemetryModule_1 = class OpenTelemetryModule {
|
|
14
|
+
/**
|
|
15
|
+
* Bootstraps the OpenTelemetry Module synchronously
|
|
16
|
+
* @param options The options for the OpenTelemetry Module
|
|
17
|
+
*/
|
|
14
18
|
static forRoot(options) {
|
|
15
19
|
return {
|
|
16
20
|
module: OpenTelemetryModule_1,
|
|
17
21
|
imports: [opentelemetry_core_module_1.OpenTelemetryCoreModule.forRoot(options)],
|
|
18
22
|
};
|
|
19
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* Bootstrap the OpenTelemetry Module asynchronously
|
|
26
|
+
* @see https://dev.to/nestjs/advanced-nestjs-how-to-build-completely-dynamic-nestjs-modules-1370
|
|
27
|
+
* @param options The options for the OpenTelemetry module
|
|
28
|
+
*/
|
|
20
29
|
static forRootAsync(options) {
|
|
21
30
|
return {
|
|
22
31
|
module: OpenTelemetryModule_1,
|
|
@@ -24,7 +33,7 @@ let OpenTelemetryModule = OpenTelemetryModule_1 = class OpenTelemetryModule {
|
|
|
24
33
|
};
|
|
25
34
|
}
|
|
26
35
|
};
|
|
27
|
-
OpenTelemetryModule =
|
|
36
|
+
exports.OpenTelemetryModule = OpenTelemetryModule;
|
|
37
|
+
exports.OpenTelemetryModule = OpenTelemetryModule = OpenTelemetryModule_1 = tslib_1.__decorate([
|
|
28
38
|
(0, common_1.Module)({})
|
|
29
39
|
], OpenTelemetryModule);
|
|
30
|
-
exports.OpenTelemetryModule = OpenTelemetryModule;
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.copyMetadataFromFunctionToFunction = void 0;
|
|
4
4
|
const copyMetadataFromFunctionToFunction = (originalFunction, newFunction) => {
|
|
5
|
+
// Get the current metadata and set onto the wrapper
|
|
6
|
+
// to ensure other decorators ( ie: NestJS EventPattern / RolesGuard )
|
|
7
|
+
// won't be affected by the use of this instrumentation
|
|
5
8
|
Reflect.getMetadataKeys(originalFunction).forEach(metadataKey => {
|
|
6
9
|
Reflect.defineMetadata(metadataKey, Reflect.getMetadata(metadataKey, originalFunction), newFunction);
|
|
7
10
|
});
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { SpanOptions } from '@opentelemetry/api';
|
|
2
|
-
export declare function Span(name?: string, options?: SpanOptions): (target: any, propertyKey:
|
|
2
|
+
export declare function Span(name?: string, options?: SpanOptions): (target: any, propertyKey: PropertyKey, propertyDescriptor: PropertyDescriptor) => void;
|
|
@@ -12,24 +12,29 @@ function Span(name, options = {}) {
|
|
|
12
12
|
const originalFunction = propertyDescriptor.value;
|
|
13
13
|
const wrappedFunction = function PropertyDescriptor(...args) {
|
|
14
14
|
const tracer = api_1.trace.getTracer('default');
|
|
15
|
-
const spanName = name || `${target.constructor.name}.${propertyKey}`;
|
|
15
|
+
const spanName = name || `${target.constructor.name}.${String(propertyKey)}`;
|
|
16
16
|
return tracer.startActiveSpan(spanName, options, span => {
|
|
17
17
|
if (originalFunction.constructor.name === 'AsyncFunction') {
|
|
18
|
-
return originalFunction
|
|
18
|
+
return (originalFunction
|
|
19
|
+
// @ts-ignore
|
|
19
20
|
.apply(this, args)
|
|
21
|
+
// @ts-ignore
|
|
20
22
|
.catch(error => {
|
|
21
23
|
recordException(span, error);
|
|
24
|
+
// Throw error to propagate it further
|
|
22
25
|
throw error;
|
|
23
26
|
})
|
|
24
27
|
.finally(() => {
|
|
25
28
|
span.end();
|
|
26
|
-
});
|
|
29
|
+
}));
|
|
27
30
|
}
|
|
28
31
|
try {
|
|
32
|
+
// @ts-ignore
|
|
29
33
|
return originalFunction.apply(this, args);
|
|
30
34
|
}
|
|
31
35
|
catch (error) {
|
|
32
36
|
recordException(span, error);
|
|
37
|
+
// Throw error to propagate it further
|
|
33
38
|
throw error;
|
|
34
39
|
}
|
|
35
40
|
finally {
|
|
@@ -1,20 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
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
|
+
var _a;
|
|
11
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
12
5
|
require("reflect-metadata");
|
|
13
6
|
const api_1 = require("@opentelemetry/api");
|
|
14
7
|
const sdk_trace_node_1 = require("@opentelemetry/sdk-trace-node");
|
|
15
8
|
const common_1 = require("@nestjs/common");
|
|
16
9
|
const span_1 = require("./span");
|
|
17
10
|
const TestDecoratorThatSetsMetadata = () => (0, common_1.SetMetadata)('some-metadata', true);
|
|
11
|
+
const symbol = Symbol('testSymbol');
|
|
18
12
|
class TestSpan {
|
|
19
13
|
singleSpan() { }
|
|
20
14
|
doubleSpan() {
|
|
@@ -25,38 +19,45 @@ class TestSpan {
|
|
|
25
19
|
throw new Error('hello world');
|
|
26
20
|
}
|
|
27
21
|
metadata() { }
|
|
22
|
+
[_a = symbol]() { }
|
|
28
23
|
}
|
|
29
|
-
__decorate([
|
|
24
|
+
tslib_1.__decorate([
|
|
30
25
|
(0, span_1.Span)(),
|
|
31
|
-
__metadata("design:type", Function),
|
|
32
|
-
__metadata("design:paramtypes", []),
|
|
33
|
-
__metadata("design:returntype", void 0)
|
|
26
|
+
tslib_1.__metadata("design:type", Function),
|
|
27
|
+
tslib_1.__metadata("design:paramtypes", []),
|
|
28
|
+
tslib_1.__metadata("design:returntype", void 0)
|
|
34
29
|
], TestSpan.prototype, "singleSpan", null);
|
|
35
|
-
__decorate([
|
|
30
|
+
tslib_1.__decorate([
|
|
36
31
|
(0, span_1.Span)(),
|
|
37
|
-
__metadata("design:type", Function),
|
|
38
|
-
__metadata("design:paramtypes", []),
|
|
39
|
-
__metadata("design:returntype", void 0)
|
|
32
|
+
tslib_1.__metadata("design:type", Function),
|
|
33
|
+
tslib_1.__metadata("design:paramtypes", []),
|
|
34
|
+
tslib_1.__metadata("design:returntype", void 0)
|
|
40
35
|
], TestSpan.prototype, "doubleSpan", null);
|
|
41
|
-
__decorate([
|
|
36
|
+
tslib_1.__decorate([
|
|
42
37
|
(0, span_1.Span)('foo', { kind: api_1.SpanKind.PRODUCER }),
|
|
43
|
-
__metadata("design:type", Function),
|
|
44
|
-
__metadata("design:paramtypes", []),
|
|
45
|
-
__metadata("design:returntype", void 0)
|
|
38
|
+
tslib_1.__metadata("design:type", Function),
|
|
39
|
+
tslib_1.__metadata("design:paramtypes", []),
|
|
40
|
+
tslib_1.__metadata("design:returntype", void 0)
|
|
46
41
|
], TestSpan.prototype, "fooProducerSpan", null);
|
|
47
|
-
__decorate([
|
|
42
|
+
tslib_1.__decorate([
|
|
48
43
|
(0, span_1.Span)(),
|
|
49
|
-
__metadata("design:type", Function),
|
|
50
|
-
__metadata("design:paramtypes", []),
|
|
51
|
-
__metadata("design:returntype", void 0)
|
|
44
|
+
tslib_1.__metadata("design:type", Function),
|
|
45
|
+
tslib_1.__metadata("design:paramtypes", []),
|
|
46
|
+
tslib_1.__metadata("design:returntype", void 0)
|
|
52
47
|
], TestSpan.prototype, "error", null);
|
|
53
|
-
__decorate([
|
|
48
|
+
tslib_1.__decorate([
|
|
54
49
|
(0, span_1.Span)(),
|
|
55
50
|
TestDecoratorThatSetsMetadata(),
|
|
56
|
-
__metadata("design:type", Function),
|
|
57
|
-
__metadata("design:paramtypes", []),
|
|
58
|
-
__metadata("design:returntype", void 0)
|
|
51
|
+
tslib_1.__metadata("design:type", Function),
|
|
52
|
+
tslib_1.__metadata("design:paramtypes", []),
|
|
53
|
+
tslib_1.__metadata("design:returntype", void 0)
|
|
59
54
|
], TestSpan.prototype, "metadata", null);
|
|
55
|
+
tslib_1.__decorate([
|
|
56
|
+
(0, span_1.Span)(),
|
|
57
|
+
tslib_1.__metadata("design:type", Function),
|
|
58
|
+
tslib_1.__metadata("design:paramtypes", []),
|
|
59
|
+
tslib_1.__metadata("design:returntype", void 0)
|
|
60
|
+
], TestSpan.prototype, _a, null);
|
|
60
61
|
describe('Span', () => {
|
|
61
62
|
let instance;
|
|
62
63
|
let traceExporter;
|
|
@@ -111,6 +112,7 @@ describe('Span', () => {
|
|
|
111
112
|
expect(instance.error).toThrowError('hello world');
|
|
112
113
|
const spans = traceExporter.getFinishedSpans();
|
|
113
114
|
expect(spans).toHaveLength(1);
|
|
115
|
+
// Contain one exception event
|
|
114
116
|
expect(spans[0].events).toHaveLength(1);
|
|
115
117
|
expect(spans[0].events[0]).toEqual({
|
|
116
118
|
name: 'exception',
|
|
@@ -119,4 +121,10 @@ describe('Span', () => {
|
|
|
119
121
|
time: expect.anything(),
|
|
120
122
|
});
|
|
121
123
|
});
|
|
124
|
+
it('should handle symbols', () => {
|
|
125
|
+
instance[symbol]();
|
|
126
|
+
const spans = traceExporter.getFinishedSpans();
|
|
127
|
+
expect(spans).toHaveLength(1);
|
|
128
|
+
expect(spans.map(span => span.name)).toEqual(['TestSpan.Symbol(testSymbol)']);
|
|
129
|
+
});
|
|
122
130
|
});
|
|
@@ -1,12 +1,7 @@
|
|
|
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
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
3
|
exports.TraceService = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
10
5
|
const api_1 = require("@opentelemetry/api");
|
|
11
6
|
const common_1 = require("@nestjs/common");
|
|
12
7
|
let TraceService = class TraceService {
|
|
@@ -20,7 +15,7 @@ let TraceService = class TraceService {
|
|
|
20
15
|
return this.getTracer().startSpan(name);
|
|
21
16
|
}
|
|
22
17
|
};
|
|
23
|
-
TraceService =
|
|
18
|
+
exports.TraceService = TraceService;
|
|
19
|
+
exports.TraceService = TraceService = tslib_1.__decorate([
|
|
24
20
|
(0, common_1.Injectable)()
|
|
25
21
|
], TraceService);
|
|
26
|
-
exports.TraceService = TraceService;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nestjs-otel",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.0",
|
|
4
4
|
"description": "NestJS OpenTelemetry Library",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"typings": "lib/index",
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
"prebuild": "rimraf lib",
|
|
9
9
|
"prepare": "husky install",
|
|
10
10
|
"build": "tsc",
|
|
11
|
-
"lint": "
|
|
12
|
-
"format": "
|
|
11
|
+
"lint": "prettier --check ./**/*.{js,json,ts}",
|
|
12
|
+
"format": "prettier --write ./**/*.{js,json,ts}",
|
|
13
13
|
"test": "npm run test:unit && npm run test:e2e",
|
|
14
14
|
"test:coverage": "jest --coverage",
|
|
15
15
|
"test:unit": "jest --passWithNoTests",
|
|
@@ -36,40 +36,36 @@
|
|
|
36
36
|
},
|
|
37
37
|
"homepage": "https://github.com/pragmaticivan/nestjs-otel#readme",
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@opentelemetry/api": "^1.
|
|
40
|
-
"@opentelemetry/host-metrics": "^0.
|
|
39
|
+
"@opentelemetry/api": "^1.8.0",
|
|
40
|
+
"@opentelemetry/host-metrics": "^0.35.1",
|
|
41
41
|
"response-time": "^2.3.2"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"@commitlint/cli": "^
|
|
45
|
-
"@commitlint/config-conventional": "^
|
|
46
|
-
"@nestjs/common": "^10.
|
|
47
|
-
"@nestjs/core": "^10.
|
|
48
|
-
"@nestjs/platform-express": "^10.
|
|
49
|
-
"@nestjs/platform-fastify": "^10.
|
|
50
|
-
"@nestjs/testing": "^10.
|
|
51
|
-
"@opentelemetry/exporter-prometheus": "^0.
|
|
52
|
-
"@opentelemetry/sdk-metrics": "^1.
|
|
53
|
-
"@opentelemetry/sdk-trace-node": "^1.
|
|
54
|
-
"@types/jest": "^29.5.
|
|
55
|
-
"@types/node": "^
|
|
56
|
-
"@types/
|
|
57
|
-
"@
|
|
58
|
-
"@typescript-eslint/parser": "5.59.0",
|
|
44
|
+
"@commitlint/cli": "^19.3.0",
|
|
45
|
+
"@commitlint/config-conventional": "^19.2.2",
|
|
46
|
+
"@nestjs/common": "^10.3.8",
|
|
47
|
+
"@nestjs/core": "^10.3.8",
|
|
48
|
+
"@nestjs/platform-express": "^10.3.8",
|
|
49
|
+
"@nestjs/platform-fastify": "^10.3.8",
|
|
50
|
+
"@nestjs/testing": "^10.3.8",
|
|
51
|
+
"@opentelemetry/exporter-prometheus": "^0.51.1",
|
|
52
|
+
"@opentelemetry/sdk-metrics": "^1.24.1",
|
|
53
|
+
"@opentelemetry/sdk-trace-node": "^1.24.1",
|
|
54
|
+
"@types/jest": "^29.5.12",
|
|
55
|
+
"@types/node": "^20.12.10",
|
|
56
|
+
"@types/response-time": "^2.3.8",
|
|
57
|
+
"@types/supertest": "^6.0.2",
|
|
59
58
|
"ansi-regex": "",
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"supertest": "^6.3.3",
|
|
71
|
-
"ts-jest": "^29.1.0",
|
|
72
|
-
"typescript": "5.0.4"
|
|
59
|
+
"husky": "^9.0.11",
|
|
60
|
+
"jest": "^29.7.0",
|
|
61
|
+
"lint-staged": "^15.2.2",
|
|
62
|
+
"prettier": "^3.2.5",
|
|
63
|
+
"reflect-metadata": "^0.2.2",
|
|
64
|
+
"rimraf": "^5.0.5",
|
|
65
|
+
"rxjs": "^7.8.1",
|
|
66
|
+
"supertest": "^7.0.0",
|
|
67
|
+
"ts-jest": "^29.1.2",
|
|
68
|
+
"typescript": "5.4.5"
|
|
73
69
|
},
|
|
74
70
|
"peerDependencies": {
|
|
75
71
|
"@nestjs/common": "^9.0.0 || ^10.0.0",
|
|
@@ -94,7 +90,9 @@
|
|
|
94
90
|
"testEnvironment": "node"
|
|
95
91
|
},
|
|
96
92
|
"lint-staged": {
|
|
97
|
-
"
|
|
93
|
+
"**/*.{js,ts,json}": [
|
|
94
|
+
"prettier --write"
|
|
95
|
+
]
|
|
98
96
|
},
|
|
99
97
|
"commitlint": {
|
|
100
98
|
"extends": [
|