2021-02-04 13:54:03 -06:00
|
|
|
// Copyright 2021 Signal Messenger, LLC
|
|
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
|
2025-06-16 09:47:18 -07:00
|
|
|
import pino from 'pino';
|
|
|
|
|
2025-06-16 11:59:31 -07:00
|
|
|
import type { LoggerType } from '../types/Logging';
|
2025-06-16 09:47:18 -07:00
|
|
|
import { Environment, getEnvironment } from '../environment';
|
|
|
|
import { reallyJsonStringify } from '../util/reallyJsonStringify';
|
|
|
|
import { getLogLevelString } from './shared';
|
|
|
|
|
|
|
|
// This file is imported by some components so we can't import `ts/util/privacy`
|
|
|
|
let redactAll = (value: string) => value;
|
|
|
|
|
|
|
|
let destination: pino.DestinationStream | undefined;
|
|
|
|
let buffer = new Array<string>();
|
|
|
|
|
|
|
|
const pinoInstance = pino(
|
|
|
|
{
|
|
|
|
formatters: {
|
|
|
|
// No point in saving pid or hostname
|
|
|
|
bindings: () => ({}),
|
|
|
|
},
|
|
|
|
hooks: {
|
|
|
|
logMethod(args, method, level) {
|
|
|
|
if (getEnvironment() !== Environment.PackagedApp) {
|
|
|
|
const consoleMethod = getLogLevelString(level);
|
|
|
|
|
|
|
|
const { msgPrefixSym } = pino.symbols as unknown as {
|
|
|
|
readonly msgPrefixSym: unique symbol;
|
|
|
|
};
|
|
|
|
const msgPrefix = (
|
|
|
|
this as unknown as Record<symbol, string | undefined>
|
|
|
|
)[msgPrefixSym];
|
|
|
|
|
|
|
|
const [message, ...extra] = args;
|
|
|
|
|
|
|
|
// `fatal` has no respective analog in `console`
|
|
|
|
// eslint-disable-next-line no-console
|
|
|
|
console[consoleMethod === 'fatal' ? 'error' : consoleMethod](
|
|
|
|
`${msgPrefix ?? ''}${message}`,
|
|
|
|
...extra
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Always call original method, but with stringified arguments for
|
|
|
|
// compatibility with existing logging.
|
|
|
|
//
|
|
|
|
// (Since pino >= 6 extra arguments that don't correspond to %d/%s/%j
|
|
|
|
// templates in the `message` are ignored)
|
|
|
|
const line = args
|
|
|
|
.map(item =>
|
|
|
|
typeof item === 'string' ? item : reallyJsonStringify(item)
|
|
|
|
)
|
|
|
|
.join(' ');
|
|
|
|
return method.call(this, line);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
timestamp: pino.stdTimeFunctions.isoTime,
|
|
|
|
redact: {
|
|
|
|
paths: ['*'],
|
|
|
|
censor: item => redactAll(item),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
write(msg) {
|
|
|
|
if (destination == null) {
|
|
|
|
buffer.push(msg);
|
|
|
|
} else {
|
|
|
|
destination.write(msg);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2025-06-16 11:59:31 -07:00
|
|
|
export const log: LoggerType = {
|
|
|
|
fatal: pinoInstance.fatal.bind(pinoInstance),
|
|
|
|
error: pinoInstance.error.bind(pinoInstance),
|
|
|
|
warn: pinoInstance.error.bind(pinoInstance),
|
|
|
|
info: pinoInstance.info.bind(pinoInstance),
|
|
|
|
debug: pinoInstance.debug.bind(pinoInstance),
|
|
|
|
trace: pinoInstance.trace.bind(pinoInstance),
|
|
|
|
child: createLogger.bind(pinoInstance),
|
|
|
|
};
|
2025-06-16 09:47:18 -07:00
|
|
|
|
2025-06-16 11:59:31 -07:00
|
|
|
export function createLogger(name: string): LoggerType {
|
2025-06-16 09:47:18 -07:00
|
|
|
const instance = pinoInstance.child({}, { msgPrefix: `[${name}] ` });
|
|
|
|
|
|
|
|
return {
|
|
|
|
fatal: instance.fatal.bind(instance),
|
|
|
|
error: instance.error.bind(instance),
|
|
|
|
warn: instance.warn.bind(instance),
|
|
|
|
info: instance.info.bind(instance),
|
|
|
|
debug: instance.debug.bind(instance),
|
|
|
|
trace: instance.trace.bind(instance),
|
2025-06-16 11:59:31 -07:00
|
|
|
child: createLogger.bind(instance),
|
2025-06-16 09:47:18 -07:00
|
|
|
};
|
|
|
|
}
|
2021-02-04 13:54:03 -06:00
|
|
|
|
|
|
|
/**
|
2025-06-16 09:47:18 -07:00
|
|
|
* Sets the low-level logging interface. Should be called early in a process's
|
|
|
|
* life.
|
2021-02-04 13:54:03 -06:00
|
|
|
*/
|
2025-06-16 09:47:18 -07:00
|
|
|
export function setPinoDestination(
|
|
|
|
newDestination: pino.DestinationStream,
|
|
|
|
newRedactAll: typeof redactAll
|
|
|
|
): void {
|
|
|
|
destination = newDestination;
|
|
|
|
redactAll = newRedactAll;
|
|
|
|
const queued = buffer;
|
|
|
|
buffer = [];
|
|
|
|
for (const msg of queued) {
|
|
|
|
destination.write(msg);
|
2021-02-04 13:54:03 -06:00
|
|
|
}
|
|
|
|
}
|