Introduce buffered console logger

This commit is contained in:
Fedor Indutny 2023-03-28 15:22:06 -07:00 committed by GitHub
parent 6dab8c70a1
commit d1791ff6be
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 67 additions and 47 deletions

View file

@ -39,7 +39,6 @@ const getHeader = (
capabilities,
remoteConfig,
statistics,
appMetrics,
user,
}: Omit<FetchLogIpcData, 'logEntries'>,
nodeVersion: string,
@ -57,29 +56,6 @@ const getHeader = (
headerSection('User info', user),
headerSection('Capabilities', capabilities),
headerSection('Remote config', remoteConfig),
headerSection(
'Metrics',
appMetrics.reduce((acc, stats, index) => {
const {
type = '?',
serviceName = '?',
name = '?',
cpu,
memory,
} = stats;
const processId = `${index}:${type}/${serviceName}/${name}`;
return {
...acc,
[processId]:
`cpuUsage=${cpu.percentCPUUsage.toFixed(2)} ` +
`wakeups=${cpu.idleWakeupsPerSecond} ` +
`workingMemory=${memory.workingSetSize} ` +
`peakWorkingMemory=${memory.peakWorkingSetSize}`,
};
}, {})
),
headerSection('Statistics', statistics),
headerSectionTitle('Logs'),
].join('\n');

View file

@ -26,7 +26,6 @@ import { CircularBuffer } from 'cirbuf';
import type { LoggerType } from '../types/Logging';
import * as Errors from '../types/errors';
import * as durations from '../util/durations';
import { createRotatingPinoDest } from '../util/rotatingPinoDest';
import * as log from './log';
@ -64,13 +63,6 @@ export async function initialize(
const logPath = join(basePath, 'logs');
mkdirSync(logPath, { recursive: true });
let appMetrics = app.getAppMetrics();
setInterval(() => {
// CPU stats are computed since the last call to `getAppMetrics`.
appMetrics = app.getAppMetrics();
}, 30 * durations.SECOND).unref();
try {
await cleanupLogs(logPath);
} catch (error) {
@ -141,7 +133,6 @@ export async function initialize(
]);
data = {
logEntries,
appMetrics,
...rest,
};
} catch (error) {
@ -340,7 +331,7 @@ export function fetchLogs(logPath: string): Promise<Array<LogEntryType>> {
export const fetchAdditionalLogData = (
mainWindow: BrowserWindow
): Promise<Omit<FetchLogIpcData, 'logEntries' | 'appMetrics'>> =>
): Promise<Omit<FetchLogIpcData, 'logEntries'>> =>
new Promise(resolve => {
mainWindow.webContents.send('additional-log-data-request');
ipc.once('additional-log-data-response', (_event, data) => {

View file

@ -2,7 +2,6 @@
// SPDX-License-Identifier: AGPL-3.0-only
import pino from 'pino';
import type { ProcessMetric } from 'electron';
import { isRecord } from '../util/isRecord';
import { redactAll } from '../util/privacy';
import { missingCaseError } from '../util/missingCaseError';
@ -16,7 +15,6 @@ export type FetchLogIpcData = {
remoteConfig: Record<string, unknown>;
statistics: Record<string, unknown>;
user: Record<string, unknown>;
appMetrics: ReadonlyArray<ProcessMetric>;
// We expect `logEntries` to be `Array<LogEntryType>`, but we don't validate that
// upfront—we only validate it when we go to log each line. This improves the

View file

@ -24,4 +24,48 @@ export const consoleLogger: LoggerType = {
console.log(...args);
},
};
export type BufferedLoggerType = LoggerType & {
writeBufferInto(logger: LoggerType): void;
};
export function createBufferedConsoleLogger(): BufferedLoggerType {
type BufferEntryType = Readonly<{
level: keyof LoggerType;
args: Array<unknown>;
}>;
const buffer = new Array<BufferEntryType>();
return {
fatal(...args: Array<unknown>) {
buffer.push({ level: 'fatal', args });
console.error(...args);
},
error(...args: Array<unknown>) {
buffer.push({ level: 'error', args });
console.error(...args);
},
warn(...args: Array<unknown>) {
buffer.push({ level: 'warn', args });
console.warn(...args);
},
info(...args: Array<unknown>) {
buffer.push({ level: 'info', args });
console.info(...args);
},
debug(...args: Array<unknown>) {
buffer.push({ level: 'debug', args });
console.debug(...args);
},
trace(...args: Array<unknown>) {
buffer.push({ level: 'trace', args });
console.log(...args);
},
writeBufferInto(output) {
for (const { level, args } of buffer) {
output[level](...args);
}
},
};
}
/* eslint-enable no-console */