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

View File

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