Centralize log file and refactor desktop logging
- Migrate to `electron-log` v5.X.X, centralizing log files to adhere to best-practices. - Add critical event logging in the log file. - Replace `ElectronLog` type with `LogFunctions` for better abstraction. - Unify log handling in `desktop-runtime-error` by removing `renderer.log` due to `electron-log` v5 changes. - Update and extend logger interfaces, removing 'I' prefix and adding common log levels to abstract `electron-log` completely. - Move logger interfaces to the application layer as it's cross-cutting concern, meanwhile keeping the implementations in the infrastructure layer. - Introduce `useLogger` hook for easier logging in Vue components. - Simplify `WindowVariables` by removing nullable properties. - Improve documentation to clearly differentiate between desktop and web versions, outlining specific features of each.
This commit is contained in:
@@ -5,33 +5,28 @@ import { exists } from '../utils/io';
|
||||
import { SupportedPlatform, CURRENT_PLATFORM } from '../utils/platform';
|
||||
import { getAppName } from '../utils/npm';
|
||||
|
||||
const LOG_FILE_NAMES = ['main', 'renderer'];
|
||||
|
||||
export async function clearAppLogFiles(
|
||||
projectDir: string,
|
||||
): Promise<void> {
|
||||
if (!projectDir) { throw new Error('missing project directory'); }
|
||||
await Promise.all(LOG_FILE_NAMES.map(async (logFileName) => {
|
||||
const logPath = await determineLogPath(projectDir, logFileName);
|
||||
if (!logPath || !await exists(logPath)) {
|
||||
log(`Skipping clearing logs, log file does not exist: ${logPath}.`);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await unlink(logPath);
|
||||
log(`Successfully cleared the log file at: ${logPath}.`);
|
||||
} catch (error) {
|
||||
die(`Failed to clear the log file at: ${logPath}. Reason: ${error}`);
|
||||
}
|
||||
}));
|
||||
const logPath = await determineLogPath(projectDir);
|
||||
if (!logPath || !await exists(logPath)) {
|
||||
log(`Skipping clearing logs, log file does not exist: ${logPath}.`);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await unlink(logPath);
|
||||
log(`Successfully cleared the log file at: ${logPath}.`);
|
||||
} catch (error) {
|
||||
die(`Failed to clear the log file at: ${logPath}. Reason: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
export async function readAppLogFile(
|
||||
projectDir: string,
|
||||
logFileName: string,
|
||||
): Promise<AppLogFileResult> {
|
||||
if (!projectDir) { throw new Error('missing project directory'); }
|
||||
const logPath = await determineLogPath(projectDir, logFileName);
|
||||
const logPath = await determineLogPath(projectDir);
|
||||
if (!logPath || !await exists(logPath)) {
|
||||
log(`No log file at: ${logPath}`, LogLevel.Warn);
|
||||
return {
|
||||
@@ -52,10 +47,9 @@ interface AppLogFileResult {
|
||||
|
||||
async function determineLogPath(
|
||||
projectDir: string,
|
||||
logFileName: string,
|
||||
): Promise<string> {
|
||||
if (!projectDir) { throw new Error('missing project directory'); }
|
||||
if (!LOG_FILE_NAMES.includes(logFileName)) { throw new Error(`unknown log file name: ${logFileName}`); }
|
||||
const logFileName = 'main.log';
|
||||
const appName = await getAppName(projectDir);
|
||||
if (!appName) {
|
||||
return die('App name not found.');
|
||||
@@ -67,19 +61,19 @@ async function determineLogPath(
|
||||
if (!process.env.HOME) {
|
||||
throw new Error('HOME environment variable is not defined');
|
||||
}
|
||||
return join(process.env.HOME, 'Library', 'Logs', appName, `${logFileName}.log`);
|
||||
return join(process.env.HOME, 'Library', 'Logs', appName, logFileName);
|
||||
},
|
||||
[SupportedPlatform.Linux]: () => {
|
||||
if (!process.env.HOME) {
|
||||
throw new Error('HOME environment variable is not defined');
|
||||
}
|
||||
return join(process.env.HOME, '.config', appName, 'logs', `${logFileName}.log`);
|
||||
return join(process.env.HOME, '.config', appName, 'logs', logFileName);
|
||||
},
|
||||
[SupportedPlatform.Windows]: () => {
|
||||
if (!process.env.USERPROFILE) {
|
||||
throw new Error('USERPROFILE environment variable is not defined');
|
||||
}
|
||||
return join(process.env.USERPROFILE, 'AppData', 'Roaming', appName, 'logs', `${logFileName}.log`);
|
||||
return join(process.env.USERPROFILE, 'AppData', 'Roaming', appName, 'logs', logFileName);
|
||||
},
|
||||
};
|
||||
const logFilePath = logFilePaths[CURRENT_PLATFORM]?.();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { splitTextIntoLines, indentText, filterEmpty } from '../utils/text';
|
||||
import { splitTextIntoLines, indentText } from '../utils/text';
|
||||
import { log, die } from '../utils/log';
|
||||
import { readAppLogFile } from './app-logs';
|
||||
import { STDERR_IGNORE_PATTERNS } from './error-ignore-patterns';
|
||||
@@ -11,8 +11,6 @@ const EXPECTED_LOG_MARKERS = [
|
||||
'[APP_INIT]',
|
||||
];
|
||||
|
||||
type ProcessType = 'main' | 'renderer';
|
||||
|
||||
export async function checkForErrors(
|
||||
stderr: string,
|
||||
windowTitles: readonly string[],
|
||||
@@ -31,13 +29,11 @@ async function gatherErrors(
|
||||
projectDir: string,
|
||||
): Promise<ExecutionError[]> {
|
||||
if (!projectDir) { throw new Error('missing project directory'); }
|
||||
const { logFileContent: mainLogs, logFilePath: mainLogFile } = await readAppLogFile(projectDir, 'main');
|
||||
const { logFileContent: rendererLogs, logFilePath: rendererLogFile } = await readAppLogFile(projectDir, 'renderer');
|
||||
const allLogs = filterEmpty([mainLogs, rendererLogs, stderr]).join('\n');
|
||||
const { logFileContent: mainLogs, logFilePath: mainLogFile } = await readAppLogFile(projectDir);
|
||||
const allLogs = [mainLogs, stderr].filter(Boolean).join('\n');
|
||||
return [
|
||||
verifyStdErr(stderr),
|
||||
verifyApplicationLogsExist('main', mainLogs, mainLogFile),
|
||||
verifyApplicationLogsExist('renderer', rendererLogs, rendererLogFile),
|
||||
verifyApplicationLogsExist(mainLogs, mainLogFile),
|
||||
...EXPECTED_LOG_MARKERS.map(
|
||||
(marker) => verifyLogMarkerExistsInLogs(allLogs, marker),
|
||||
),
|
||||
@@ -72,13 +68,12 @@ function formatError(error: ExecutionError): string {
|
||||
}
|
||||
|
||||
function verifyApplicationLogsExist(
|
||||
processType: ProcessType,
|
||||
logContent: string | undefined,
|
||||
logFilePath: string,
|
||||
): ExecutionError | undefined {
|
||||
if (!logContent?.length) {
|
||||
return describeError(
|
||||
`Missing application (${processType}) logs`,
|
||||
'Missing application logs',
|
||||
'Application logs are empty not were not found.'
|
||||
+ `\nLog path: ${logFilePath}`,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user