/** * 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 } export class SelfMonitorCollector extends CollectorPlugin { constructor(opts = {}) { super({ name: 'self-monitor', intervalMs: opts.intervalMs }) /** @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 }