From fc5338903b20d428a26439a36bb8a9b3f535257f Mon Sep 17 00:00:00 2001 From: Carlos Valente <34649812+cpvalente@users.noreply.github.com> Date: Fri, 23 Feb 2024 08:52:08 +0100 Subject: [PATCH] feat: generate crash report (#787) --- apps/server/src/app.ts | 3 ++ apps/server/src/setup.ts | 3 ++ apps/server/src/utils/generateCrashReport.ts | 49 ++++++++++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 apps/server/src/utils/generateCrashReport.ts diff --git a/apps/server/src/app.ts b/apps/server/src/app.ts index 7aef7db95..58ac79de4 100644 --- a/apps/server/src/app.ts +++ b/apps/server/src/app.ts @@ -45,6 +45,7 @@ import { populateDemo } from './modules/loadDemo.js'; import { getState, updateRundownData } from './stores/runtimeState.js'; import { setRundown } from './services/rundown-service/RundownService.js'; import { getPlayableEvents } from './services/rundown-service/rundownUtils.js'; +import { generateCrashReport } from './utils/generateCrashReport.js'; console.log(`Starting Ontime version ${ONTIME_VERSION}`); @@ -286,12 +287,14 @@ process.on('exit', (code) => console.log(`Ontime shutdown with code: ${code}`)); process.on('unhandledRejection', async (error) => { console.error('Error: unhandled rejection', error); + generateCrashReport(error); logger.error(LogOrigin.Server, `Error: unhandled rejection ${error}`); await shutdown(1); }); process.on('uncaughtException', async (error) => { console.error('Error: uncaught exception', error); + generateCrashReport(error); logger.error(LogOrigin.Server, `Error: uncaught exception ${error}`); await shutdown(1); }); diff --git a/apps/server/src/setup.ts b/apps/server/src/setup.ts index e2fddea2a..3734bd47f 100644 --- a/apps/server/src/setup.ts +++ b/apps/server/src/setup.ts @@ -123,3 +123,6 @@ export const pathToStartDemo = config.demo.filename.map((file) => { // path to restore file export const resolveRestoreFile = join(getAppDataPath(), config.restoreFile); + +// path to crash reports +export const resolveCrashReportDirectory = getAppDataPath(); diff --git a/apps/server/src/utils/generateCrashReport.ts b/apps/server/src/utils/generateCrashReport.ts new file mode 100644 index 000000000..82e954e6a --- /dev/null +++ b/apps/server/src/utils/generateCrashReport.ts @@ -0,0 +1,49 @@ +import { writeFileSync } from 'fs'; +import { join } from 'path'; + +import { ONTIME_VERSION } from '../ONTIME_VERSION.js'; +import { get } from '../services/rundown-service/rundownCache.js'; +import { getState } from '../stores/runtimeState.js'; +import { resolveCrashReportDirectory } from '../setup.js'; + +/** + * Writes a file to the crash report location + * @param fileName + * @param content + */ +function writeToFile(fileName: string, content: object) { + const path = join(resolveCrashReportDirectory, fileName); + try { + const textContent = JSON.stringify(content, null, 2); + writeFileSync(path, textContent); + } catch (e_rror) { + /** We do not handle the error here */ + } +} + +/* + * Generates a crash report + * @param error + */ +export function generateCrashReport(maybeError: unknown) { + const timeNow = new Date().toISOString(); + const runtimeState = getState(); + const rundownState = get(); + const error = + maybeError instanceof Error + ? { + message: maybeError.message, + stack: maybeError.stack || 'No stack trace available', + } + : String(maybeError); + + const crashReport = { + time: timeNow, + version: ONTIME_VERSION, + error, + runtimeState, + rundownState, + }; + + writeToFile(`crash-log-${timeNow}.log`, crashReport); +}