This commit is contained in:
2026-02-19 09:51:34 +00:00
parent 7c3197455f
commit 32d75804c0
7 changed files with 878 additions and 99 deletions

View File

@@ -5,37 +5,36 @@ export class SmartMetrics {
public started = false;
public sourceNameArg: string;
public logger: plugins.smartlog.Smartlog;
public registry: plugins.promClient.Registry;
public registry: plugins.prom.Registry;
public maxMemoryMB: number;
// Prometheus gauges for custom metrics
private cpuPercentageGauge: plugins.promClient.Gauge<string>;
private memoryPercentageGauge: plugins.promClient.Gauge<string>;
private memoryUsageBytesGauge: plugins.promClient.Gauge<string>;
private cpuPercentageGauge: plugins.prom.Gauge;
private memoryPercentageGauge: plugins.prom.Gauge;
private memoryUsageBytesGauge: plugins.prom.Gauge;
// HTTP server for Prometheus endpoint
private prometheusServer?: plugins.http.Server;
private prometheusPort?: number;
public setup() {
const collectDefaultMetrics = plugins.promClient.collectDefaultMetrics;
this.registry = new plugins.promClient.Registry();
collectDefaultMetrics({ register: this.registry });
this.registry = new plugins.prom.Registry();
plugins.prom.collectDefaultMetrics(this.registry);
// Initialize custom gauges
this.cpuPercentageGauge = new plugins.promClient.Gauge({
this.cpuPercentageGauge = new plugins.prom.Gauge({
name: 'smartmetrics_cpu_percentage',
help: 'Current CPU usage percentage',
registers: [this.registry]
});
this.memoryPercentageGauge = new plugins.promClient.Gauge({
this.memoryPercentageGauge = new plugins.prom.Gauge({
name: 'smartmetrics_memory_percentage',
help: 'Current memory usage percentage',
registers: [this.registry]
});
this.memoryUsageBytesGauge = new plugins.promClient.Gauge({
this.memoryUsageBytesGauge = new plugins.prom.Gauge({
name: 'smartmetrics_memory_usage_bytes',
help: 'Current memory usage in bytes',
registers: [this.registry]
@@ -110,23 +109,23 @@ export class SmartMetrics {
public async getMetrics() {
let pids: number[] = [];
try {
pids = await plugins.pidtree(process.pid);
pids = await plugins.pidtree.getChildPids(process.pid);
} catch {
// pidtree can fail if process tree cannot be read
}
const stats = await plugins.pidusage([process.pid, ...pids]);
const stats = await plugins.pidusage.getPidUsage([process.pid, ...pids]);
let cpuPercentage = 0;
for (const stat of Object.keys(stats)) {
if (!stats[stat]) continue;
cpuPercentage += stats[stat].cpu;
if (!stats[stat as any]) continue;
cpuPercentage += stats[stat as any].cpu;
}
let cpuUsageText = `${Math.round(cpuPercentage * 100) / 100} %`;
let memoryUsageBytes = 0;
for (const stat of Object.keys(stats)) {
if (!stats[stat]) continue;
memoryUsageBytes += stats[stat].memory;
if (!stats[stat as any]) continue;
memoryUsageBytes += stats[stat as any].memory;
}
let memoryPercentage =
@@ -149,15 +148,15 @@ export class SmartMetrics {
// Calculate Node.js metrics directly
const cpuUsage = process.cpuUsage();
const process_cpu_seconds_total = (cpuUsage.user + cpuUsage.system) / 1000000; // Convert from microseconds to seconds
const heapStats = plugins.v8.getHeapStatistics();
const nodejs_heap_size_total_bytes = heapStats.total_heap_size;
// Note: Active handles and requests are internal Node.js metrics that require deprecated APIs
// We return 0 here, but the Prometheus default collectors will track the real values
const nodejs_active_handles_total = 0;
const nodejs_active_requests_total = 0;
const returnMetrics: interfaces.IMetricsSnapshot = {
process_cpu_seconds_total,
nodejs_active_handles_total,
@@ -175,7 +174,7 @@ export class SmartMetrics {
public async getPrometheusFormattedMetrics(): Promise<string> {
// Update metrics to ensure gauges have latest values
await this.getMetrics();
// Return Prometheus text exposition format
return await this.registry.metrics();
}
@@ -185,7 +184,7 @@ export class SmartMetrics {
this.logger.log('warn', 'Prometheus endpoint is already running');
return;
}
this.prometheusServer = plugins.http.createServer(async (req, res) => {
if (req.url === '/metrics' && req.method === 'GET') {
try {
@@ -202,7 +201,7 @@ export class SmartMetrics {
res.end('Not Found');
}
});
this.prometheusPort = port;
this.prometheusServer.listen(port, () => {
this.logger.log('info', `Prometheus metrics endpoint available at http://localhost:${port}/metrics`);
@@ -213,12 +212,12 @@ export class SmartMetrics {
if (!this.prometheusServer) {
return;
}
const port = this.prometheusPort;
this.prometheusServer.close(() => {
this.logger.log('info', `Prometheus metrics endpoint on port ${port} has been shut down`);
});
this.prometheusServer = undefined;
this.prometheusPort = undefined;
}