Better usage of pino

This commit is contained in:
Fedor Indutny
2025-06-16 09:47:18 -07:00
committed by GitHub
parent 58f006aac2
commit f6c19c548e
60 changed files with 489 additions and 738 deletions

View File

@@ -42,6 +42,7 @@ import { safeParseInteger } from '../ts/util/numbers';
import { parseLoose } from '../ts/util/schemas';
import { sleep } from '../ts/util/sleep';
import { toWebStream } from '../ts/util/toWebStream';
import * as log from '../ts/logging/log';
import {
deleteAll as deleteAllAttachments,
deleteAllBadges,
@@ -127,7 +128,7 @@ async function safeDecryptToSink(
timeout: GROWING_FILE_TIMEOUT,
});
file.on('error', (error: Error) => {
console.warn(
log.warn(
'safeDecryptToSync/incremental: growing-file emitted an error:',
Errors.toLogFormat(error)
);
@@ -215,7 +216,7 @@ async function safeDecryptToSink(
return;
}
console.error(
log.error(
'handleAttachmentRequest: decryption error',
Errors.toLogFormat(error)
);
@@ -307,13 +308,13 @@ async function cleanupOrphanedAttachments({
});
const orphanedAttachments = new Set(await getAllAttachments(userDataPath));
console.log(
log.info(
'cleanupOrphanedAttachments: found ' +
`${orphanedAttachments.size} attachments on disk`
);
const orphanedDownloads = new Set(await getAllDownloads(userDataPath));
console.log(
log.info(
'cleanupOrphanedAttachments: found ' +
`${orphanedDownloads.size} downloads on disk`
);
@@ -330,13 +331,13 @@ async function cleanupOrphanedAttachments({
}
}
console.log(
log.info(
`cleanupOrphanedAttachments: Got ${conversationAttachments.length} conversation attachments,` +
` ${orphanedAttachments.size} remain`
);
if (missingConversationAttachments > 0) {
console.warn(
log.warn(
`cleanupOrphanedAttachments: ${missingConversationAttachments} conversation attachments were not found on disk`
);
}
@@ -352,13 +353,13 @@ async function cleanupOrphanedAttachments({
}
}
console.log(
log.info(
`cleanupOrphanedAttachments: found ${downloads.length} known downloads, ` +
`${orphanedDownloads.size} remain`
);
if (missing > 0) {
console.warn(
log.warn(
`cleanupOrphanedAttachments: ${missing} downloads were not found on disk`
);
}
@@ -433,13 +434,13 @@ function deleteOrphanedAttachments({
}
}
console.log(
log.info(
`cleanupOrphanedAttachments: ${totalAttachmentsFound} message ` +
`attachments; ${orphanedAttachments.size} remain`
);
if (totalMissing > 0) {
console.warn(
log.warn(
`cleanupOrphanedAttachments: ${totalMissing} message attachments were not found on disk`
);
}
@@ -449,7 +450,7 @@ function deleteOrphanedAttachments({
attachments: Array.from(orphanedAttachments),
});
console.log(
log.info(
`cleanupOrphanedAttachments: found ${totalDownloadsFound} downloads ` +
`${orphanedDownloads.size} remain`
);
@@ -464,13 +465,10 @@ function deleteOrphanedAttachments({
try {
await runWithPossibleException();
} catch (error) {
console.error(
'deleteOrphanedAttachments: error',
Errors.toLogFormat(error)
);
log.error('deleteOrphanedAttachments: error', Errors.toLogFormat(error));
} finally {
const duration = Date.now() - start;
console.log(`deleteOrphanedAttachments: took ${duration}ms`);
log.info(`deleteOrphanedAttachments: took ${duration}ms`);
}
}
@@ -534,7 +532,7 @@ export function initialize({
_block,
});
const duration = Date.now() - start;
console.log(`cleanupOrphanedAttachments: took ${duration}ms`);
log.info(`cleanupOrphanedAttachments: took ${duration}ms`);
}
);
@@ -542,7 +540,7 @@ export function initialize({
const start = Date.now();
await deleteStaleDownloads(configDir);
const duration = Date.now() - start;
console.log(`cleanupDownloads: took ${duration}ms`);
log.info(`cleanupDownloads: took ${duration}ms`);
});
protocol.handle('attachment', handleAttachmentRequest);
@@ -680,7 +678,7 @@ export async function handleAttachmentRequest(req: Request): Promise<Response> {
context,
});
} catch (error) {
console.error('handleAttachmentRequest: error', Errors.toLogFormat(error));
log.error('handleAttachmentRequest: error', Errors.toLogFormat(error));
throw error;
}
}
@@ -733,13 +731,13 @@ function handleRangeRequest({
// Chromium only sends open-ended ranges: "start-"
const match = range.match(/^bytes=(\d+)-$/);
if (match == null) {
console.error(`attachment_channel: invalid range header: ${range}`);
log.error(`attachment_channel: invalid range header: ${range}`);
return create200Response();
}
const startParam = safeParseInteger(match[1]);
if (startParam == null) {
console.error(`attachment_channel: invalid range header: ${range}`);
log.error(`attachment_channel: invalid range header: ${range}`);
return create200Response();
}

View File

@@ -20,6 +20,7 @@ import {
} from '../ts/AttachmentCrypto';
import type { LocalAttachmentV2Type } from '../ts/types/Attachment';
import * as Errors from '../ts/types/errors';
import * as log from '../ts/logging/log';
const PATH = 'attachments.noindex';
const AVATAR_PATH = 'avatars.noindex';
@@ -155,7 +156,7 @@ export const deleteStaleDownloads = async (
if (error.code === 'ENOENT') {
return;
}
console.error(
log.error(
'deleteStaleDownloads: failed to get file stats',
Errors.toLogFormat(error)
);
@@ -169,7 +170,7 @@ export const deleteStaleDownloads = async (
if (stale.length === 0) {
return;
}
console.log(`deleteStaleDownloads: found ${stale.length}`);
log.info(`deleteStaleDownloads: found ${stale.length}`);
await deleteAllDownloads({ userDataPath, downloads: stale });
};
@@ -184,7 +185,7 @@ export const deleteAll = async ({
await pMap(attachments, deleteFromDisk, { concurrency: FS_CONCURRENCY });
console.log(`deleteAll: deleted ${attachments.length} files`);
log.info(`deleteAll: deleted ${attachments.length} files`);
};
export const deleteAllDownloads = async ({
@@ -198,7 +199,7 @@ export const deleteAllDownloads = async ({
await pMap(downloads, deleteFromDisk, { concurrency: FS_CONCURRENCY });
console.log(`deleteAllDownloads: deleted ${downloads.length} files`);
log.info(`deleteAllDownloads: deleted ${downloads.length} files`);
};
export const deleteAllStickers = async ({
@@ -212,7 +213,7 @@ export const deleteAllStickers = async ({
await pMap(stickers, deleteFromDisk, { concurrency: FS_CONCURRENCY });
console.log(`deleteAllStickers: deleted ${stickers.length} files`);
log.info(`deleteAllStickers: deleted ${stickers.length} files`);
};
export const deleteAllBadges = async ({
@@ -233,7 +234,7 @@ export const deleteAllBadges = async ({
}
}
console.log(`deleteAllBadges: deleted ${filesDeleted} files`);
log.info(`deleteAllBadges: deleted ${filesDeleted} files`);
};
export const deleteAllDraftAttachments = async ({
@@ -247,7 +248,7 @@ export const deleteAllDraftAttachments = async ({
await pMap(attachments, deleteFromDisk, { concurrency: FS_CONCURRENCY });
console.log(`deleteAllDraftAttachments: deleted ${attachments.length} files`);
log.info(`deleteAllDraftAttachments: deleted ${attachments.length} files`);
};
export const readAndDecryptDataFromDisk = async ({

View File

@@ -7,6 +7,7 @@ import { sync as writeFileSync } from 'write-file-atomic';
import { get } from 'lodash';
import { set } from 'lodash/fp';
import { strictAssert } from '../ts/util/assert';
import * as log from '../ts/logging/log';
const ENCODING = 'utf8';
@@ -36,10 +37,10 @@ export function start({
try {
incomingJson = readFileSync(targetPath, ENCODING);
cachedValue = incomingJson ? JSON.parse(incomingJson) : undefined;
console.log(`config/get: Successfully read ${name} config file`);
log.info(`config/get: Successfully read ${name} config file`);
if (!cachedValue) {
console.log(
log.info(
`config/start: ${name} config value was falsy, cache is now empty object`
);
cachedValue = Object.create(null);
@@ -50,11 +51,11 @@ export function start({
}
if (incomingJson) {
console.log(
log.info(
`config/start: ${name} config file was malformed, starting afresh`
);
} else {
console.log(
log.info(
`config/start: Did not find ${name} config file (or it was empty), cache is now empty object`
);
}
@@ -68,7 +69,7 @@ export function start({
function ourSet(keyPath: string, value: unknown): void {
const newCachedValue = set(keyPath, value, cachedValue);
console.log(`config/set: Saving ${name} config to disk`);
log.info(`config/set: Saving ${name} config to disk`);
if (!throwOnFilesystemErrors) {
cachedValue = newCachedValue;
@@ -76,13 +77,13 @@ export function start({
const outgoingJson = JSON.stringify(newCachedValue, null, ' ');
try {
writeFileSync(targetPath, outgoingJson, ENCODING);
console.log(`config/set: Saved ${name} config to disk`);
log.info(`config/set: Saved ${name} config to disk`);
cachedValue = newCachedValue;
} catch (err: unknown) {
if (throwOnFilesystemErrors) {
throw err;
} else {
console.warn(
log.warn(
`config/set: Failed to save ${name} config to disk; only updating in-memory data`
);
}
@@ -90,17 +91,17 @@ export function start({
}
function remove(): void {
console.log(`config/remove: Deleting ${name} config from disk`);
log.info(`config/remove: Deleting ${name} config from disk`);
try {
unlinkSync(targetPath);
console.log(`config/remove: Deleted ${name} config from disk`);
log.info(`config/remove: Deleted ${name} config from disk`);
} catch (err: unknown) {
const errCode: unknown = get(err, 'code');
if (throwOnFilesystemErrors) {
strictAssert(errCode === 'ENOENT', 'Expected deletion of no file');
console.log(`config/remove: No ${name} config on disk, did nothing`);
log.info(`config/remove: No ${name} config on disk, did nothing`);
} else {
console.warn(
log.warn(
`config/remove: Got ${String(
errCode
)} when removing ${name} config from disk`

View File

@@ -12,6 +12,7 @@ import {
setEnvironment,
parseEnvironment,
} from '../ts/environment';
import * as log from '../ts/logging/log';
// In production mode, NODE_ENV cannot be customized by the user
if (app.isPackaged) {
@@ -51,7 +52,7 @@ const config: IConfig = require('config');
if (getEnvironment() !== Environment.PackagedApp) {
config.util.getConfigSources().forEach(source => {
console.log(`config: Using config source ${basename(source.name)}`);
log.info(`config: Using config source ${basename(source.name)}`);
});
}

View File

@@ -99,14 +99,14 @@ async function eraseDumps(
}
export function setup(
getLogger: () => LoggerType,
logger: LoggerType,
showDebugLogWindow: () => Promise<void>,
forceEnable = false
): void {
const isEnabled = !isProduction(app.getVersion()) || forceEnable;
if (isEnabled) {
getLogger().info(`crashReporter: ${forceEnable ? 'force ' : ''}enabled`);
logger.info(`crashReporter: ${forceEnable ? 'force ' : ''}enabled`);
crashReporter.start({ uploadToServer: false });
}
@@ -127,7 +127,7 @@ export function setup(
return fullPath;
}
} catch (error) {
getLogger().error(
logger.error(
`crashReports: failed to read crash report ${fullPath} due to error`,
Errors.toLogFormat(error)
);
@@ -136,7 +136,7 @@ export function setup(
try {
await unlink(fullPath);
} catch (error) {
getLogger().error(
logger.error(
`crashReports: failed to unlink crash report ${fullPath}`,
Errors.toLogFormat(error)
);
@@ -147,9 +147,7 @@ export function setup(
).filter(isNotNil);
if (filteredDumps.length !== 0) {
getLogger().warn(
`crashReports: ${filteredDumps.length} pending dumps found`
);
logger.warn(`crashReports: ${filteredDumps.length} pending dumps found`);
}
return filteredDumps.length;
});
@@ -164,7 +162,6 @@ export function setup(
return;
}
const logger = getLogger();
logger.warn(`crashReports: logging ${pendingDumps.length} dumps`);
await Promise.all(
@@ -225,6 +222,6 @@ export function setup(
const pendingDumps = await getPendingDumps();
await eraseDumps(getLogger(), pendingDumps);
await eraseDumps(logger, pendingDumps);
});
}

View File

@@ -6,6 +6,7 @@ import { readFile } from 'fs/promises';
import { DNSFallbackSchema } from '../ts/types/DNSFallback';
import type { DNSFallbackType } from '../ts/types/DNSFallback';
import { parseUnknown } from '../ts/util/schemas';
import * as log from '../ts/logging/log';
let cached: DNSFallbackType | undefined;
@@ -19,7 +20,7 @@ export async function getDNSFallback(): Promise<DNSFallbackType> {
try {
str = await readFile(configPath, 'utf8');
} catch (error) {
console.error(
log.error(
'Warning: build/dns-fallback.json not build, run `npm run build:dns-fallback`'
);
cached = [];

View File

@@ -6,6 +6,7 @@ import os from 'node:os';
import * as Errors from '../ts/types/errors';
import { redactAll } from '../ts/util/privacy';
import * as log from '../ts/logging/log';
import { reallyJsonStringify } from '../ts/util/reallyJsonStringify';
import type { LocaleType } from './locale';
@@ -15,10 +16,8 @@ let copyErrorAndQuitText = 'Copy error and quit';
function handleError(prefix: string, error: Error): void {
const formattedError = Errors.toLogFormat(error);
if (console._error) {
console._error(`${prefix}:`, formattedError);
}
console.error(`${prefix}:`, formattedError);
log.error(`${prefix}:`, formattedError);
if (app.isReady()) {
// title field is not shown on macOS, so we don't use it

View File

@@ -42,11 +42,11 @@ import { createSupportUrl } from '../ts/util/createSupportUrl';
import { missingCaseError } from '../ts/util/missingCaseError';
import { strictAssert } from '../ts/util/assert';
import { drop } from '../ts/util/drop';
import { createBufferedConsoleLogger } from '../ts/util/consoleLogger';
import type { ThemeSettingType } from '../ts/types/StorageUIKeys';
import { ThemeType } from '../ts/types/Util';
import * as Errors from '../ts/types/errors';
import { resolveCanonicalLocales } from '../ts/util/resolveCanonicalLocales';
import * as log from '../ts/logging/log';
import * as debugLog from '../ts/logging/debuglogs';
import * as uploadDebugLog from '../ts/logging/uploadDebugLog';
import { explodePromise } from '../ts/util/explodePromise';
@@ -92,7 +92,7 @@ import {
isContentProtectionEnabledByDefault,
} from '../ts/types/Settings';
import * as ephemeralConfig from './ephemeral_config';
import * as logging from '../ts/logging/main_process_logging';
import * as mainProcessLogging from '../ts/logging/main_process_logging';
import { MainSQL } from '../ts/sql/main';
import * as sqlChannels from './sql_channel';
import * as windowState from './window_state';
@@ -113,7 +113,6 @@ import { getHeicConverter } from '../ts/workers/heicConverterMain';
import type { LocaleDirection, LocaleType } from './locale';
import { load as loadLocale } from './locale';
import type { LoggerType } from '../ts/types/Logging';
import { HourCyclePreference } from '../ts/types/I18N';
import { ScreenShareStatus } from '../ts/types/Calling';
import type { ParsedSignalRoute } from '../ts/util/signalRoutes';
@@ -142,12 +141,7 @@ let mainWindow: BrowserWindow | undefined;
let mainWindowCreated = false;
let loadingWindow: BrowserWindow | undefined;
// Create a buffered logger to hold our log lines until we fully initialize
// the logger in `app.on('ready')`
const consoleLogger = createBufferedConsoleLogger();
// These will be set after app fires the 'ready' event
let logger: LoggerType | undefined;
let preferredSystemLocales: Array<string> | undefined;
let localeOverride: string | null | undefined;
@@ -217,7 +211,7 @@ const DISABLE_SCREEN_SECURITY = process.argv.some(
const CLI_LANG = cliOptions.lang as string | undefined;
setupCrashReports(getLogger, showDebugLogWindow, FORCE_ENABLE_CRASH_REPORTS);
setupCrashReports(log, showDebugLogWindow, FORCE_ENABLE_CRASH_REPORTS);
let sendDummyKeystroke: undefined | (() => void);
if (OS.isWindows()) {
@@ -226,10 +220,7 @@ if (OS.isWindows()) {
const windowsNotifications = require('./WindowsNotifications');
sendDummyKeystroke = windowsNotifications.sendDummyKeystroke;
} catch (error) {
getLogger().error(
'Failed to initialize Windows Notifications:',
error.stack
);
log.error('Failed to initialize Windows Notifications:', error.stack);
}
}
@@ -250,10 +241,10 @@ function showWindow() {
}
if (!process.mas) {
console.log('making app single instance');
log.info('making app single instance');
const gotLock = app.requestSingleInstanceLock();
if (!gotLock) {
console.log('quitting; we are the second instance');
log.info('quitting; we are the second instance');
app.exit();
} else {
app.on('second-instance', (_e: Electron.Event, argv: Array<string>) => {
@@ -269,12 +260,6 @@ if (!process.mas) {
showWindow();
}
if (!logger) {
console.log(
'second-instance: logger not initialized; skipping further checks'
);
return;
}
const route = maybeGetIncomingSignalRoute(argv);
if (route != null) {
@@ -311,14 +296,14 @@ const heicConverter = getHeicConverter();
async function getSpellCheckSetting(): Promise<boolean> {
const value = ephemeralConfig.get('spell-check');
if (typeof value === 'boolean') {
getLogger().info('got fast spellcheck setting', value);
log.info('got fast spellcheck setting', value);
return value;
}
// Default to `true` if setting doesn't exist yet
ephemeralConfig.set('spell-check', true);
getLogger().info('initializing spellcheck setting', true);
log.info('initializing spellcheck setting', true);
return true;
}
@@ -332,7 +317,7 @@ async function getThemeSetting({
}: GetThemeSettingOptionsType = {}): Promise<ThemeSettingType> {
const value = ephemeralConfig.get('theme-setting');
if (value !== undefined) {
getLogger().info('got fast theme-setting value', value);
log.info('got fast theme-setting value', value);
} else if (ephemeralOnly) {
return 'system';
}
@@ -345,7 +330,7 @@ async function getThemeSetting({
if (value !== validatedResult) {
ephemeralConfig.set('theme-setting', validatedResult);
getLogger().info('saving theme-setting value', validatedResult);
log.info('saving theme-setting value', validatedResult);
}
return validatedResult;
@@ -386,14 +371,14 @@ async function getLocaleOverrideSetting(): Promise<string | null> {
const value = ephemeralConfig.get('localeOverride');
// eslint-disable-next-line eqeqeq -- Checking for null explicitly
if (typeof value === 'string' || value === null) {
getLogger().info('got fast localeOverride setting', value);
log.info('got fast localeOverride setting', value);
return value;
}
// Default to `null` if setting doesn't exist yet
ephemeralConfig.set('localeOverride', null);
getLogger().info('initializing localeOverride setting', null);
log.info('initializing localeOverride setting', null);
return null;
}
@@ -449,15 +434,6 @@ if (windowFromUserConfig) {
let menuOptions: CreateTemplateOptionsType | undefined;
function getLogger(): LoggerType {
if (!logger) {
console.warn('getLogger: Logger not yet initialized!');
return consoleLogger;
}
return logger;
}
function getPreferredSystemLocales(): Array<string> {
if (!preferredSystemLocales) {
throw new Error('getPreferredSystemLocales: Locales not yet initialized!');
@@ -537,7 +513,7 @@ async function handleUrl(rawTarget: string) {
try {
await shell.openExternal(rawTarget);
} catch (error) {
getLogger().error(`Failed to open url: ${Errors.toLogFormat(error)}`);
log.error(`Failed to open url: ${Errors.toLogFormat(error)}`);
}
}
}
@@ -555,7 +531,7 @@ async function handleCommonWindowEvents(window: BrowserWindow) {
window.webContents.on(
'preload-error',
(_event: Electron.Event, preloadPath: string, error: Error) => {
getLogger().error(`Preload error in ${preloadPath}: `, error.message);
log.error(`Preload error in ${preloadPath}: `, error.message);
}
);
@@ -668,7 +644,7 @@ async function safeLoadURL(window: BrowserWindow, url: string): Promise<void> {
(wasDestroyed || windowState.readyForShutdown()) &&
error?.code === 'ERR_FAILED'
) {
getLogger().warn(
log.warn(
'safeLoadURL: ignoring ERR_FAILED because we are shutting down',
error
);
@@ -758,14 +734,14 @@ async function createWindow() {
isNumber(windowOptions.width) &&
isNumber(windowOptions.height);
if (haveFullWindowsBounds) {
getLogger().info(
log.info(
`visibleOnAnyScreen(window): x=${windowOptions.x}, y=${windowOptions.y}, ` +
`width=${windowOptions.width}, height=${windowOptions.height}`
);
const visibleOnAnyScreen = some(screen.getAllDisplays(), display => {
const displayBounds = get(display, 'bounds');
getLogger().info(
log.info(
`visibleOnAnyScreen(display #${display.id}): ` +
`x=${displayBounds.x}, y=${displayBounds.y}, ` +
`width=${displayBounds.width}, height=${displayBounds.height}`
@@ -774,16 +750,13 @@ async function createWindow() {
return isVisible(windowOptions as BoundsType, displayBounds);
});
if (!visibleOnAnyScreen) {
getLogger().info('visibleOnAnyScreen: Location reset needed');
log.info('visibleOnAnyScreen: Location reset needed');
delete windowOptions.x;
delete windowOptions.y;
}
}
getLogger().info(
'Initializing BrowserWindow config:',
JSON.stringify(windowOptions)
);
log.info('Initializing BrowserWindow config:', windowOptions);
// Create the browser window.
mainWindow = new BrowserWindow(windowOptions);
@@ -797,7 +770,7 @@ async function createWindow() {
getPreferredSystemLocales(),
getLocaleOverride(),
getResolvedMessagesLocale().i18n,
getLogger()
log
);
if (!startInTray && windowConfig && windowConfig.maximized) {
mainWindow.maximize();
@@ -814,10 +787,7 @@ async function createWindow() {
return;
}
getLogger().info(
'Updating BrowserWindow config: %s',
JSON.stringify(windowConfig)
);
log.info('Updating BrowserWindow config:', windowConfig);
ephemeralConfig.set('window', windowConfig);
}
const debouncedSaveStats = debounce(saveWindowStats, 500);
@@ -878,11 +848,11 @@ async function createWindow() {
// Electron before the app quits.
mainWindow.on('close', async e => {
if (!mainWindow) {
getLogger().info('close event: no main window');
log.info('close event: no main window');
return;
}
getLogger().info('close event', {
log.info('close event', {
readyForShutdown: windowState.readyForShutdown(),
shouldQuit: windowState.shouldQuit(),
});
@@ -906,7 +876,7 @@ async function createWindow() {
try {
shouldClose = await maybeRequestCloseConfirmation();
} catch (error) {
getLogger().warn(
log.warn(
'Error while requesting close confirmation.',
Errors.toLogFormat(error)
);
@@ -947,12 +917,12 @@ async function createWindow() {
if (usingTrayIcon) {
const shownTrayNotice = ephemeralConfig.get('shown-tray-notice');
if (shownTrayNotice) {
getLogger().info('close: not showing tray notice');
log.info('close: not showing tray notice');
return;
}
ephemeralConfig.set('shown-tray-notice', true);
getLogger().info('close: showing tray notice');
log.info('close: showing tray notice');
const n = new Notification({
title: getResolvedMessagesLocale().i18n(
@@ -984,7 +954,7 @@ async function createWindow() {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
getLogger().info('main window closed event');
log.info('main window closed event');
mainWindow = undefined;
if (settingsChannel) {
settingsChannel.setMainWindow(mainWindow);
@@ -995,13 +965,13 @@ async function createWindow() {
});
mainWindow.on('enter-full-screen', () => {
getLogger().info('mainWindow enter-full-screen event');
log.info('mainWindow enter-full-screen event');
if (mainWindow) {
mainWindow.webContents.send('full-screen-change', true);
}
});
mainWindow.on('leave-full-screen', () => {
getLogger().info('mainWindow leave-full-screen event');
log.info('mainWindow leave-full-screen event');
if (mainWindow) {
mainWindow.webContents.send('full-screen-change', false);
}
@@ -1031,19 +1001,19 @@ async function createWindow() {
mainWindow.webContents.send('ci:event', 'db-initialized', {});
if (shouldShowWindow) {
getLogger().info('showing main window');
log.info('showing main window');
mainWindow.show();
}
};
if (OS.isLinux() && OS.isWaylandEnabled()) {
mainWindow.webContents.once('did-finish-load', async () => {
getLogger().info('main window webContents did-finish-load');
log.info('main window webContents did-finish-load');
drop(maybeShowMainWindow());
});
} else {
mainWindow.once('ready-to-show', async () => {
getLogger().info('main window is ready-to-show');
log.info('main window is ready-to-show');
drop(maybeShowMainWindow());
});
}
@@ -1059,20 +1029,20 @@ async function createWindow() {
// Renderer asks if we are done with the database
ipc.handle('database-ready', async () => {
if (!sqlInitPromise) {
getLogger().error('database-ready requested, but sqlInitPromise is falsey');
log.error('database-ready requested, but sqlInitPromise is falsey');
return;
}
const { error } = await sqlInitPromise;
if (error) {
getLogger().error(
log.error(
'database-ready requested, but got sql error',
Errors.toLogFormat(error)
);
return;
}
getLogger().info('sending `database-ready`');
log.info('sending `database-ready`');
});
ipc.handle(
@@ -1143,10 +1113,10 @@ ipc.on('set-is-call-active', (_event, isCallActive) => {
let backgroundThrottling: boolean;
if (isCallActive) {
getLogger().info('Background throttling disabled because a call is active');
log.info('Background throttling disabled because a call is active');
backgroundThrottling = false;
} else {
getLogger().info('Background throttling enabled because no call is active');
log.info('Background throttling enabled because no call is active');
backgroundThrottling = true;
}
@@ -1192,23 +1162,20 @@ async function readyForUpdates() {
);
},
getMainWindow,
logger: getLogger(),
logger: log,
sql,
});
} catch (error) {
getLogger().error(
'Error starting update checks:',
Errors.toLogFormat(error)
);
log.error('Error starting update checks:', Errors.toLogFormat(error));
}
}
async function forceUpdate() {
try {
getLogger().info('starting force update');
log.info('starting force update');
await updater.force();
} catch (error) {
getLogger().error('Error during force update:', Errors.toLogFormat(error));
log.error('Error during force update:', Errors.toLogFormat(error));
}
}
@@ -1605,7 +1572,7 @@ const runSQLCorruptionHandler = async () => {
// `onDatabaseInitializationError`.
const error = await sql.whenCorrupted();
getLogger().error(
log.error(
'Detected sql corruption in main process. ' +
`Restarting the application immediately. Error: ${error.message}`
);
@@ -1620,15 +1587,13 @@ const runSQLReadonlyHandler = async () => {
// `onDatabaseInitializationError`.
const error = await sql.whenReadonly();
getLogger().error(
`Detected readonly sql database in main process: ${error.message}`
);
log.error(`Detected readonly sql database in main process: ${error.message}`);
throw error;
};
function generateSQLKey(): string {
getLogger().info(
log.info(
'key/initialize: Generating new encryption key, since we did not find it on disk'
);
// https://www.zetetic.net/sqlcipher/sqlcipher-api/#key
@@ -1673,31 +1638,29 @@ function getSQLKey(): string {
throw new Error("Can't decrypt database key");
}
getLogger().info('getSQLKey: decrypting key');
log.info('getSQLKey: decrypting key');
const encrypted = Buffer.from(modernKeyValue, 'hex');
key = safeStorage.decryptString(encrypted);
if (legacyKeyValue != null) {
getLogger().info('getSQLKey: removing legacy key');
log.info('getSQLKey: removing legacy key');
userConfig.set('key', undefined);
}
if (isLinux && previousBackend == null) {
getLogger().info(
`getSQLKey: saving safeStorageBackend: ${safeStorageBackend}`
);
log.info(`getSQLKey: saving safeStorageBackend: ${safeStorageBackend}`);
userConfig.set('safeStorageBackend', safeStorageBackend);
}
} else if (typeof legacyKeyValue === 'string') {
key = legacyKeyValue;
update = isEncryptionAvailable;
if (update) {
getLogger().info('getSQLKey: migrating key');
log.info('getSQLKey: migrating key');
} else {
getLogger().info('getSQLKey: using legacy key');
log.info('getSQLKey: using legacy key');
}
} else {
getLogger().warn("getSQLKey: got key from config, but it wasn't a string");
log.warn("getSQLKey: got key from config, but it wasn't a string");
key = generateSQLKey();
update = true;
}
@@ -1707,19 +1670,17 @@ function getSQLKey(): string {
}
if (isEncryptionAvailable) {
getLogger().info('getSQLKey: updating encrypted key in the config');
log.info('getSQLKey: updating encrypted key in the config');
const encrypted = safeStorage.encryptString(key).toString('hex');
userConfig.set('encryptedKey', encrypted);
userConfig.set('key', undefined);
if (isLinux && safeStorageBackend) {
getLogger().info(
`getSQLKey: saving safeStorageBackend: ${safeStorageBackend}`
);
log.info(`getSQLKey: saving safeStorageBackend: ${safeStorageBackend}`);
userConfig.set('safeStorageBackend', safeStorageBackend);
}
} else {
getLogger().info('getSQLKey: updating plaintext key in the config');
log.info('getSQLKey: updating plaintext key in the config');
userConfig.set('key', key);
}
@@ -1741,7 +1702,7 @@ async function initializeSQL(
appVersion: app.getVersion(),
configDir: userDataPath,
key: 'abcd',
logger: getLogger(),
logger: log,
});
} catch {
// Do nothing, we fail right below anyway.
@@ -1765,7 +1726,7 @@ async function initializeSQL(
appVersion: app.getVersion(),
configDir: userDataPath,
key,
logger: getLogger(),
logger: log,
});
} catch (error: unknown) {
if (error instanceof Error) {
@@ -1792,7 +1753,7 @@ async function initializeSQL(
}
function onUnknownSqlError(error: Error) {
getLogger().error('Unknown SQL Error:', Errors.toLogFormat(error));
log.error('Unknown SQL Error:', Errors.toLogFormat(error));
if (mainWindow) {
mainWindow.webContents.send('sql-error');
}
@@ -1901,10 +1862,10 @@ const onDatabaseInitializationError = async (error: Error) => {
});
if (confirmationButtonIndex === confirmDeleteAllDataButtonIndex) {
getLogger().error('onDatabaseInitializationError: Deleting all data');
log.error('onDatabaseInitializationError: Deleting all data');
await sql.removeDB();
userConfig.remove();
getLogger().error(
log.error(
'onDatabaseInitializationError: Requesting immediate restart after quit'
);
app.relaunch();
@@ -1917,7 +1878,7 @@ const onDatabaseInitializationError = async (error: Error) => {
);
}
getLogger().error('onDatabaseInitializationError: Quitting application');
log.error('onDatabaseInitializationError: Quitting application');
app.exit(1);
};
@@ -2007,7 +1968,7 @@ app.on('ready', async () => {
realpath(app.getAppPath()),
]);
updateDefaultSession(session.defaultSession, getLogger);
updateDefaultSession(session.defaultSession, log);
if (getEnvironment() !== Environment.Test) {
installFileHandler({
@@ -2025,10 +1986,7 @@ app.on('ready', async () => {
session: session.defaultSession,
});
logger = await logging.initialize(getMainWindow);
// Write buffered information into newly created logger.
consoleLogger.writeBufferInto(logger);
await mainProcessLogging.initialize(getMainWindow);
const resourceService = OptionalResourceService.create(
join(userDataPath, 'optionalResources')
@@ -2043,19 +2001,15 @@ app.on('ready', async () => {
localeOverride = await getLocaleOverrideSetting();
const hourCyclePreference = getHourCyclePreference();
logger.info(`app.ready: hour cycle preference: ${hourCyclePreference}`);
log.info(`app.ready: hour cycle preference: ${hourCyclePreference}`);
logger.info(
`app.ready: preferred system locales: ${preferredSystemLocales.join(
', '
)}`
);
log.info('app.ready: preferred system locales:', preferredSystemLocales);
resolvedTranslationsLocale = loadLocale({
preferredSystemLocales,
localeOverride,
localeDirectionTestingOverride,
hourCyclePreference,
logger: getLogger(),
logger: log,
});
}
@@ -2070,13 +2024,13 @@ app.on('ready', async () => {
(await systemTraySettingCache.get()) === SystemTraySetting.Uninitialized
) {
const newValue = getDefaultSystemTraySetting(OS, app.getVersion());
getLogger().info(`app.ready: setting system-tray-setting to ${newValue}`);
log.info(`app.ready: setting system-tray-setting to ${newValue}`);
systemTraySettingCache.set(newValue);
ephemeralConfig.set('system-tray-setting', newValue);
if (OS.isWindows()) {
getLogger().info('app.ready: enabling open at login');
log.info('app.ready: enabling open at login');
app.setLoginItemSettings({
...(await getDefaultLoginItemSettings()),
openAtLogin: true,
@@ -2103,7 +2057,7 @@ app.on('ready', async () => {
}
// Default login item settings might have changed, so update the object.
getLogger().info('refresh-auto-launch: new value', openAtLogin);
log.info('refresh-auto-launch: new value', openAtLogin);
app.setLoginItemSettings({
...(await getDefaultLoginItemSettings()),
openAtLogin,
@@ -2128,7 +2082,7 @@ app.on('ready', async () => {
const messageTime = loadTime - preloadTime - connectTime;
const messagesPerSec = (processedCount * 1000) / messageTime;
const innerLogger = getLogger();
const innerLogger = log;
innerLogger.info('App loaded - time:', loadTime);
innerLogger.info('SQL init - time:', sqlInitTime);
innerLogger.info('Preload Compile - time:', preloadCompileTime);
@@ -2162,8 +2116,8 @@ app.on('ready', async () => {
});
}
logger.info('app ready');
logger.info(`starting version ${packageJson.version}`);
log.info('app ready');
log.info(`starting version ${packageJson.version}`);
// This logging helps us debug user reports about broken devices.
{
@@ -2175,7 +2129,7 @@ app.on('ready', async () => {
} else {
getMediaAccessStatus = noop;
}
logger.info(
log.info(
'media access status',
getMediaAccessStatus('microphone'),
getMediaAccessStatus('camera'),
@@ -2206,7 +2160,7 @@ app.on('ready', async () => {
return;
}
getLogger().info(
log.info(
'sql.initialize is taking more than three seconds; showing loading dialog'
);
@@ -2248,16 +2202,13 @@ app.on('ready', async () => {
try {
await attachments.clearTempPath(userDataPath);
} catch (err) {
logger.error(
'main/ready: Error deleting temp dir:',
Errors.toLogFormat(err)
);
log.error('main/ready: Error deleting temp dir:', Errors.toLogFormat(err));
}
try {
await attachments.deleteStaleDownloads(userDataPath);
} catch (err) {
logger.error(
log.error(
'main/ready: Error deleting stale downloads:',
Errors.toLogFormat(err)
);
@@ -2286,7 +2237,7 @@ app.on('ready', async () => {
const { error: sqlError } = await sqlInitPromise;
if (sqlError) {
getLogger().error('sql.initialize was unsuccessful; returning early');
log.error('sql.initialize was unsuccessful; returning early');
await onDatabaseInitializationError(sqlError);
@@ -2301,7 +2252,7 @@ app.on('ready', async () => {
await sql.sqlWrite('removeItemById', IDB_KEY);
}
} catch (err) {
getLogger().error(
log.error(
'(ready event handler) error deleting IndexedDB:',
Errors.toLogFormat(err)
);
@@ -2356,7 +2307,7 @@ function setupMenu(options?: Partial<CreateTemplateOptionsType>) {
showKeyboardShortcuts,
showSettings: () => {
if (!settingsChannel) {
getLogger().warn(
log.warn(
'showSettings: No settings channel; cannot open settings tab.'
);
return;
@@ -2393,7 +2344,7 @@ async function maybeRequestCloseConfirmation(): Promise<boolean> {
return true;
}
getLogger().info(
log.info(
'maybeRequestCloseConfirmation: Checking to see if close confirmation is needed'
);
const request = new Promise<boolean>(resolveFn => {
@@ -2405,14 +2356,14 @@ async function maybeRequestCloseConfirmation(): Promise<boolean> {
}
ipc.once('received-close-confirmation', (_event, result) => {
getLogger().info('maybeRequestCloseConfirmation: Response received');
log.info('maybeRequestCloseConfirmation: Response received');
clearTimeoutIfNecessary(timeout);
resolveFn(result);
});
ipc.once('requested-close-confirmation', () => {
getLogger().info(
log.info(
'maybeRequestCloseConfirmation: Confirmation dialog shown, waiting for user.'
);
clearTimeoutIfNecessary(timeout);
@@ -2423,7 +2374,7 @@ async function maybeRequestCloseConfirmation(): Promise<boolean> {
// Wait a short time then proceed. Normally the dialog should be
// shown right away.
timeout = setTimeout(() => {
getLogger().error(
log.error(
'maybeRequestCloseConfirmation: Response never received; continuing with close.'
);
resolveFn(true);
@@ -2433,7 +2384,7 @@ async function maybeRequestCloseConfirmation(): Promise<boolean> {
try {
return await request;
} catch (error) {
getLogger().error(
log.error(
'maybeRequestCloseConfirmation error:',
Errors.toLogFormat(error)
);
@@ -2446,7 +2397,7 @@ async function requestShutdown() {
return;
}
getLogger().info('requestShutdown: Requesting close of mainWindow...');
log.info('requestShutdown: Requesting close of mainWindow...');
const request = new Promise<void>(resolveFn => {
let timeout: NodeJS.Timeout | undefined;
@@ -2456,13 +2407,10 @@ async function requestShutdown() {
}
ipc.once('now-ready-for-shutdown', (_event, error) => {
getLogger().info('requestShutdown: Response received');
log.info('requestShutdown: Response received');
if (error) {
getLogger().error(
'requestShutdown: got error, still shutting down.',
error
);
log.error('requestShutdown: got error, still shutting down.', error);
}
clearTimeoutIfNecessary(timeout);
@@ -2477,7 +2425,7 @@ async function requestShutdown() {
// Note: two minutes is also our timeout for SQL tasks in data.js in the browser.
timeout = setTimeout(
() => {
getLogger().error(
log.error(
'requestShutdown: Response never received; forcing shutdown.'
);
resolveFn();
@@ -2489,7 +2437,7 @@ async function requestShutdown() {
try {
await request;
} catch (error) {
getLogger().error('requestShutdown error:', Errors.toLogFormat(error));
log.error('requestShutdown error:', Errors.toLogFormat(error));
}
}
@@ -2512,7 +2460,7 @@ function getWindowDebugInfo() {
}
app.on('before-quit', e => {
getLogger().info('before-quit event', {
log.info('before-quit event', {
readyForShutdown: windowState.readyForShutdown(),
shouldQuit: windowState.shouldQuit(),
hasEventBeenPrevented: e.defaultPrevented,
@@ -2524,14 +2472,14 @@ app.on('before-quit', e => {
});
app.on('will-quit', e => {
getLogger().info('will-quit event', {
log.info('will-quit event', {
hasEventBeenPrevented: e.defaultPrevented,
...getWindowDebugInfo(),
});
});
app.on('quit', e => {
getLogger().info('quit event', {
log.info('quit event', {
hasEventBeenPrevented: e.defaultPrevented,
...getWindowDebugInfo(),
});
@@ -2539,7 +2487,7 @@ app.on('quit', e => {
// Quit when all windows are closed.
app.on('window-all-closed', () => {
getLogger().info('main process handling window-all-closed');
log.info('main process handling window-all-closed');
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
const shouldAutoClose = !OS.isMacOS() || isTestEnvironment(getEnvironment());
@@ -2618,7 +2566,7 @@ ipc.on('draw-attention', () => {
});
ipc.on('restart', () => {
getLogger().info('Relaunching application');
log.info('Relaunching application');
app.relaunch();
app.quit();
});
@@ -2710,10 +2658,7 @@ ipc.handle(
try {
await showPermissionsPopupWindow(forCalling, forCamera);
} catch (error) {
getLogger().error(
'show-permissions-popup error:',
Errors.toLogFormat(error)
);
log.error('show-permissions-popup error:', Errors.toLogFormat(error));
}
}
);
@@ -2868,7 +2813,7 @@ ipc.handle('DebugLogs.upload', async (_event, content: string) => {
return uploadDebugLog.upload({
content,
appVersion: app.getVersion(),
logger: getLogger(),
logger: log,
});
});
@@ -2912,8 +2857,6 @@ function maybeGetIncomingSignalRoute(argv: Array<string>) {
}
function handleSignalRoute(route: ParsedSignalRoute) {
const log = getLogger();
if (mainWindow == null || !mainWindow.webContents) {
log.error('handleSignalRoute: mainWindow is null or missing webContents');
return;
@@ -2983,7 +2926,7 @@ ipc.handle('ensure-file-permissions', () => ensureFilePermissions());
* @param {string[]} [onlyFiles] - Only ensure permissions on these given files
*/
async function ensureFilePermissions(onlyFiles?: Array<string>) {
getLogger().info('Begin ensuring permissions');
log.info('Begin ensuring permissions');
const start = Date.now();
const userDataPath = await realpath(app.getPath('userData'));
@@ -2998,7 +2941,7 @@ async function ensureFilePermissions(onlyFiles?: Array<string>) {
ignore: ['**/Singleton*'],
});
getLogger().info(`Ensuring file permissions for ${files.length} files`);
log.info(`Ensuring file permissions for ${files.length} files`);
// Touch each file in a queue
const q = new PQueue({ concurrency: 5, timeout: 1000 * 60 * 2 });
@@ -3009,10 +2952,7 @@ async function ensureFilePermissions(onlyFiles?: Array<string>) {
try {
await chmod(normalize(f), isDir ? 0o700 : 0o600);
} catch (error) {
getLogger().error(
'ensureFilePermissions: Error from chmod',
error.message
);
log.error('ensureFilePermissions: Error from chmod', error.message);
}
})
)
@@ -3020,7 +2960,7 @@ async function ensureFilePermissions(onlyFiles?: Array<string>) {
await q.onEmpty();
getLogger().info(`Finish ensuring permissions in ${Date.now() - start}ms`);
log.info(`Finish ensuring permissions in ${Date.now() - start}ms`);
}
ipc.handle('get-media-access-status', async (_event, value) => {
@@ -3063,7 +3003,7 @@ ipc.handle('get-auto-launch', async () => {
ipc.handle('set-auto-launch', async (_event, value) => {
const openAtLogin = Boolean(value);
getLogger().info('set-auto-launch: new value', openAtLogin);
log.info('set-auto-launch: new value', openAtLogin);
app.setLoginItemSettings({
...(await getDefaultLoginItemSettings()),
openAtLogin,
@@ -3080,7 +3020,7 @@ ipc.on('show-item-in-folder', (_event, folder) => {
ipc.handle('show-save-dialog', async (_event, { defaultPath }) => {
if (!mainWindow) {
getLogger().warn('show-save-dialog: no main window');
log.warn('show-save-dialog: no main window');
return { canceled: true };
}
@@ -3128,7 +3068,7 @@ ipc.handle(
if (useMainWindow) {
if (!mainWindow) {
getLogger().warn('show-open-folder-dialog: no main window');
log.warn('show-open-folder-dialog: no main window');
return { canceled: true };
}
@@ -3155,9 +3095,7 @@ ipc.handle(
}
if (selectedDirPaths.length > 1) {
getLogger().warn(
'show-open-folder-dialog: multiple directories selected'
);
log.warn('show-open-folder-dialog: multiple directories selected');
return { canceled: true };
}

View File

@@ -7,6 +7,7 @@
import type { session as ElectronSession, Session } from 'electron';
import type { ConfigType } from './base_config';
import * as log from '../ts/logging/log';
const PERMISSIONS: Record<string, boolean> = {
// Allowed
@@ -67,12 +68,12 @@ function _createPermissionHandler(
}
if (PERMISSIONS[permission]) {
console.log(`Approving request for permission '${permission}'`);
log.info(`Approving request for permission '${permission}'`);
callback(true);
return;
}
console.log(`Denying request for permission '${permission}'`);
log.info(`Denying request for permission '${permission}'`);
callback(false);
};
}

View File

@@ -15,6 +15,7 @@ import {
getTempPath,
getUpdateCachePath,
} from './attachments';
import * as log from '../ts/logging/log';
type CallbackType = (response: string | ProtocolResponse) => void;
@@ -91,9 +92,7 @@ function _createFileHandler({
const properCasing = isWindows ? realPath.toLowerCase() : realPath;
if (!isAbsolute(realPath)) {
console.log(
`Warning: denying request to non-absolute path '${realPath}'`
);
log.info(`Warning: denying request to non-absolute path '${realPath}'`);
// This is an "Access Denied" error. See [Chromium's net error list][0].
//
// [0]: https://source.chromium.org/chromium/chromium/src/+/master:net/base/net_error_list.h;l=57;drc=a836ee9868cf1b9673fce362a82c98aba3e195de
@@ -108,7 +107,7 @@ function _createFileHandler({
}
}
console.log(
log.info(
`Warning: denying request to path '${realPath}' (allowedRoots: '${allowedRoots}')`
);
callback({ error: -10 });
@@ -117,9 +116,7 @@ function _createFileHandler({
err && typeof err.message === 'string'
? err.message
: 'no error message';
console.log(
`Warning: denying request because of an error: ${errorMessage}`
);
log.info(`Warning: denying request because of an error: ${errorMessage}`);
callback({ error: -300 });
}

View File

@@ -11,6 +11,7 @@ import type { MenuListType } from '../ts/types/menu';
import type { LocalizerType } from '../ts/types/Util';
import { strictAssert } from '../ts/util/assert';
import type { LoggerType } from '../ts/types/Logging';
import * as log from '../ts/logging/log';
import { handleAttachmentRequest } from './attachment_channel';
export const FAKE_DEFAULT_LOCALE = 'und'; // 'und' is the BCP 47 subtag for "undetermined"
@@ -84,12 +85,9 @@ export const setup = (
const availableLocales = session.availableSpellCheckerLanguages;
const languages = getLanguages(combinedLocales, availableLocales, 'en');
console.log('spellcheck: user locales:', combinedLocales);
console.log(
'spellcheck: available spellchecker languages:',
availableLocales
);
console.log('spellcheck: setting languages to:', languages);
log.info('spellcheck: user locales:', combinedLocales);
log.info('spellcheck: available spellchecker languages:', availableLocales);
log.info('spellcheck: setting languages to:', languages);
session.setSpellCheckerLanguages(languages);
browserWindow.webContents.on('context-menu', (_event, params) => {

View File

@@ -4,6 +4,7 @@
import { app } from 'electron';
import packageJson from '../package.json';
import * as log from '../ts/logging/log';
import * as GlobalErrors from './global_errors';
GlobalErrors.addHandler();
@@ -13,7 +14,7 @@ GlobalErrors.addHandler();
process.umask(0o077);
export const AUMID = `org.whispersystems.${packageJson.name}`;
console.log('Set Windows Application User Model ID (AUMID)', {
log.info('Set Windows Application User Model ID (AUMID)', {
AUMID,
});
app.setAppUserModelId(AUMID);

View File

@@ -14,7 +14,7 @@ const SPELL_CHECKER_DICTIONARY_DOWNLOAD_URL = `https://updates.signal.org/deskto
export function updateDefaultSession(
session: Session,
getLogger: () => LoggerType
logger: LoggerType
): void {
session.setSpellCheckerDictionaryDownloadURL(
SPELL_CHECKER_DICTIONARY_DOWNLOAD_URL
@@ -74,7 +74,7 @@ export function updateDefaultSession(
// Electron throws error here, but this is the only way to cancel the
// request.
}
getLogger().error('Failed to get desktopCapturer sources', error);
logger.error('Failed to get desktopCapturer sources', error);
}
},
{ useSystemPicker: false }

View File

@@ -7,6 +7,7 @@ import { app } from 'electron';
import { start } from './base_config';
import config from './config';
import * as log from '../ts/logging/log';
import * as Errors from '../ts/types/errors';
let userData: string | undefined;
@@ -24,13 +25,13 @@ if (userData !== undefined) {
try {
mkdirSync(userData, { recursive: true });
} catch (error) {
console.error('Failed to create userData', Errors.toLogFormat(error));
log.error('Failed to create userData', Errors.toLogFormat(error));
}
app.setPath('userData', userData);
}
console.log(`userData: ${app.getPath('userData')}`);
log.info(`userData: ${app.getPath('userData')}`);
const userDataPath = app.getPath('userData');
const targetPath = join(userDataPath, 'config.json');