()
| 77 | * every child process Electron spawns. |
| 78 | */ |
| 79 | export const initErrorReporting = () => { |
| 80 | if (errorReportingEnabled) { |
| 81 | Sentry.init({ |
| 82 | dsn: sentryDsn, |
| 83 | release: releaseTag(), |
| 84 | environment: environmentTag(), |
| 85 | initialScope: { |
| 86 | tags: { |
| 87 | platform: process.platform, |
| 88 | arch: process.arch, |
| 89 | runId, |
| 90 | }, |
| 91 | }, |
| 92 | }); |
| 93 | } else { |
| 94 | // No DSN baked in — keep native crash dumps local so a user-reported |
| 95 | // crash still leaves minidumps for the diagnostics zip to collect. |
| 96 | crashReporter.start({ uploadToServer: false, compress: true }); |
| 97 | } |
| 98 | |
| 99 | // Persist process-death signals to main.log regardless of Sentry — these |
| 100 | // are the events a "the app just disappeared" report hinges on. Sentry's |
| 101 | // ChildProcess integration reports them upstream; this keeps a local copy. |
| 102 | app.on("child-process-gone", (_event, details) => { |
| 103 | log.error("[crash] child process gone", details); |
| 104 | }); |
| 105 | app.on("render-process-gone", (_event, webContents, details) => { |
| 106 | log.error("[crash] render process gone", { url: webContents.getURL(), ...details }); |
| 107 | }); |
| 108 | |
| 109 | // Main-process uncaught errors: electron-log writes them to main.log and |
| 110 | // keeps the process alive (matching its default), Sentry (when enabled) |
| 111 | // captures them via its own integrations. |
| 112 | log.errorHandler.startCatching({ showDialog: false }); |
| 113 | |
| 114 | // Every log line becomes a Sentry breadcrumb, so an error event arrives |
| 115 | // with the recent log context (sidecar restarts, update checks, …) instead |
| 116 | // of a bare stack. Hooked on the file transport only so each line is |
| 117 | // recorded once. No-ops when Sentry is disabled. |
| 118 | log.hooks.push((message, transport) => { |
| 119 | if (transport !== log.transports.file) return message; |
| 120 | Sentry.addBreadcrumb({ |
| 121 | category: message.scope ?? "main", |
| 122 | level: message.level === "warn" ? "warning" : message.level === "error" ? "error" : "info", |
| 123 | message: message.data |
| 124 | .map((part) => (typeof part === "string" ? part : JSON.stringify(part))) |
| 125 | .join(" ") |
| 126 | .slice(0, 1024), |
| 127 | }); |
| 128 | return message; |
| 129 | }); |
| 130 | }; |
| 131 | |
| 132 | /** |
| 133 | * Report a sidecar crash that happened after a successful boot. The startup |
no test coverage detected