@pawells/nestjs-shared 1.0.0-dev.3052c75
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/LICENSE +21 -0
- package/README.md +802 -0
- package/build/LICENSE +21 -0
- package/build/README.md +802 -0
- package/build/common/common.module.d.ts +49 -0
- package/build/common/common.module.d.ts.map +1 -0
- package/build/common/common.module.js +178 -0
- package/build/common/common.module.js.map +1 -0
- package/build/common/constants/histogram-buckets.constants.d.ts +12 -0
- package/build/common/constants/histogram-buckets.constants.d.ts.map +1 -0
- package/build/common/constants/histogram-buckets.constants.js +51 -0
- package/build/common/constants/histogram-buckets.constants.js.map +1 -0
- package/build/common/constants/http-status.constants.d.ts +27 -0
- package/build/common/constants/http-status.constants.d.ts.map +1 -0
- package/build/common/constants/http-status.constants.js +27 -0
- package/build/common/constants/http-status.constants.js.map +1 -0
- package/build/common/constants/timeout.constants.d.ts +29 -0
- package/build/common/constants/timeout.constants.d.ts.map +1 -0
- package/build/common/constants/timeout.constants.js +45 -0
- package/build/common/constants/timeout.constants.js.map +1 -0
- package/build/common/controllers/metrics.controller.d.ts +23 -0
- package/build/common/controllers/metrics.controller.d.ts.map +1 -0
- package/build/common/controllers/metrics.controller.js +66 -0
- package/build/common/controllers/metrics.controller.js.map +1 -0
- package/build/common/decorators/common-decorators.d.ts +90 -0
- package/build/common/decorators/common-decorators.d.ts.map +1 -0
- package/build/common/decorators/common-decorators.js +101 -0
- package/build/common/decorators/common-decorators.js.map +1 -0
- package/build/common/decorators/decorator-factory.d.ts +108 -0
- package/build/common/decorators/decorator-factory.d.ts.map +1 -0
- package/build/common/decorators/decorator-factory.js +104 -0
- package/build/common/decorators/decorator-factory.js.map +1 -0
- package/build/common/decorators/guard.decorators.d.ts +48 -0
- package/build/common/decorators/guard.decorators.d.ts.map +1 -0
- package/build/common/decorators/guard.decorators.js +49 -0
- package/build/common/decorators/guard.decorators.js.map +1 -0
- package/build/common/decorators/index.d.ts +10 -0
- package/build/common/decorators/index.d.ts.map +1 -0
- package/build/common/decorators/index.js +11 -0
- package/build/common/decorators/index.js.map +1 -0
- package/build/common/decorators/instrument.decorator.d.ts +128 -0
- package/build/common/decorators/instrument.decorator.d.ts.map +1 -0
- package/build/common/decorators/instrument.decorator.js +165 -0
- package/build/common/decorators/instrument.decorator.js.map +1 -0
- package/build/common/decorators/metric.decorators.d.ts +42 -0
- package/build/common/decorators/metric.decorators.d.ts.map +1 -0
- package/build/common/decorators/metric.decorators.js +85 -0
- package/build/common/decorators/metric.decorators.js.map +1 -0
- package/build/common/decorators/request-property.decorator.d.ts +65 -0
- package/build/common/decorators/request-property.decorator.d.ts.map +1 -0
- package/build/common/decorators/request-property.decorator.js +102 -0
- package/build/common/decorators/request-property.decorator.js.map +1 -0
- package/build/common/errors/base-application-error.d.ts +98 -0
- package/build/common/errors/base-application-error.d.ts.map +1 -0
- package/build/common/errors/base-application-error.js +133 -0
- package/build/common/errors/base-application-error.js.map +1 -0
- package/build/common/errors/error-factory.d.ts +93 -0
- package/build/common/errors/error-factory.d.ts.map +1 -0
- package/build/common/errors/error-factory.js +105 -0
- package/build/common/errors/error-factory.js.map +1 -0
- package/build/common/errors/index.d.ts +13 -0
- package/build/common/errors/index.d.ts.map +1 -0
- package/build/common/errors/index.js +15 -0
- package/build/common/errors/index.js.map +1 -0
- package/build/common/factories/index.d.ts +5 -0
- package/build/common/factories/index.d.ts.map +1 -0
- package/build/common/factories/index.js +3 -0
- package/build/common/factories/index.js.map +1 -0
- package/build/common/factories/module-factory.d.ts +178 -0
- package/build/common/factories/module-factory.d.ts.map +1 -0
- package/build/common/factories/module-factory.js +253 -0
- package/build/common/factories/module-factory.js.map +1 -0
- package/build/common/factories/rate-limit-config.factory.d.ts +79 -0
- package/build/common/factories/rate-limit-config.factory.d.ts.map +1 -0
- package/build/common/factories/rate-limit-config.factory.js +115 -0
- package/build/common/factories/rate-limit-config.factory.js.map +1 -0
- package/build/common/factories/security-bootstrap.factory.d.ts +77 -0
- package/build/common/factories/security-bootstrap.factory.d.ts.map +1 -0
- package/build/common/factories/security-bootstrap.factory.js +222 -0
- package/build/common/factories/security-bootstrap.factory.js.map +1 -0
- package/build/common/filters/global-exception.filter.d.ts +78 -0
- package/build/common/filters/global-exception.filter.d.ts.map +1 -0
- package/build/common/filters/global-exception.filter.js +192 -0
- package/build/common/filters/global-exception.filter.js.map +1 -0
- package/build/common/filters/http-exception.filter.d.ts +37 -0
- package/build/common/filters/http-exception.filter.d.ts.map +1 -0
- package/build/common/filters/http-exception.filter.js +91 -0
- package/build/common/filters/http-exception.filter.js.map +1 -0
- package/build/common/guards/csrf.guard.d.ts +53 -0
- package/build/common/guards/csrf.guard.d.ts.map +1 -0
- package/build/common/guards/csrf.guard.js +109 -0
- package/build/common/guards/csrf.guard.js.map +1 -0
- package/build/common/guards/metrics.guard.d.ts +42 -0
- package/build/common/guards/metrics.guard.d.ts.map +1 -0
- package/build/common/guards/metrics.guard.js +124 -0
- package/build/common/guards/metrics.guard.js.map +1 -0
- package/build/common/index.d.ts +43 -0
- package/build/common/index.d.ts.map +1 -0
- package/build/common/index.js +50 -0
- package/build/common/index.js.map +1 -0
- package/build/common/interceptors/http-client.interceptor.d.ts +11 -0
- package/build/common/interceptors/http-client.interceptor.d.ts.map +1 -0
- package/build/common/interceptors/http-client.interceptor.js +69 -0
- package/build/common/interceptors/http-client.interceptor.js.map +1 -0
- package/build/common/interceptors/http-instrumentation.interceptor.d.ts +64 -0
- package/build/common/interceptors/http-instrumentation.interceptor.d.ts.map +1 -0
- package/build/common/interceptors/http-instrumentation.interceptor.js +148 -0
- package/build/common/interceptors/http-instrumentation.interceptor.js.map +1 -0
- package/build/common/interceptors/http-metrics.interceptor.d.ts +46 -0
- package/build/common/interceptors/http-metrics.interceptor.d.ts.map +1 -0
- package/build/common/interceptors/http-metrics.interceptor.js +120 -0
- package/build/common/interceptors/http-metrics.interceptor.js.map +1 -0
- package/build/common/interceptors/logging.interceptor.d.ts +22 -0
- package/build/common/interceptors/logging.interceptor.d.ts.map +1 -0
- package/build/common/interceptors/logging.interceptor.js +67 -0
- package/build/common/interceptors/logging.interceptor.js.map +1 -0
- package/build/common/interfaces/cache-provider.interface.d.ts +54 -0
- package/build/common/interfaces/cache-provider.interface.d.ts.map +1 -0
- package/build/common/interfaces/cache-provider.interface.js +6 -0
- package/build/common/interfaces/cache-provider.interface.js.map +1 -0
- package/build/common/interfaces/index.d.ts +7 -0
- package/build/common/interfaces/index.d.ts.map +1 -0
- package/build/common/interfaces/index.js +3 -0
- package/build/common/interfaces/index.js.map +1 -0
- package/build/common/interfaces/log-context.interface.d.ts +77 -0
- package/build/common/interfaces/log-context.interface.d.ts.map +1 -0
- package/build/common/interfaces/log-context.interface.js +2 -0
- package/build/common/interfaces/log-context.interface.js.map +1 -0
- package/build/common/interfaces/log-entry.interface.d.ts +26 -0
- package/build/common/interfaces/log-entry.interface.d.ts.map +1 -0
- package/build/common/interfaces/log-entry.interface.js +33 -0
- package/build/common/interfaces/log-entry.interface.js.map +1 -0
- package/build/common/interfaces/logger.interface.d.ts +62 -0
- package/build/common/interfaces/logger.interface.d.ts.map +1 -0
- package/build/common/interfaces/logger.interface.js +2 -0
- package/build/common/interfaces/logger.interface.js.map +1 -0
- package/build/common/interfaces/metrics-exporter.interface.d.ts +275 -0
- package/build/common/interfaces/metrics-exporter.interface.d.ts.map +1 -0
- package/build/common/interfaces/metrics-exporter.interface.js +8 -0
- package/build/common/interfaces/metrics-exporter.interface.js.map +1 -0
- package/build/common/metrics/base-metrics-collector.d.ts +81 -0
- package/build/common/metrics/base-metrics-collector.d.ts.map +1 -0
- package/build/common/metrics/base-metrics-collector.js +88 -0
- package/build/common/metrics/base-metrics-collector.js.map +1 -0
- package/build/common/metrics/index.d.ts +2 -0
- package/build/common/metrics/index.d.ts.map +1 -0
- package/build/common/metrics/index.js +2 -0
- package/build/common/metrics/index.js.map +1 -0
- package/build/common/metrics.module.d.ts +50 -0
- package/build/common/metrics.module.d.ts.map +1 -0
- package/build/common/metrics.module.js +77 -0
- package/build/common/metrics.module.js.map +1 -0
- package/build/common/modules/throttler.module.d.ts +69 -0
- package/build/common/modules/throttler.module.d.ts.map +1 -0
- package/build/common/modules/throttler.module.js +117 -0
- package/build/common/modules/throttler.module.js.map +1 -0
- package/build/common/pipes/base-validation.pipe.d.ts +67 -0
- package/build/common/pipes/base-validation.pipe.d.ts.map +1 -0
- package/build/common/pipes/base-validation.pipe.js +95 -0
- package/build/common/pipes/base-validation.pipe.js.map +1 -0
- package/build/common/pipes/validation.pipe.d.ts +32 -0
- package/build/common/pipes/validation.pipe.d.ts.map +1 -0
- package/build/common/pipes/validation.pipe.js +60 -0
- package/build/common/pipes/validation.pipe.js.map +1 -0
- package/build/common/registry/instrumentation-registry.d.ts +227 -0
- package/build/common/registry/instrumentation-registry.d.ts.map +1 -0
- package/build/common/registry/instrumentation-registry.js +414 -0
- package/build/common/registry/instrumentation-registry.js.map +1 -0
- package/build/common/services/audit-logger.service.d.ts +91 -0
- package/build/common/services/audit-logger.service.d.ts.map +1 -0
- package/build/common/services/audit-logger.service.js +180 -0
- package/build/common/services/audit-logger.service.js.map +1 -0
- package/build/common/services/csrf.service.d.ts +202 -0
- package/build/common/services/csrf.service.d.ts.map +1 -0
- package/build/common/services/csrf.service.js +478 -0
- package/build/common/services/csrf.service.js.map +1 -0
- package/build/common/services/error-categorizer.service.d.ts +82 -0
- package/build/common/services/error-categorizer.service.d.ts.map +1 -0
- package/build/common/services/error-categorizer.service.js +339 -0
- package/build/common/services/error-categorizer.service.js.map +1 -0
- package/build/common/services/error-sanitizer.service.d.ts +146 -0
- package/build/common/services/error-sanitizer.service.d.ts.map +1 -0
- package/build/common/services/error-sanitizer.service.js +287 -0
- package/build/common/services/error-sanitizer.service.js.map +1 -0
- package/build/common/services/health-check.service.d.ts +86 -0
- package/build/common/services/health-check.service.d.ts.map +1 -0
- package/build/common/services/health-check.service.js +132 -0
- package/build/common/services/health-check.service.js.map +1 -0
- package/build/common/services/http-client.service.d.ts +113 -0
- package/build/common/services/http-client.service.d.ts.map +1 -0
- package/build/common/services/http-client.service.js +294 -0
- package/build/common/services/http-client.service.js.map +1 -0
- package/build/common/services/logger.service.d.ts +189 -0
- package/build/common/services/logger.service.d.ts.map +1 -0
- package/build/common/services/logger.service.js +423 -0
- package/build/common/services/logger.service.js.map +1 -0
- package/build/common/services/metrics-registry.service.d.ts +98 -0
- package/build/common/services/metrics-registry.service.d.ts.map +1 -0
- package/build/common/services/metrics-registry.service.js +262 -0
- package/build/common/services/metrics-registry.service.js.map +1 -0
- package/build/common/services/nest-logger-adapter.service.d.ts +62 -0
- package/build/common/services/nest-logger-adapter.service.d.ts.map +1 -0
- package/build/common/services/nest-logger-adapter.service.js +120 -0
- package/build/common/services/nest-logger-adapter.service.js.map +1 -0
- package/build/common/utils/error.utils.d.ts +16 -0
- package/build/common/utils/error.utils.d.ts.map +1 -0
- package/build/common/utils/error.utils.js +26 -0
- package/build/common/utils/error.utils.js.map +1 -0
- package/build/common/utils/lazy-getter.types.d.ts +190 -0
- package/build/common/utils/lazy-getter.types.d.ts.map +1 -0
- package/build/common/utils/lazy-getter.types.js +114 -0
- package/build/common/utils/lazy-getter.types.js.map +1 -0
- package/build/common/utils/module.utils.d.ts +33 -0
- package/build/common/utils/module.utils.d.ts.map +1 -0
- package/build/common/utils/module.utils.js +48 -0
- package/build/common/utils/module.utils.js.map +1 -0
- package/build/common/utils/sanitization.utils.d.ts +69 -0
- package/build/common/utils/sanitization.utils.d.ts.map +1 -0
- package/build/common/utils/sanitization.utils.js +141 -0
- package/build/common/utils/sanitization.utils.js.map +1 -0
- package/build/config/config.module.d.ts +30 -0
- package/build/config/config.module.d.ts.map +1 -0
- package/build/config/config.module.js +49 -0
- package/build/config/config.module.js.map +1 -0
- package/build/config/config.service.d.ts +74 -0
- package/build/config/config.service.d.ts.map +1 -0
- package/build/config/config.service.js +145 -0
- package/build/config/config.service.js.map +1 -0
- package/build/config/config.types.d.ts +143 -0
- package/build/config/config.types.d.ts.map +1 -0
- package/build/config/config.types.js +2 -0
- package/build/config/config.types.js.map +1 -0
- package/build/config/decorators/config.decorators.d.ts +43 -0
- package/build/config/decorators/config.decorators.d.ts.map +1 -0
- package/build/config/decorators/config.decorators.js +68 -0
- package/build/config/decorators/config.decorators.js.map +1 -0
- package/build/config/decorators/index.d.ts +2 -0
- package/build/config/decorators/index.d.ts.map +1 -0
- package/build/config/decorators/index.js +2 -0
- package/build/config/decorators/index.js.map +1 -0
- package/build/config/index.d.ts +7 -0
- package/build/config/index.d.ts.map +1 -0
- package/build/config/index.js +9 -0
- package/build/config/index.js.map +1 -0
- package/build/config/validation.utils.d.ts +136 -0
- package/build/config/validation.utils.d.ts.map +1 -0
- package/build/config/validation.utils.js +263 -0
- package/build/config/validation.utils.js.map +1 -0
- package/build/errors/index.d.ts +9 -0
- package/build/errors/index.d.ts.map +1 -0
- package/build/errors/index.js +12 -0
- package/build/errors/index.js.map +1 -0
- package/build/guards/custom-throttle.guard.d.ts +28 -0
- package/build/guards/custom-throttle.guard.d.ts.map +1 -0
- package/build/guards/custom-throttle.guard.js +52 -0
- package/build/guards/custom-throttle.guard.js.map +1 -0
- package/build/guards/index.d.ts +2 -0
- package/build/guards/index.d.ts.map +1 -0
- package/build/guards/index.js +2 -0
- package/build/guards/index.js.map +1 -0
- package/build/index.d.ts +53 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +61 -0
- package/build/index.js.map +1 -0
- package/build/logging/index.d.ts +7 -0
- package/build/logging/index.d.ts.map +1 -0
- package/build/logging/index.js +7 -0
- package/build/logging/index.js.map +1 -0
- package/build/metrics/index.d.ts +6 -0
- package/build/metrics/index.d.ts.map +1 -0
- package/build/metrics/index.js +11 -0
- package/build/metrics/index.js.map +1 -0
- package/build/package.json +72 -0
- package/build/security/index.d.ts +8 -0
- package/build/security/index.d.ts.map +1 -0
- package/build/security/index.js +11 -0
- package/build/security/index.js.map +1 -0
- package/build/test-setup.d.ts +2 -0
- package/build/test-setup.d.ts.map +1 -0
- package/build/test-setup.js +40 -0
- package/build/test-setup.js.map +1 -0
- package/build/validation/index.d.ts +6 -0
- package/build/validation/index.d.ts.map +1 -0
- package/build/validation/index.js +8 -0
- package/build/validation/index.js.map +1 -0
- package/package.json +71 -0
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { OnModuleInit } from '@nestjs/common';
|
|
2
|
+
import { ModuleRef } from '@nestjs/core';
|
|
3
|
+
import { AppLogger } from '../services/logger.service.js';
|
|
4
|
+
import type { IMetricsExporter, MetricDescriptor, MetricValue } from '../interfaces/metrics-exporter.interface.js';
|
|
5
|
+
import { LazyModuleRefService } from '../utils/lazy-getter.types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Central registry for metrics collection and export
|
|
8
|
+
*
|
|
9
|
+
* Stores metric descriptors and recorded values, manages event-based and pull-based
|
|
10
|
+
* exporters, and provides both push (event) and pull (query) patterns for metric access.
|
|
11
|
+
*
|
|
12
|
+
* @injectable
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* // Register a metric descriptor
|
|
17
|
+
* registry.registerDescriptor({
|
|
18
|
+
* name: 'http_request_duration_seconds',
|
|
19
|
+
* type: 'histogram',
|
|
20
|
+
* help: 'Request duration in seconds',
|
|
21
|
+
* labelNames: ['method', 'route', 'status_code'],
|
|
22
|
+
* buckets: [0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1],
|
|
23
|
+
* unit: 'seconds',
|
|
24
|
+
* });
|
|
25
|
+
*
|
|
26
|
+
* // Record a metric value
|
|
27
|
+
* registry.recordMetric('http_request_duration_seconds', 0.125, {
|
|
28
|
+
* method: 'GET',
|
|
29
|
+
* route: '/api/users',
|
|
30
|
+
* status_code: '200',
|
|
31
|
+
* });
|
|
32
|
+
*
|
|
33
|
+
* // Subscribe to metric events
|
|
34
|
+
* const unsubscribe = registry.on('http_request_duration_seconds', (value) => {
|
|
35
|
+
* console.log('Recorded:', value);
|
|
36
|
+
* });
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export declare class InstrumentationRegistry implements OnModuleInit, LazyModuleRefService {
|
|
40
|
+
/**
|
|
41
|
+
* Maximum number of metric values to store per metric.
|
|
42
|
+
* Prevents unbounded memory growth when recording values continuously.
|
|
43
|
+
* Older values are discarded in a rolling window approach.
|
|
44
|
+
*/
|
|
45
|
+
private static readonly MAX_VALUES_PER_METRIC;
|
|
46
|
+
/**
|
|
47
|
+
* Map of metric descriptors by name
|
|
48
|
+
* @private
|
|
49
|
+
*/
|
|
50
|
+
private readonly descriptors;
|
|
51
|
+
/**
|
|
52
|
+
* Map of recorded metric values by metric name
|
|
53
|
+
* @private
|
|
54
|
+
*/
|
|
55
|
+
private readonly values;
|
|
56
|
+
/**
|
|
57
|
+
* List of registered exporters
|
|
58
|
+
* @private
|
|
59
|
+
*/
|
|
60
|
+
private readonly exporters;
|
|
61
|
+
/**
|
|
62
|
+
* Map of event listeners by metric name
|
|
63
|
+
* @private
|
|
64
|
+
*/
|
|
65
|
+
private readonly listeners;
|
|
66
|
+
/**
|
|
67
|
+
* Lazy-loaded contextual logger
|
|
68
|
+
* @private
|
|
69
|
+
*/
|
|
70
|
+
private _logger;
|
|
71
|
+
/**
|
|
72
|
+
* Getter for contextual logger (lazy initialization)
|
|
73
|
+
* @private
|
|
74
|
+
*/
|
|
75
|
+
private get logger();
|
|
76
|
+
readonly Module: ModuleRef;
|
|
77
|
+
constructor(module: ModuleRef);
|
|
78
|
+
get AppLogger(): AppLogger;
|
|
79
|
+
onModuleInit(): void;
|
|
80
|
+
/**
|
|
81
|
+
* Register standard HTTP metrics that are always available
|
|
82
|
+
* @private
|
|
83
|
+
*/
|
|
84
|
+
private registerHttpMetrics;
|
|
85
|
+
/**
|
|
86
|
+
* Register a metric descriptor
|
|
87
|
+
*
|
|
88
|
+
* Registers a metric descriptor once during initialization. Throws an error if the
|
|
89
|
+
* descriptor name already exists with a different configuration. Idempotent when
|
|
90
|
+
* called with the exact same descriptor.
|
|
91
|
+
*
|
|
92
|
+
* @param descriptor - The metric descriptor to register
|
|
93
|
+
* @throws Error if metric name already registered with different configuration
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```typescript
|
|
97
|
+
* registry.registerDescriptor({
|
|
98
|
+
* name: 'custom_metric_seconds',
|
|
99
|
+
* type: 'histogram',
|
|
100
|
+
* help: 'Custom metric',
|
|
101
|
+
* labelNames: ['service'],
|
|
102
|
+
* buckets: [0.1, 0.5, 1],
|
|
103
|
+
* });
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
registerDescriptor(descriptor: MetricDescriptor): void;
|
|
107
|
+
/**
|
|
108
|
+
* Check if two metric descriptors are equal
|
|
109
|
+
* @private
|
|
110
|
+
*/
|
|
111
|
+
private descriptorsAreEqual;
|
|
112
|
+
/**
|
|
113
|
+
* Record a metric value
|
|
114
|
+
*
|
|
115
|
+
* Records a metric value with the given name, numeric value, and optional labels.
|
|
116
|
+
* Timestamp is automatically set to `performance.now()`. Emits to all event-based
|
|
117
|
+
* exporters and to named listeners.
|
|
118
|
+
*
|
|
119
|
+
* @param name - The metric name (must be registered via registerDescriptor)
|
|
120
|
+
* @param value - The numeric value to record
|
|
121
|
+
* @param labels - Optional label/tag values for the metric
|
|
122
|
+
* @throws Error if metric descriptor is not registered
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```typescript
|
|
126
|
+
* registry.recordMetric('http_request_duration_seconds', 0.025, {
|
|
127
|
+
* method: 'POST',
|
|
128
|
+
* route: '/api/create',
|
|
129
|
+
* status_code: '201',
|
|
130
|
+
* });
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
133
|
+
recordMetric(name: string, value: number, labels?: Record<string, string | number>): void;
|
|
134
|
+
/**
|
|
135
|
+
* Get all recorded metric values
|
|
136
|
+
*
|
|
137
|
+
* Returns a copy of all currently recorded metric values across all metrics.
|
|
138
|
+
* The returned map is a shallow copy — mutation of the returned map does not affect
|
|
139
|
+
* internal state, but arrays within it should not be mutated.
|
|
140
|
+
*
|
|
141
|
+
* @returns Map of metric name to array of recorded values
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* ```typescript
|
|
145
|
+
* const allMetrics = registry.getAllMetrics();
|
|
146
|
+
* for (const [name, values] of allMetrics.entries()) {
|
|
147
|
+
* console.log(`${name}: ${values.length} values recorded`);
|
|
148
|
+
* }
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
getAllMetrics(): Map<string, MetricValue[]>;
|
|
152
|
+
/**
|
|
153
|
+
* Get recorded values for a single metric by name
|
|
154
|
+
*
|
|
155
|
+
* @param name - The metric name
|
|
156
|
+
* @returns Array of recorded values for the metric
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```typescript
|
|
160
|
+
* const values = registry.getMetric('http_request_duration_seconds');
|
|
161
|
+
* console.log(`Recorded ${values.length} request duration measurements`);
|
|
162
|
+
* ```
|
|
163
|
+
*/
|
|
164
|
+
getMetric(name: string): MetricValue[];
|
|
165
|
+
/**
|
|
166
|
+
* Subscribe to a specific metric by name
|
|
167
|
+
*
|
|
168
|
+
* Registers a listener for a specific metric name. The listener is called synchronously
|
|
169
|
+
* each time a value is recorded for that metric. Returns an unsubscribe function that
|
|
170
|
+
* can be called to remove the listener.
|
|
171
|
+
*
|
|
172
|
+
* @param metricName - The metric name to listen to
|
|
173
|
+
* @param handler - Callback function called with each recorded metric value
|
|
174
|
+
* @returns Unsubscribe function to remove the listener
|
|
175
|
+
*
|
|
176
|
+
* @example
|
|
177
|
+
* ```typescript
|
|
178
|
+
* const unsubscribe = registry.on('http_request_duration_seconds', (value) => {
|
|
179
|
+
* console.log('Request duration recorded:', value.value, value.labels);
|
|
180
|
+
* });
|
|
181
|
+
*
|
|
182
|
+
* // Later, unsubscribe if needed
|
|
183
|
+
* unsubscribe();
|
|
184
|
+
* ```
|
|
185
|
+
*/
|
|
186
|
+
on(metricName: string, handler: (value: MetricValue) => void): () => void;
|
|
187
|
+
/**
|
|
188
|
+
* Register a metrics exporter
|
|
189
|
+
*
|
|
190
|
+
* Registers an exporter (e.g., Prometheus, OpenTelemetry) with the registry.
|
|
191
|
+
* If the exporter supports event-based notifications, it will receive calls to
|
|
192
|
+
* `onMetricRecorded` for each metric recorded after registration.
|
|
193
|
+
*
|
|
194
|
+
* The exporter's `onDescriptorRegistered` method is called immediately for all
|
|
195
|
+
* already-registered descriptors, allowing the exporter to initialize instruments.
|
|
196
|
+
*
|
|
197
|
+
* @param exporter - The metrics exporter to register
|
|
198
|
+
*
|
|
199
|
+
* @example
|
|
200
|
+
* ```typescript
|
|
201
|
+
* const prometheusExporter = new PrometheusExporter(registry);
|
|
202
|
+
* registry.registerExporter(prometheusExporter);
|
|
203
|
+
*
|
|
204
|
+
* const otExporter = new OpenTelemetryExporter();
|
|
205
|
+
* registry.registerExporter(otExporter);
|
|
206
|
+
* ```
|
|
207
|
+
*/
|
|
208
|
+
registerExporter(exporter: IMetricsExporter): void;
|
|
209
|
+
/**
|
|
210
|
+
* Shutdown the registry and all registered exporters
|
|
211
|
+
*
|
|
212
|
+
* Called during application shutdown. Calls the `shutdown()` method on all
|
|
213
|
+
* registered exporters to allow them to flush buffered metrics, close connections,
|
|
214
|
+
* and clean up resources.
|
|
215
|
+
*
|
|
216
|
+
* @returns Promise that resolves when all exporters have been shut down
|
|
217
|
+
*
|
|
218
|
+
* @example
|
|
219
|
+
* ```typescript
|
|
220
|
+
* app.onModuleDestroy(async () => {
|
|
221
|
+
* await registry.shutdown();
|
|
222
|
+
* });
|
|
223
|
+
* ```
|
|
224
|
+
*/
|
|
225
|
+
shutdown(): Promise<void>;
|
|
226
|
+
}
|
|
227
|
+
//# sourceMappingURL=instrumentation-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instrumentation-registry.d.ts","sourceRoot":"","sources":["../../../src/common/registry/instrumentation-registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAE1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,6CAA6C,CAAC;AACnH,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAGrE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,qBACa,uBAAwB,YAAW,YAAY,EAAE,oBAAoB;IACjF;;;;OAIG;IAEH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,qBAAqB,CAAQ;IAErD;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAuC;IAEnE;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoC;IAE3D;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA0B;IAEpD;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA0D;IAEpF;;;OAGG;IACH,OAAO,CAAC,OAAO,CAAgC;IAE/C;;;OAGG;IACH,OAAO,KAAK,MAAM,GAGjB;IAED,SAAgB,MAAM,EAAE,SAAS,CAAC;gBAEtB,MAAM,EAAE,SAAS;IAI7B,IAAW,SAAS,IAAI,SAAS,CAEhC;IAEM,YAAY,IAAI,IAAI;IAI3B;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IA6B3B;;;;;;;;;;;;;;;;;;;;OAoBG;IACI,kBAAkB,CAAC,UAAU,EAAE,gBAAgB,GAAG,IAAI;IAoC7D;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAW3B;;;;;;;;;;;;;;;;;;;;OAoBG;IACI,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,GAAG,IAAI;IAsDhG;;;;;;;;;;;;;;;;OAgBG;IACI,aAAa,IAAI,GAAG,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC;IAIlD;;;;;;;;;;;OAWG;IACI,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,EAAE;IAI7C;;;;;;;;;;;;;;;;;;;;OAoBG;IACI,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,GAAG,MAAM,IAAI;IAchF;;;;;;;;;;;;;;;;;;;;OAoBG;IACI,gBAAgB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,IAAI;IAmBzD;;;;;;;;;;;;;;;OAeG;IACU,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAmBtC"}
|
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
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;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
var InstrumentationRegistry_1;
|
|
11
|
+
import { Injectable } from '@nestjs/common';
|
|
12
|
+
import { ModuleRef } from '@nestjs/core';
|
|
13
|
+
import { performance } from 'node:perf_hooks';
|
|
14
|
+
import { AppLogger } from '../services/logger.service.js';
|
|
15
|
+
import { getErrorMessage } from '../utils/error.utils.js';
|
|
16
|
+
/**
|
|
17
|
+
* Central registry for metrics collection and export
|
|
18
|
+
*
|
|
19
|
+
* Stores metric descriptors and recorded values, manages event-based and pull-based
|
|
20
|
+
* exporters, and provides both push (event) and pull (query) patterns for metric access.
|
|
21
|
+
*
|
|
22
|
+
* @injectable
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* // Register a metric descriptor
|
|
27
|
+
* registry.registerDescriptor({
|
|
28
|
+
* name: 'http_request_duration_seconds',
|
|
29
|
+
* type: 'histogram',
|
|
30
|
+
* help: 'Request duration in seconds',
|
|
31
|
+
* labelNames: ['method', 'route', 'status_code'],
|
|
32
|
+
* buckets: [0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1],
|
|
33
|
+
* unit: 'seconds',
|
|
34
|
+
* });
|
|
35
|
+
*
|
|
36
|
+
* // Record a metric value
|
|
37
|
+
* registry.recordMetric('http_request_duration_seconds', 0.125, {
|
|
38
|
+
* method: 'GET',
|
|
39
|
+
* route: '/api/users',
|
|
40
|
+
* status_code: '200',
|
|
41
|
+
* });
|
|
42
|
+
*
|
|
43
|
+
* // Subscribe to metric events
|
|
44
|
+
* const unsubscribe = registry.on('http_request_duration_seconds', (value) => {
|
|
45
|
+
* console.log('Recorded:', value);
|
|
46
|
+
* });
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
let InstrumentationRegistry = class InstrumentationRegistry {
|
|
50
|
+
static { InstrumentationRegistry_1 = this; }
|
|
51
|
+
/**
|
|
52
|
+
* Maximum number of metric values to store per metric.
|
|
53
|
+
* Prevents unbounded memory growth when recording values continuously.
|
|
54
|
+
* Older values are discarded in a rolling window approach.
|
|
55
|
+
*/
|
|
56
|
+
// eslint-disable-next-line no-magic-numbers
|
|
57
|
+
static MAX_VALUES_PER_METRIC = 1000;
|
|
58
|
+
/**
|
|
59
|
+
* Map of metric descriptors by name
|
|
60
|
+
* @private
|
|
61
|
+
*/
|
|
62
|
+
descriptors = new Map();
|
|
63
|
+
/**
|
|
64
|
+
* Map of recorded metric values by metric name
|
|
65
|
+
* @private
|
|
66
|
+
*/
|
|
67
|
+
values = new Map();
|
|
68
|
+
/**
|
|
69
|
+
* List of registered exporters
|
|
70
|
+
* @private
|
|
71
|
+
*/
|
|
72
|
+
exporters = [];
|
|
73
|
+
/**
|
|
74
|
+
* Map of event listeners by metric name
|
|
75
|
+
* @private
|
|
76
|
+
*/
|
|
77
|
+
listeners = new Map();
|
|
78
|
+
/**
|
|
79
|
+
* Lazy-loaded contextual logger
|
|
80
|
+
* @private
|
|
81
|
+
*/
|
|
82
|
+
_logger;
|
|
83
|
+
/**
|
|
84
|
+
* Getter for contextual logger (lazy initialization)
|
|
85
|
+
* @private
|
|
86
|
+
*/
|
|
87
|
+
get logger() {
|
|
88
|
+
this._logger ??= this.AppLogger.createContextualLogger(InstrumentationRegistry_1.name);
|
|
89
|
+
return this._logger;
|
|
90
|
+
}
|
|
91
|
+
Module;
|
|
92
|
+
constructor(module) {
|
|
93
|
+
this.Module = module;
|
|
94
|
+
}
|
|
95
|
+
get AppLogger() {
|
|
96
|
+
return this.Module.get(AppLogger);
|
|
97
|
+
}
|
|
98
|
+
onModuleInit() {
|
|
99
|
+
this.registerHttpMetrics();
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Register standard HTTP metrics that are always available
|
|
103
|
+
* @private
|
|
104
|
+
*/
|
|
105
|
+
registerHttpMetrics() {
|
|
106
|
+
this.registerDescriptor({
|
|
107
|
+
name: 'http_request_duration_seconds',
|
|
108
|
+
type: 'histogram',
|
|
109
|
+
help: 'Duration of HTTP requests in seconds',
|
|
110
|
+
labelNames: ['method', 'route', 'status_code'],
|
|
111
|
+
// eslint-disable-next-line no-magic-numbers
|
|
112
|
+
buckets: [0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1, 2.5, 5, 10],
|
|
113
|
+
unit: 'seconds',
|
|
114
|
+
});
|
|
115
|
+
this.registerDescriptor({
|
|
116
|
+
name: 'http_requests_total',
|
|
117
|
+
type: 'counter',
|
|
118
|
+
help: 'Total number of HTTP requests',
|
|
119
|
+
labelNames: ['method', 'route', 'status_code'],
|
|
120
|
+
});
|
|
121
|
+
this.registerDescriptor({
|
|
122
|
+
name: 'http_request_size_bytes',
|
|
123
|
+
type: 'histogram',
|
|
124
|
+
help: 'Size of HTTP request bodies in bytes',
|
|
125
|
+
labelNames: ['method', 'route'],
|
|
126
|
+
// eslint-disable-next-line no-magic-numbers
|
|
127
|
+
buckets: [100, 1000, 10000, 100000, 1000000],
|
|
128
|
+
unit: 'bytes',
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Register a metric descriptor
|
|
133
|
+
*
|
|
134
|
+
* Registers a metric descriptor once during initialization. Throws an error if the
|
|
135
|
+
* descriptor name already exists with a different configuration. Idempotent when
|
|
136
|
+
* called with the exact same descriptor.
|
|
137
|
+
*
|
|
138
|
+
* @param descriptor - The metric descriptor to register
|
|
139
|
+
* @throws Error if metric name already registered with different configuration
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* ```typescript
|
|
143
|
+
* registry.registerDescriptor({
|
|
144
|
+
* name: 'custom_metric_seconds',
|
|
145
|
+
* type: 'histogram',
|
|
146
|
+
* help: 'Custom metric',
|
|
147
|
+
* labelNames: ['service'],
|
|
148
|
+
* buckets: [0.1, 0.5, 1],
|
|
149
|
+
* });
|
|
150
|
+
* ```
|
|
151
|
+
*/
|
|
152
|
+
registerDescriptor(descriptor) {
|
|
153
|
+
const existing = this.descriptors.get(descriptor.name);
|
|
154
|
+
if (existing) {
|
|
155
|
+
// Check if descriptors are identical
|
|
156
|
+
if (this.descriptorsAreEqual(existing, descriptor)) {
|
|
157
|
+
// Idempotent: same descriptor already registered
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
// Conflict: different descriptor with same name
|
|
161
|
+
throw new Error(`Metric descriptor conflict: descriptor with name "${descriptor.name}" is already registered with different configuration`);
|
|
162
|
+
}
|
|
163
|
+
// Register new descriptor
|
|
164
|
+
this.descriptors.set(descriptor.name, descriptor);
|
|
165
|
+
this.values.set(descriptor.name, []);
|
|
166
|
+
// Notify all registered exporters
|
|
167
|
+
for (const exporter of this.exporters) {
|
|
168
|
+
try {
|
|
169
|
+
if (exporter.onDescriptorRegistered) {
|
|
170
|
+
exporter.onDescriptorRegistered(descriptor);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
this.logger.error('Error notifying exporter of descriptor registration', 'InstrumentationRegistry', {
|
|
175
|
+
exporterIndex: this.exporters.indexOf(exporter),
|
|
176
|
+
metricName: descriptor.name,
|
|
177
|
+
error: getErrorMessage(error),
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Check if two metric descriptors are equal
|
|
184
|
+
* @private
|
|
185
|
+
*/
|
|
186
|
+
descriptorsAreEqual(a, b) {
|
|
187
|
+
return (a.name === b.name &&
|
|
188
|
+
a.type === b.type &&
|
|
189
|
+
a.help === b.help &&
|
|
190
|
+
JSON.stringify(a.labelNames) === JSON.stringify(b.labelNames) &&
|
|
191
|
+
JSON.stringify(a.buckets) === JSON.stringify(b.buckets) &&
|
|
192
|
+
a.unit === b.unit);
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Record a metric value
|
|
196
|
+
*
|
|
197
|
+
* Records a metric value with the given name, numeric value, and optional labels.
|
|
198
|
+
* Timestamp is automatically set to `performance.now()`. Emits to all event-based
|
|
199
|
+
* exporters and to named listeners.
|
|
200
|
+
*
|
|
201
|
+
* @param name - The metric name (must be registered via registerDescriptor)
|
|
202
|
+
* @param value - The numeric value to record
|
|
203
|
+
* @param labels - Optional label/tag values for the metric
|
|
204
|
+
* @throws Error if metric descriptor is not registered
|
|
205
|
+
*
|
|
206
|
+
* @example
|
|
207
|
+
* ```typescript
|
|
208
|
+
* registry.recordMetric('http_request_duration_seconds', 0.025, {
|
|
209
|
+
* method: 'POST',
|
|
210
|
+
* route: '/api/create',
|
|
211
|
+
* status_code: '201',
|
|
212
|
+
* });
|
|
213
|
+
* ```
|
|
214
|
+
*/
|
|
215
|
+
recordMetric(name, value, labels) {
|
|
216
|
+
const descriptor = this.descriptors.get(name);
|
|
217
|
+
if (!descriptor) {
|
|
218
|
+
throw new Error(`Metric descriptor not found: "${name}". Register the descriptor first using registerDescriptor().`);
|
|
219
|
+
}
|
|
220
|
+
const metricValue = {
|
|
221
|
+
descriptor,
|
|
222
|
+
value,
|
|
223
|
+
labels: labels ?? {},
|
|
224
|
+
timestamp: performance.now(),
|
|
225
|
+
};
|
|
226
|
+
// Store in-memory values with rolling window
|
|
227
|
+
const valuesArray = this.values.get(name);
|
|
228
|
+
if (valuesArray) {
|
|
229
|
+
valuesArray.push(metricValue);
|
|
230
|
+
// Enforce rolling window: discard oldest values if we exceed the limit
|
|
231
|
+
if (valuesArray.length > InstrumentationRegistry_1.MAX_VALUES_PER_METRIC) {
|
|
232
|
+
valuesArray.shift();
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
// Notify event-based exporters
|
|
236
|
+
for (const exporter of this.exporters) {
|
|
237
|
+
try {
|
|
238
|
+
if (exporter.supportsEventBased && exporter.onMetricRecorded) {
|
|
239
|
+
exporter.onMetricRecorded(metricValue);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
catch (error) {
|
|
243
|
+
this.logger.error('Error in event-based exporter onMetricRecorded', 'InstrumentationRegistry', {
|
|
244
|
+
exporterIndex: this.exporters.indexOf(exporter),
|
|
245
|
+
metricName: name,
|
|
246
|
+
error: getErrorMessage(error),
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
// Notify named listeners
|
|
251
|
+
const namedListeners = this.listeners.get(name);
|
|
252
|
+
if (namedListeners) {
|
|
253
|
+
for (const handler of namedListeners) {
|
|
254
|
+
try {
|
|
255
|
+
handler(metricValue);
|
|
256
|
+
}
|
|
257
|
+
catch (error) {
|
|
258
|
+
this.logger.error('Error in metric listener', 'InstrumentationRegistry', {
|
|
259
|
+
metricName: name,
|
|
260
|
+
error: getErrorMessage(error),
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Get all recorded metric values
|
|
268
|
+
*
|
|
269
|
+
* Returns a copy of all currently recorded metric values across all metrics.
|
|
270
|
+
* The returned map is a shallow copy — mutation of the returned map does not affect
|
|
271
|
+
* internal state, but arrays within it should not be mutated.
|
|
272
|
+
*
|
|
273
|
+
* @returns Map of metric name to array of recorded values
|
|
274
|
+
*
|
|
275
|
+
* @example
|
|
276
|
+
* ```typescript
|
|
277
|
+
* const allMetrics = registry.getAllMetrics();
|
|
278
|
+
* for (const [name, values] of allMetrics.entries()) {
|
|
279
|
+
* console.log(`${name}: ${values.length} values recorded`);
|
|
280
|
+
* }
|
|
281
|
+
* ```
|
|
282
|
+
*/
|
|
283
|
+
getAllMetrics() {
|
|
284
|
+
return new Map(this.values);
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Get recorded values for a single metric by name
|
|
288
|
+
*
|
|
289
|
+
* @param name - The metric name
|
|
290
|
+
* @returns Array of recorded values for the metric
|
|
291
|
+
*
|
|
292
|
+
* @example
|
|
293
|
+
* ```typescript
|
|
294
|
+
* const values = registry.getMetric('http_request_duration_seconds');
|
|
295
|
+
* console.log(`Recorded ${values.length} request duration measurements`);
|
|
296
|
+
* ```
|
|
297
|
+
*/
|
|
298
|
+
getMetric(name) {
|
|
299
|
+
return this.values.get(name) ?? [];
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Subscribe to a specific metric by name
|
|
303
|
+
*
|
|
304
|
+
* Registers a listener for a specific metric name. The listener is called synchronously
|
|
305
|
+
* each time a value is recorded for that metric. Returns an unsubscribe function that
|
|
306
|
+
* can be called to remove the listener.
|
|
307
|
+
*
|
|
308
|
+
* @param metricName - The metric name to listen to
|
|
309
|
+
* @param handler - Callback function called with each recorded metric value
|
|
310
|
+
* @returns Unsubscribe function to remove the listener
|
|
311
|
+
*
|
|
312
|
+
* @example
|
|
313
|
+
* ```typescript
|
|
314
|
+
* const unsubscribe = registry.on('http_request_duration_seconds', (value) => {
|
|
315
|
+
* console.log('Request duration recorded:', value.value, value.labels);
|
|
316
|
+
* });
|
|
317
|
+
*
|
|
318
|
+
* // Later, unsubscribe if needed
|
|
319
|
+
* unsubscribe();
|
|
320
|
+
* ```
|
|
321
|
+
*/
|
|
322
|
+
on(metricName, handler) {
|
|
323
|
+
const handlers = this.listeners.get(metricName) ?? [];
|
|
324
|
+
handlers.push(handler);
|
|
325
|
+
this.listeners.set(metricName, handlers);
|
|
326
|
+
// Return unsubscribe function
|
|
327
|
+
return () => {
|
|
328
|
+
const idx = handlers.indexOf(handler);
|
|
329
|
+
if (idx >= 0) {
|
|
330
|
+
handlers.splice(idx, 1);
|
|
331
|
+
}
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Register a metrics exporter
|
|
336
|
+
*
|
|
337
|
+
* Registers an exporter (e.g., Prometheus, OpenTelemetry) with the registry.
|
|
338
|
+
* If the exporter supports event-based notifications, it will receive calls to
|
|
339
|
+
* `onMetricRecorded` for each metric recorded after registration.
|
|
340
|
+
*
|
|
341
|
+
* The exporter's `onDescriptorRegistered` method is called immediately for all
|
|
342
|
+
* already-registered descriptors, allowing the exporter to initialize instruments.
|
|
343
|
+
*
|
|
344
|
+
* @param exporter - The metrics exporter to register
|
|
345
|
+
*
|
|
346
|
+
* @example
|
|
347
|
+
* ```typescript
|
|
348
|
+
* const prometheusExporter = new PrometheusExporter(registry);
|
|
349
|
+
* registry.registerExporter(prometheusExporter);
|
|
350
|
+
*
|
|
351
|
+
* const otExporter = new OpenTelemetryExporter();
|
|
352
|
+
* registry.registerExporter(otExporter);
|
|
353
|
+
* ```
|
|
354
|
+
*/
|
|
355
|
+
registerExporter(exporter) {
|
|
356
|
+
this.exporters.push(exporter);
|
|
357
|
+
// Call onDescriptorRegistered for all existing descriptors
|
|
358
|
+
for (const descriptor of this.descriptors.values()) {
|
|
359
|
+
try {
|
|
360
|
+
if (exporter.onDescriptorRegistered) {
|
|
361
|
+
exporter.onDescriptorRegistered(descriptor);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
catch (error) {
|
|
365
|
+
this.logger.error('Error notifying exporter during registration', 'InstrumentationRegistry', {
|
|
366
|
+
exporterIndex: this.exporters.length - 1,
|
|
367
|
+
metricName: descriptor.name,
|
|
368
|
+
error: getErrorMessage(error),
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Shutdown the registry and all registered exporters
|
|
375
|
+
*
|
|
376
|
+
* Called during application shutdown. Calls the `shutdown()` method on all
|
|
377
|
+
* registered exporters to allow them to flush buffered metrics, close connections,
|
|
378
|
+
* and clean up resources.
|
|
379
|
+
*
|
|
380
|
+
* @returns Promise that resolves when all exporters have been shut down
|
|
381
|
+
*
|
|
382
|
+
* @example
|
|
383
|
+
* ```typescript
|
|
384
|
+
* app.onModuleDestroy(async () => {
|
|
385
|
+
* await registry.shutdown();
|
|
386
|
+
* });
|
|
387
|
+
* ```
|
|
388
|
+
*/
|
|
389
|
+
async shutdown() {
|
|
390
|
+
const shutdownPromises = this.exporters
|
|
391
|
+
.map((exporter) => {
|
|
392
|
+
try {
|
|
393
|
+
const result = exporter.shutdown?.();
|
|
394
|
+
if (result instanceof Promise) {
|
|
395
|
+
return result;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
catch (error) {
|
|
399
|
+
this.logger.error('Error during exporter shutdown', 'InstrumentationRegistry', {
|
|
400
|
+
exporterIndex: this.exporters.indexOf(exporter),
|
|
401
|
+
error: getErrorMessage(error),
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
return Promise.resolve();
|
|
405
|
+
});
|
|
406
|
+
await Promise.all(shutdownPromises);
|
|
407
|
+
}
|
|
408
|
+
};
|
|
409
|
+
InstrumentationRegistry = InstrumentationRegistry_1 = __decorate([
|
|
410
|
+
Injectable(),
|
|
411
|
+
__metadata("design:paramtypes", [ModuleRef])
|
|
412
|
+
], InstrumentationRegistry);
|
|
413
|
+
export { InstrumentationRegistry };
|
|
414
|
+
//# sourceMappingURL=instrumentation-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instrumentation-registry.js","sourceRoot":"","sources":["../../../src/common/registry/instrumentation-registry.ts"],"names":[],"mappings":"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"}
|