metrics: support clusters

This commit is contained in:
hyperdefined 2025-06-04 00:43:34 -04:00
parent 77c4e134c7
commit 87b92a7a62
No known key found for this signature in database
GPG Key ID: 38C93C4835071D4A
2 changed files with 39 additions and 29 deletions

View File

@ -3,8 +3,7 @@ import http from "node:http";
import rateLimit from "express-rate-limit"; import rateLimit from "express-rate-limit";
import { setGlobalDispatcher, ProxyAgent } from "undici"; import { setGlobalDispatcher, ProxyAgent } from "undici";
import { getCommit, getBranch, getRemote, getVersion } from "@imput/version-info"; import { getCommit, getBranch, getRemote, getVersion } from "@imput/version-info";
import registry from "../misc/metrics.js" import { httpRequests, httpRequestDuration, WORKER_ID, aggregatorRegistry } from "../misc/metrics.js";
import { httpRequests, httpRequestDuration } from "../misc/metrics.js"
import jwt from "../security/jwt.js"; import jwt from "../security/jwt.js";
import stream from "../stream/stream.js"; import stream from "../stream/stream.js";
@ -118,11 +117,11 @@ export const runAPI = async (express, app, __dirname, isPrimary = true) => {
if (metrics) { if (metrics) {
app.use((req, res, next) => { app.use((req, res, next) => {
const end = httpRequestDuration.startTimer({ method: req.method }); const end = httpRequestDuration.startTimer({ method: req.method, worker_id: WORKER_ID });
res.on('finish', () => { res.on('finish', () => {
httpRequests.labels(req.method, res.statusCode.toString()).inc(); httpRequests.labels(req.method, res.statusCode.toString(), WORKER_ID).inc();
end(); end();
}); });
next(); next();
@ -389,20 +388,26 @@ export const runAPI = async (express, app, __dirname, isPrimary = true) => {
YouTubeSession.setup(); YouTubeSession.setup();
} }
if (metrics) { if (metrics && isPrimary) {
const metricsApp = express(); const metricsApp = express();
metricsApp.get('/metrics', async (req, res) => { metricsApp.get('/metrics', async (req, res) => {
res.set('Content-Type', registry.contentType); try {
res.send(await registry.metrics()); const data = await aggregatorRegistry.clusterMetrics();
}); res.set('Content-Type', 'text/plain');
metricsApp.listen(env.metricsPort, '127.0.0.1', () => { res.end(data);
console.log(`${Green('[✓]')} prometheus metrics running on 127.0.0.1:${env.metricsPort}/metrics`); } catch (err) {
res.status(500).end(err.message);
}
}); });
metricsApp.get('/*', (req, res) => { metricsApp.get('/*', (req, res) => {
res.redirect('/metrics'); res.redirect('/metrics');
}) });
metricsApp.listen(env.metricsPort, '127.0.0.1', () => {
console.log(`${Green('[✓]')} prometheus metrics running on 127.0.0.1:${env.metricsPort}/metrics`);
});
} }
}); });

View File

@ -1,33 +1,38 @@
import { Registry } from 'prom-client'; import { collectDefaultMetrics, Counter, Histogram, Registry, AggregatorRegistry } from 'prom-client';
import { collectDefaultMetrics, Counter, Histogram } from "prom-client";
const registry = new Registry(); import cluster from 'node:cluster';
export default registry;
collectDefaultMetrics({ register: registry }); export const WORKER_ID = `worker_${cluster.worker?.id ?? process.pid}`;
export const registry = new Registry();
export const aggregatorRegistry = new AggregatorRegistry();
collectDefaultMetrics({
register: registry
});
export const failedRequests = new Counter({ export const failedRequests = new Counter({
name: 'cobalt_fail_request_count', name: 'cobalt_fail_request_count',
help: 'Total number of failed requests', help: 'Total number of failed requests',
labelNames: ['service'], labelNames: ['service', 'worker_id'],
}); });
export const successfulRequests = new Counter({ export const successfulRequests = new Counter({
name: 'cobalt_success_request_count', name: 'cobalt_success_request_count',
help: 'Total number of successful requests', help: 'Total number of successful requests',
labelNames: ['service'], labelNames: ['service', 'worker_id'],
}); });
export const httpRequests = new Counter({ export const httpRequests = new Counter({
name: 'http_requests_total', name: 'http_requests_total',
help: 'Total number of HTTP requests', help: 'Total number of HTTP requests',
labelNames: ['method', 'status'], labelNames: ['method', 'status', 'worker_id'],
}); });
export const httpRequestDuration = new Histogram({ export const httpRequestDuration = new Histogram({
name: 'http_request_duration_seconds', name: 'http_request_duration_seconds',
help: 'Duration of HTTP requests in seconds', help: 'Duration of HTTP requests in seconds',
labelNames: ['method'], labelNames: ['method', 'worker_id'],
buckets: [0.1, 0.5, 1, 1.5, 2, 5], buckets: [0.1, 0.5, 1, 1.5, 2, 5],
}); });
@ -36,10 +41,10 @@ registry.registerMetric(successfulRequests);
registry.registerMetric(httpRequests); registry.registerMetric(httpRequests);
registry.registerMetric(httpRequestDuration); registry.registerMetric(httpRequestDuration);
export function incrementFailed(type) { export function incrementFailed(service) {
failedRequests.labels(type).inc(); failedRequests.labels(service, WORKER_ID).inc();
} }
export function incrementSuccessful(type) { export function incrementSuccessful(service) {
successfulRequests.labels(type).inc(); successfulRequests.labels(service, WORKER_ID).inc();
} }