@mdf.js/service-registry
Version:
MMS - API - Service Registry
162 lines • 6.78 kB
JavaScript
"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