Files
makelore/electron/main/performance-diagnostics.ts

54 lines
1.7 KiB
TypeScript

import { app, BrowserWindow, webContents } from 'electron';
import { monitorEventLoopDelay } from 'node:perf_hooks';
export type PerformanceSnapshot = {
capturedAt: number;
eventLoopDelayMs: number;
gpu: ReturnType<typeof app.getGPUFeatureStatus>;
processes: Array<{
pid: number;
type: string;
cpuPercent: number;
workingSetSize: number;
}>;
windows: number;
webContents: number;
background: {
activity: { visible: boolean; module: string | null };
leaseCount: number;
};
};
type LifecycleDiagnostics = {
getActivity(): { visible: boolean; module: string | null };
getLeaseCount(): number;
};
// Keep the sampler alive for the process lifetime, but only expose aggregate
// histogram values. No request payloads, URLs or project data enter this
// diagnostic path.
const eventLoopMonitor = monitorEventLoopDelay({ resolution: 20 });
eventLoopMonitor.enable();
export function collectPerformanceSnapshot(lifecycle?: LifecycleDiagnostics): PerformanceSnapshot {
const eventLoopDelayMs = eventLoopMonitor.max / 1e6;
eventLoopMonitor.reset();
return {
capturedAt: Date.now(),
eventLoopDelayMs: Math.round(eventLoopDelayMs * 100) / 100,
gpu: app.getGPUFeatureStatus(),
processes: app.getAppMetrics().map((metric) => ({
pid: metric.pid,
type: metric.type,
cpuPercent: metric.cpu.percentCPUUsage,
workingSetSize: metric.memory.workingSetSize,
})),
windows: BrowserWindow.getAllWindows().length,
webContents: webContents.getAllWebContents().length,
background: {
activity: lifecycle?.getActivity() ?? { visible: true, module: null },
leaseCount: lifecycle?.getLeaseCount() ?? 0,
},
};
}