UNPKG

@mdf.js/service-registry

Version:

MMS - API - Service Registry

162 lines 6.78 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Aggregator = void 0; const tslib_1 = require("tslib"); const cluster_1 = tslib_1.__importDefault(require("cluster")); const prom_client_1 = require("prom-client"); /** * MetricsAggregator class manages all the metrics for this artifact, * integrating with Prometheus for metrics collection and aggregation. */ class Aggregator { /** * Create a new instance of MetricsAggregator * @param logger - Instance for logging * @param port - Optional AggregatorRegistry for cluster metrics */ constructor(logger, port) { this.logger = logger; this.port = port; /** Default prom-client registry for collecting default metrics */ this.defaultRegistry = prom_client_1.register; /** Map to keep track of registered services */ this.components = new Map(); // Collect default metrics and label them with the instance identifier this.collectDefaultMetrics(this.defaultRegistry); this._registry = new prom_client_1.Registry(); this.updateAggregatorRegistry(this._registry, port); // Stryker disable next-line all this.logger.debug(`New metric aggregator instance created: ${this._registry.contentType}`); } /** * Update the aggregator registry based on the current environment and node type */ updateAggregatorRegistry(registry, port) { var _a, _b, _c; if (port !== undefined) { if (cluster_1.default.isPrimary) { // Stryker disable next-line all this.logger.debug(`The metrics aggregator is running in the primary node, we will collect the metrics from the application, the default prom-client registry, and the cluster registry`); this._registry.setDefaultLabels({ NODE_APP_INSTANCE: (_a = process.env['NODE_APP_INSTANCE']) !== null && _a !== void 0 ? _a : 'primary', }); prom_client_1.AggregatorRegistry.setRegistries([registry, this.defaultRegistry, port]); } else { // Stryker disable next-line all this.logger.debug(`The metrics aggregator is running in a worker node, we will collect the metrics from the application and the default prom-client registry`); this._registry.setDefaultLabels({ NODE_APP_INSTANCE: (_b = process.env['NODE_APP_INSTANCE']) !== null && _b !== void 0 ? _b : `worker${(_c = cluster_1.default.worker) === null || _c === void 0 ? void 0 : _c.id}`, }); prom_client_1.AggregatorRegistry.setRegistries([registry, this.defaultRegistry]); } } } /** * Add default metrics to the registry if they are not already present * @param register - Registry to add the default metrics */ collectDefaultMetrics(register) { var _a, _b; if (!register.getSingleMetric('process_cpu_user_seconds_total')) { (0, prom_client_1.collectDefaultMetrics)({ register, labels: { NODE_APP_INSTANCE: ((_a = process.env['NODE_APP_INSTANCE']) !== null && _a !== void 0 ? _a : !cluster_1.default.isPrimary) ? `worker${(_b = cluster_1.default.worker) === null || _b === void 0 ? void 0 : _b.id}` : `primary`, }, }); } } /** * Register a service or a list of services in the aggregator * @param service - Service to register in the aggregator */ register(service) { const _services = Array.isArray(service) ? service : [service]; for (const entry of _services) { if (!this.components.has(entry.name)) { if ('metrics' in entry && entry.metrics instanceof prom_client_1.Registry) { // Stryker disable next-line all this.logger.debug(`Registering metrics for service: ${entry.name}`); this._registry = prom_client_1.Registry.merge([this._registry, entry.metrics]); this.components.set(entry.name, entry); this.updateAggregatorRegistry(this._registry, this.port); } else { // Stryker disable next-line all this.logger.debug(`Service ${entry.name} does not have metrics to register`); } } else { // Stryker disable next-line all this.logger.warn(`Service ${entry.name} is already registered`); } } } /** Return the registry used by the aggregator */ get registry() { return this._registry; } /** Return the metrics in text/plain format */ async metricsText() { let metrics = await this._registry.metrics(); metrics += await this.defaultRegistry.metrics(); if (this.port && cluster_1.default.isPrimary) { metrics += await this.port.clusterMetrics(); } return { metrics, contentType: this._registry.contentType, }; } /** Return the actual metrics in JSON format */ async metricsJSON() { const contentType = 'application/json'; const metrics = [ ...(await this._registry.getMetricsAsJSON()), ...(await this.defaultRegistry.getMetricsAsJSON()), ]; return { metrics, contentType, }; } /** * Retrieves a single metric by name from the registry. * @param name - The name of the metric to retrieve */ getMetric(name) { return this._registry.getSingleMetric(name); } /** * Retrieves a single metric value in Prometheus format by name. * @param name - The name of the metric to retrieve */ async getMetricAsString(name) { return this._registry.getSingleMetricAsString(name); } /** * Retrieves a single metric value in JSON format by name. * @param name - The name of the metric to retrieve */ async getMetricAsJSON(name) { const metrics = [ ...(await this._registry.getMetricsAsJSON()), ...(await this.defaultRegistry.getMetricsAsJSON()), ]; return metrics.find(entry => entry.name === name); } /** Clear the registry */ clear() { this.logger.debug('Clearing all metrics from the registry.'); this._registry.clear(); this.defaultRegistry.clear(); if (this.port) { this.port.clear(); } } } exports.Aggregator = Aggregator; //# sourceMappingURL=Aggregator.js.map