Files
peardata/server/services/collectors/self-monitor.js
T
Raven Scott 1d902a89b0
CI / test (push) Successful in 1m1s
Release rolling / release (push) Successful in 7m25s
Experimental CPU Optimize Techniques
2026-07-21 11:58:29 -04:00

136 lines
3.3 KiB
JavaScript

/**
* PearData process self-monitor (always enabled).
*
* Charts: peardata.cpu, peardata.mem, peardata.charts
*/
import { CollectorPlugin } from './plugin.js'
import { registerChart, getAllChartDefs } from '../../../shared/metrics.js'
import logger from '../../utils/logger.js'
const log = logger.child('self-monitor')
const CHART_CPU = {
id: 'peardata.cpu',
name: 'peardata.cpu',
context: 'peardata.cpu',
title: 'PearData CPU usage',
units: 'percentage',
family: 'peardata',
chartType: 'line',
priority: 9000,
plugin: 'self-monitor',
dimensions: [
{ id: 'user', name: 'user', algorithm: 'absolute' },
{ id: 'system', name: 'system', algorithm: 'absolute' },
],
}
const CHART_MEM = {
id: 'peardata.mem',
name: 'peardata.mem',
context: 'peardata.mem',
title: 'PearData memory',
units: 'MiB',
family: 'peardata',
chartType: 'area',
priority: 9010,
plugin: 'self-monitor',
dimensions: [
{ id: 'rss', name: 'rss', algorithm: 'absolute' },
{ id: 'heap', name: 'heap', algorithm: 'absolute' },
],
}
const CHART_CHARTS = {
id: 'peardata.charts',
name: 'peardata.charts',
context: 'peardata.charts',
title: 'Registered chart count',
units: 'charts',
family: 'peardata',
chartType: 'line',
priority: 9020,
plugin: 'self-monitor',
dimensions: [{ id: 'count', name: 'count', algorithm: 'absolute' }],
}
export function isSelfMonitorEnabled() {
return true
}
const SELF_MONITOR_INTERVAL = Number(process.env.PEARDATA_SELF_MONITOR_MS) || 5000
export class SelfMonitorCollector extends CollectorPlugin {
constructor(opts = {}) {
super({ name: 'self-monitor', intervalMs: opts.intervalMs || SELF_MONITOR_INTERVAL })
/** @type {{ user: number, system: number }|null} */
this._prevCpu = null
/** @type {number|null} */
this._prevWallMs = null
}
isEnabled() {
return isSelfMonitorEnabled()
}
start() {
registerChart(CHART_CPU)
registerChart(CHART_MEM)
registerChart(CHART_CHARTS)
log.info('Self-monitor collector started')
super.start()
}
async collect() {
const ts = Date.now()
const mem = process.memoryUsage()
const cpu = process.cpuUsage()
let userPct = 0
let sysPct = 0
if (this._prevCpu && this._prevWallMs && ts > this._prevWallMs) {
const dtSec = (ts - this._prevWallMs) / 1000
if (dtSec > 0) {
const dUser = cpu.user - this._prevCpu.user
const dSys = cpu.system - this._prevCpu.system
userPct = (dUser / 1e6 / dtSec) * 100
sysPct = (dSys / 1e6 / dtSec) * 100
}
}
this._prevCpu = { user: cpu.user, system: cpu.system }
this._prevWallMs = ts
return [
{
chart: 'peardata.cpu',
context: 'peardata.cpu',
ts,
values: { user: userPct, system: sysPct },
},
{
chart: 'peardata.mem',
context: 'peardata.mem',
ts,
values: {
rss: mem.rss / (1024 * 1024),
heap: mem.heapUsed / (1024 * 1024),
},
},
{
chart: 'peardata.charts',
context: 'peardata.charts',
ts,
values: { count: getAllChartDefs().length },
},
]
}
}
/** @type {SelfMonitorCollector|null} */
let singleton = null
export function getSelfMonitorCollector() {
if (!singleton) singleton = new SelfMonitorCollector()
return singleton
}