diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e68a03..16509e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ All notable changes to this project will be documented in this file. +### v3.3.0 + +* feat(metrics): add gauges for meeting and user Redis mappings +* fix(metrics): properly handle Prometheus collection failures +* fix(metrics): handle promises in setCollectorWithGenerator + ### v3.2.2 * fix: handle missing checksum in API requests diff --git a/package-lock.json b/package-lock.json index 4fd649c..cf0bbdc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "bbb-webhooks", - "version": "3.2.2", + "version": "3.3.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "bbb-webhooks", - "version": "3.2.2", + "version": "3.3.0", "dependencies": { "bullmq": "4.17.0", "config": "^3.3.7", @@ -3889,6 +3889,7 @@ "version": "14.2.0", "resolved": "https://registry.npmjs.org/prom-client/-/prom-client-14.2.0.tgz", "integrity": "sha512-sF308EhTenb/pDRPakm+WgiN+VdM/T1RaHj1x+MvAuT8UiQP8JmOEbxVqtkbfR4LrvOg5n7ic01kRBDGXjYikA==", + "license": "Apache-2.0", "dependencies": { "tdigest": "^0.1.1" }, diff --git a/package.json b/package.json index f17c620..0defb8f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bbb-webhooks", - "version": "3.2.2", + "version": "3.3.0", "description": "A BigBlueButton mudule for events WebHooks", "type": "module", "scripts": { diff --git a/src/metrics/index.js b/src/metrics/index.js index cc1d64d..708b1a6 100644 --- a/src/metrics/index.js +++ b/src/metrics/index.js @@ -25,6 +25,8 @@ const METRIC_NAMES = { MODULE_STATUS: `${PREFIX}module_status`, EVENT_PROCESS_FAILURES: `${PREFIX}event_process_failures`, EVENT_DISPATCH_FAILURES: `${PREFIX}event_dispatch_failures`, + MEETING_MAPPINGS: `${PREFIX}meeting_mappings`, + USER_MAPPINGS: `${PREFIX}user_mappings`, } let METRICS = {} @@ -79,6 +81,16 @@ const buildDefaultMetrics = () => { help: 'Number of event dispatch failures', labelNames: ['outputEventId', 'module'], }), + + [METRIC_NAMES.MEETING_MAPPINGS]: new Gauge({ + name: METRIC_NAMES.MEETING_MAPPINGS, + help: 'Number of meeting mappings saved in the database', + }), + + [METRIC_NAMES.USER_MAPPINGS]: new Gauge({ + name: METRIC_NAMES.USER_MAPPINGS, + help: 'Number of user mappings saved in the database', + }), } } diff --git a/src/metrics/prometheus-agent.js b/src/metrics/prometheus-agent.js index 30c23fc..5f0fa26 100644 --- a/src/metrics/prometheus-agent.js +++ b/src/metrics/prometheus-agent.js @@ -49,14 +49,13 @@ class PrometheusScrapeAgent { async _collect (response) { try { const _response = await this.collect(response); - _response.writeHead(200, { 'Content-Type': promclient.register.contentType }); const content = await promclient.register.metrics(); + _response.writeHead(200, { 'Content-Type': promclient.register.contentType }); _response.end(content); } catch (error) { + this.logger.error('Prometheus: error collecting metrics', error); response.writeHead(500) - response.end(error.message); - this.logger.error('Prometheus: error collecting metrics', - { errorCode: error.code, errorMessage: error.message }); + response.end("Error collecting metrics"); } } @@ -172,8 +171,9 @@ class PrometheusScrapeAgent { /** * metric.collect. */ - metric.collect = () => { - metric.set(generator()); + metric.collect = async () => { + const value = await generator(); + metric.set(value); }; } } diff --git a/src/process/event-processor.js b/src/process/event-processor.js index f4928de..f622479 100644 --- a/src/process/event-processor.js +++ b/src/process/event-processor.js @@ -21,6 +21,42 @@ export default class EventProcessor { this.outputs = outputs; this._exporter = Metrics.agent; + this._setMetricsCollectors(); + } + + /** + * _setMetricsCollectors - Sets the metrics collectors for the event processor. + * @private + */ + _setMetricsCollectors() { + const collectIDMappings = async () => { + try { + const mappings = await IDMapping.get().getAll(); + return mappings?.length || 0; + } catch (error) { + Logger.error('error getting ID mappings', error); + return 0; + } + } + + const collectUserMappings = async () => { + try { + const mappings = await UserMapping.get().getAll(); + return mappings?.length || 0; + } catch (error) { + Logger.error('error getting user mappings', error); + return 0; + } + } + + this._exporter.setCollectorWithGenerator( + Metrics.METRIC_NAMES.MEETING_MAPPINGS, + collectIDMappings, + ); + this._exporter.setCollectorWithGenerator( + Metrics.METRIC_NAMES.USER_MAPPINGS, + collectUserMappings, + ); } _trackModuleEvents() {