logging and presenting cpu/memory usage when app is force-closed (#1894)

closes #1803 











<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Detects when the app was force-closed and shows a dialog with the last
known CPU and memory usage. Adds background performance monitoring so we
can surface metrics on next launch.

- **New Features**
- Start a performance monitor at app launch; captures process and system
memory/CPU every 30s and on quit.
- Persist metrics in settings.lastKnownPerformance and track
settings.isRunning to detect improper shutdowns.
- On startup, if the previous run was force-closed, send a
"force-close-detected" IPC event after the window loads.
  - Add ForceCloseDialog to display timestamped process/system metrics.
- Whitelist the new IPC channel in preload and listen for it on the home
page.

<sup>Written for commit 0543cdc234da7f94024e8506749aaa9ca36ef916.
Summary will update automatically on new commits.</sup>

<!-- End of auto-generated description by cubic. -->
This commit is contained in:
Mohamed Aziz Mejri
2025-12-14 21:07:56 +01:00
committed by GitHub
parent a4ab1a7f84
commit 9d33f3757d
38 changed files with 606 additions and 48 deletions

View File

@@ -24,6 +24,10 @@ import {
AddPromptDataSchema,
AddPromptPayload,
} from "./ipc/deep_link_data";
import {
startPerformanceMonitoring,
stopPerformanceMonitoring,
} from "./utils/performance_monitor";
import fs from "fs";
log.errorHandler.startCatching();
@@ -82,6 +86,24 @@ export async function onReady() {
}
initializeDatabase();
const settings = readSettings();
// Check if app was force-closed
if (settings.isRunning) {
logger.warn("App was force-closed on previous run");
// Store performance data to send after window is created
if (settings.lastKnownPerformance) {
logger.warn("Last known performance:", settings.lastKnownPerformance);
pendingForceCloseData = settings.lastKnownPerformance;
}
}
// Set isRunning to true at startup
writeSettings({ isRunning: true });
// Start performance monitoring
startPerformanceMonitoring();
await onFirstRunMaybe(settings);
createWindow();
@@ -151,6 +173,7 @@ declare global {
}
let mainWindow: BrowserWindow | null = null;
let pendingForceCloseData: any = null;
const createWindow = () => {
// Create the browser window.
@@ -187,6 +210,16 @@ const createWindow = () => {
mainWindow.webContents.openDevTools();
}
// Send force-close event if it was detected
if (pendingForceCloseData) {
mainWindow.webContents.once("did-finish-load", () => {
mainWindow?.webContents.send("force-close-detected", {
performanceData: pendingForceCloseData,
});
pendingForceCloseData = null;
});
}
// Enable native context menu on right-click
mainWindow.webContents.on("context-menu", (event, params) => {
// Prevent any default behavior and show our own menu
@@ -414,6 +447,16 @@ app.on("window-all-closed", () => {
}
});
// Only set isRunning to false when the app is properly quit by the user
app.on("will-quit", () => {
logger.info("App is quitting, setting isRunning to false");
// Stop performance monitoring and capture final metrics
stopPerformanceMonitoring();
writeSettings({ isRunning: false });
});
app.on("activate", () => {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.