(options: ServerCrashLogOptions)
| 89 | } |
| 90 | |
| 91 | export function appendServerCrashLogSync(options: ServerCrashLogOptions): string { |
| 92 | let entry: string; |
| 93 | try { |
| 94 | entry = buildServerCrashLogEntry(options); |
| 95 | } catch (error) { |
| 96 | // Crash hooks must survive even if the current working directory disappeared |
| 97 | // or another formatting helper throws while we're already handling a fatal error. |
| 98 | entry = `${(options.timestamp ?? new Date()).toISOString()} [mux server crash] ${options.event}\nfailed_to_build_crash_entry=${getErrorMessage(error)}\n`; |
| 99 | } |
| 100 | |
| 101 | const logFilePath = options.logFilePath ?? getLogFilePath(); |
| 102 | |
| 103 | // Fatal crashes can terminate the process before the async logger flushes, |
| 104 | // so server-mode crash hooks append a compact entry synchronously. |
| 105 | try { |
| 106 | // eslint-disable-next-line local/no-sync-fs-methods -- crash handlers must create the log directory before the process exits. |
| 107 | fs.mkdirSync(path.dirname(logFilePath), { recursive: true }); |
| 108 | // eslint-disable-next-line local/no-sync-fs-methods -- synchronous append is intentional so fatal exits still leave a breadcrumb. |
| 109 | fs.appendFileSync(logFilePath, entry, "utf-8"); |
| 110 | } catch { |
| 111 | // Best effort: crash logging must never trigger a second failure. |
| 112 | } |
| 113 | |
| 114 | return entry; |
| 115 | } |
no test coverage detected