Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 79db79de96 | |||
| a01e21663f |
@@ -1,5 +1,11 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2026-03-23 - 3.0.3 - fix(prometheus)
|
||||||
|
clean up default Prometheus metric collectors on stop
|
||||||
|
|
||||||
|
- Return cleanup handlers from default metric registration for event loop and GC observers.
|
||||||
|
- Dispose registered Prometheus default metric collectors when stopping Smartmetrics to prevent lingering observers.
|
||||||
|
|
||||||
## 2026-03-02 - 3.0.2 - fix(pidusage)
|
## 2026-03-02 - 3.0.2 - fix(pidusage)
|
||||||
prune history entries for PIDs not present in the requested set to avoid stale data and memory growth
|
prune history entries for PIDs not present in the requested set to avoid stale data and memory growth
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@push.rocks/smartmetrics",
|
"name": "@push.rocks/smartmetrics",
|
||||||
"version": "3.0.2",
|
"version": "3.0.3",
|
||||||
"private": false,
|
"private": false,
|
||||||
"description": "A package for easy collection and reporting of system and process metrics.",
|
"description": "A package for easy collection and reporting of system and process metrics.",
|
||||||
"main": "dist_ts/index.js",
|
"main": "dist_ts/index.js",
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@push.rocks/smartmetrics',
|
name: '@push.rocks/smartmetrics',
|
||||||
version: '3.0.2',
|
version: '3.0.3',
|
||||||
description: 'A package for easy collection and reporting of system and process metrics.'
|
description: 'A package for easy collection and reporting of system and process metrics.'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,10 +22,11 @@ export class SmartMetrics {
|
|||||||
// HTTP server for Prometheus endpoint
|
// HTTP server for Prometheus endpoint
|
||||||
private prometheusServer?: plugins.http.Server;
|
private prometheusServer?: plugins.http.Server;
|
||||||
private prometheusPort?: number;
|
private prometheusPort?: number;
|
||||||
|
private cleanupDefaultMetrics?: () => void;
|
||||||
|
|
||||||
public setup() {
|
public setup() {
|
||||||
this.registry = new plugins.prom.Registry();
|
this.registry = new plugins.prom.Registry();
|
||||||
plugins.prom.collectDefaultMetrics(this.registry);
|
this.cleanupDefaultMetrics = plugins.prom.collectDefaultMetrics(this.registry);
|
||||||
|
|
||||||
// Initialize custom gauges
|
// Initialize custom gauges
|
||||||
this.cpuPercentageGauge = new plugins.prom.Gauge({
|
this.cpuPercentageGauge = new plugins.prom.Gauge({
|
||||||
@@ -295,5 +296,9 @@ export class SmartMetrics {
|
|||||||
public stop() {
|
public stop() {
|
||||||
this.started = false;
|
this.started = false;
|
||||||
this.disablePrometheusEndpoint();
|
this.disablePrometheusEndpoint();
|
||||||
|
if (this.cleanupDefaultMetrics) {
|
||||||
|
this.cleanupDefaultMetrics();
|
||||||
|
this.cleanupDefaultMetrics = undefined;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -288,20 +288,25 @@ export class Histogram implements IMetric {
|
|||||||
|
|
||||||
// ── Default Metrics Collectors ──────────────────────────────────────────────
|
// ── Default Metrics Collectors ──────────────────────────────────────────────
|
||||||
|
|
||||||
export function collectDefaultMetrics(registry: Registry): void {
|
export function collectDefaultMetrics(registry: Registry): () => void {
|
||||||
registerProcessCpuTotal(registry);
|
registerProcessCpuTotal(registry);
|
||||||
registerProcessStartTime(registry);
|
registerProcessStartTime(registry);
|
||||||
registerProcessMemory(registry);
|
registerProcessMemory(registry);
|
||||||
registerProcessOpenFds(registry);
|
registerProcessOpenFds(registry);
|
||||||
registerProcessMaxFds(registry);
|
registerProcessMaxFds(registry);
|
||||||
registerEventLoopLag(registry);
|
const cleanupEventLoop = registerEventLoopLag(registry);
|
||||||
registerProcessHandles(registry);
|
registerProcessHandles(registry);
|
||||||
registerProcessRequests(registry);
|
registerProcessRequests(registry);
|
||||||
registerProcessResources(registry);
|
registerProcessResources(registry);
|
||||||
registerHeapSizeAndUsed(registry);
|
registerHeapSizeAndUsed(registry);
|
||||||
registerHeapSpaces(registry);
|
registerHeapSpaces(registry);
|
||||||
registerVersion(registry);
|
registerVersion(registry);
|
||||||
registerGc(registry);
|
const cleanupGc = registerGc(registry);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
cleanupEventLoop();
|
||||||
|
cleanupGc();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function registerProcessCpuTotal(registry: Registry): void {
|
function registerProcessCpuTotal(registry: Registry): void {
|
||||||
@@ -420,7 +425,7 @@ function registerProcessMaxFds(registry: Registry): void {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function registerEventLoopLag(registry: Registry): void {
|
function registerEventLoopLag(registry: Registry): () => void {
|
||||||
let histogram: ReturnType<typeof monitorEventLoopDelay> | null = null;
|
let histogram: ReturnType<typeof monitorEventLoopDelay> | null = null;
|
||||||
try {
|
try {
|
||||||
histogram = monitorEventLoopDelay({ resolution: 10 });
|
histogram = monitorEventLoopDelay({ resolution: 10 });
|
||||||
@@ -496,6 +501,13 @@ function registerEventLoopLag(registry: Registry): void {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (histogram) {
|
||||||
|
histogram.disable();
|
||||||
|
histogram = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function registerProcessHandles(registry: Registry): void {
|
function registerProcessHandles(registry: Registry): void {
|
||||||
@@ -632,7 +644,7 @@ function registerVersion(registry: Registry): void {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function registerGc(registry: Registry): void {
|
function registerGc(registry: Registry): () => void {
|
||||||
const gcHistogram = new Histogram({
|
const gcHistogram = new Histogram({
|
||||||
name: 'nodejs_gc_duration_seconds',
|
name: 'nodejs_gc_duration_seconds',
|
||||||
help: 'Garbage collection duration by kind, in seconds.',
|
help: 'Garbage collection duration by kind, in seconds.',
|
||||||
@@ -649,8 +661,9 @@ function registerGc(registry: Registry): void {
|
|||||||
15: 'All',
|
15: 'All',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let obs: PerformanceObserver | null = null;
|
||||||
try {
|
try {
|
||||||
const obs = new PerformanceObserver((list) => {
|
obs = new PerformanceObserver((list) => {
|
||||||
for (const entry of list.getEntries()) {
|
for (const entry of list.getEntries()) {
|
||||||
const gcEntry = entry as any;
|
const gcEntry = entry as any;
|
||||||
const kind = kindLabels[gcEntry.detail?.kind ?? gcEntry.kind] || 'Unknown';
|
const kind = kindLabels[gcEntry.detail?.kind ?? gcEntry.kind] || 'Unknown';
|
||||||
@@ -661,6 +674,13 @@ function registerGc(registry: Registry): void {
|
|||||||
} catch {
|
} catch {
|
||||||
// GC observation not available
|
// GC observation not available
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (obs) {
|
||||||
|
obs.disconnect();
|
||||||
|
obs = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Helpers ─────────────────────────────────────────────────────────────────
|
// ── Helpers ─────────────────────────────────────────────────────────────────
|
||||||
|
|||||||
Reference in New Issue
Block a user