Import log instead of using it off of window
This commit is contained in:
parent
8eb0dd3116
commit
65ddf0a9e8
155 changed files with 3654 additions and 3433 deletions
|
@ -6,7 +6,6 @@
|
|||
/* eslint-disable no-console */
|
||||
|
||||
import { ipcRenderer as ipc } from 'electron';
|
||||
import _ from 'lodash';
|
||||
import * as path from 'path';
|
||||
import pino from 'pino';
|
||||
import { createStream } from 'rotating-file-stream';
|
||||
|
@ -16,28 +15,15 @@ import {
|
|||
LogLevel as SignalClientLogLevel,
|
||||
} from '@signalapp/signal-client';
|
||||
|
||||
import { uploadDebugLogs } from './debuglogs';
|
||||
import { redactAll } from '../util/privacy';
|
||||
import {
|
||||
FetchLogIpcData,
|
||||
LogEntryType,
|
||||
LogLevel,
|
||||
cleanArgs,
|
||||
getLogLevelString,
|
||||
isFetchLogIpcData,
|
||||
isLogEntry,
|
||||
levelMaxLength,
|
||||
} from './shared';
|
||||
import * as log from './log';
|
||||
import { reallyJsonStringify } from '../util/reallyJsonStringify';
|
||||
import { Environment, getEnvironment } from '../environment';
|
||||
|
||||
// To make it easier to visually scan logs, we make all levels the same length
|
||||
const levelFromName = pino().levels.values;
|
||||
const levelMaxLength: number = Object.keys(levelFromName).reduce(
|
||||
(maxLength, level) => Math.max(maxLength, level.length),
|
||||
0
|
||||
);
|
||||
|
||||
// Backwards-compatible logging, simple strings and no level (defaulted to INFO)
|
||||
function now() {
|
||||
const date = new Date();
|
||||
|
@ -53,91 +39,6 @@ if (window.console) {
|
|||
console.log = consoleLog;
|
||||
}
|
||||
|
||||
// The mechanics of preparing a log for publish
|
||||
|
||||
const headerSectionTitle = (title: string) => `========= ${title} =========`;
|
||||
|
||||
const headerSection = (
|
||||
title: string,
|
||||
data: Readonly<Record<string, unknown>>
|
||||
): string => {
|
||||
const sortedEntries = _.sortBy(Object.entries(data), ([key]) => key);
|
||||
return [
|
||||
headerSectionTitle(title),
|
||||
...sortedEntries.map(
|
||||
([key, value]) => `${key}: ${redactAll(String(value))}`
|
||||
),
|
||||
'',
|
||||
].join('\n');
|
||||
};
|
||||
|
||||
const getHeader = ({
|
||||
capabilities,
|
||||
remoteConfig,
|
||||
statistics,
|
||||
user,
|
||||
}: Omit<FetchLogIpcData, 'logEntries'>): string =>
|
||||
[
|
||||
headerSection('System info', {
|
||||
Time: Date.now(),
|
||||
'User agent': window.navigator.userAgent,
|
||||
'Node version': window.getNodeVersion(),
|
||||
Environment: getEnvironment(),
|
||||
'App version': window.getVersion(),
|
||||
}),
|
||||
headerSection('User info', user),
|
||||
headerSection('Capabilities', capabilities),
|
||||
headerSection('Remote config', remoteConfig),
|
||||
headerSection('Statistics', statistics),
|
||||
headerSectionTitle('Logs'),
|
||||
].join('\n');
|
||||
|
||||
const getLevel = _.memoize((level: LogLevel): string => {
|
||||
const text = getLogLevelString(level);
|
||||
return text.toUpperCase().padEnd(levelMaxLength, ' ');
|
||||
});
|
||||
|
||||
function formatLine(mightBeEntry: unknown): string {
|
||||
const entry: LogEntryType = isLogEntry(mightBeEntry)
|
||||
? mightBeEntry
|
||||
: {
|
||||
level: LogLevel.Error,
|
||||
msg: `Invalid IPC data when fetching logs. Here's what we could recover: ${reallyJsonStringify(
|
||||
mightBeEntry
|
||||
)}`,
|
||||
time: new Date().toISOString(),
|
||||
};
|
||||
|
||||
return `${getLevel(entry.level)} ${entry.time} ${entry.msg}`;
|
||||
}
|
||||
|
||||
function fetch(): Promise<string> {
|
||||
return new Promise(resolve => {
|
||||
ipc.send('fetch-log');
|
||||
|
||||
ipc.on('fetched-log', (_event, data: unknown) => {
|
||||
let header: string;
|
||||
let body: string;
|
||||
if (isFetchLogIpcData(data)) {
|
||||
const { logEntries } = data;
|
||||
header = getHeader(data);
|
||||
body = logEntries.map(formatLine).join('\n');
|
||||
} else {
|
||||
header = headerSectionTitle('Partial logs');
|
||||
const entry: LogEntryType = {
|
||||
level: LogLevel.Error,
|
||||
msg: 'Invalid IPC data when fetching logs; dropping all logs',
|
||||
time: new Date().toISOString(),
|
||||
};
|
||||
body = formatLine(entry);
|
||||
}
|
||||
|
||||
const result = `${header}\n${body}`;
|
||||
resolve(result);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
let globalLogger: undefined | pino.Logger;
|
||||
let shouldRestart = false;
|
||||
|
||||
|
@ -176,8 +77,6 @@ export function initialize(): void {
|
|||
);
|
||||
}
|
||||
|
||||
const publish = uploadDebugLogs;
|
||||
|
||||
// A modern logging interface for the browser
|
||||
|
||||
function logAtLevel(level: LogLevel, ...args: ReadonlyArray<unknown>): void {
|
||||
|
@ -201,27 +100,26 @@ function logAtLevel(level: LogLevel, ...args: ReadonlyArray<unknown>): void {
|
|||
|
||||
log.setLogAtLevel(logAtLevel);
|
||||
|
||||
window.log = {
|
||||
window.SignalWindow = window.SignalWindow || {};
|
||||
window.SignalWindow.log = {
|
||||
fatal: log.fatal,
|
||||
error: log.error,
|
||||
warn: log.warn,
|
||||
info: log.info,
|
||||
debug: log.debug,
|
||||
trace: log.trace,
|
||||
fetch,
|
||||
publish,
|
||||
};
|
||||
|
||||
window.onerror = (_message, _script, _line, _col, error) => {
|
||||
const errorInfo = error && error.stack ? error.stack : JSON.stringify(error);
|
||||
window.log.error(`Top-level unhandled error: ${errorInfo}`);
|
||||
log.error(`Top-level unhandled error: ${errorInfo}`);
|
||||
};
|
||||
|
||||
window.addEventListener('unhandledrejection', rejectionEvent => {
|
||||
const error = rejectionEvent.reason;
|
||||
const errorString =
|
||||
error && error.stack ? error.stack : JSON.stringify(error);
|
||||
window.log.error(`Top-level unhandled promise rejection: ${errorString}`);
|
||||
log.error(`Top-level unhandled promise rejection: ${errorString}`);
|
||||
});
|
||||
|
||||
initLogger(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue