Convert logging infrastructure to TypeScript
This commit is contained in:
parent
10ace53845
commit
a8787e7c9e
19 changed files with 595 additions and 331 deletions
152
js/logging.js
152
js/logging.js
|
@ -1,152 +0,0 @@
|
|||
// Copyright 2017-2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
/* eslint-env node */
|
||||
|
||||
/* eslint-disable no-console */
|
||||
|
||||
const electron = require('electron');
|
||||
const _ = require('lodash');
|
||||
|
||||
const { uploadDebugLogs } = require('../ts/logging/debuglogs');
|
||||
const Privacy = require('./modules/privacy');
|
||||
const { createBatcher } = require('../ts/util/batcher');
|
||||
|
||||
const ipc = electron.ipcRenderer;
|
||||
|
||||
// Default Bunyan levels: https://github.com/trentm/node-bunyan#levels
|
||||
// To make it easier to visually scan logs, we make all levels the same length
|
||||
const BLANK_LEVEL = ' ';
|
||||
const LEVELS = {
|
||||
60: 'fatal',
|
||||
50: 'error',
|
||||
40: 'warn ',
|
||||
30: 'info ',
|
||||
20: 'debug',
|
||||
10: 'trace',
|
||||
};
|
||||
|
||||
// Backwards-compatible logging, simple strings and no level (defaulted to INFO)
|
||||
function now() {
|
||||
const date = new Date();
|
||||
return date.toJSON();
|
||||
}
|
||||
|
||||
// To avoid [Object object] in our log since console.log handles non-strings smoothly
|
||||
function cleanArgsForIPC(args) {
|
||||
const str = args.map(item => {
|
||||
if (typeof item !== 'string') {
|
||||
try {
|
||||
return JSON.stringify(item);
|
||||
} catch (error) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
return item;
|
||||
});
|
||||
|
||||
return str.join(' ');
|
||||
}
|
||||
|
||||
function log(...args) {
|
||||
logAtLevel('info', 'INFO ', ...args);
|
||||
}
|
||||
|
||||
if (window.console) {
|
||||
console._log = console.log;
|
||||
console.log = log;
|
||||
}
|
||||
|
||||
// The mechanics of preparing a log for publish
|
||||
|
||||
function getHeader() {
|
||||
let header = window.navigator.userAgent;
|
||||
|
||||
header += ` node/${window.getNodeVersion()}`;
|
||||
header += ` env/${window.getEnvironment()}`;
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
function getLevel(level) {
|
||||
const text = LEVELS[level];
|
||||
if (!text) {
|
||||
return BLANK_LEVEL;
|
||||
}
|
||||
|
||||
return text.toUpperCase();
|
||||
}
|
||||
|
||||
function formatLine(entry) {
|
||||
return `${getLevel(entry.level)} ${entry.time} ${entry.msg}`;
|
||||
}
|
||||
|
||||
function format(entries) {
|
||||
return Privacy.redactAll(entries.map(formatLine).join('\n'));
|
||||
}
|
||||
|
||||
function fetch() {
|
||||
return new Promise(resolve => {
|
||||
ipc.send('fetch-log');
|
||||
|
||||
ipc.on('fetched-log', (event, text) => {
|
||||
const result = `${getHeader()}\n${format(text)}`;
|
||||
resolve(result);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const publish = uploadDebugLogs;
|
||||
|
||||
// A modern logging interface for the browser
|
||||
|
||||
const env = window.getEnvironment();
|
||||
const IS_PRODUCTION = env === 'production';
|
||||
|
||||
const ipcBatcher = createBatcher({
|
||||
wait: 500,
|
||||
maxSize: 500,
|
||||
processBatch: items => {
|
||||
ipc.send('batch-log', items);
|
||||
},
|
||||
});
|
||||
|
||||
// The Bunyan API: https://github.com/trentm/node-bunyan#log-method-api
|
||||
function logAtLevel(level, prefix, ...args) {
|
||||
if (!IS_PRODUCTION) {
|
||||
console._log(prefix, now(), ...args);
|
||||
}
|
||||
|
||||
const str = cleanArgsForIPC(args);
|
||||
const logText = Privacy.redactAll(str);
|
||||
|
||||
ipcBatcher.add({
|
||||
timestamp: Date.now(),
|
||||
level,
|
||||
logText,
|
||||
});
|
||||
}
|
||||
|
||||
window.log = {
|
||||
fatal: _.partial(logAtLevel, 'fatal', 'FATAL'),
|
||||
error: _.partial(logAtLevel, 'error', 'ERROR'),
|
||||
warn: _.partial(logAtLevel, 'warn', 'WARN '),
|
||||
info: _.partial(logAtLevel, 'info', 'INFO '),
|
||||
debug: _.partial(logAtLevel, 'debug', 'DEBUG'),
|
||||
trace: _.partial(logAtLevel, 'trace', '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}`);
|
||||
};
|
||||
|
||||
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}`);
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue