@adalo/metrics 0.1.65 → 0.1.67

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.
@@ -87,7 +87,7 @@ class QueueRedisMetricsClient extends RedisMetricsClient {
87
87
  * @returns {object|any} Redis config object for BeeQueue or Redis client instance
88
88
  */
89
89
  getConfigForDifferentRedis = () => {
90
- if (isIORedis(this.client)) {
90
+ if (isIORedis(this.redisClient)) {
91
91
  const {
92
92
  host,
93
93
  port,
@@ -1 +1 @@
1
- {"version":3,"file":"metricsQueueRedisClient.js","names":["Queue","require","RedisMetricsClient","isIORedis","QueueRedisMetricsClient","constructor","redisClient","metricsConfig","getConfiguredQueueNames","process","env","METRICS_APP_REDIS_BQ","Error","allQueues","split","map","q","trim","filter","Boolean","length","Set","startupValidation","queueNames","console","info","error","message","queueCache","Map","queueJobsGauge","createGauge","name","help","labelNames","withDefaultLabels","_setCleanupHandlers","getConfigForDifferentRedis","client","host","port","db","password","options","collectSingleQueueMetrics","queueName","has","set","redis","isWorker","getEvents","sendEvents","queue","get","health","checkHealth","labels","getDefaultLabels","queue_name","status","waiting","active","succeeded","failed","delayed","warn","collectQueueMetrics","collectRedisMetrics","Promise","allSettled","gatewayPush","metricsLogValues","metricObjects","registry","getMetricsAsJSON","JSON","stringify","includes","startPush","intervalSec","_startPush","catch","err","on","cleanup","close","exit","module","exports"],"sources":["../src/metricsQueueRedisClient.js"],"sourcesContent":["const Queue = require('bee-queue')\nconst { RedisMetricsClient } = require('.')\nconst { isIORedis } = require('./redisUtils')\n\n/**\n * QueueRedisMetricsClient extends MetricsClient to collect\n * Redis and Bee Queue metrics periodically and push them to Prometheus Pushgateway.\n *\n * @extends RedisMetricsClient\n */\nclass QueueRedisMetricsClient extends RedisMetricsClient {\n /**\n * @param {Object} options\n * @param {any} options.redisClient - Redis client instance (required)\n * @param {string} [options.appName] - Application name (from MetricsClient)\n * @param {string} [options.dynoId] - Dyno/instance ID (from MetricsClient)\n * @param {string} [options.processType] - Process type (from MetricsClient)\n * @param {boolean} [options.enabled] - Enable metrics collection (from MetricsClient)\n * @param {boolean} [options.logValues] - Log metrics values (from MetricsClient)\n * @param {string} [options.pushgatewayUrl] - PushGateway URL (from MetricsClient)\n * @param {string} [options.pushgatewaySecret] - PushGateway secret token (from MetricsClient)\n * @param {number} [options.intervalSec] - Interval in seconds for pushing metrics (from MetricsClient)\n * @param {boolean} [options.removeOldMetrics] - Remove old metrics by service (from MetricsClient)\n * @param {boolean} [options.scripDefaultMetrics] - Skip default metrics creation (from MetricsClient)\n * @param {function} [options.startupValidation] - Function to validate startup (from MetricsClient)\n */\n constructor({ redisClient, metricsConfig = {} } = {}) {\n const getConfiguredQueueNames = () => {\n if (!process.env.METRICS_APP_REDIS_BQ) {\n throw new Error(\n 'No queues configured for monitoring. Set METRICS_APP_REDIS_BQ with comma-separated queue names'\n )\n }\n\n const allQueues = process.env.METRICS_APP_REDIS_BQ.split(',')\n .map(q => q.trim())\n .filter(Boolean)\n\n if (allQueues.length === 0) {\n throw new Error(\n 'METRICS_APP_REDIS_BQ is empty or contains only whitespace. ' +\n 'Example: METRICS_APP_REDIS_BQ=\"adalo-compile,adalo-migrations\"'\n )\n }\n\n return [...new Set(allQueues)]\n }\n\n const startupValidation = () => {\n try {\n const queueNames = getConfiguredQueueNames()\n console.info(\n `[queue-metrics] Queue & Redis metrics collection starting for ${queueNames.length} queues`\n )\n return true\n } catch (error) {\n console.error(`[queue-metrics] ❌ Cannot start: ${error.message}`)\n console.error(\n `[queue-metrics] 💡 Example: METRICS_APP_REDIS_BQ=\"adalo-compile,adalo-migrations\"`\n )\n console.error(\n `[queue-metrics] 💡 Optional: METRICS_QUEUE_INTERVAL_SEC=\"10\"`\n )\n console.error(`[queue-metrics] Skipping queue metrics collection`)\n return false\n }\n }\n\n super({\n ...metricsConfig,\n redisClient,\n startupValidation,\n })\n\n this.getConfiguredQueueNames = getConfiguredQueueNames\n this.startupValidation = startupValidation\n\n /** Cache for queue objects to avoid multiple connections */\n this.queueCache = new Map()\n\n /** Gauge for queue jobs by status */\n this.queueJobsGauge = this.createGauge({\n name: 'app_queue_jobs_count',\n help: 'Number of app jobs in the queue by status',\n labelNames: this.withDefaultLabels(['queue_name', 'status']),\n })\n\n this._setCleanupHandlers()\n }\n\n /**\n * Get the correct Redis configuration for a queue depending on the client type\n *\n * For ioredis, returns { host, port, db, password } because BeeQueue\n * cannot accept the full client instance.\n * For other Redis clients (v3/v4), returns the client instance directly.\n *\n * @returns {object|any} Redis config object for BeeQueue or Redis client instance\n */\n getConfigForDifferentRedis = () => {\n if (isIORedis(this.client)) {\n const { host, port, db, password } = this.redisClient.options\n return { host, port, db, password }\n }\n\n return this.redisClient\n }\n\n /**\n * Collect metrics for a single Bee Queue and set gauges\n * @param {string} queueName - Name of the queue\n * @returns {Promise<void>}\n */\n collectSingleQueueMetrics = async queueName => {\n try {\n if (!this.queueCache.has(queueName)) {\n this.queueCache.set(\n queueName,\n new Queue(queueName, {\n redis: this.getConfigForDifferentRedis(),\n isWorker: false,\n getEvents: false,\n sendEvents: false,\n })\n )\n }\n\n const queue = this.queueCache.get(queueName)\n const health = await queue.checkHealth()\n\n const labels = {\n ...this.getDefaultLabels(),\n queue_name: queueName,\n }\n\n this.queueJobsGauge.set(\n { ...labels, status: 'waiting' },\n health.waiting || 0\n )\n this.queueJobsGauge.set(\n { ...labels, status: 'active' },\n health.active || 0\n )\n this.queueJobsGauge.set(\n { ...labels, status: 'succeeded' },\n health.succeeded || 0\n )\n this.queueJobsGauge.set(\n { ...labels, status: 'failed' },\n health.failed || 0\n )\n this.queueJobsGauge.set(\n { ...labels, status: 'delayed' },\n health.delayed || 0\n )\n } catch (error) {\n console.warn(\n `[queue-metrics] Failed to collect metrics for queue ${queueName}:`,\n error.message\n )\n }\n }\n\n /**\n * Collect metrics for all queues and Redis, then push to Pushgateway\n * @returns {Promise<void>}\n */\n collectQueueMetrics = async () => {\n try {\n const queueNames = this.getConfiguredQueueNames()\n\n await this.collectRedisMetrics()\n await Promise.allSettled(\n queueNames.map(queueName => this.collectSingleQueueMetrics(queueName))\n )\n\n await this.gatewayPush()\n\n if (this.metricsLogValues) {\n const metricObjects = await this.registry.getMetricsAsJSON()\n console.info(\n `[queue-metrics] Collected metrics for ${queueNames.length} queues:`,\n JSON.stringify(metricObjects, null, 2)\n )\n }\n } catch (error) {\n if (\n error.message?.includes('No queues configured') ||\n error.message?.includes('METRICS_APP_REDIS_BQ')\n ) {\n console.error(\n `[queue-metrics] ❌ Configuration error: ${error.message}`\n )\n console.error(\n `[queue-metrics] 💡 Example config: METRICS_APP_REDIS_BQ=\"adalo-compile,adalo-migrations\"`\n )\n } else {\n console.error(\n `[queue-metrics] Failed to collect queue metrics: ${error.message}`\n )\n }\n throw error\n }\n }\n\n /**\n * Start periodic collection.\n * @param {number} [intervalSec=this.intervalSec] - Interval in seconds\n */\n startPush = (intervalSec = this.intervalSec) => {\n this._startPush(intervalSec, () => {\n this.collectQueueMetrics().catch(err => {\n console.error(\n `[queue-metrics] Failed to collect queue & Redis metrics:`,\n err\n )\n })\n })\n }\n\n _setCleanupHandlers = () => {\n process.on('SIGINT', this.cleanup)\n process.on('SIGTERM', this.cleanup)\n }\n\n /**\n * Cleanup queues and exit process.\n * @returns {Promise<void>}\n */\n cleanup = async () => {\n for (const [queueName, queue] of this.queueCache) {\n try {\n await queue.close()\n } catch (err) {\n console.error(`[queue-metrics] Error closing queue ${queueName}:`, err)\n }\n }\n process.exit(0)\n }\n}\n\nmodule.exports = { QueueRedisMetricsClient }\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"metricsQueueRedisClient.js","names":["Queue","require","RedisMetricsClient","isIORedis","QueueRedisMetricsClient","constructor","redisClient","metricsConfig","getConfiguredQueueNames","process","env","METRICS_APP_REDIS_BQ","Error","allQueues","split","map","q","trim","filter","Boolean","length","Set","startupValidation","queueNames","console","info","error","message","queueCache","Map","queueJobsGauge","createGauge","name","help","labelNames","withDefaultLabels","_setCleanupHandlers","getConfigForDifferentRedis","host","port","db","password","options","collectSingleQueueMetrics","queueName","has","set","redis","isWorker","getEvents","sendEvents","queue","get","health","checkHealth","labels","getDefaultLabels","queue_name","status","waiting","active","succeeded","failed","delayed","warn","collectQueueMetrics","collectRedisMetrics","Promise","allSettled","gatewayPush","metricsLogValues","metricObjects","registry","getMetricsAsJSON","JSON","stringify","includes","startPush","intervalSec","_startPush","catch","err","on","cleanup","close","exit","module","exports"],"sources":["../src/metricsQueueRedisClient.js"],"sourcesContent":["const Queue = require('bee-queue')\nconst { RedisMetricsClient } = require('.')\nconst { isIORedis } = require('./redisUtils')\n\n/**\n * QueueRedisMetricsClient extends MetricsClient to collect\n * Redis and Bee Queue metrics periodically and push them to Prometheus Pushgateway.\n *\n * @extends RedisMetricsClient\n */\nclass QueueRedisMetricsClient extends RedisMetricsClient {\n /**\n * @param {Object} options\n * @param {any} options.redisClient - Redis client instance (required)\n * @param {string} [options.appName] - Application name (from MetricsClient)\n * @param {string} [options.dynoId] - Dyno/instance ID (from MetricsClient)\n * @param {string} [options.processType] - Process type (from MetricsClient)\n * @param {boolean} [options.enabled] - Enable metrics collection (from MetricsClient)\n * @param {boolean} [options.logValues] - Log metrics values (from MetricsClient)\n * @param {string} [options.pushgatewayUrl] - PushGateway URL (from MetricsClient)\n * @param {string} [options.pushgatewaySecret] - PushGateway secret token (from MetricsClient)\n * @param {number} [options.intervalSec] - Interval in seconds for pushing metrics (from MetricsClient)\n * @param {boolean} [options.removeOldMetrics] - Remove old metrics by service (from MetricsClient)\n * @param {boolean} [options.scripDefaultMetrics] - Skip default metrics creation (from MetricsClient)\n * @param {function} [options.startupValidation] - Function to validate startup (from MetricsClient)\n */\n constructor({ redisClient, metricsConfig = {} } = {}) {\n const getConfiguredQueueNames = () => {\n if (!process.env.METRICS_APP_REDIS_BQ) {\n throw new Error(\n 'No queues configured for monitoring. Set METRICS_APP_REDIS_BQ with comma-separated queue names'\n )\n }\n\n const allQueues = process.env.METRICS_APP_REDIS_BQ.split(',')\n .map(q => q.trim())\n .filter(Boolean)\n\n if (allQueues.length === 0) {\n throw new Error(\n 'METRICS_APP_REDIS_BQ is empty or contains only whitespace. ' +\n 'Example: METRICS_APP_REDIS_BQ=\"adalo-compile,adalo-migrations\"'\n )\n }\n\n return [...new Set(allQueues)]\n }\n\n const startupValidation = () => {\n try {\n const queueNames = getConfiguredQueueNames()\n console.info(\n `[queue-metrics] Queue & Redis metrics collection starting for ${queueNames.length} queues`\n )\n return true\n } catch (error) {\n console.error(`[queue-metrics] ❌ Cannot start: ${error.message}`)\n console.error(\n `[queue-metrics] 💡 Example: METRICS_APP_REDIS_BQ=\"adalo-compile,adalo-migrations\"`\n )\n console.error(\n `[queue-metrics] 💡 Optional: METRICS_QUEUE_INTERVAL_SEC=\"10\"`\n )\n console.error(`[queue-metrics] Skipping queue metrics collection`)\n return false\n }\n }\n\n super({\n ...metricsConfig,\n redisClient,\n startupValidation,\n })\n\n this.getConfiguredQueueNames = getConfiguredQueueNames\n this.startupValidation = startupValidation\n\n /** Cache for queue objects to avoid multiple connections */\n this.queueCache = new Map()\n\n /** Gauge for queue jobs by status */\n this.queueJobsGauge = this.createGauge({\n name: 'app_queue_jobs_count',\n help: 'Number of app jobs in the queue by status',\n labelNames: this.withDefaultLabels(['queue_name', 'status']),\n })\n\n this._setCleanupHandlers()\n }\n\n /**\n * Get the correct Redis configuration for a queue depending on the client type\n *\n * For ioredis, returns { host, port, db, password } because BeeQueue\n * cannot accept the full client instance.\n * For other Redis clients (v3/v4), returns the client instance directly.\n *\n * @returns {object|any} Redis config object for BeeQueue or Redis client instance\n */\n getConfigForDifferentRedis = () => {\n if (isIORedis(this.redisClient)) {\n const { host, port, db, password } = this.redisClient.options\n return { host, port, db, password }\n }\n\n return this.redisClient\n }\n\n /**\n * Collect metrics for a single Bee Queue and set gauges\n * @param {string} queueName - Name of the queue\n * @returns {Promise<void>}\n */\n collectSingleQueueMetrics = async queueName => {\n try {\n if (!this.queueCache.has(queueName)) {\n this.queueCache.set(\n queueName,\n new Queue(queueName, {\n redis: this.getConfigForDifferentRedis(),\n isWorker: false,\n getEvents: false,\n sendEvents: false,\n })\n )\n }\n\n const queue = this.queueCache.get(queueName)\n const health = await queue.checkHealth()\n\n const labels = {\n ...this.getDefaultLabels(),\n queue_name: queueName,\n }\n\n this.queueJobsGauge.set(\n { ...labels, status: 'waiting' },\n health.waiting || 0\n )\n this.queueJobsGauge.set(\n { ...labels, status: 'active' },\n health.active || 0\n )\n this.queueJobsGauge.set(\n { ...labels, status: 'succeeded' },\n health.succeeded || 0\n )\n this.queueJobsGauge.set(\n { ...labels, status: 'failed' },\n health.failed || 0\n )\n this.queueJobsGauge.set(\n { ...labels, status: 'delayed' },\n health.delayed || 0\n )\n } catch (error) {\n console.warn(\n `[queue-metrics] Failed to collect metrics for queue ${queueName}:`,\n error.message\n )\n }\n }\n\n /**\n * Collect metrics for all queues and Redis, then push to Pushgateway\n * @returns {Promise<void>}\n */\n collectQueueMetrics = async () => {\n try {\n const queueNames = this.getConfiguredQueueNames()\n\n await this.collectRedisMetrics()\n await Promise.allSettled(\n queueNames.map(queueName => this.collectSingleQueueMetrics(queueName))\n )\n\n await this.gatewayPush()\n\n if (this.metricsLogValues) {\n const metricObjects = await this.registry.getMetricsAsJSON()\n console.info(\n `[queue-metrics] Collected metrics for ${queueNames.length} queues:`,\n JSON.stringify(metricObjects, null, 2)\n )\n }\n } catch (error) {\n if (\n error.message?.includes('No queues configured') ||\n error.message?.includes('METRICS_APP_REDIS_BQ')\n ) {\n console.error(\n `[queue-metrics] ❌ Configuration error: ${error.message}`\n )\n console.error(\n `[queue-metrics] 💡 Example config: METRICS_APP_REDIS_BQ=\"adalo-compile,adalo-migrations\"`\n )\n } else {\n console.error(\n `[queue-metrics] Failed to collect queue metrics: ${error.message}`\n )\n }\n throw error\n }\n }\n\n /**\n * Start periodic collection.\n * @param {number} [intervalSec=this.intervalSec] - Interval in seconds\n */\n startPush = (intervalSec = this.intervalSec) => {\n this._startPush(intervalSec, () => {\n this.collectQueueMetrics().catch(err => {\n console.error(\n `[queue-metrics] Failed to collect queue & Redis metrics:`,\n err\n )\n })\n })\n }\n\n _setCleanupHandlers = () => {\n process.on('SIGINT', this.cleanup)\n process.on('SIGTERM', this.cleanup)\n }\n\n /**\n * Cleanup queues and exit process.\n * @returns {Promise<void>}\n */\n cleanup = async () => {\n for (const [queueName, queue] of this.queueCache) {\n try {\n await queue.close()\n } catch (err) {\n console.error(`[queue-metrics] Error closing queue ${queueName}:`, err)\n }\n }\n process.exit(0)\n }\n}\n\nmodule.exports = { QueueRedisMetricsClient }\n"],"mappings":"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","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"metricsRedisClient.d.ts","sourceRoot":"","sources":["../src/metricsRedisClient.js"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH;IACE;;;;;;;;;;;;;;OAcG;IACH;QAbwB,WAAW,EAAxB,GAAG;QACc,OAAO;QACP,MAAM;QACN,WAAW;QACV,OAAO;QACP,SAAS;QACV,cAAc;QACd,iBAAiB;QACjB,WAAW;QACV,gBAAgB;QAChB,mBAAmB;QAClB,iBAAiB;OAwC9C;IAzBC,oCAAoC;IACpC,iBAA8B;IAE9B,yCAAyC;IACzC,2DAIE;IAEF,mCAAmC;IACnC,sDAIE;IAEF,sCAAsC;IACtC,qDAIE;IAKJ,6CAgCC;IAED;;;OAGG;IACH,2BAFa,QAAQ,IAAI,CAAC,CAyDzB;IAED;;;OAGG;IACH,wBAFa,QAAQ,IAAI,CAAC,CAoBzB;IAED;;;OAGG;IACH,sDAMC;CA2BF"}
1
+ {"version":3,"file":"metricsRedisClient.d.ts","sourceRoot":"","sources":["../src/metricsRedisClient.js"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH;IACE;;;;;;;;;;;;;;OAcG;IACH;QAbwB,WAAW,EAAxB,GAAG;QACc,OAAO;QACP,MAAM;QACN,WAAW;QACV,OAAO;QACP,SAAS;QACV,cAAc;QACd,iBAAiB;QACjB,WAAW;QACV,gBAAgB;QAChB,mBAAmB;QAClB,iBAAiB;OAwC9C;IAzBC,oCAAoC;IACpC,iBAA8B;IAE9B,yCAAyC;IACzC,2DAIE;IAEF,mCAAmC;IACnC,sDAIE;IAEF,sCAAsC;IACtC,qDAIE;IAKJ,6CA2CC;IAED;;;OAGG;IACH,2BAFa,QAAQ,IAAI,CAAC,CAyDzB;IAED;;;OAGG;IACH,wBAFa,QAAQ,IAAI,CAAC,CAoBzB;IAED;;;OAGG;IACH,sDAMC;CA2BF"}
@@ -3,6 +3,9 @@
3
3
  const {
4
4
  MetricsClient
5
5
  } = require('.');
6
+ const {
7
+ isIORedis
8
+ } = require('./redisUtils');
6
9
 
7
10
  /**
8
11
  * RedisMetricsClient extends MetricsClient to collect
@@ -68,6 +71,17 @@ class RedisMetricsClient extends MetricsClient {
68
71
  console.log('Redis client constructor name:', this.redisClient.constructor.name);
69
72
  console.log('Redis client info function:', this.redisClient.info);
70
73
 
74
+ // node-redis ioredis
75
+ if (isIORedis(this.redisClient)) {
76
+ console.log('Detected node-redis ioredis');
77
+ try {
78
+ const result = await this.redisClient.info(section);
79
+ return result;
80
+ } catch (err) {
81
+ throw new Error(`Failed to get Redis INFO: ${err.message}`);
82
+ }
83
+ }
84
+
71
85
  // node-redis v3 (uses callback)
72
86
  if (typeof this.redisClient.send_command === 'function') {
73
87
  console.log('Detected node-redis v3');
@@ -80,7 +94,7 @@ class RedisMetricsClient extends MetricsClient {
80
94
 
81
95
  // node-redis v4 or ioredis (info returns Promise)
82
96
  if (typeof this.redisClient.info === 'function') {
83
- console.log('Detected node-redis v4 or ioredis');
97
+ console.log('Detected node-redis v4');
84
98
  try {
85
99
  const result = await this.redisClient.info(section);
86
100
  return result;
@@ -1 +1 @@
1
- {"version":3,"file":"metricsRedisClient.js","names":["MetricsClient","require","RedisMetricsClient","constructor","redisClient","metricsConfig","intervalSec","parseInt","process","env","METRICS_QUEUE_INTERVAL_SEC","scripDefaultMetrics","processType","redisConnectionsGauge","createGauge","name","help","labelNames","withDefaultLabels","redisMemoryGauge","redisStatsGauge","_setCleanupHandlers","getRedisInfo","section","Error","console","log","info","send_command","Promise","resolve","reject","err","result","message","collectRedisMetrics","clientsInfo","memoryInfo","statsInfo","all","labels","getDefaultLabels","parseRedisInfo","infoStr","Object","fromEntries","split","filter","line","startsWith","map","parts","length","clients","memory","stats","connected_clients","set","connection_type","used_memory","memory_type","maxmemory","instantaneous_ops_per_sec","operation","error","warn","pushRedisMetrics","gatewayPush","metricsLogValues","metricObjects","registry","getMetricsAsJSON","JSON","stringify","startPush","_startPush","catch","cleanup","quit","disconnect","exit","on","module","exports"],"sources":["../src/metricsRedisClient.js"],"sourcesContent":["const { MetricsClient } = require('.')\n\n/**\n * RedisMetricsClient extends MetricsClient to collect\n * Redis metrics periodically and push them to Prometheus Pushgateway.\n *\n * @extends MetricsClient\n */\nclass RedisMetricsClient extends MetricsClient {\n /**\n * @param {Object} options\n * @param {any} options.redisClient - Redis client instance (required)\n * @param {string} [options.appName] - Application name (from MetricsClient)\n * @param {string} [options.dynoId] - Dyno/instance ID (from MetricsClient)\n * @param {string} [options.processType] - Process type (from MetricsClient)\n * @param {boolean} [options.enabled] - Enable metrics collection (from MetricsClient)\n * @param {boolean} [options.logValues] - Log metrics values (from MetricsClient)\n * @param {string} [options.pushgatewayUrl] - PushGateway URL (from MetricsClient)\n * @param {string} [options.pushgatewaySecret] - PushGateway secret token (from MetricsClient)\n * @param {number} [options.intervalSec] - Interval in seconds for pushing metrics (from MetricsClient)\n * @param {boolean} [options.removeOldMetrics] - Remove old metrics by service (from MetricsClient)\n * @param {boolean} [options.scripDefaultMetrics] - Skip default metrics creation (from MetricsClient)\n * @param {function} [options.startupValidation] - Function to validate startup (from MetricsClient)\n */\n constructor({ redisClient, ...metricsConfig } = {}) {\n const intervalSec =\n metricsConfig.intervalSec ||\n parseInt(process.env.METRICS_QUEUE_INTERVAL_SEC || '', 10) ||\n 5\n\n super({\n ...metricsConfig,\n scripDefaultMetrics: true,\n processType: metricsConfig.processType || 'redis-metrics',\n intervalSec,\n })\n\n /** Redis client used for metrics */\n this.redisClient = redisClient\n\n /** Gauge for Redis client connections */\n this.redisConnectionsGauge = this.createGauge({\n name: 'app_redis_connections_count',\n help: 'Number of Redis client connections',\n labelNames: this.withDefaultLabels(['connection_type']),\n })\n\n /** Gauge for Redis memory usage */\n this.redisMemoryGauge = this.createGauge({\n name: 'app_redis_memory_bytes',\n help: 'Redis memory usage in bytes',\n labelNames: this.withDefaultLabels(['memory_type']),\n })\n\n /** Gauge for Redis operation stats */\n this.redisStatsGauge = this.createGauge({\n name: 'app_redis_stats_total',\n help: 'Redis operation statistics',\n labelNames: this.withDefaultLabels(['operation']),\n })\n\n this._setCleanupHandlers()\n }\n\n getRedisInfo = async section => {\n if (!this.redisClient) throw new Error('Redis client not provided')\n\n console.log(\n 'Redis client constructor name:',\n this.redisClient.constructor.name\n )\n console.log('Redis client info function:', this.redisClient.info)\n\n // node-redis v3 (uses callback)\n if (typeof this.redisClient.send_command === 'function') {\n console.log('Detected node-redis v3')\n return new Promise((resolve, reject) => {\n this.redisClient.info(section, (err, result) => {\n if (err) reject(err)\n else resolve(result)\n })\n })\n }\n\n // node-redis v4 or ioredis (info returns Promise)\n if (typeof this.redisClient.info === 'function') {\n console.log('Detected node-redis v4 or ioredis')\n try {\n const result = await this.redisClient.info(section)\n return result\n } catch (err) {\n throw new Error(`Failed to get Redis INFO: ${err.message}`)\n }\n }\n\n throw new Error('Unsupported Redis client type')\n }\n\n /**\n * Collect basic Redis INFO metrics: clients, memory, stats\n * @returns {Promise<void>}\n */\n collectRedisMetrics = async () => {\n try {\n const [clientsInfo, memoryInfo, statsInfo] = await Promise.all([\n this.getRedisInfo('clients'),\n this.getRedisInfo('memory'),\n this.getRedisInfo('stats'),\n ])\n\n const labels = this.getDefaultLabels()\n\n const parseRedisInfo = infoStr =>\n Object.fromEntries(\n infoStr\n .split('\\r\\n')\n .filter(line => line && !line.startsWith('#'))\n .map(line => line.split(':', 2))\n .filter(parts => parts.length === 2 && parts[0] && parts[1])\n )\n\n const clients = parseRedisInfo(clientsInfo)\n const memory = parseRedisInfo(memoryInfo)\n const stats = parseRedisInfo(statsInfo)\n\n if (clients.connected_clients) {\n this.redisConnectionsGauge.set(\n { ...labels, connection_type: 'connected' },\n parseInt(clients.connected_clients, 10) || 0\n )\n }\n\n if (memory.used_memory) {\n this.redisMemoryGauge.set(\n { ...labels, memory_type: 'used' },\n parseInt(memory.used_memory, 10) || 0\n )\n }\n if (memory.maxmemory) {\n this.redisMemoryGauge.set(\n { ...labels, memory_type: 'max' },\n parseInt(memory.maxmemory, 10) || 0\n )\n }\n\n if (stats.instantaneous_ops_per_sec) {\n this.redisStatsGauge.set(\n { ...labels, operation: 'ops_per_sec' },\n parseInt(stats.instantaneous_ops_per_sec, 10) || 0\n )\n }\n } catch (error) {\n console.warn(\n `[redis-metrics] Failed to collect Redis metrics:`,\n error.message\n )\n }\n }\n\n /**\n * Collect metrics for all Redis and push to Prometheus Pushgateway\n * @returns {Promise<void>}\n */\n pushRedisMetrics = async () => {\n try {\n await this.collectRedisMetrics()\n await this.gatewayPush()\n\n if (this.metricsLogValues) {\n const metricObjects = await this.registry.getMetricsAsJSON()\n console.info(\n `[redis-metrics] Collected metrics for Redis`,\n JSON.stringify(metricObjects, null, 2)\n )\n }\n } catch (error) {\n console.error(\n `[redis-metrics] Failed to collect Redis metrics: ${error.message}`\n )\n throw error\n }\n }\n\n /**\n * Start periodic collection.\n * @param {number} [intervalSec=this.intervalSec] - Interval in seconds\n */\n startPush = (intervalSec = this.intervalSec) => {\n this._startPush(intervalSec, () => {\n this.pushRedisMetrics().catch(err => {\n console.error(`[redis-metrics] Failed to push Redis metrics:`, err)\n })\n })\n }\n\n /**\n * Cleanup Redis client and exit process.\n * @returns {Promise<void>}\n */\n cleanup = async () => {\n try {\n if (!this.redisClient) return\n\n if (typeof this.redisClient.quit === 'function') {\n // node-redis v3 or v4\n await this.redisClient.quit()\n } else if (typeof this.redisClient.disconnect === 'function') {\n // ioredis\n await this.redisClient.disconnect()\n }\n } catch (err) {\n console.error('[redis-metrics] Error closing Redis client:', err)\n }\n process.exit(0)\n }\n\n _setCleanupHandlers = () => {\n process.on('SIGINT', this.cleanup)\n process.on('SIGTERM', this.cleanup)\n }\n}\n\nmodule.exports = { RedisMetricsClient }\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"metricsRedisClient.js","names":["MetricsClient","require","isIORedis","RedisMetricsClient","constructor","redisClient","metricsConfig","intervalSec","parseInt","process","env","METRICS_QUEUE_INTERVAL_SEC","scripDefaultMetrics","processType","redisConnectionsGauge","createGauge","name","help","labelNames","withDefaultLabels","redisMemoryGauge","redisStatsGauge","_setCleanupHandlers","getRedisInfo","section","Error","console","log","info","result","err","message","send_command","Promise","resolve","reject","collectRedisMetrics","clientsInfo","memoryInfo","statsInfo","all","labels","getDefaultLabels","parseRedisInfo","infoStr","Object","fromEntries","split","filter","line","startsWith","map","parts","length","clients","memory","stats","connected_clients","set","connection_type","used_memory","memory_type","maxmemory","instantaneous_ops_per_sec","operation","error","warn","pushRedisMetrics","gatewayPush","metricsLogValues","metricObjects","registry","getMetricsAsJSON","JSON","stringify","startPush","_startPush","catch","cleanup","quit","disconnect","exit","on","module","exports"],"sources":["../src/metricsRedisClient.js"],"sourcesContent":["const { MetricsClient } = require('.')\nconst { isIORedis } = require('./redisUtils')\n\n/**\n * RedisMetricsClient extends MetricsClient to collect\n * Redis metrics periodically and push them to Prometheus Pushgateway.\n *\n * @extends MetricsClient\n */\nclass RedisMetricsClient extends MetricsClient {\n /**\n * @param {Object} options\n * @param {any} options.redisClient - Redis client instance (required)\n * @param {string} [options.appName] - Application name (from MetricsClient)\n * @param {string} [options.dynoId] - Dyno/instance ID (from MetricsClient)\n * @param {string} [options.processType] - Process type (from MetricsClient)\n * @param {boolean} [options.enabled] - Enable metrics collection (from MetricsClient)\n * @param {boolean} [options.logValues] - Log metrics values (from MetricsClient)\n * @param {string} [options.pushgatewayUrl] - PushGateway URL (from MetricsClient)\n * @param {string} [options.pushgatewaySecret] - PushGateway secret token (from MetricsClient)\n * @param {number} [options.intervalSec] - Interval in seconds for pushing metrics (from MetricsClient)\n * @param {boolean} [options.removeOldMetrics] - Remove old metrics by service (from MetricsClient)\n * @param {boolean} [options.scripDefaultMetrics] - Skip default metrics creation (from MetricsClient)\n * @param {function} [options.startupValidation] - Function to validate startup (from MetricsClient)\n */\n constructor({ redisClient, ...metricsConfig } = {}) {\n const intervalSec =\n metricsConfig.intervalSec ||\n parseInt(process.env.METRICS_QUEUE_INTERVAL_SEC || '', 10) ||\n 5\n\n super({\n ...metricsConfig,\n scripDefaultMetrics: true,\n processType: metricsConfig.processType || 'redis-metrics',\n intervalSec,\n })\n\n /** Redis client used for metrics */\n this.redisClient = redisClient\n\n /** Gauge for Redis client connections */\n this.redisConnectionsGauge = this.createGauge({\n name: 'app_redis_connections_count',\n help: 'Number of Redis client connections',\n labelNames: this.withDefaultLabels(['connection_type']),\n })\n\n /** Gauge for Redis memory usage */\n this.redisMemoryGauge = this.createGauge({\n name: 'app_redis_memory_bytes',\n help: 'Redis memory usage in bytes',\n labelNames: this.withDefaultLabels(['memory_type']),\n })\n\n /** Gauge for Redis operation stats */\n this.redisStatsGauge = this.createGauge({\n name: 'app_redis_stats_total',\n help: 'Redis operation statistics',\n labelNames: this.withDefaultLabels(['operation']),\n })\n\n this._setCleanupHandlers()\n }\n\n getRedisInfo = async section => {\n if (!this.redisClient) throw new Error('Redis client not provided')\n\n console.log(\n 'Redis client constructor name:',\n this.redisClient.constructor.name\n )\n console.log('Redis client info function:', this.redisClient.info)\n\n // node-redis ioredis\n if (isIORedis(this.redisClient)) {\n console.log('Detected node-redis ioredis')\n try {\n const result = await this.redisClient.info(section)\n return result\n } catch (err) {\n throw new Error(`Failed to get Redis INFO: ${err.message}`)\n }\n }\n\n // node-redis v3 (uses callback)\n if (typeof this.redisClient.send_command === 'function') {\n console.log('Detected node-redis v3')\n return new Promise((resolve, reject) => {\n this.redisClient.info(section, (err, result) => {\n if (err) reject(err)\n else resolve(result)\n })\n })\n }\n\n // node-redis v4 or ioredis (info returns Promise)\n if (typeof this.redisClient.info === 'function') {\n console.log('Detected node-redis v4')\n try {\n const result = await this.redisClient.info(section)\n return result\n } catch (err) {\n throw new Error(`Failed to get Redis INFO: ${err.message}`)\n }\n }\n\n throw new Error('Unsupported Redis client type')\n }\n\n /**\n * Collect basic Redis INFO metrics: clients, memory, stats\n * @returns {Promise<void>}\n */\n collectRedisMetrics = async () => {\n try {\n const [clientsInfo, memoryInfo, statsInfo] = await Promise.all([\n this.getRedisInfo('clients'),\n this.getRedisInfo('memory'),\n this.getRedisInfo('stats'),\n ])\n\n const labels = this.getDefaultLabels()\n\n const parseRedisInfo = infoStr =>\n Object.fromEntries(\n infoStr\n .split('\\r\\n')\n .filter(line => line && !line.startsWith('#'))\n .map(line => line.split(':', 2))\n .filter(parts => parts.length === 2 && parts[0] && parts[1])\n )\n\n const clients = parseRedisInfo(clientsInfo)\n const memory = parseRedisInfo(memoryInfo)\n const stats = parseRedisInfo(statsInfo)\n\n if (clients.connected_clients) {\n this.redisConnectionsGauge.set(\n { ...labels, connection_type: 'connected' },\n parseInt(clients.connected_clients, 10) || 0\n )\n }\n\n if (memory.used_memory) {\n this.redisMemoryGauge.set(\n { ...labels, memory_type: 'used' },\n parseInt(memory.used_memory, 10) || 0\n )\n }\n if (memory.maxmemory) {\n this.redisMemoryGauge.set(\n { ...labels, memory_type: 'max' },\n parseInt(memory.maxmemory, 10) || 0\n )\n }\n\n if (stats.instantaneous_ops_per_sec) {\n this.redisStatsGauge.set(\n { ...labels, operation: 'ops_per_sec' },\n parseInt(stats.instantaneous_ops_per_sec, 10) || 0\n )\n }\n } catch (error) {\n console.warn(\n `[redis-metrics] Failed to collect Redis metrics:`,\n error.message\n )\n }\n }\n\n /**\n * Collect metrics for all Redis and push to Prometheus Pushgateway\n * @returns {Promise<void>}\n */\n pushRedisMetrics = async () => {\n try {\n await this.collectRedisMetrics()\n await this.gatewayPush()\n\n if (this.metricsLogValues) {\n const metricObjects = await this.registry.getMetricsAsJSON()\n console.info(\n `[redis-metrics] Collected metrics for Redis`,\n JSON.stringify(metricObjects, null, 2)\n )\n }\n } catch (error) {\n console.error(\n `[redis-metrics] Failed to collect Redis metrics: ${error.message}`\n )\n throw error\n }\n }\n\n /**\n * Start periodic collection.\n * @param {number} [intervalSec=this.intervalSec] - Interval in seconds\n */\n startPush = (intervalSec = this.intervalSec) => {\n this._startPush(intervalSec, () => {\n this.pushRedisMetrics().catch(err => {\n console.error(`[redis-metrics] Failed to push Redis metrics:`, err)\n })\n })\n }\n\n /**\n * Cleanup Redis client and exit process.\n * @returns {Promise<void>}\n */\n cleanup = async () => {\n try {\n if (!this.redisClient) return\n\n if (typeof this.redisClient.quit === 'function') {\n // node-redis v3 or v4\n await this.redisClient.quit()\n } else if (typeof this.redisClient.disconnect === 'function') {\n // ioredis\n await this.redisClient.disconnect()\n }\n } catch (err) {\n console.error('[redis-metrics] Error closing Redis client:', err)\n }\n process.exit(0)\n }\n\n _setCleanupHandlers = () => {\n process.on('SIGINT', this.cleanup)\n process.on('SIGTERM', this.cleanup)\n }\n}\n\nmodule.exports = { RedisMetricsClient }\n"],"mappings":"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","ignoreList":[]}
@@ -23,7 +23,7 @@ export function createSetClientNameForIoredis(defaultAppName?: string | undefine
23
23
  * Check if a Redis client is an ioredis instance
24
24
  *
25
25
  * @param {any} client - Redis client instance
26
- * @returns {boolean} True if the client is ioredis, false otherwise
26
+ * @returns {boolean} True if the client is ioredis
27
27
  */
28
28
  export function isIORedis(client: any): boolean;
29
29
  //# sourceMappingURL=redisUtils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"redisUtils.d.ts","sourceRoot":"","sources":["../src/redisUtils.js"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,6FAFsB,GAAG,QAAQ,MAAM,KAAK,IAAI,CAuB/C;AA4BD;;;;;GAKG;AACH,6FAFsB,GAAG,QAAQ,MAAM,KAAK,IAAI,CAsB/C;AApDD;;;;;GAKG;AACH,6FAFsB,GAAG,QAAQ,MAAM,KAAK,IAAI,CAoB/C;AA8BD;;;;;GAKG;AACH,kCAHW,GAAG,GACD,OAAO,CAUnB"}
1
+ {"version":3,"file":"redisUtils.d.ts","sourceRoot":"","sources":["../src/redisUtils.js"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,6FAFsB,GAAG,QAAQ,MAAM,KAAK,IAAI,CAuB/C;AA4BD;;;;;GAKG;AACH,6FAFsB,GAAG,QAAQ,MAAM,KAAK,IAAI,CAsB/C;AApDD;;;;;GAKG;AACH,6FAFsB,GAAG,QAAQ,MAAM,KAAK,IAAI,CAoB/C;AA8BD;;;;;GAKG;AACH,kCAHW,GAAG,GACD,OAAO,CAiBnB"}
package/lib/redisUtils.js CHANGED
@@ -73,10 +73,18 @@ const createSetClientNameForRedisV4 = (defaultAppName = 'undefined-app') => {
73
73
  * Check if a Redis client is an ioredis instance
74
74
  *
75
75
  * @param {any} client - Redis client instance
76
- * @returns {boolean} True if the client is ioredis, false otherwise
76
+ * @returns {boolean} True if the client is ioredis
77
77
  */
78
78
  const isIORedis = client => {
79
- return client && typeof client.connect === 'function' && typeof client.disconnect === 'function' && client.status !== undefined && client.options !== undefined;
79
+ const result = client && typeof client.sendCommand === 'function' && typeof client.disconnect === 'function' && client.options !== undefined;
80
+ console.log('[debug] isIORedis client.sendCommand:', client.sendCommand);
81
+ console.log('[debug] isIORedis client.sendCommand === \'function\':', typeof client.sendCommand === 'function');
82
+ console.log('[debug] isIORedis client.disconnect:', client.disconnect);
83
+ console.log('[debug] isIORedis client.disconnect === \'function\':', typeof client.disconnect === 'function');
84
+ console.log('[debug] isIORedis client.options:', client.options);
85
+ console.log('[debug] isIORedis client.options !== undefined:', client.options !== undefined);
86
+ console.log('[debug] isIORedis check:', result, 'constructor:', client?.constructor?.name);
87
+ return result;
80
88
  };
81
89
  module.exports = {
82
90
  createSetClientNameForRedisV3,
@@ -1 +1 @@
1
- {"version":3,"file":"redisUtils.js","names":["createSetClientNameForRedisV3","defaultAppName","client","name","appName","process","env","METRICS_APP_NAME","dyno","BUILD_DYNO_PROCESS_TYPE","NODE_ENV","on","send_command","err","console","error","log","pid","createSetClientNameForIoredis","once","call","then","catch","createSetClientNameForRedisV4","sendCommand","isIORedis","connect","disconnect","status","undefined","options","module","exports"],"sources":["../src/redisUtils.js"],"sourcesContent":["/**\n * Creates a configured setClientName function for node-redis v3.\n *\n * @param {string} [defaultAppName='undefined-app'] - Fallback app name if METRICS_APP_NAME is not set.\n * @returns {(client: any, name: string) => void}\n */\nconst createSetClientNameForRedisV3 = (defaultAppName = 'undefined-app') => {\n return (client, name) => {\n const appName = process.env.METRICS_APP_NAME || defaultAppName\n const dyno = process.env.BUILD_DYNO_PROCESS_TYPE || 'undefined-dyno'\n\n if (process.env.NODE_ENV !== 'test') {\n client.on('connect', () => {\n client.send_command(\n 'CLIENT',\n ['SETNAME', `${appName}:${dyno}:${name}`],\n err => {\n if (err) {\n console.error(`Failed to set client name for ${name}:`, err)\n } else {\n console.log(`Connected to Redis for pid:${process.pid} (${name})`)\n }\n }\n )\n })\n }\n }\n}\n\n/**\n * Creates a function to set Redis client name for ioredis.\n *\n * @param {string} [defaultAppName='undefined-app']\n * @returns {(client: any, name: string) => void}\n */\nconst createSetClientNameForIoredis = (defaultAppName = 'undefined-app') => {\n return (client, name) => {\n const appName = process.env.METRICS_APP_NAME || defaultAppName\n const dyno = process.env.BUILD_DYNO_PROCESS_TYPE || 'undefined-dyno'\n\n if (process.env.NODE_ENV !== 'test') {\n client.once('connect', () => {\n client\n .call('CLIENT', ['SETNAME', `${appName}:${dyno}:${name}`])\n .then(() => {\n console.log(`Connected to Redis for pid:${process.pid} (${name})`)\n })\n .catch(err => {\n console.error(`Failed to set client name for ${name}:`, err)\n })\n })\n }\n }\n}\n\n/**\n * Creates a function to set Redis client name for node-redis v4.\n *\n * @param {string} [defaultAppName='undefined-app']\n * @returns {(client: any, name: string) => void}\n */\nconst createSetClientNameForRedisV4 = (defaultAppName = 'undefined-app') => {\n return (client, name) => {\n const appName = process.env.METRICS_APP_NAME || defaultAppName\n const dyno = process.env.BUILD_DYNO_PROCESS_TYPE || 'undefined-dyno'\n\n if (process.env.NODE_ENV !== 'test') {\n client.on('ready', async () => {\n try {\n await client.sendCommand([\n 'CLIENT',\n 'SETNAME',\n `${appName}:${dyno}:${name}`,\n ])\n console.log(`Connected to Redis for pid:${process.pid} (${name})`)\n } catch (err) {\n console.error(`Failed to set client name for ${name}:`, err)\n }\n })\n }\n }\n}\n\n/**\n * Check if a Redis client is an ioredis instance\n *\n * @param {any} client - Redis client instance\n * @returns {boolean} True if the client is ioredis, false otherwise\n */\nconst isIORedis = client => {\n return (\n client &&\n typeof client.connect === 'function' &&\n typeof client.disconnect === 'function' &&\n client.status !== undefined &&\n client.options !== undefined\n )\n}\n\nmodule.exports = {\n createSetClientNameForRedisV3,\n createSetClientNameForRedisV4,\n createSetClientNameForIoredis,\n isIORedis,\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"redisUtils.js","names":["createSetClientNameForRedisV3","defaultAppName","client","name","appName","process","env","METRICS_APP_NAME","dyno","BUILD_DYNO_PROCESS_TYPE","NODE_ENV","on","send_command","err","console","error","log","pid","createSetClientNameForIoredis","once","call","then","catch","createSetClientNameForRedisV4","sendCommand","isIORedis","result","disconnect","options","undefined","constructor","module","exports"],"sources":["../src/redisUtils.js"],"sourcesContent":["/**\n * Creates a configured setClientName function for node-redis v3.\n *\n * @param {string} [defaultAppName='undefined-app'] - Fallback app name if METRICS_APP_NAME is not set.\n * @returns {(client: any, name: string) => void}\n */\nconst createSetClientNameForRedisV3 = (defaultAppName = 'undefined-app') => {\n return (client, name) => {\n const appName = process.env.METRICS_APP_NAME || defaultAppName\n const dyno = process.env.BUILD_DYNO_PROCESS_TYPE || 'undefined-dyno'\n\n if (process.env.NODE_ENV !== 'test') {\n client.on('connect', () => {\n client.send_command(\n 'CLIENT',\n ['SETNAME', `${appName}:${dyno}:${name}`],\n err => {\n if (err) {\n console.error(`Failed to set client name for ${name}:`, err)\n } else {\n console.log(`Connected to Redis for pid:${process.pid} (${name})`)\n }\n }\n )\n })\n }\n }\n}\n\n/**\n * Creates a function to set Redis client name for ioredis.\n *\n * @param {string} [defaultAppName='undefined-app']\n * @returns {(client: any, name: string) => void}\n */\nconst createSetClientNameForIoredis = (defaultAppName = 'undefined-app') => {\n return (client, name) => {\n const appName = process.env.METRICS_APP_NAME || defaultAppName\n const dyno = process.env.BUILD_DYNO_PROCESS_TYPE || 'undefined-dyno'\n\n if (process.env.NODE_ENV !== 'test') {\n client.once('connect', () => {\n client\n .call('CLIENT', ['SETNAME', `${appName}:${dyno}:${name}`])\n .then(() => {\n console.log(`Connected to Redis for pid:${process.pid} (${name})`)\n })\n .catch(err => {\n console.error(`Failed to set client name for ${name}:`, err)\n })\n })\n }\n }\n}\n\n/**\n * Creates a function to set Redis client name for node-redis v4.\n *\n * @param {string} [defaultAppName='undefined-app']\n * @returns {(client: any, name: string) => void}\n */\nconst createSetClientNameForRedisV4 = (defaultAppName = 'undefined-app') => {\n return (client, name) => {\n const appName = process.env.METRICS_APP_NAME || defaultAppName\n const dyno = process.env.BUILD_DYNO_PROCESS_TYPE || 'undefined-dyno'\n\n if (process.env.NODE_ENV !== 'test') {\n client.on('ready', async () => {\n try {\n await client.sendCommand([\n 'CLIENT',\n 'SETNAME',\n `${appName}:${dyno}:${name}`,\n ])\n console.log(`Connected to Redis for pid:${process.pid} (${name})`)\n } catch (err) {\n console.error(`Failed to set client name for ${name}:`, err)\n }\n })\n }\n }\n}\n\n/**\n * Check if a Redis client is an ioredis instance\n *\n * @param {any} client - Redis client instance\n * @returns {boolean} True if the client is ioredis\n */\nconst isIORedis = client => {\n const result =\n client &&\n typeof client.sendCommand === 'function' &&\n typeof client.disconnect === 'function' &&\n client.options !== undefined;\n console.log('[debug] isIORedis client.sendCommand:', client.sendCommand);\n console.log('[debug] isIORedis client.sendCommand === \\'function\\':', typeof client.sendCommand === 'function');\n console.log('[debug] isIORedis client.disconnect:', client.disconnect);\n console.log('[debug] isIORedis client.disconnect === \\'function\\':', typeof client.disconnect === 'function');\n console.log('[debug] isIORedis client.options:', client.options);\n console.log('[debug] isIORedis client.options !== undefined:', client.options !== undefined);\n\n console.log('[debug] isIORedis check:', result, 'constructor:', client?.constructor?.name);\n return result;\n};\n\nmodule.exports = {\n createSetClientNameForRedisV3,\n createSetClientNameForRedisV4,\n createSetClientNameForIoredis,\n isIORedis,\n}\n"],"mappings":"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","ignoreList":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adalo/metrics",
3
- "version": "0.1.65",
3
+ "version": "0.1.67",
4
4
  "description": "Reusable metrics utilities for Node.js and Laravel apps",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -98,7 +98,7 @@ class QueueRedisMetricsClient extends RedisMetricsClient {
98
98
  * @returns {object|any} Redis config object for BeeQueue or Redis client instance
99
99
  */
100
100
  getConfigForDifferentRedis = () => {
101
- if (isIORedis(this.client)) {
101
+ if (isIORedis(this.redisClient)) {
102
102
  const { host, port, db, password } = this.redisClient.options
103
103
  return { host, port, db, password }
104
104
  }
@@ -1,4 +1,5 @@
1
1
  const { MetricsClient } = require('.')
2
+ const { isIORedis } = require('./redisUtils')
2
3
 
3
4
  /**
4
5
  * RedisMetricsClient extends MetricsClient to collect
@@ -71,6 +72,17 @@ class RedisMetricsClient extends MetricsClient {
71
72
  )
72
73
  console.log('Redis client info function:', this.redisClient.info)
73
74
 
75
+ // node-redis ioredis
76
+ if (isIORedis(this.redisClient)) {
77
+ console.log('Detected node-redis ioredis')
78
+ try {
79
+ const result = await this.redisClient.info(section)
80
+ return result
81
+ } catch (err) {
82
+ throw new Error(`Failed to get Redis INFO: ${err.message}`)
83
+ }
84
+ }
85
+
74
86
  // node-redis v3 (uses callback)
75
87
  if (typeof this.redisClient.send_command === 'function') {
76
88
  console.log('Detected node-redis v3')
@@ -84,7 +96,7 @@ class RedisMetricsClient extends MetricsClient {
84
96
 
85
97
  // node-redis v4 or ioredis (info returns Promise)
86
98
  if (typeof this.redisClient.info === 'function') {
87
- console.log('Detected node-redis v4 or ioredis')
99
+ console.log('Detected node-redis v4')
88
100
  try {
89
101
  const result = await this.redisClient.info(section)
90
102
  return result
package/src/redisUtils.js CHANGED
@@ -85,17 +85,24 @@ const createSetClientNameForRedisV4 = (defaultAppName = 'undefined-app') => {
85
85
  * Check if a Redis client is an ioredis instance
86
86
  *
87
87
  * @param {any} client - Redis client instance
88
- * @returns {boolean} True if the client is ioredis, false otherwise
88
+ * @returns {boolean} True if the client is ioredis
89
89
  */
90
90
  const isIORedis = client => {
91
- return (
91
+ const result =
92
92
  client &&
93
- typeof client.connect === 'function' &&
93
+ typeof client.sendCommand === 'function' &&
94
94
  typeof client.disconnect === 'function' &&
95
- client.status !== undefined &&
96
- client.options !== undefined
97
- )
98
- }
95
+ client.options !== undefined;
96
+ console.log('[debug] isIORedis client.sendCommand:', client.sendCommand);
97
+ console.log('[debug] isIORedis client.sendCommand === \'function\':', typeof client.sendCommand === 'function');
98
+ console.log('[debug] isIORedis client.disconnect:', client.disconnect);
99
+ console.log('[debug] isIORedis client.disconnect === \'function\':', typeof client.disconnect === 'function');
100
+ console.log('[debug] isIORedis client.options:', client.options);
101
+ console.log('[debug] isIORedis client.options !== undefined:', client.options !== undefined);
102
+
103
+ console.log('[debug] isIORedis check:', result, 'constructor:', client?.constructor?.name);
104
+ return result;
105
+ };
99
106
 
100
107
  module.exports = {
101
108
  createSetClientNameForRedisV3,