Fix all sources to comply with eslint rules introduced in 2.0.0 (no logic changes).

This commit is contained in:
2026-01-09 19:19:15 -06:00
parent 8b0acc6f40
commit 642078e728
8 changed files with 131 additions and 131 deletions
+22 -22
View File
@@ -1,32 +1,32 @@
import { LogMessage, LogLevel, flattenMessage, FlattenedLogMessage } from './log-message'; import { LogMessage, LogLevel, flattenMessage, FlattenedLogMessage } from './log-message'
import { LogAppender } from './log-appender'; import { LogAppender } from './log-appender'
export class ApiLogAppender implements LogAppender { export class ApiLogAppender implements LogAppender {
public batchSize = 10; public batchSize = 10
public minimumTimePassedInSec = 60; public minimumTimePassedInSec = 60
public maximumTimePassedInSec = 120; public maximumTimePassedInSec = 120
public threshold = LogLevel.ALL; public threshold = LogLevel.ALL
private msgBuffer: FlattenedLogMessage[] = []; private msgBuffer: FlattenedLogMessage[] = []
private lastSent = 0; private lastSent = 0
constructor( constructor(
public readonly apiEndpoint: string, public readonly apiEndpoint: string,
public authToken?: string, public authToken?: string,
threshold?: LogLevel threshold?: LogLevel
) { ) {
setTimeout(this.checkPost, 1000); setTimeout(this.checkPost, 1000)
if (threshold) { if (threshold) {
this.threshold = threshold; this.threshold = threshold
} }
} }
public appendMessage(msg: LogMessage): void { public appendMessage(msg: LogMessage): void {
if (this.threshold && msg.level < this.threshold) { if (this.threshold && msg.level < this.threshold) {
return; return
} }
this.msgBuffer.push(flattenMessage(msg)); this.msgBuffer.push(flattenMessage(msg))
} }
private doPost() { private doPost() {
@@ -39,29 +39,29 @@ export class ApiLogAppender implements LogAppender {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
Authorization: `Bearer ${this.authToken}` Authorization: `Bearer ${this.authToken}`
} }
}); })
this.lastSent = Date.now(); this.lastSent = Date.now()
this.msgBuffer = []; this.msgBuffer = []
} }
} }
private checkPost = () => { private checkPost = () => {
const now = Date.now(); const now = Date.now()
const min = this.lastSent + this.minimumTimePassedInSec * 1000; const min = this.lastSent + this.minimumTimePassedInSec * 1000
const max = this.lastSent + this.maximumTimePassedInSec * 1000; const max = this.lastSent + this.maximumTimePassedInSec * 1000
if ( if (
(this.msgBuffer.length >= this.batchSize && min < now) || (this.msgBuffer.length >= this.batchSize && min < now) ||
(this.msgBuffer.length > 0 && max < now) (this.msgBuffer.length > 0 && max < now)
) { ) {
this.doPost(); this.doPost()
} }
setTimeout( setTimeout(
this.checkPost, this.checkPost,
Math.max(10000, this.minimumTimePassedInSec * 1000) Math.max(10000, this.minimumTimePassedInSec * 1000)
); )
}; }
} }
export default ApiLogAppender; export default ApiLogAppender
+29 -29
View File
@@ -3,8 +3,8 @@ import {
LogLevel, LogLevel,
LogMessage, LogMessage,
LogMessageFormatter, LogMessageFormatter,
} from "./log-message"; } from './log-message'
import { LogAppender } from "./log-appender"; import { LogAppender } from './log-appender'
/** /**
* A log appender that writes log messages to the console. The behavior of the * A log appender that writes log messages to the console. The behavior of the
@@ -18,68 +18,68 @@ import { LogAppender } from "./log-appender";
* data for inspection in the browser's developer tools. * data for inspection in the browser's developer tools.
*/ */
export class ConsoleLogAppender implements LogAppender { export class ConsoleLogAppender implements LogAppender {
public threshold = LogLevel.ALL; public threshold = LogLevel.ALL
public formatter: LogMessageFormatter = flattenMessage; public formatter: LogMessageFormatter = flattenMessage
constructor(threshold?: LogLevel, formatter?: LogMessageFormatter) { constructor(threshold?: LogLevel, formatter?: LogMessageFormatter) {
if (threshold) { if (threshold) {
this.threshold = threshold; this.threshold = threshold
} }
if (formatter) { if (formatter) {
this.formatter = formatter; this.formatter = formatter
} }
} }
public appendMessage(msg: LogMessage): void { public appendMessage(msg: LogMessage): void {
if (this.threshold && msg.level < this.threshold) { if (this.threshold && msg.level < this.threshold) {
return; return
} }
let logMethod = console.log; let logMethod = console.log
switch (msg.level) { switch (msg.level) {
case LogLevel.ALL: case LogLevel.ALL:
case LogLevel.TRACE: case LogLevel.TRACE:
logMethod = console.trace; logMethod = console.trace
break; break
case LogLevel.LOG: case LogLevel.LOG:
logMethod = console.log; logMethod = console.log
break; break
case LogLevel.DEBUG: case LogLevel.DEBUG:
logMethod = console.debug; logMethod = console.debug
break; break
case LogLevel.INFO: case LogLevel.INFO:
logMethod = console.info; logMethod = console.info
break; break
case LogLevel.WARN: case LogLevel.WARN:
logMethod = console.warn; logMethod = console.warn
break; break
case LogLevel.ERROR: case LogLevel.ERROR:
case LogLevel.FATAL: case LogLevel.FATAL:
logMethod = console.error; logMethod = console.error
break; break
} }
const fmtMsg = this.formatter(msg); const fmtMsg = this.formatter(msg)
if (typeof fmtMsg === "string") { if (typeof fmtMsg === 'string') {
if (msg.err || msg.stacktrace) { if (msg.err || msg.stacktrace) {
logMethod(fmtMsg, msg.err ?? msg.stacktrace); logMethod(fmtMsg, msg.err ?? msg.stacktrace)
} else { } else {
logMethod(fmtMsg); logMethod(fmtMsg)
} }
} else { } else {
const { msg: innerMsg, _err, _stacktrace, ...rest } = fmtMsg; const { msg: innerMsg, _err, _stacktrace, ...rest } = fmtMsg
const summary = `${LogLevel[msg.level]} -- ${msg.scope}: ${ const summary = `${LogLevel[msg.level]} -- ${msg.scope}: ${
innerMsg ?? fmtMsg.method innerMsg ?? fmtMsg.method
}\n`; }\n`
if (msg.err || msg.stacktrace) { if (msg.err || msg.stacktrace) {
logMethod(summary, msg.err ?? msg.stacktrace, rest); logMethod(summary, msg.err ?? msg.stacktrace, rest)
} else { } else {
logMethod(summary, rest); logMethod(summary, rest)
} }
} }
} }
} }
export default ConsoleLogAppender; export default ConsoleLogAppender
+6 -6
View File
@@ -1,6 +1,6 @@
export * from './log-message'; export * from './log-message'
export * from './log-appender'; export * from './log-appender'
export * from './log-service'; export * from './log-service'
export * from './console-log-appender'; export * from './console-log-appender'
export * from './api-log-appender'; export * from './api-log-appender'
export * from './logger'; export * from './logger'
+2 -2
View File
@@ -1,8 +1,8 @@
import { LogLevel, LogMessage } from './log-message'; import { LogLevel, LogMessage } from './log-message'
export interface LogAppender { export interface LogAppender {
threshold: LogLevel; threshold: LogLevel;
appendMessage(message: LogMessage): void; appendMessage(message: LogMessage): void;
} }
export default LogAppender; export default LogAppender
+15 -15
View File
@@ -1,4 +1,4 @@
import { omit } from "./util"; import { omit } from './util'
export enum LogLevel { export enum LogLevel {
ALL = 0, ALL = 0,
@@ -16,9 +16,9 @@ export function parseLogLevel(
defaultLevel = LogLevel.INFO, defaultLevel = LogLevel.INFO,
): LogLevel { ): LogLevel {
if (str in LogLevel) { if (str in LogLevel) {
return LogLevel[str as keyof typeof LogLevel] as LogLevel; return LogLevel[str as keyof typeof LogLevel] as LogLevel
} else { } else {
return defaultLevel; return defaultLevel
} }
} }
@@ -57,21 +57,21 @@ export type FlattenedLogMessage = Record<string, unknown>;
* ``` * ```
*/ */
export function flattenMessage(logMsg: LogMessage): FlattenedLogMessage { export function flattenMessage(logMsg: LogMessage): FlattenedLogMessage {
if (typeof logMsg.msg === "string") { if (typeof logMsg.msg === 'string') {
return { ...logMsg, level: LogLevel[logMsg.level] }; return { ...logMsg, level: LogLevel[logMsg.level] }
} else { } else {
const { msg, ...rest } = logMsg; const { msg, ...rest } = logMsg
return { return {
...omit(msg, [ ...omit(msg, [
"scope", 'scope',
"level", 'level',
"stacktrace", 'stacktrace',
"err", 'err',
"ts", 'ts',
]), ]),
...rest, ...rest,
level: LogLevel[logMsg.level], level: LogLevel[logMsg.level],
}; }
} }
} }
export type LogMessageFormatter = ( export type LogMessageFormatter = (
@@ -79,11 +79,11 @@ export type LogMessageFormatter = (
) => string | FlattenedLogMessage; ) => string | FlattenedLogMessage;
export function structuredLogMessageFormatter(msg: LogMessage): string { export function structuredLogMessageFormatter(msg: LogMessage): string {
return JSON.stringify(flattenMessage(msg)); return JSON.stringify(flattenMessage(msg))
} }
export function simpleTextLogMessageFormatter(msg: LogMessage): string { export function simpleTextLogMessageFormatter(msg: LogMessage): string {
return `[${msg.scope}] - ${msg.level}: ${msg.msg}`; return `[${msg.scope}] - ${msg.level}: ${msg.msg}`
} }
export default LogMessage; export default LogMessage
+16 -16
View File
@@ -1,7 +1,7 @@
import { LogLevel } from './log-message'; import { LogLevel } from './log-message'
import { Logger } from './logger'; import { Logger } from './logger'
const ROOT_LOGGER_NAME = 'ROOT'; const ROOT_LOGGER_NAME = 'ROOT'
/** /**
* Service for managing loggers. A LogService instance defines * Service for managing loggers. A LogService instance defines
@@ -10,19 +10,19 @@ const ROOT_LOGGER_NAME = 'ROOT';
* module. * module.
*/ */
export class LogService { export class LogService {
private loggers: Record<string, Logger>; private loggers: Record<string, Logger>
public get ROOT_LOGGER() { public get ROOT_LOGGER() {
return this.loggers[ROOT_LOGGER_NAME]; return this.loggers[ROOT_LOGGER_NAME]
} }
public constructor() { public constructor() {
this.loggers = {}; this.loggers = {}
this.loggers[ROOT_LOGGER_NAME] = new Logger( this.loggers[ROOT_LOGGER_NAME] = new Logger(
ROOT_LOGGER_NAME, ROOT_LOGGER_NAME,
undefined, undefined,
LogLevel.ALL, LogLevel.ALL,
); )
} }
/** /**
@@ -55,28 +55,28 @@ export class LogService {
*/ */
public getLogger(name: string, threshold?: LogLevel): Logger { public getLogger(name: string, threshold?: LogLevel): Logger {
if (this.loggers[name]) { if (this.loggers[name]) {
return this.loggers[name]; return this.loggers[name]
} }
let parentLogger: Logger; let parentLogger: Logger
const parentLoggerName = Object.keys(this.loggers) const parentLoggerName = Object.keys(this.loggers)
.filter((n: string) => name.startsWith(n)) .filter((n: string) => name.startsWith(n))
.reduce( .reduce(
(acc: string, cur: string) => (acc.length > cur.length ? acc : cur), (acc: string, cur: string) => (acc.length > cur.length ? acc : cur),
'', '',
); )
if (parentLoggerName) { if (parentLoggerName) {
parentLogger = this.loggers[parentLoggerName]; parentLogger = this.loggers[parentLoggerName]
} else { } else {
parentLogger = this.ROOT_LOGGER; parentLogger = this.ROOT_LOGGER
} }
this.loggers[name] = parentLogger.createChildLogger(name, threshold); this.loggers[name] = parentLogger.createChildLogger(name, threshold)
return this.loggers[name]; return this.loggers[name]
} }
} }
export const logService = new LogService(); export const logService = new LogService()
export default logService; export default logService
+38 -38
View File
@@ -1,11 +1,11 @@
import { LogLevel, LogMessage } from './log-message'; import { LogLevel, LogMessage } from './log-message'
import { LogAppender } from './log-appender'; import { LogAppender } from './log-appender'
export type DeferredMsg = () => string | Record<string, unknown>; export type DeferredMsg = () => string | Record<string, unknown>;
export type MessageType = string | DeferredMsg | Record<string, unknown>; export type MessageType = string | DeferredMsg | Record<string, unknown>;
export function isDeferredMsg(msg: MessageType): msg is DeferredMsg { export function isDeferredMsg(msg: MessageType): msg is DeferredMsg {
return typeof msg === 'function'; return typeof msg === 'function'
} }
/** /**
@@ -41,7 +41,7 @@ export function isDeferredMsg(msg: MessageType): msg is DeferredMsg {
* For more details, see *LogService#getLogger*. * For more details, see *LogService#getLogger*.
*/ */
export class Logger { export class Logger {
public appenders: LogAppender[] = []; public appenders: LogAppender[] = []
public constructor( public constructor(
public readonly name: string, public readonly name: string,
@@ -50,7 +50,7 @@ export class Logger {
) {} ) {}
public createChildLogger(name: string, threshold?: LogLevel): Logger { public createChildLogger(name: string, threshold?: LogLevel): Logger {
return new Logger(name, this, threshold); return new Logger(name, this, threshold)
} }
public doLog( public doLog(
@@ -59,7 +59,7 @@ export class Logger {
stacktrace?: string, stacktrace?: string,
): void { ): void {
if (level < this.getEffectiveThreshold()) { if (level < this.getEffectiveThreshold()) {
return; return
} }
const logMsg: LogMessage = { const logMsg: LogMessage = {
@@ -68,77 +68,77 @@ export class Logger {
msg: '', msg: '',
stacktrace: '', stacktrace: '',
ts: new Date(), ts: new Date(),
};
if (msg === undefined || msg === null) {
logMsg.msg = msg;
logMsg.stacktrace = stacktrace ?? '';
} else if (msg instanceof Error) {
const err = msg as Error;
logMsg.err = err;
logMsg.msg = `${err.name}: ${err.message}`;
logMsg.stacktrace = stacktrace ?? err.stack ?? '';
} else if (isDeferredMsg(msg)) {
logMsg.msg = msg();
logMsg.stacktrace = stacktrace == null ? '' : stacktrace;
} else {
// string | object
logMsg.msg = msg;
logMsg.stacktrace = stacktrace == null ? '' : stacktrace;
} }
this.sendToAppenders(logMsg); if (msg === undefined || msg === null) {
logMsg.msg = msg
logMsg.stacktrace = stacktrace ?? ''
} else if (msg instanceof Error) {
const err = msg as Error
logMsg.err = err
logMsg.msg = `${err.name}: ${err.message}`
logMsg.stacktrace = stacktrace ?? err.stack ?? ''
} else if (isDeferredMsg(msg)) {
logMsg.msg = msg()
logMsg.stacktrace = stacktrace == null ? '' : stacktrace
} else {
// string | object
logMsg.msg = msg
logMsg.stacktrace = stacktrace == null ? '' : stacktrace
}
this.sendToAppenders(logMsg)
} }
public trace(msg: Error | MessageType, stacktrace?: string): void { public trace(msg: Error | MessageType, stacktrace?: string): void {
this.doLog(LogLevel.TRACE, msg, stacktrace); this.doLog(LogLevel.TRACE, msg, stacktrace)
} }
public debug(msg: Error | MessageType, stacktrace?: string): void { public debug(msg: Error | MessageType, stacktrace?: string): void {
this.doLog(LogLevel.DEBUG, msg, stacktrace); this.doLog(LogLevel.DEBUG, msg, stacktrace)
} }
public log(msg: MessageType, stacktrace?: string): void { public log(msg: MessageType, stacktrace?: string): void {
this.doLog(LogLevel.LOG, msg, stacktrace); this.doLog(LogLevel.LOG, msg, stacktrace)
} }
public info(msg: MessageType, stacktrace?: string): void { public info(msg: MessageType, stacktrace?: string): void {
this.doLog(LogLevel.INFO, msg, stacktrace); this.doLog(LogLevel.INFO, msg, stacktrace)
} }
public warn(msg: MessageType, stacktrace?: string): void { public warn(msg: MessageType, stacktrace?: string): void {
this.doLog(LogLevel.WARN, msg, stacktrace); this.doLog(LogLevel.WARN, msg, stacktrace)
} }
public error(msg: Error | MessageType, stacktrace?: string): void { public error(msg: Error | MessageType, stacktrace?: string): void {
this.doLog(LogLevel.ERROR, msg, stacktrace); this.doLog(LogLevel.ERROR, msg, stacktrace)
} }
public fatal(msg: Error | MessageType, stacktrace?: string): void { public fatal(msg: Error | MessageType, stacktrace?: string): void {
this.doLog(LogLevel.FATAL, msg, stacktrace); this.doLog(LogLevel.FATAL, msg, stacktrace)
} }
protected sendToAppenders(logMsg: LogMessage) { protected sendToAppenders(logMsg: LogMessage) {
this.appenders.forEach((app) => { this.appenders.forEach((app) => {
app.appendMessage(logMsg); app.appendMessage(logMsg)
}); })
if (this.parentLogger) { if (this.parentLogger) {
this.parentLogger.sendToAppenders(logMsg); this.parentLogger.sendToAppenders(logMsg)
} }
} }
protected getEffectiveThreshold(): LogLevel { protected getEffectiveThreshold(): LogLevel {
if (this.threshold) { if (this.threshold) {
return this.threshold; return this.threshold
} }
if (this.parentLogger) { if (this.parentLogger) {
return this.parentLogger.getEffectiveThreshold(); return this.parentLogger.getEffectiveThreshold()
} }
// should never happen (root logger should always have a threshold // should never happen (root logger should always have a threshold
return LogLevel.ALL; return LogLevel.ALL
} }
} }
export default Logger; export default Logger
+3 -3
View File
@@ -2,11 +2,11 @@ export function omit(
obj: Record<string, unknown>, obj: Record<string, unknown>,
keys: string[], keys: string[],
): Record<string, unknown> { ): Record<string, unknown> {
const result: Record<string, unknown> = {}; const result: Record<string, unknown> = {}
for (const key in obj) { for (const key in obj) {
if (!keys.includes(key)) { if (!keys.includes(key)) {
result[key] = obj[key]; result[key] = obj[key]
} }
} }
return result; return result
} }