@nestjs-redisx/metrics 1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 NestJS RedisX Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,46 @@
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/nestjs-redisx/nestjs-redisx/main/website/public/images/logo.png" alt="NestJS RedisX" />
3
+ </p>
4
+
5
+ # @nestjs-redisx/metrics
6
+
7
+ [![npm](https://img.shields.io/npm/v/@nestjs-redisx/metrics)](https://www.npmjs.com/package/@nestjs-redisx/metrics)
8
+ [![npm downloads](https://img.shields.io/npm/dm/@nestjs-redisx/metrics)](https://www.npmjs.com/package/@nestjs-redisx/metrics)
9
+ [![license](https://img.shields.io/npm/l/@nestjs-redisx/metrics)](https://opensource.org/licenses/MIT)
10
+
11
+ Prometheus metrics plugin for NestJS RedisX. Exposes Redis command latencies, connection pool stats, cache hit rates, and custom metrics via a `/metrics` endpoint. `prom-client` is bundled.
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install @nestjs-redisx/core @nestjs-redisx/metrics ioredis
17
+ ```
18
+
19
+ ## Quick Example
20
+
21
+ ```typescript
22
+ import { RedisModule } from '@nestjs-redisx/core';
23
+ import { MetricsPlugin } from '@nestjs-redisx/metrics';
24
+
25
+ @Module({
26
+ imports: [
27
+ RedisModule.forRoot({
28
+ clients: { host: 'localhost', port: 6379 },
29
+ plugins: [
30
+ new MetricsPlugin({ prefix: 'redisx_', exposeEndpoint: true }),
31
+ ],
32
+ }),
33
+ ],
34
+ })
35
+ export class AppModule {}
36
+
37
+ // Scrape: curl http://localhost:3000/metrics
38
+ ```
39
+
40
+ ## Documentation
41
+
42
+ Full documentation: [nestjs-redisx.dev/en/reference/metrics/](https://nestjs-redisx.dev/en/reference/metrics/)
43
+
44
+ ## License
45
+
46
+ MIT
@@ -0,0 +1,8 @@
1
+ export { MetricsPlugin } from './metrics.plugin';
2
+ export { MetricsService } from './metrics/application/services/metrics.service';
3
+ export type { IMetricsService } from './metrics/application/ports';
4
+ export { MetricsController } from './metrics/api/controllers/metrics.controller';
5
+ export type { IMetricsPluginOptions, IMetricsJson } from './shared/types';
6
+ export { MetricsError, MetricRegistrationError } from './shared/errors';
7
+ export { METRICS_PLUGIN_OPTIONS, METRICS_SERVICE, METRICS_REGISTRY } from './shared/constants';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGjD,OAAO,EAAE,cAAc,EAAE,MAAM,gDAAgD,CAAC;AAGhF,YAAY,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAGnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,8CAA8C,CAAC;AAGjF,YAAY,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAG1E,OAAO,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAGxE,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,352 @@
1
+ 'use strict';
2
+
3
+ var common = require('@nestjs/common');
4
+ var promClient = require('prom-client');
5
+ var core = require('@nestjs-redisx/core');
6
+
7
+ function _interopNamespace(e) {
8
+ if (e && e.__esModule) return e;
9
+ var n = Object.create(null);
10
+ if (e) {
11
+ Object.keys(e).forEach(function (k) {
12
+ if (k !== 'default') {
13
+ var d = Object.getOwnPropertyDescriptor(e, k);
14
+ Object.defineProperty(n, k, d.get ? d : {
15
+ enumerable: true,
16
+ get: function () { return e[k]; }
17
+ });
18
+ }
19
+ });
20
+ }
21
+ n.default = e;
22
+ return Object.freeze(n);
23
+ }
24
+
25
+ var promClient__namespace = /*#__PURE__*/_interopNamespace(promClient);
26
+
27
+ var __defProp = Object.defineProperty;
28
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
29
+ var __decorateClass = (decorators, target, key, kind) => {
30
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
31
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
32
+ if (decorator = decorators[i])
33
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
34
+ if (kind && result) __defProp(target, key, result);
35
+ return result;
36
+ };
37
+ var __decorateParam = (index, decorator) => (target, key) => decorator(target, key, index);
38
+
39
+ // src/shared/constants/index.ts
40
+ var METRICS_PLUGIN_OPTIONS = /* @__PURE__ */ Symbol.for("METRICS_PLUGIN_OPTIONS");
41
+ var METRICS_SERVICE = /* @__PURE__ */ Symbol.for("METRICS_SERVICE");
42
+ var METRICS_REGISTRY = /* @__PURE__ */ Symbol.for("METRICS_REGISTRY");
43
+ var MetricsError = class extends core.RedisXError {
44
+ constructor(message, cause) {
45
+ super(message, core.ErrorCode.OP_FAILED, cause);
46
+ }
47
+ };
48
+ var MetricRegistrationError = class extends MetricsError {
49
+ constructor(metricName, cause) {
50
+ super(`Failed to register metric "${metricName}"`, cause);
51
+ }
52
+ };
53
+
54
+ // src/metrics/application/services/metrics.service.ts
55
+ exports.MetricsService = class MetricsService {
56
+ constructor(config) {
57
+ this.config = config;
58
+ this.enabled = config.enabled !== false;
59
+ this.prefix = config.prefix ?? "redisx_";
60
+ this.defaultLabels = config.defaultLabels ?? {};
61
+ this.latencyBuckets = config.histogramBuckets ?? [1e-3, 5e-3, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10];
62
+ this.registry = new promClient__namespace.Registry();
63
+ this.registry.setDefaultLabels(this.defaultLabels);
64
+ }
65
+ registry;
66
+ counters = /* @__PURE__ */ new Map();
67
+ histograms = /* @__PURE__ */ new Map();
68
+ gauges = /* @__PURE__ */ new Map();
69
+ prefix;
70
+ defaultLabels;
71
+ latencyBuckets;
72
+ enabled;
73
+ defaultMetricsInterval;
74
+ onModuleInit() {
75
+ if (!this.enabled) {
76
+ return;
77
+ }
78
+ this.registerStandardMetrics();
79
+ if (this.config.collectDefaultMetrics !== false) {
80
+ const collectInterval = this.config.collectInterval ?? 15e3;
81
+ promClient__namespace.collectDefaultMetrics({
82
+ register: this.registry,
83
+ prefix: this.prefix,
84
+ ...collectInterval > 0 ? { timeout: collectInterval } : {}
85
+ });
86
+ }
87
+ }
88
+ onModuleDestroy() {
89
+ this.registry.clear();
90
+ }
91
+ registerStandardMetrics() {
92
+ const commandMetrics = this.config.commandMetrics !== false;
93
+ const pluginMetrics = this.config.pluginMetrics !== false;
94
+ if (commandMetrics) {
95
+ this.registerCounter(`${this.prefix}commands_total`, "Total Redis commands executed", ["command", "client", "status"]);
96
+ this.registerHistogram(`${this.prefix}command_duration_seconds`, "Redis command latency in seconds", ["command", "client"], this.latencyBuckets);
97
+ this.registerGauge(`${this.prefix}connections_active`, "Number of active Redis connections", ["client"]);
98
+ this.registerCounter(`${this.prefix}errors_total`, "Total Redis errors", ["client", "error_type"]);
99
+ }
100
+ if (pluginMetrics) {
101
+ this.registerCounter(`${this.prefix}cache_hits_total`, "Total cache hits", ["layer"]);
102
+ this.registerCounter(`${this.prefix}cache_misses_total`, "Total cache misses", ["layer"]);
103
+ this.registerGauge(`${this.prefix}cache_hit_ratio`, "Cache hit ratio (0-1)", ["layer"]);
104
+ this.registerGauge(`${this.prefix}cache_size`, "Current cache size", ["layer"]);
105
+ this.registerCounter(`${this.prefix}cache_stampede_prevented_total`, "Total cache stampede prevention activations");
106
+ this.registerCounter(`${this.prefix}lock_acquisitions_total`, "Total lock acquisition attempts", ["status"]);
107
+ this.registerHistogram(`${this.prefix}lock_wait_duration_seconds`, "Lock wait time in seconds", [], this.latencyBuckets);
108
+ this.registerHistogram(`${this.prefix}lock_hold_duration_seconds`, "Lock hold time in seconds", [], this.latencyBuckets);
109
+ this.registerGauge(`${this.prefix}locks_active`, "Number of currently held locks");
110
+ this.registerCounter(`${this.prefix}ratelimit_requests_total`, "Total rate limit requests", ["status"]);
111
+ this.registerCounter(`${this.prefix}stream_messages_published_total`, "Total stream messages published", ["stream"]);
112
+ this.registerCounter(`${this.prefix}stream_messages_consumed_total`, "Total stream messages consumed", ["stream", "group", "status"]);
113
+ this.registerHistogram(`${this.prefix}stream_publish_duration_seconds`, "Stream publish latency in seconds", ["stream"], this.latencyBuckets);
114
+ this.registerCounter(`${this.prefix}stream_publish_errors_total`, "Total stream publish errors", ["stream"]);
115
+ this.registerHistogram(`${this.prefix}stream_processing_duration_seconds`, "Stream message processing time in seconds", ["stream", "group"], this.latencyBuckets);
116
+ this.registerCounter(`${this.prefix}idempotency_requests_total`, "Total idempotency requests", ["status"]);
117
+ this.registerHistogram(`${this.prefix}idempotency_duration_seconds`, "Idempotency check duration in seconds", [], this.latencyBuckets);
118
+ }
119
+ }
120
+ incrementCounter(name, labels, value = 1) {
121
+ if (!this.enabled) {
122
+ return;
123
+ }
124
+ const counter = this.counters.get(name);
125
+ if (!counter) {
126
+ return;
127
+ }
128
+ if (labels) {
129
+ counter.inc(labels, value);
130
+ } else {
131
+ counter.inc(value);
132
+ }
133
+ }
134
+ observeHistogram(name, value, labels) {
135
+ if (!this.enabled) {
136
+ return;
137
+ }
138
+ const histogram = this.histograms.get(name);
139
+ if (!histogram) {
140
+ return;
141
+ }
142
+ if (labels) {
143
+ histogram.observe(labels, value);
144
+ } else {
145
+ histogram.observe(value);
146
+ }
147
+ }
148
+ startTimer(name, labels) {
149
+ if (!this.enabled) {
150
+ return () => 0;
151
+ }
152
+ const histogram = this.histograms.get(name);
153
+ if (!histogram) {
154
+ return () => 0;
155
+ }
156
+ const startTime = Date.now();
157
+ return () => {
158
+ const duration = (Date.now() - startTime) / 1e3;
159
+ this.observeHistogram(name, duration, labels);
160
+ return duration;
161
+ };
162
+ }
163
+ setGauge(name, value, labels) {
164
+ if (!this.enabled) {
165
+ return;
166
+ }
167
+ const gauge = this.gauges.get(name);
168
+ if (!gauge) {
169
+ return;
170
+ }
171
+ if (labels) {
172
+ gauge.set(labels, value);
173
+ } else {
174
+ gauge.set(value);
175
+ }
176
+ }
177
+ incrementGauge(name, labels, value = 1) {
178
+ if (!this.enabled) {
179
+ return;
180
+ }
181
+ const gauge = this.gauges.get(name);
182
+ if (!gauge) {
183
+ return;
184
+ }
185
+ if (labels) {
186
+ gauge.inc(labels, value);
187
+ } else {
188
+ gauge.inc(value);
189
+ }
190
+ }
191
+ decrementGauge(name, labels, value = 1) {
192
+ if (!this.enabled) {
193
+ return;
194
+ }
195
+ const gauge = this.gauges.get(name);
196
+ if (!gauge) {
197
+ return;
198
+ }
199
+ if (labels) {
200
+ gauge.dec(labels, value);
201
+ } else {
202
+ gauge.dec(value);
203
+ }
204
+ }
205
+ async getMetrics() {
206
+ if (!this.enabled) {
207
+ return "";
208
+ }
209
+ return this.registry.metrics();
210
+ }
211
+ async getMetricsJson() {
212
+ if (!this.enabled) {
213
+ return [];
214
+ }
215
+ const metrics = await this.registry.getMetricsAsJSON();
216
+ return metrics.map((metric) => ({
217
+ name: metric.name,
218
+ help: metric.help,
219
+ type: String(metric.type),
220
+ values: metric.values.map((v) => ({
221
+ labels: v.labels ?? {},
222
+ value: v.value
223
+ }))
224
+ }));
225
+ }
226
+ registerCounter(name, help, labelNames = []) {
227
+ if (!this.enabled) {
228
+ return;
229
+ }
230
+ try {
231
+ const counter = new promClient__namespace.Counter({
232
+ name,
233
+ help,
234
+ labelNames,
235
+ registers: [this.registry]
236
+ });
237
+ this.counters.set(name, counter);
238
+ } catch (error) {
239
+ throw new MetricRegistrationError(name, error instanceof Error ? error : void 0);
240
+ }
241
+ }
242
+ registerHistogram(name, help, labelNames = [], buckets) {
243
+ if (!this.enabled) {
244
+ return;
245
+ }
246
+ try {
247
+ const histogram = new promClient__namespace.Histogram({
248
+ name,
249
+ help,
250
+ labelNames,
251
+ buckets: buckets ?? this.latencyBuckets,
252
+ registers: [this.registry]
253
+ });
254
+ this.histograms.set(name, histogram);
255
+ } catch (error) {
256
+ throw new MetricRegistrationError(name, error instanceof Error ? error : void 0);
257
+ }
258
+ }
259
+ registerGauge(name, help, labelNames = []) {
260
+ if (!this.enabled) {
261
+ return;
262
+ }
263
+ try {
264
+ const gauge = new promClient__namespace.Gauge({
265
+ name,
266
+ help,
267
+ labelNames,
268
+ registers: [this.registry]
269
+ });
270
+ this.gauges.set(name, gauge);
271
+ } catch (error) {
272
+ throw new MetricRegistrationError(name, error instanceof Error ? error : void 0);
273
+ }
274
+ }
275
+ };
276
+ exports.MetricsService = __decorateClass([
277
+ common.Injectable(),
278
+ __decorateParam(0, common.Inject(METRICS_PLUGIN_OPTIONS))
279
+ ], exports.MetricsService);
280
+ exports.MetricsController = class MetricsController {
281
+ constructor(metricsService) {
282
+ this.metricsService = metricsService;
283
+ }
284
+ async getMetrics() {
285
+ return this.metricsService.getMetrics();
286
+ }
287
+ };
288
+ __decorateClass([
289
+ common.Get(),
290
+ common.Header("Content-Type", "text/plain; version=0.0.4; charset=utf-8")
291
+ ], exports.MetricsController.prototype, "getMetrics", 1);
292
+ exports.MetricsController = __decorateClass([
293
+ common.Controller("metrics"),
294
+ __decorateParam(0, common.Inject(METRICS_SERVICE))
295
+ ], exports.MetricsController);
296
+
297
+ // src/metrics.plugin.ts
298
+ var DEFAULT_METRICS_CONFIG = {
299
+ enabled: true,
300
+ prefix: "redisx_",
301
+ exposeEndpoint: true,
302
+ endpoint: "/metrics",
303
+ histogramBuckets: [1e-3, 5e-3, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10],
304
+ collectDefaultMetrics: true,
305
+ commandMetrics: true,
306
+ pluginMetrics: true,
307
+ collectInterval: 15e3
308
+ };
309
+ var MetricsPlugin = class {
310
+ constructor(options = {}) {
311
+ this.options = options;
312
+ }
313
+ name = "metrics";
314
+ version = "0.1.0";
315
+ description = "Prometheus metrics collection and export";
316
+ getProviders() {
317
+ const config = {
318
+ enabled: this.options.enabled ?? DEFAULT_METRICS_CONFIG.enabled,
319
+ prefix: this.options.prefix ?? DEFAULT_METRICS_CONFIG.prefix,
320
+ exposeEndpoint: this.options.exposeEndpoint ?? DEFAULT_METRICS_CONFIG.exposeEndpoint,
321
+ endpoint: this.options.endpoint ?? DEFAULT_METRICS_CONFIG.endpoint,
322
+ histogramBuckets: this.options.histogramBuckets ?? DEFAULT_METRICS_CONFIG.histogramBuckets,
323
+ collectDefaultMetrics: this.options.collectDefaultMetrics ?? DEFAULT_METRICS_CONFIG.collectDefaultMetrics,
324
+ commandMetrics: this.options.commandMetrics ?? DEFAULT_METRICS_CONFIG.commandMetrics,
325
+ pluginMetrics: this.options.pluginMetrics ?? DEFAULT_METRICS_CONFIG.pluginMetrics,
326
+ collectInterval: this.options.collectInterval ?? DEFAULT_METRICS_CONFIG.collectInterval,
327
+ defaultLabels: this.options.defaultLabels
328
+ };
329
+ return [
330
+ { provide: METRICS_PLUGIN_OPTIONS, useValue: config },
331
+ { provide: METRICS_SERVICE, useClass: exports.MetricsService }
332
+ ];
333
+ }
334
+ getExports() {
335
+ return [METRICS_SERVICE];
336
+ }
337
+ getControllers() {
338
+ if (this.options.exposeEndpoint !== false) {
339
+ return [exports.MetricsController];
340
+ }
341
+ return [];
342
+ }
343
+ };
344
+
345
+ exports.METRICS_PLUGIN_OPTIONS = METRICS_PLUGIN_OPTIONS;
346
+ exports.METRICS_REGISTRY = METRICS_REGISTRY;
347
+ exports.METRICS_SERVICE = METRICS_SERVICE;
348
+ exports.MetricRegistrationError = MetricRegistrationError;
349
+ exports.MetricsError = MetricsError;
350
+ exports.MetricsPlugin = MetricsPlugin;
351
+ //# sourceMappingURL=index.js.map
352
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/shared/constants/index.ts","../src/shared/errors/index.ts","../src/metrics/application/services/metrics.service.ts","../src/metrics/api/controllers/metrics.controller.ts","../src/metrics.plugin.ts"],"names":["RedisXError","ErrorCode","MetricsService","promClient","Injectable","MetricsController","Get","Header","Controller","Inject"],"mappings":"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","file":"index.js","sourcesContent":["export const METRICS_PLUGIN_OPTIONS = Symbol.for('METRICS_PLUGIN_OPTIONS');\nexport const METRICS_SERVICE = Symbol.for('METRICS_SERVICE');\nexport const METRICS_REGISTRY = Symbol.for('METRICS_REGISTRY');\n","import { RedisXError, ErrorCode } from '@nestjs-redisx/core';\n\nexport class MetricsError extends RedisXError {\n constructor(message: string, cause?: Error) {\n super(message, ErrorCode.OP_FAILED, cause);\n }\n}\n\nexport class MetricRegistrationError extends MetricsError {\n constructor(metricName: string, cause?: Error) {\n super(`Failed to register metric \"${metricName}\"`, cause);\n }\n}\n","import { Injectable, Inject, OnModuleInit, OnModuleDestroy } from '@nestjs/common';\nimport * as promClient from 'prom-client';\n\nimport { METRICS_PLUGIN_OPTIONS } from '../../../shared/constants';\nimport { MetricRegistrationError } from '../../../shared/errors';\nimport { IMetricsPluginOptions, IMetricsJson } from '../../../shared/types';\nimport { IMetricsService } from '../ports/metrics-service.port';\n\n@Injectable()\nexport class MetricsService implements IMetricsService, OnModuleInit, OnModuleDestroy {\n private readonly registry: promClient.Registry;\n private readonly counters = new Map<string, promClient.Counter>();\n private readonly histograms = new Map<string, promClient.Histogram>();\n private readonly gauges = new Map<string, promClient.Gauge>();\n private readonly prefix: string;\n private readonly defaultLabels: Record<string, string>;\n private readonly latencyBuckets: number[];\n private readonly enabled: boolean;\n private defaultMetricsInterval?: ReturnType<typeof setInterval>;\n\n constructor(\n @Inject(METRICS_PLUGIN_OPTIONS)\n private readonly config: IMetricsPluginOptions,\n ) {\n this.enabled = config.enabled !== false;\n this.prefix = config.prefix ?? 'redisx_';\n this.defaultLabels = config.defaultLabels ?? {};\n this.latencyBuckets = config.histogramBuckets ?? [0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10];\n\n this.registry = new promClient.Registry();\n this.registry.setDefaultLabels(this.defaultLabels);\n }\n\n onModuleInit(): void {\n if (!this.enabled) {\n return;\n }\n\n this.registerStandardMetrics();\n\n if (this.config.collectDefaultMetrics !== false) {\n const collectInterval = this.config.collectInterval ?? 15000;\n promClient.collectDefaultMetrics({\n register: this.registry,\n prefix: this.prefix,\n ...(collectInterval > 0 ? { timeout: collectInterval } : {}),\n });\n }\n }\n\n onModuleDestroy(): void {\n this.registry.clear();\n }\n\n private registerStandardMetrics(): void {\n const commandMetrics = this.config.commandMetrics !== false;\n const pluginMetrics = this.config.pluginMetrics !== false;\n\n // Core metrics\n if (commandMetrics) {\n this.registerCounter(`${this.prefix}commands_total`, 'Total Redis commands executed', ['command', 'client', 'status']);\n\n this.registerHistogram(`${this.prefix}command_duration_seconds`, 'Redis command latency in seconds', ['command', 'client'], this.latencyBuckets);\n\n this.registerGauge(`${this.prefix}connections_active`, 'Number of active Redis connections', ['client']);\n\n this.registerCounter(`${this.prefix}errors_total`, 'Total Redis errors', ['client', 'error_type']);\n }\n\n // Plugin-specific metrics\n if (pluginMetrics) {\n // Cache metrics\n this.registerCounter(`${this.prefix}cache_hits_total`, 'Total cache hits', ['layer']);\n\n this.registerCounter(`${this.prefix}cache_misses_total`, 'Total cache misses', ['layer']);\n\n this.registerGauge(`${this.prefix}cache_hit_ratio`, 'Cache hit ratio (0-1)', ['layer']);\n\n this.registerGauge(`${this.prefix}cache_size`, 'Current cache size', ['layer']);\n\n this.registerCounter(`${this.prefix}cache_stampede_prevented_total`, 'Total cache stampede prevention activations');\n\n // Lock metrics\n this.registerCounter(`${this.prefix}lock_acquisitions_total`, 'Total lock acquisition attempts', ['status']);\n\n this.registerHistogram(`${this.prefix}lock_wait_duration_seconds`, 'Lock wait time in seconds', [], this.latencyBuckets);\n\n this.registerHistogram(`${this.prefix}lock_hold_duration_seconds`, 'Lock hold time in seconds', [], this.latencyBuckets);\n\n this.registerGauge(`${this.prefix}locks_active`, 'Number of currently held locks');\n\n // Rate limit metrics\n this.registerCounter(`${this.prefix}ratelimit_requests_total`, 'Total rate limit requests', ['status']);\n\n // Stream metrics\n this.registerCounter(`${this.prefix}stream_messages_published_total`, 'Total stream messages published', ['stream']);\n\n this.registerCounter(`${this.prefix}stream_messages_consumed_total`, 'Total stream messages consumed', ['stream', 'group', 'status']);\n\n this.registerHistogram(`${this.prefix}stream_publish_duration_seconds`, 'Stream publish latency in seconds', ['stream'], this.latencyBuckets);\n\n this.registerCounter(`${this.prefix}stream_publish_errors_total`, 'Total stream publish errors', ['stream']);\n\n this.registerHistogram(`${this.prefix}stream_processing_duration_seconds`, 'Stream message processing time in seconds', ['stream', 'group'], this.latencyBuckets);\n\n // Idempotency metrics\n this.registerCounter(`${this.prefix}idempotency_requests_total`, 'Total idempotency requests', ['status']);\n\n this.registerHistogram(`${this.prefix}idempotency_duration_seconds`, 'Idempotency check duration in seconds', [], this.latencyBuckets);\n }\n }\n\n incrementCounter(name: string, labels?: Record<string, string>, value = 1): void {\n if (!this.enabled) {\n return;\n }\n\n const counter = this.counters.get(name);\n if (!counter) {\n return;\n }\n\n if (labels) {\n counter.inc(labels, value);\n } else {\n counter.inc(value);\n }\n }\n\n observeHistogram(name: string, value: number, labels?: Record<string, string>): void {\n if (!this.enabled) {\n return;\n }\n\n const histogram = this.histograms.get(name);\n if (!histogram) {\n return;\n }\n\n if (labels) {\n histogram.observe(labels, value);\n } else {\n histogram.observe(value);\n }\n }\n\n startTimer(name: string, labels?: Record<string, string>): () => number {\n if (!this.enabled) {\n return () => 0;\n }\n\n const histogram = this.histograms.get(name);\n if (!histogram) {\n return () => 0;\n }\n\n const startTime = Date.now();\n\n return () => {\n const duration = (Date.now() - startTime) / 1000;\n this.observeHistogram(name, duration, labels);\n return duration;\n };\n }\n\n setGauge(name: string, value: number, labels?: Record<string, string>): void {\n if (!this.enabled) {\n return;\n }\n\n const gauge = this.gauges.get(name);\n if (!gauge) {\n return;\n }\n\n if (labels) {\n gauge.set(labels, value);\n } else {\n gauge.set(value);\n }\n }\n\n incrementGauge(name: string, labels?: Record<string, string>, value = 1): void {\n if (!this.enabled) {\n return;\n }\n\n const gauge = this.gauges.get(name);\n if (!gauge) {\n return;\n }\n\n if (labels) {\n gauge.inc(labels, value);\n } else {\n gauge.inc(value);\n }\n }\n\n decrementGauge(name: string, labels?: Record<string, string>, value = 1): void {\n if (!this.enabled) {\n return;\n }\n\n const gauge = this.gauges.get(name);\n if (!gauge) {\n return;\n }\n\n if (labels) {\n gauge.dec(labels, value);\n } else {\n gauge.dec(value);\n }\n }\n\n async getMetrics(): Promise<string> {\n if (!this.enabled) {\n return '';\n }\n\n return this.registry.metrics();\n }\n\n async getMetricsJson(): Promise<IMetricsJson[]> {\n if (!this.enabled) {\n return [];\n }\n\n const metrics = await this.registry.getMetricsAsJSON();\n\n return metrics.map((metric: promClient.MetricObjectWithValues<promClient.MetricValue<string>>) => ({\n name: metric.name,\n help: metric.help,\n type: String(metric.type),\n values: metric.values.map((v: promClient.MetricValue<string>) => ({\n labels: (v.labels as Record<string, string>) ?? {},\n value: v.value,\n })),\n }));\n }\n\n registerCounter(name: string, help: string, labelNames: string[] = []): void {\n if (!this.enabled) {\n return;\n }\n\n try {\n const counter = new promClient.Counter({\n name,\n help,\n labelNames,\n registers: [this.registry],\n });\n\n this.counters.set(name, counter);\n } catch (error) {\n throw new MetricRegistrationError(name, error instanceof Error ? error : undefined);\n }\n }\n\n registerHistogram(name: string, help: string, labelNames: string[] = [], buckets?: number[]): void {\n if (!this.enabled) {\n return;\n }\n\n try {\n const histogram = new promClient.Histogram({\n name,\n help,\n labelNames,\n buckets: buckets ?? this.latencyBuckets,\n registers: [this.registry],\n });\n\n this.histograms.set(name, histogram);\n } catch (error) {\n throw new MetricRegistrationError(name, error instanceof Error ? error : undefined);\n }\n }\n\n registerGauge(name: string, help: string, labelNames: string[] = []): void {\n if (!this.enabled) {\n return;\n }\n\n try {\n const gauge = new promClient.Gauge({\n name,\n help,\n labelNames,\n registers: [this.registry],\n });\n\n this.gauges.set(name, gauge);\n } catch (error) {\n throw new MetricRegistrationError(name, error instanceof Error ? error : undefined);\n }\n }\n}\n","import { Controller, Get, Header, Inject } from '@nestjs/common';\n\nimport { METRICS_SERVICE } from '../../../shared/constants';\nimport { IMetricsService } from '../../application/ports/metrics-service.port';\n\n@Controller('metrics')\nexport class MetricsController {\n constructor(@Inject(METRICS_SERVICE) private readonly metricsService: IMetricsService) {}\n\n @Get()\n @Header('Content-Type', 'text/plain; version=0.0.4; charset=utf-8')\n async getMetrics(): Promise<string> {\n return this.metricsService.getMetrics();\n }\n}\n","/**\n * Metrics plugin for NestJS RedisX.\n * Provides Prometheus metrics collection and export.\n */\n\nimport { Provider, Type } from '@nestjs/common';\nimport { IRedisXPlugin } from '@nestjs-redisx/core';\nimport { METRICS_PLUGIN_OPTIONS, METRICS_SERVICE } from './shared/constants';\nimport { IMetricsPluginOptions } from './shared/types';\nimport { MetricsService } from './metrics/application/services/metrics.service';\nimport { MetricsController } from './metrics/api/controllers/metrics.controller';\n\nconst DEFAULT_METRICS_CONFIG: Required<Omit<IMetricsPluginOptions, 'isGlobal' | 'defaultLabels'>> = {\n enabled: true,\n prefix: 'redisx_',\n exposeEndpoint: true,\n endpoint: '/metrics',\n histogramBuckets: [0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10],\n collectDefaultMetrics: true,\n commandMetrics: true,\n pluginMetrics: true,\n collectInterval: 15000,\n};\n\n/**\n * Metrics plugin for NestJS RedisX.\n *\n * Provides Prometheus metrics:\n * - Redis command latency\n * - Connection pool stats\n * - Cache hit/miss rates\n * - Error counts\n * - HTTP endpoint for Prometheus scraping\n *\n * @example\n * ```typescript\n * @Module({\n * imports: [\n * RedisModule.forRoot({\n * clients: { host: 'localhost', port: 6379 },\n * plugins: [\n * new MetricsPlugin({\n * enabled: true,\n * exposeEndpoint: true,\n * endpoint: '/metrics',\n * }),\n * ],\n * }),\n * ],\n * })\n * export class AppModule {}\n * ```\n */\nexport class MetricsPlugin implements IRedisXPlugin {\n readonly name = 'metrics';\n readonly version = '0.1.0';\n readonly description = 'Prometheus metrics collection and export';\n\n constructor(private readonly options: IMetricsPluginOptions = {}) {}\n\n getProviders(): Provider[] {\n const config: IMetricsPluginOptions = {\n enabled: this.options.enabled ?? DEFAULT_METRICS_CONFIG.enabled,\n prefix: this.options.prefix ?? DEFAULT_METRICS_CONFIG.prefix,\n exposeEndpoint: this.options.exposeEndpoint ?? DEFAULT_METRICS_CONFIG.exposeEndpoint,\n endpoint: this.options.endpoint ?? DEFAULT_METRICS_CONFIG.endpoint,\n histogramBuckets: this.options.histogramBuckets ?? DEFAULT_METRICS_CONFIG.histogramBuckets,\n collectDefaultMetrics: this.options.collectDefaultMetrics ?? DEFAULT_METRICS_CONFIG.collectDefaultMetrics,\n commandMetrics: this.options.commandMetrics ?? DEFAULT_METRICS_CONFIG.commandMetrics,\n pluginMetrics: this.options.pluginMetrics ?? DEFAULT_METRICS_CONFIG.pluginMetrics,\n collectInterval: this.options.collectInterval ?? DEFAULT_METRICS_CONFIG.collectInterval,\n defaultLabels: this.options.defaultLabels,\n };\n\n return [\n { provide: METRICS_PLUGIN_OPTIONS, useValue: config },\n { provide: METRICS_SERVICE, useClass: MetricsService },\n ];\n }\n\n getExports(): Array<string | symbol | Provider> {\n return [METRICS_SERVICE];\n }\n\n getControllers(): Type[] {\n // Only expose controller if endpoint is enabled\n if (this.options.exposeEndpoint !== false) {\n return [MetricsController];\n }\n return [];\n }\n}\n"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,325 @@
1
+ import { Injectable, Inject, Get, Header, Controller } from '@nestjs/common';
2
+ import * as promClient from 'prom-client';
3
+ import { RedisXError, ErrorCode } from '@nestjs-redisx/core';
4
+
5
+ var __defProp = Object.defineProperty;
6
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
+ var __decorateClass = (decorators, target, key, kind) => {
8
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
9
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
10
+ if (decorator = decorators[i])
11
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
12
+ if (kind && result) __defProp(target, key, result);
13
+ return result;
14
+ };
15
+ var __decorateParam = (index, decorator) => (target, key) => decorator(target, key, index);
16
+
17
+ // src/shared/constants/index.ts
18
+ var METRICS_PLUGIN_OPTIONS = /* @__PURE__ */ Symbol.for("METRICS_PLUGIN_OPTIONS");
19
+ var METRICS_SERVICE = /* @__PURE__ */ Symbol.for("METRICS_SERVICE");
20
+ var METRICS_REGISTRY = /* @__PURE__ */ Symbol.for("METRICS_REGISTRY");
21
+ var MetricsError = class extends RedisXError {
22
+ constructor(message, cause) {
23
+ super(message, ErrorCode.OP_FAILED, cause);
24
+ }
25
+ };
26
+ var MetricRegistrationError = class extends MetricsError {
27
+ constructor(metricName, cause) {
28
+ super(`Failed to register metric "${metricName}"`, cause);
29
+ }
30
+ };
31
+
32
+ // src/metrics/application/services/metrics.service.ts
33
+ var MetricsService = class {
34
+ constructor(config) {
35
+ this.config = config;
36
+ this.enabled = config.enabled !== false;
37
+ this.prefix = config.prefix ?? "redisx_";
38
+ this.defaultLabels = config.defaultLabels ?? {};
39
+ this.latencyBuckets = config.histogramBuckets ?? [1e-3, 5e-3, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10];
40
+ this.registry = new promClient.Registry();
41
+ this.registry.setDefaultLabels(this.defaultLabels);
42
+ }
43
+ registry;
44
+ counters = /* @__PURE__ */ new Map();
45
+ histograms = /* @__PURE__ */ new Map();
46
+ gauges = /* @__PURE__ */ new Map();
47
+ prefix;
48
+ defaultLabels;
49
+ latencyBuckets;
50
+ enabled;
51
+ defaultMetricsInterval;
52
+ onModuleInit() {
53
+ if (!this.enabled) {
54
+ return;
55
+ }
56
+ this.registerStandardMetrics();
57
+ if (this.config.collectDefaultMetrics !== false) {
58
+ const collectInterval = this.config.collectInterval ?? 15e3;
59
+ promClient.collectDefaultMetrics({
60
+ register: this.registry,
61
+ prefix: this.prefix,
62
+ ...collectInterval > 0 ? { timeout: collectInterval } : {}
63
+ });
64
+ }
65
+ }
66
+ onModuleDestroy() {
67
+ this.registry.clear();
68
+ }
69
+ registerStandardMetrics() {
70
+ const commandMetrics = this.config.commandMetrics !== false;
71
+ const pluginMetrics = this.config.pluginMetrics !== false;
72
+ if (commandMetrics) {
73
+ this.registerCounter(`${this.prefix}commands_total`, "Total Redis commands executed", ["command", "client", "status"]);
74
+ this.registerHistogram(`${this.prefix}command_duration_seconds`, "Redis command latency in seconds", ["command", "client"], this.latencyBuckets);
75
+ this.registerGauge(`${this.prefix}connections_active`, "Number of active Redis connections", ["client"]);
76
+ this.registerCounter(`${this.prefix}errors_total`, "Total Redis errors", ["client", "error_type"]);
77
+ }
78
+ if (pluginMetrics) {
79
+ this.registerCounter(`${this.prefix}cache_hits_total`, "Total cache hits", ["layer"]);
80
+ this.registerCounter(`${this.prefix}cache_misses_total`, "Total cache misses", ["layer"]);
81
+ this.registerGauge(`${this.prefix}cache_hit_ratio`, "Cache hit ratio (0-1)", ["layer"]);
82
+ this.registerGauge(`${this.prefix}cache_size`, "Current cache size", ["layer"]);
83
+ this.registerCounter(`${this.prefix}cache_stampede_prevented_total`, "Total cache stampede prevention activations");
84
+ this.registerCounter(`${this.prefix}lock_acquisitions_total`, "Total lock acquisition attempts", ["status"]);
85
+ this.registerHistogram(`${this.prefix}lock_wait_duration_seconds`, "Lock wait time in seconds", [], this.latencyBuckets);
86
+ this.registerHistogram(`${this.prefix}lock_hold_duration_seconds`, "Lock hold time in seconds", [], this.latencyBuckets);
87
+ this.registerGauge(`${this.prefix}locks_active`, "Number of currently held locks");
88
+ this.registerCounter(`${this.prefix}ratelimit_requests_total`, "Total rate limit requests", ["status"]);
89
+ this.registerCounter(`${this.prefix}stream_messages_published_total`, "Total stream messages published", ["stream"]);
90
+ this.registerCounter(`${this.prefix}stream_messages_consumed_total`, "Total stream messages consumed", ["stream", "group", "status"]);
91
+ this.registerHistogram(`${this.prefix}stream_publish_duration_seconds`, "Stream publish latency in seconds", ["stream"], this.latencyBuckets);
92
+ this.registerCounter(`${this.prefix}stream_publish_errors_total`, "Total stream publish errors", ["stream"]);
93
+ this.registerHistogram(`${this.prefix}stream_processing_duration_seconds`, "Stream message processing time in seconds", ["stream", "group"], this.latencyBuckets);
94
+ this.registerCounter(`${this.prefix}idempotency_requests_total`, "Total idempotency requests", ["status"]);
95
+ this.registerHistogram(`${this.prefix}idempotency_duration_seconds`, "Idempotency check duration in seconds", [], this.latencyBuckets);
96
+ }
97
+ }
98
+ incrementCounter(name, labels, value = 1) {
99
+ if (!this.enabled) {
100
+ return;
101
+ }
102
+ const counter = this.counters.get(name);
103
+ if (!counter) {
104
+ return;
105
+ }
106
+ if (labels) {
107
+ counter.inc(labels, value);
108
+ } else {
109
+ counter.inc(value);
110
+ }
111
+ }
112
+ observeHistogram(name, value, labels) {
113
+ if (!this.enabled) {
114
+ return;
115
+ }
116
+ const histogram = this.histograms.get(name);
117
+ if (!histogram) {
118
+ return;
119
+ }
120
+ if (labels) {
121
+ histogram.observe(labels, value);
122
+ } else {
123
+ histogram.observe(value);
124
+ }
125
+ }
126
+ startTimer(name, labels) {
127
+ if (!this.enabled) {
128
+ return () => 0;
129
+ }
130
+ const histogram = this.histograms.get(name);
131
+ if (!histogram) {
132
+ return () => 0;
133
+ }
134
+ const startTime = Date.now();
135
+ return () => {
136
+ const duration = (Date.now() - startTime) / 1e3;
137
+ this.observeHistogram(name, duration, labels);
138
+ return duration;
139
+ };
140
+ }
141
+ setGauge(name, value, labels) {
142
+ if (!this.enabled) {
143
+ return;
144
+ }
145
+ const gauge = this.gauges.get(name);
146
+ if (!gauge) {
147
+ return;
148
+ }
149
+ if (labels) {
150
+ gauge.set(labels, value);
151
+ } else {
152
+ gauge.set(value);
153
+ }
154
+ }
155
+ incrementGauge(name, labels, value = 1) {
156
+ if (!this.enabled) {
157
+ return;
158
+ }
159
+ const gauge = this.gauges.get(name);
160
+ if (!gauge) {
161
+ return;
162
+ }
163
+ if (labels) {
164
+ gauge.inc(labels, value);
165
+ } else {
166
+ gauge.inc(value);
167
+ }
168
+ }
169
+ decrementGauge(name, labels, value = 1) {
170
+ if (!this.enabled) {
171
+ return;
172
+ }
173
+ const gauge = this.gauges.get(name);
174
+ if (!gauge) {
175
+ return;
176
+ }
177
+ if (labels) {
178
+ gauge.dec(labels, value);
179
+ } else {
180
+ gauge.dec(value);
181
+ }
182
+ }
183
+ async getMetrics() {
184
+ if (!this.enabled) {
185
+ return "";
186
+ }
187
+ return this.registry.metrics();
188
+ }
189
+ async getMetricsJson() {
190
+ if (!this.enabled) {
191
+ return [];
192
+ }
193
+ const metrics = await this.registry.getMetricsAsJSON();
194
+ return metrics.map((metric) => ({
195
+ name: metric.name,
196
+ help: metric.help,
197
+ type: String(metric.type),
198
+ values: metric.values.map((v) => ({
199
+ labels: v.labels ?? {},
200
+ value: v.value
201
+ }))
202
+ }));
203
+ }
204
+ registerCounter(name, help, labelNames = []) {
205
+ if (!this.enabled) {
206
+ return;
207
+ }
208
+ try {
209
+ const counter = new promClient.Counter({
210
+ name,
211
+ help,
212
+ labelNames,
213
+ registers: [this.registry]
214
+ });
215
+ this.counters.set(name, counter);
216
+ } catch (error) {
217
+ throw new MetricRegistrationError(name, error instanceof Error ? error : void 0);
218
+ }
219
+ }
220
+ registerHistogram(name, help, labelNames = [], buckets) {
221
+ if (!this.enabled) {
222
+ return;
223
+ }
224
+ try {
225
+ const histogram = new promClient.Histogram({
226
+ name,
227
+ help,
228
+ labelNames,
229
+ buckets: buckets ?? this.latencyBuckets,
230
+ registers: [this.registry]
231
+ });
232
+ this.histograms.set(name, histogram);
233
+ } catch (error) {
234
+ throw new MetricRegistrationError(name, error instanceof Error ? error : void 0);
235
+ }
236
+ }
237
+ registerGauge(name, help, labelNames = []) {
238
+ if (!this.enabled) {
239
+ return;
240
+ }
241
+ try {
242
+ const gauge = new promClient.Gauge({
243
+ name,
244
+ help,
245
+ labelNames,
246
+ registers: [this.registry]
247
+ });
248
+ this.gauges.set(name, gauge);
249
+ } catch (error) {
250
+ throw new MetricRegistrationError(name, error instanceof Error ? error : void 0);
251
+ }
252
+ }
253
+ };
254
+ MetricsService = __decorateClass([
255
+ Injectable(),
256
+ __decorateParam(0, Inject(METRICS_PLUGIN_OPTIONS))
257
+ ], MetricsService);
258
+ var MetricsController = class {
259
+ constructor(metricsService) {
260
+ this.metricsService = metricsService;
261
+ }
262
+ async getMetrics() {
263
+ return this.metricsService.getMetrics();
264
+ }
265
+ };
266
+ __decorateClass([
267
+ Get(),
268
+ Header("Content-Type", "text/plain; version=0.0.4; charset=utf-8")
269
+ ], MetricsController.prototype, "getMetrics", 1);
270
+ MetricsController = __decorateClass([
271
+ Controller("metrics"),
272
+ __decorateParam(0, Inject(METRICS_SERVICE))
273
+ ], MetricsController);
274
+
275
+ // src/metrics.plugin.ts
276
+ var DEFAULT_METRICS_CONFIG = {
277
+ enabled: true,
278
+ prefix: "redisx_",
279
+ exposeEndpoint: true,
280
+ endpoint: "/metrics",
281
+ histogramBuckets: [1e-3, 5e-3, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10],
282
+ collectDefaultMetrics: true,
283
+ commandMetrics: true,
284
+ pluginMetrics: true,
285
+ collectInterval: 15e3
286
+ };
287
+ var MetricsPlugin = class {
288
+ constructor(options = {}) {
289
+ this.options = options;
290
+ }
291
+ name = "metrics";
292
+ version = "0.1.0";
293
+ description = "Prometheus metrics collection and export";
294
+ getProviders() {
295
+ const config = {
296
+ enabled: this.options.enabled ?? DEFAULT_METRICS_CONFIG.enabled,
297
+ prefix: this.options.prefix ?? DEFAULT_METRICS_CONFIG.prefix,
298
+ exposeEndpoint: this.options.exposeEndpoint ?? DEFAULT_METRICS_CONFIG.exposeEndpoint,
299
+ endpoint: this.options.endpoint ?? DEFAULT_METRICS_CONFIG.endpoint,
300
+ histogramBuckets: this.options.histogramBuckets ?? DEFAULT_METRICS_CONFIG.histogramBuckets,
301
+ collectDefaultMetrics: this.options.collectDefaultMetrics ?? DEFAULT_METRICS_CONFIG.collectDefaultMetrics,
302
+ commandMetrics: this.options.commandMetrics ?? DEFAULT_METRICS_CONFIG.commandMetrics,
303
+ pluginMetrics: this.options.pluginMetrics ?? DEFAULT_METRICS_CONFIG.pluginMetrics,
304
+ collectInterval: this.options.collectInterval ?? DEFAULT_METRICS_CONFIG.collectInterval,
305
+ defaultLabels: this.options.defaultLabels
306
+ };
307
+ return [
308
+ { provide: METRICS_PLUGIN_OPTIONS, useValue: config },
309
+ { provide: METRICS_SERVICE, useClass: MetricsService }
310
+ ];
311
+ }
312
+ getExports() {
313
+ return [METRICS_SERVICE];
314
+ }
315
+ getControllers() {
316
+ if (this.options.exposeEndpoint !== false) {
317
+ return [MetricsController];
318
+ }
319
+ return [];
320
+ }
321
+ };
322
+
323
+ export { METRICS_PLUGIN_OPTIONS, METRICS_REGISTRY, METRICS_SERVICE, MetricRegistrationError, MetricsController, MetricsError, MetricsPlugin, MetricsService };
324
+ //# sourceMappingURL=index.mjs.map
325
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/shared/constants/index.ts","../src/shared/errors/index.ts","../src/metrics/application/services/metrics.service.ts","../src/metrics/api/controllers/metrics.controller.ts","../src/metrics.plugin.ts"],"names":["Inject"],"mappings":"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","file":"index.mjs","sourcesContent":["export const METRICS_PLUGIN_OPTIONS = Symbol.for('METRICS_PLUGIN_OPTIONS');\nexport const METRICS_SERVICE = Symbol.for('METRICS_SERVICE');\nexport const METRICS_REGISTRY = Symbol.for('METRICS_REGISTRY');\n","import { RedisXError, ErrorCode } from '@nestjs-redisx/core';\n\nexport class MetricsError extends RedisXError {\n constructor(message: string, cause?: Error) {\n super(message, ErrorCode.OP_FAILED, cause);\n }\n}\n\nexport class MetricRegistrationError extends MetricsError {\n constructor(metricName: string, cause?: Error) {\n super(`Failed to register metric \"${metricName}\"`, cause);\n }\n}\n","import { Injectable, Inject, OnModuleInit, OnModuleDestroy } from '@nestjs/common';\nimport * as promClient from 'prom-client';\n\nimport { METRICS_PLUGIN_OPTIONS } from '../../../shared/constants';\nimport { MetricRegistrationError } from '../../../shared/errors';\nimport { IMetricsPluginOptions, IMetricsJson } from '../../../shared/types';\nimport { IMetricsService } from '../ports/metrics-service.port';\n\n@Injectable()\nexport class MetricsService implements IMetricsService, OnModuleInit, OnModuleDestroy {\n private readonly registry: promClient.Registry;\n private readonly counters = new Map<string, promClient.Counter>();\n private readonly histograms = new Map<string, promClient.Histogram>();\n private readonly gauges = new Map<string, promClient.Gauge>();\n private readonly prefix: string;\n private readonly defaultLabels: Record<string, string>;\n private readonly latencyBuckets: number[];\n private readonly enabled: boolean;\n private defaultMetricsInterval?: ReturnType<typeof setInterval>;\n\n constructor(\n @Inject(METRICS_PLUGIN_OPTIONS)\n private readonly config: IMetricsPluginOptions,\n ) {\n this.enabled = config.enabled !== false;\n this.prefix = config.prefix ?? 'redisx_';\n this.defaultLabels = config.defaultLabels ?? {};\n this.latencyBuckets = config.histogramBuckets ?? [0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10];\n\n this.registry = new promClient.Registry();\n this.registry.setDefaultLabels(this.defaultLabels);\n }\n\n onModuleInit(): void {\n if (!this.enabled) {\n return;\n }\n\n this.registerStandardMetrics();\n\n if (this.config.collectDefaultMetrics !== false) {\n const collectInterval = this.config.collectInterval ?? 15000;\n promClient.collectDefaultMetrics({\n register: this.registry,\n prefix: this.prefix,\n ...(collectInterval > 0 ? { timeout: collectInterval } : {}),\n });\n }\n }\n\n onModuleDestroy(): void {\n this.registry.clear();\n }\n\n private registerStandardMetrics(): void {\n const commandMetrics = this.config.commandMetrics !== false;\n const pluginMetrics = this.config.pluginMetrics !== false;\n\n // Core metrics\n if (commandMetrics) {\n this.registerCounter(`${this.prefix}commands_total`, 'Total Redis commands executed', ['command', 'client', 'status']);\n\n this.registerHistogram(`${this.prefix}command_duration_seconds`, 'Redis command latency in seconds', ['command', 'client'], this.latencyBuckets);\n\n this.registerGauge(`${this.prefix}connections_active`, 'Number of active Redis connections', ['client']);\n\n this.registerCounter(`${this.prefix}errors_total`, 'Total Redis errors', ['client', 'error_type']);\n }\n\n // Plugin-specific metrics\n if (pluginMetrics) {\n // Cache metrics\n this.registerCounter(`${this.prefix}cache_hits_total`, 'Total cache hits', ['layer']);\n\n this.registerCounter(`${this.prefix}cache_misses_total`, 'Total cache misses', ['layer']);\n\n this.registerGauge(`${this.prefix}cache_hit_ratio`, 'Cache hit ratio (0-1)', ['layer']);\n\n this.registerGauge(`${this.prefix}cache_size`, 'Current cache size', ['layer']);\n\n this.registerCounter(`${this.prefix}cache_stampede_prevented_total`, 'Total cache stampede prevention activations');\n\n // Lock metrics\n this.registerCounter(`${this.prefix}lock_acquisitions_total`, 'Total lock acquisition attempts', ['status']);\n\n this.registerHistogram(`${this.prefix}lock_wait_duration_seconds`, 'Lock wait time in seconds', [], this.latencyBuckets);\n\n this.registerHistogram(`${this.prefix}lock_hold_duration_seconds`, 'Lock hold time in seconds', [], this.latencyBuckets);\n\n this.registerGauge(`${this.prefix}locks_active`, 'Number of currently held locks');\n\n // Rate limit metrics\n this.registerCounter(`${this.prefix}ratelimit_requests_total`, 'Total rate limit requests', ['status']);\n\n // Stream metrics\n this.registerCounter(`${this.prefix}stream_messages_published_total`, 'Total stream messages published', ['stream']);\n\n this.registerCounter(`${this.prefix}stream_messages_consumed_total`, 'Total stream messages consumed', ['stream', 'group', 'status']);\n\n this.registerHistogram(`${this.prefix}stream_publish_duration_seconds`, 'Stream publish latency in seconds', ['stream'], this.latencyBuckets);\n\n this.registerCounter(`${this.prefix}stream_publish_errors_total`, 'Total stream publish errors', ['stream']);\n\n this.registerHistogram(`${this.prefix}stream_processing_duration_seconds`, 'Stream message processing time in seconds', ['stream', 'group'], this.latencyBuckets);\n\n // Idempotency metrics\n this.registerCounter(`${this.prefix}idempotency_requests_total`, 'Total idempotency requests', ['status']);\n\n this.registerHistogram(`${this.prefix}idempotency_duration_seconds`, 'Idempotency check duration in seconds', [], this.latencyBuckets);\n }\n }\n\n incrementCounter(name: string, labels?: Record<string, string>, value = 1): void {\n if (!this.enabled) {\n return;\n }\n\n const counter = this.counters.get(name);\n if (!counter) {\n return;\n }\n\n if (labels) {\n counter.inc(labels, value);\n } else {\n counter.inc(value);\n }\n }\n\n observeHistogram(name: string, value: number, labels?: Record<string, string>): void {\n if (!this.enabled) {\n return;\n }\n\n const histogram = this.histograms.get(name);\n if (!histogram) {\n return;\n }\n\n if (labels) {\n histogram.observe(labels, value);\n } else {\n histogram.observe(value);\n }\n }\n\n startTimer(name: string, labels?: Record<string, string>): () => number {\n if (!this.enabled) {\n return () => 0;\n }\n\n const histogram = this.histograms.get(name);\n if (!histogram) {\n return () => 0;\n }\n\n const startTime = Date.now();\n\n return () => {\n const duration = (Date.now() - startTime) / 1000;\n this.observeHistogram(name, duration, labels);\n return duration;\n };\n }\n\n setGauge(name: string, value: number, labels?: Record<string, string>): void {\n if (!this.enabled) {\n return;\n }\n\n const gauge = this.gauges.get(name);\n if (!gauge) {\n return;\n }\n\n if (labels) {\n gauge.set(labels, value);\n } else {\n gauge.set(value);\n }\n }\n\n incrementGauge(name: string, labels?: Record<string, string>, value = 1): void {\n if (!this.enabled) {\n return;\n }\n\n const gauge = this.gauges.get(name);\n if (!gauge) {\n return;\n }\n\n if (labels) {\n gauge.inc(labels, value);\n } else {\n gauge.inc(value);\n }\n }\n\n decrementGauge(name: string, labels?: Record<string, string>, value = 1): void {\n if (!this.enabled) {\n return;\n }\n\n const gauge = this.gauges.get(name);\n if (!gauge) {\n return;\n }\n\n if (labels) {\n gauge.dec(labels, value);\n } else {\n gauge.dec(value);\n }\n }\n\n async getMetrics(): Promise<string> {\n if (!this.enabled) {\n return '';\n }\n\n return this.registry.metrics();\n }\n\n async getMetricsJson(): Promise<IMetricsJson[]> {\n if (!this.enabled) {\n return [];\n }\n\n const metrics = await this.registry.getMetricsAsJSON();\n\n return metrics.map((metric: promClient.MetricObjectWithValues<promClient.MetricValue<string>>) => ({\n name: metric.name,\n help: metric.help,\n type: String(metric.type),\n values: metric.values.map((v: promClient.MetricValue<string>) => ({\n labels: (v.labels as Record<string, string>) ?? {},\n value: v.value,\n })),\n }));\n }\n\n registerCounter(name: string, help: string, labelNames: string[] = []): void {\n if (!this.enabled) {\n return;\n }\n\n try {\n const counter = new promClient.Counter({\n name,\n help,\n labelNames,\n registers: [this.registry],\n });\n\n this.counters.set(name, counter);\n } catch (error) {\n throw new MetricRegistrationError(name, error instanceof Error ? error : undefined);\n }\n }\n\n registerHistogram(name: string, help: string, labelNames: string[] = [], buckets?: number[]): void {\n if (!this.enabled) {\n return;\n }\n\n try {\n const histogram = new promClient.Histogram({\n name,\n help,\n labelNames,\n buckets: buckets ?? this.latencyBuckets,\n registers: [this.registry],\n });\n\n this.histograms.set(name, histogram);\n } catch (error) {\n throw new MetricRegistrationError(name, error instanceof Error ? error : undefined);\n }\n }\n\n registerGauge(name: string, help: string, labelNames: string[] = []): void {\n if (!this.enabled) {\n return;\n }\n\n try {\n const gauge = new promClient.Gauge({\n name,\n help,\n labelNames,\n registers: [this.registry],\n });\n\n this.gauges.set(name, gauge);\n } catch (error) {\n throw new MetricRegistrationError(name, error instanceof Error ? error : undefined);\n }\n }\n}\n","import { Controller, Get, Header, Inject } from '@nestjs/common';\n\nimport { METRICS_SERVICE } from '../../../shared/constants';\nimport { IMetricsService } from '../../application/ports/metrics-service.port';\n\n@Controller('metrics')\nexport class MetricsController {\n constructor(@Inject(METRICS_SERVICE) private readonly metricsService: IMetricsService) {}\n\n @Get()\n @Header('Content-Type', 'text/plain; version=0.0.4; charset=utf-8')\n async getMetrics(): Promise<string> {\n return this.metricsService.getMetrics();\n }\n}\n","/**\n * Metrics plugin for NestJS RedisX.\n * Provides Prometheus metrics collection and export.\n */\n\nimport { Provider, Type } from '@nestjs/common';\nimport { IRedisXPlugin } from '@nestjs-redisx/core';\nimport { METRICS_PLUGIN_OPTIONS, METRICS_SERVICE } from './shared/constants';\nimport { IMetricsPluginOptions } from './shared/types';\nimport { MetricsService } from './metrics/application/services/metrics.service';\nimport { MetricsController } from './metrics/api/controllers/metrics.controller';\n\nconst DEFAULT_METRICS_CONFIG: Required<Omit<IMetricsPluginOptions, 'isGlobal' | 'defaultLabels'>> = {\n enabled: true,\n prefix: 'redisx_',\n exposeEndpoint: true,\n endpoint: '/metrics',\n histogramBuckets: [0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10],\n collectDefaultMetrics: true,\n commandMetrics: true,\n pluginMetrics: true,\n collectInterval: 15000,\n};\n\n/**\n * Metrics plugin for NestJS RedisX.\n *\n * Provides Prometheus metrics:\n * - Redis command latency\n * - Connection pool stats\n * - Cache hit/miss rates\n * - Error counts\n * - HTTP endpoint for Prometheus scraping\n *\n * @example\n * ```typescript\n * @Module({\n * imports: [\n * RedisModule.forRoot({\n * clients: { host: 'localhost', port: 6379 },\n * plugins: [\n * new MetricsPlugin({\n * enabled: true,\n * exposeEndpoint: true,\n * endpoint: '/metrics',\n * }),\n * ],\n * }),\n * ],\n * })\n * export class AppModule {}\n * ```\n */\nexport class MetricsPlugin implements IRedisXPlugin {\n readonly name = 'metrics';\n readonly version = '0.1.0';\n readonly description = 'Prometheus metrics collection and export';\n\n constructor(private readonly options: IMetricsPluginOptions = {}) {}\n\n getProviders(): Provider[] {\n const config: IMetricsPluginOptions = {\n enabled: this.options.enabled ?? DEFAULT_METRICS_CONFIG.enabled,\n prefix: this.options.prefix ?? DEFAULT_METRICS_CONFIG.prefix,\n exposeEndpoint: this.options.exposeEndpoint ?? DEFAULT_METRICS_CONFIG.exposeEndpoint,\n endpoint: this.options.endpoint ?? DEFAULT_METRICS_CONFIG.endpoint,\n histogramBuckets: this.options.histogramBuckets ?? DEFAULT_METRICS_CONFIG.histogramBuckets,\n collectDefaultMetrics: this.options.collectDefaultMetrics ?? DEFAULT_METRICS_CONFIG.collectDefaultMetrics,\n commandMetrics: this.options.commandMetrics ?? DEFAULT_METRICS_CONFIG.commandMetrics,\n pluginMetrics: this.options.pluginMetrics ?? DEFAULT_METRICS_CONFIG.pluginMetrics,\n collectInterval: this.options.collectInterval ?? DEFAULT_METRICS_CONFIG.collectInterval,\n defaultLabels: this.options.defaultLabels,\n };\n\n return [\n { provide: METRICS_PLUGIN_OPTIONS, useValue: config },\n { provide: METRICS_SERVICE, useClass: MetricsService },\n ];\n }\n\n getExports(): Array<string | symbol | Provider> {\n return [METRICS_SERVICE];\n }\n\n getControllers(): Type[] {\n // Only expose controller if endpoint is enabled\n if (this.options.exposeEndpoint !== false) {\n return [MetricsController];\n }\n return [];\n }\n}\n"]}
@@ -0,0 +1,7 @@
1
+ import { IMetricsService } from '../../application/ports/metrics-service.port';
2
+ export declare class MetricsController {
3
+ private readonly metricsService;
4
+ constructor(metricsService: IMetricsService);
5
+ getMetrics(): Promise<string>;
6
+ }
7
+ //# sourceMappingURL=metrics.controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.controller.d.ts","sourceRoot":"","sources":["../../../../src/metrics/api/controllers/metrics.controller.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,8CAA8C,CAAC;AAE/E,qBACa,iBAAiB;IACS,OAAO,CAAC,QAAQ,CAAC,cAAc;gBAAd,cAAc,EAAE,eAAe;IAI/E,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;CAGpC"}
@@ -0,0 +1,2 @@
1
+ export type { IMetricsService } from './metrics-service.port';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/metrics/application/ports/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { IMetricsJson } from '../../../shared/types';
2
+ export interface IMetricsService {
3
+ incrementCounter(name: string, labels?: Record<string, string>, value?: number): void;
4
+ observeHistogram(name: string, value: number, labels?: Record<string, string>): void;
5
+ startTimer(name: string, labels?: Record<string, string>): () => number;
6
+ setGauge(name: string, value: number, labels?: Record<string, string>): void;
7
+ incrementGauge(name: string, labels?: Record<string, string>, value?: number): void;
8
+ decrementGauge(name: string, labels?: Record<string, string>, value?: number): void;
9
+ getMetrics(): Promise<string>;
10
+ getMetricsJson(): Promise<IMetricsJson[]>;
11
+ registerCounter(name: string, help: string, labelNames?: string[]): void;
12
+ registerHistogram(name: string, help: string, labelNames?: string[], buckets?: number[]): void;
13
+ registerGauge(name: string, help: string, labelNames?: string[]): void;
14
+ }
15
+ //# sourceMappingURL=metrics-service.port.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics-service.port.d.ts","sourceRoot":"","sources":["../../../../src/metrics/application/ports/metrics-service.port.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAErD,MAAM,WAAW,eAAe;IAE9B,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAGtF,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;IACrF,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,MAAM,CAAC;IAGxE,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;IAC7E,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpF,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAGpF,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9B,cAAc,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAG1C,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACzE,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC/F,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;CACxE"}
@@ -0,0 +1,31 @@
1
+ import { OnModuleInit, OnModuleDestroy } from '@nestjs/common';
2
+ import { IMetricsPluginOptions, IMetricsJson } from '../../../shared/types';
3
+ import { IMetricsService } from '../ports/metrics-service.port';
4
+ export declare class MetricsService implements IMetricsService, OnModuleInit, OnModuleDestroy {
5
+ private readonly config;
6
+ private readonly registry;
7
+ private readonly counters;
8
+ private readonly histograms;
9
+ private readonly gauges;
10
+ private readonly prefix;
11
+ private readonly defaultLabels;
12
+ private readonly latencyBuckets;
13
+ private readonly enabled;
14
+ private defaultMetricsInterval?;
15
+ constructor(config: IMetricsPluginOptions);
16
+ onModuleInit(): void;
17
+ onModuleDestroy(): void;
18
+ private registerStandardMetrics;
19
+ incrementCounter(name: string, labels?: Record<string, string>, value?: number): void;
20
+ observeHistogram(name: string, value: number, labels?: Record<string, string>): void;
21
+ startTimer(name: string, labels?: Record<string, string>): () => number;
22
+ setGauge(name: string, value: number, labels?: Record<string, string>): void;
23
+ incrementGauge(name: string, labels?: Record<string, string>, value?: number): void;
24
+ decrementGauge(name: string, labels?: Record<string, string>, value?: number): void;
25
+ getMetrics(): Promise<string>;
26
+ getMetricsJson(): Promise<IMetricsJson[]>;
27
+ registerCounter(name: string, help: string, labelNames?: string[]): void;
28
+ registerHistogram(name: string, help: string, labelNames?: string[], buckets?: number[]): void;
29
+ registerGauge(name: string, help: string, labelNames?: string[]): void;
30
+ }
31
+ //# sourceMappingURL=metrics.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.service.d.ts","sourceRoot":"","sources":["../../../../src/metrics/application/services/metrics.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,YAAY,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAKnF,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC5E,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAEhE,qBACa,cAAe,YAAW,eAAe,EAAE,YAAY,EAAE,eAAe;IAajF,OAAO,CAAC,QAAQ,CAAC,MAAM;IAZzB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsB;IAC/C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAyC;IAClE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA2C;IACtE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuC;IAC9D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAyB;IACvD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAW;IAC1C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,sBAAsB,CAAC,CAAiC;gBAI7C,MAAM,EAAE,qBAAqB;IAWhD,YAAY,IAAI,IAAI;IAiBpB,eAAe,IAAI,IAAI;IAIvB,OAAO,CAAC,uBAAuB;IA0D/B,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,KAAK,SAAI,GAAG,IAAI;IAiBhF,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAiBpF,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,MAAM;IAmBvE,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAiB5E,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,KAAK,SAAI,GAAG,IAAI;IAiB9E,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,KAAK,SAAI,GAAG,IAAI;IAiBxE,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAQ7B,cAAc,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;IAkB/C,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,GAAE,MAAM,EAAO,GAAG,IAAI;IAmB5E,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,GAAE,MAAM,EAAO,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI;IAoBlG,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,GAAE,MAAM,EAAO,GAAG,IAAI;CAkB3E"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Metrics plugin for NestJS RedisX.
3
+ * Provides Prometheus metrics collection and export.
4
+ */
5
+ import { Provider, Type } from '@nestjs/common';
6
+ import { IRedisXPlugin } from '@nestjs-redisx/core';
7
+ import { IMetricsPluginOptions } from './shared/types';
8
+ /**
9
+ * Metrics plugin for NestJS RedisX.
10
+ *
11
+ * Provides Prometheus metrics:
12
+ * - Redis command latency
13
+ * - Connection pool stats
14
+ * - Cache hit/miss rates
15
+ * - Error counts
16
+ * - HTTP endpoint for Prometheus scraping
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * @Module({
21
+ * imports: [
22
+ * RedisModule.forRoot({
23
+ * clients: { host: 'localhost', port: 6379 },
24
+ * plugins: [
25
+ * new MetricsPlugin({
26
+ * enabled: true,
27
+ * exposeEndpoint: true,
28
+ * endpoint: '/metrics',
29
+ * }),
30
+ * ],
31
+ * }),
32
+ * ],
33
+ * })
34
+ * export class AppModule {}
35
+ * ```
36
+ */
37
+ export declare class MetricsPlugin implements IRedisXPlugin {
38
+ private readonly options;
39
+ readonly name = "metrics";
40
+ readonly version = "0.1.0";
41
+ readonly description = "Prometheus metrics collection and export";
42
+ constructor(options?: IMetricsPluginOptions);
43
+ getProviders(): Provider[];
44
+ getExports(): Array<string | symbol | Provider>;
45
+ getControllers(): Type[];
46
+ }
47
+ //# sourceMappingURL=metrics.plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.plugin.d.ts","sourceRoot":"","sources":["../src/metrics.plugin.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAgBvD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAAa,aAAc,YAAW,aAAa;IAKrC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJpC,QAAQ,CAAC,IAAI,aAAa;IAC1B,QAAQ,CAAC,OAAO,WAAW;IAC3B,QAAQ,CAAC,WAAW,8CAA8C;gBAErC,OAAO,GAAE,qBAA0B;IAEhE,YAAY,IAAI,QAAQ,EAAE;IAoB1B,UAAU,IAAI,KAAK,CAAC,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAC;IAI/C,cAAc,IAAI,IAAI,EAAE;CAOzB"}
@@ -0,0 +1,4 @@
1
+ export declare const METRICS_PLUGIN_OPTIONS: unique symbol;
2
+ export declare const METRICS_SERVICE: unique symbol;
3
+ export declare const METRICS_REGISTRY: unique symbol;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/shared/constants/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,sBAAsB,eAAuC,CAAC;AAC3E,eAAO,MAAM,eAAe,eAAgC,CAAC;AAC7D,eAAO,MAAM,gBAAgB,eAAiC,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { RedisXError } from '@nestjs-redisx/core';
2
+ export declare class MetricsError extends RedisXError {
3
+ constructor(message: string, cause?: Error);
4
+ }
5
+ export declare class MetricRegistrationError extends MetricsError {
6
+ constructor(metricName: string, cause?: Error);
7
+ }
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/shared/errors/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAa,MAAM,qBAAqB,CAAC;AAE7D,qBAAa,YAAa,SAAQ,WAAW;gBAC/B,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAG3C;AAED,qBAAa,uBAAwB,SAAQ,YAAY;gBAC3C,UAAU,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAG9C"}
@@ -0,0 +1,68 @@
1
+ export interface IMetricsPluginOptions {
2
+ /**
3
+ * Make the module global.
4
+ * @default false
5
+ */
6
+ isGlobal?: boolean;
7
+ /**
8
+ * Enable metrics collection.
9
+ * @default true
10
+ */
11
+ enabled?: boolean;
12
+ /**
13
+ * Metrics prefix.
14
+ * @default 'redisx_'
15
+ */
16
+ prefix?: string;
17
+ /**
18
+ * Default labels added to all metrics.
19
+ */
20
+ defaultLabels?: Record<string, string>;
21
+ /**
22
+ * Histogram buckets for latency (in seconds).
23
+ * @default [0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10]
24
+ */
25
+ histogramBuckets?: number[];
26
+ /**
27
+ * Expose /metrics endpoint.
28
+ * @default true
29
+ */
30
+ exposeEndpoint?: boolean;
31
+ /**
32
+ * Metrics endpoint path.
33
+ * Note: NestJS `@Controller()` path is a compile-time constant.
34
+ * This option is reserved for future use. The endpoint is always `/metrics`.
35
+ * @default '/metrics'
36
+ */
37
+ endpoint?: string;
38
+ /**
39
+ * Collect default Node.js metrics.
40
+ * @default true
41
+ */
42
+ collectDefaultMetrics?: boolean;
43
+ /**
44
+ * Enable detailed command metrics.
45
+ * @default true
46
+ */
47
+ commandMetrics?: boolean;
48
+ /**
49
+ * Enable plugin-specific metrics (cache, locks, etc).
50
+ * @default true
51
+ */
52
+ pluginMetrics?: boolean;
53
+ /**
54
+ * Collection interval for gauges (ms).
55
+ * @default 15000
56
+ */
57
+ collectInterval?: number;
58
+ }
59
+ export interface IMetricsJson {
60
+ name: string;
61
+ help: string;
62
+ type: string;
63
+ values: Array<{
64
+ labels: Record<string, string>;
65
+ value: number;
66
+ }>;
67
+ }
68
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/shared/types/index.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEvC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAE5B;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAEhC;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,KAAK,CAAC;QACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC/B,KAAK,EAAE,MAAM,CAAC;KACf,CAAC,CAAC;CACJ"}
package/package.json ADDED
@@ -0,0 +1,73 @@
1
+ {
2
+ "name": "@nestjs-redisx/metrics",
3
+ "version": "1.0.0",
4
+ "description": "Prometheus metrics plugin for NestJS RedisX with custom metrics support",
5
+ "author": "NestJS RedisX Team",
6
+ "license": "MIT",
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "require": "./dist/index.js",
13
+ "import": "./dist/index.js",
14
+ "default": "./dist/index.js"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "README.md",
20
+ "LICENSE"
21
+ ],
22
+ "scripts": {
23
+ "build": "tsup",
24
+ "test": "SKIP_INTEGRATION=true vitest run",
25
+ "test:watch": "SKIP_INTEGRATION=true vitest",
26
+ "test:cov": "SKIP_INTEGRATION=true vitest run --coverage",
27
+ "lint": "eslint \"{src,test}/**/*.ts\"",
28
+ "format": "prettier --write \"{src,test}/**/*.ts\""
29
+ },
30
+ "dependencies": {
31
+ "prom-client": "^15.1.0"
32
+ },
33
+ "keywords": [
34
+ "nestjs",
35
+ "redis",
36
+ "metrics",
37
+ "prometheus",
38
+ "monitoring",
39
+ "observability"
40
+ ],
41
+ "repository": {
42
+ "type": "git",
43
+ "url": "https://github.com/nestjs-redisx/nestjs-redisx.git",
44
+ "directory": "packages/metrics"
45
+ },
46
+ "homepage": "https://nestjs-redisx.dev/en/reference/metrics/",
47
+ "bugs": {
48
+ "url": "https://github.com/nestjs-redisx/nestjs-redisx/issues"
49
+ },
50
+ "peerDependencies": {
51
+ "@nestjs-redisx/core": "^1.0.0",
52
+ "@nestjs/common": "^10.0.0",
53
+ "@nestjs/core": "^10.0.0",
54
+ "reflect-metadata": "^0.2.0",
55
+ "rxjs": "^7.8.0"
56
+ },
57
+ "devDependencies": {
58
+ "@nestjs/testing": "^10.0.0",
59
+ "@types/express": "^4.17.0",
60
+ "@types/node": "^20.0.0",
61
+ "@typescript-eslint/eslint-plugin": "^6.0.0",
62
+ "@typescript-eslint/parser": "^6.0.0",
63
+ "eslint": "^8.0.0",
64
+ "prettier": "^3.0.0",
65
+ "tsup": "^8.0.0",
66
+ "typescript": "^5.3.0",
67
+ "vitest": "^1.6.0",
68
+ "@vitest/coverage-v8": "^1.6.0"
69
+ },
70
+ "publishConfig": {
71
+ "access": "public"
72
+ }
73
+ }