UNPKG

kuzzle-plugin-prometheus

Version:
151 lines 6.9 kB
"use strict"; /* * Kuzzle, a backend software, self-hostable and ready to use * to power modern apps * * Copyright 2015-2021 Kuzzle * mailto: support AT kuzzle.io * website: http://kuzzle.io * * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.MetricService = void 0; const prom_client_1 = require("prom-client"); /** * MetricService is a service to handle metrics from the Kuzzle API and the application. * @property {{ core: CoreMetrics, requestDuration?: Histogram<string> }} metrics - The application metrics to register. * @property {{[key: string]: Registry}} registries - The Prometheus registry to register metrics. */ class MetricService { /** * @param {PrometheusPluginConfiguration} config - The plugin configuration */ constructor(config) { this.labels = config.labels; this.registries = { core: new prom_client_1.Registry(), }; this.metrics = { core: { api: { concurrentRequests: new prom_client_1.Gauge({ name: `${config.core.prefix}api_concurrent_requests`, help: 'Number of concurrent requests', labelNames: Object.keys(this.labels), registers: [this.registries.core] }), pendingRequests: new prom_client_1.Gauge({ name: `${config.core.prefix}api_pending_requests`, help: 'Number of pending requests', labelNames: Object.keys(this.labels), registers: [this.registries.core] }), }, network: { connections: new prom_client_1.Gauge({ name: `${config.core.prefix}network_connections`, help: 'Number of connections', labelNames: ['protocol', ...Object.keys(this.labels)], registers: [this.registries.core] }), }, realtime: { rooms: new prom_client_1.Gauge({ name: `${config.core.prefix}realtime_rooms`, help: 'Number of rooms', labelNames: Object.keys(this.labels), registers: [this.registries.core] }), subscriptions: new prom_client_1.Gauge({ name: `${config.core.prefix}realtime_subscriptions`, help: 'Number of subscriptions', labelNames: Object.keys(this.labels), registers: [this.registries.core] }), }, }, }; if (config.core.monitorRequestDuration) { // Need to be registered in a separate registry to avoid // the core registry resetting in updateCoreMetrics this.registries.requestDuration = new prom_client_1.Registry(); this.metrics.requestDuration = new prom_client_1.Histogram({ name: `${config.core.prefix}api_request_duration_ms`, help: 'Duration of Kuzzle requests in ms', labelNames: ['action', 'controller', 'protocol', 'status', ...Object.keys(this.labels)], registers: [this.registries.requestDuration], buckets: [0.10, 5, 15, 50, 100, 200, 300, 400, 500] }); } if (config.default.enabled) { this.registries.default = new prom_client_1.Registry(); (0, prom_client_1.collectDefaultMetrics)({ register: this.registries.default, prefix: config.default.prefix, labels: this.labels, eventLoopMonitoringPrecision: config.default.eventLoopMonitoringPrecision, gcDurationBuckets: config.default.gcDurationBuckets, }); } } /** * Update the Prometheus coreMetrics with from the server:metrics JSON response * @param {JSONObject} jsonMetrics - The server:metrics JSON response */ updateCoreMetrics(jsonMetrics) { // Past metrics are oudated, so we need to reset them this.registries.core.resetMetrics(); for (const component of Object.keys(jsonMetrics)) { for (const metric of Object.keys(jsonMetrics[component])) { if (typeof this.metrics.core[component][metric] === 'undefined') { continue; } if (typeof jsonMetrics[component][metric] === 'number') { this.metrics.core[component][metric].set(this.labels, jsonMetrics[component][metric]); } // Only for network.connections metric since we label it using protocol name if (typeof jsonMetrics[component][metric] === 'object') { for (const protocol of Object.keys(jsonMetrics[component][metric])) { this.metrics.core[component][metric].set({ protocol, ...this.labels }, jsonMetrics[component][metric][protocol]); } } } } } /** * Merge all the Prometheus registries into one and returns metrics as Prometheus text format * @returns {string} All the regitries metrics formatted as a Prometheus text */ getMetrics() { return prom_client_1.Registry.merge(Object.values(this.registries)).metrics(); } /** * Returns the content type used to export metrics to Prometheus * @returns {string} The content type used to export metrics to Prometheus */ getPrometheusContentType() { return this.registries.core.contentType; } /** * Record response time in the Prometheus responseTime histogram * @param {number} time - Time in ms * @param {{[key: string]: string | number}} labels - Labels to add to the metric */ recordResponseTime(time, labels) { this.metrics.requestDuration.labels({ ...labels, ...this.labels }).observe(time); } } exports.MetricService = MetricService; //# sourceMappingURL=MetricService.js.map