js-logging/src/console-log-appender.ts
Jonathan Bernard a89a41520c ConsoleLogAppender writes a human-readable summary when logging structured data.
Taking advantage of the new LogMessageFormatter return type, the
ConsoleLogAppender logs the formatted message as-is if it is a string,
but when processing structured data inserts a string summary consisting
of the message level, scope, and message summary or method. The full
object is still logged to the console as well for inspection.
2025-01-07 09:30:21 -06:00

84 lines
2.3 KiB
TypeScript

import {
flattenMessage,
LogLevel,
LogMessage,
LogMessageFormatter,
} from "./log-message";
import { LogAppender } from "./log-appender";
/**
* A log appender that writes log messages to the console. The behavior of the
* log appender can be configured with a threshold level and a message
* formatter.
*
* When the message formatter returns a string value, that value is logged to
* the console as-is. When the message formatter returns an object, a summary
* string is logged to the console, followed by the object itself. This allows
* logs to be easily read in the console, while still providing the structured
* data for inspection in the browser's developer tools.
*/
export class ConsoleLogAppender implements LogAppender {
public threshold = LogLevel.ALL;
public formatter: LogMessageFormatter = flattenMessage;
constructor(threshold?: LogLevel, formatter?: LogMessageFormatter) {
if (threshold) {
this.threshold = threshold;
}
if (formatter) {
this.formatter = formatter;
}
}
public appendMessage(msg: LogMessage): void {
if (this.threshold && msg.level < this.threshold) {
return;
}
let logMethod = console.log;
switch (msg.level) {
case LogLevel.ALL:
case LogLevel.TRACE:
case LogLevel.LOG:
logMethod = console.log;
break;
case LogLevel.DEBUG:
logMethod = console.debug;
break;
case LogLevel.INFO:
logMethod = console.info;
break;
case LogLevel.WARN:
logMethod = console.warn;
break;
case LogLevel.ERROR:
case LogLevel.FATAL:
logMethod = console.trace;
break;
}
const fmtMsg = this.formatter(msg);
if (typeof fmtMsg === "string") {
if (msg.error || msg.stacktrace) {
logMethod(fmtMsg, msg.error ?? msg.stacktrace);
} else {
logMethod(fmtMsg);
}
} else {
const { message, _error, _stacktrace, ...rest } = fmtMsg;
const summary = `${LogLevel[msg.level]} -- ${msg.scope}: ${
message ?? fmtMsg.method
}\n`;
if (msg.error || msg.stacktrace) {
logMethod(summary, msg.error ?? msg.stacktrace, rest);
} else {
logMethod(summary, rest);
}
}
}
}
export default ConsoleLogAppender;