如何在控制台更新Winston历史日志?多实例场景实现方法
问题
需要同时使用多个Logger实例,每个Logger对应的日志行能记录自身的历史日志。之前用单Logger实例时日志可读性极差,难以区分不同模块的日志上下文。
示例代码:
Logger.getLogger("A").info("test1: A"); Logger.getLogger("B").info("Message with label: B"); Logger.getLogger("A").info("test2: A");
期望输出:
2022-12-11T14:49:39.829Z info [A] test2: A // prev log was 'test1: A' 2022-12-11T14:49:39.828Z info [B] Message with label: B
实现方案
可以通过单例模式+实例级历史追踪来实现,核心思路是给每个命名的Logger实例维护独立的日志历史,在输出新日志时自动附加上一条日志的内容。
1. 实现带历史追踪的Logger类
用TypeScript编写的完整实现如下:
class Logger { // 静态Map存储所有命名Logger实例,保证单例 private static instances: Map<string, Logger> = new Map(); // 每个实例维护自己的最后一条日志内容 private lastLog: string | null = null; private constructor(private name: string) {} // 获取指定名称的Logger实例,不存在则创建 static getLogger(name: string): Logger { if (!Logger.instances.has(name)) { Logger.instances.set(name, new Logger(name)); } return Logger.instances.get(name)!; } // 实现info级别的日志输出 info(message: string): void { const timestamp = new Date().toISOString(); const level = "info"; // 构建输出内容,存在历史日志则附加备注 let output = `${timestamp} ${level} [${this.name}] ${message}`; if (this.lastLog) { output += ` // prev log was '${this.lastLog}'`; } // 更新当前实例的最后一条日志 this.lastLog = message; // 输出到控制台(可替换为文件写入等逻辑) console.log(output); } }
2. 关键逻辑说明
- 单例管理:通过
static getLogger方法和instancesMap,确保相同名称的Logger只会创建一个实例,避免重复初始化。 - 实例级历史:每个Logger实例的
lastLog属性只记录自身的最后一条日志,不同名称的实例互不干扰。 - 格式化输出:日志内容包含时间戳、级别、实例名称、消息,以及可选的历史日志备注,完全匹配期望格式。
3. 验证示例代码
运行你提供的示例代码:
Logger.getLogger("A").info("test1: A"); Logger.getLogger("B").info("Message with label: B"); Logger.getLogger("A").info("test2: A");
输出结果(时间戳会随实际运行时间变化):
2022-12-11T14:49:39.827Z info [A] test1: A 2022-12-11T14:49:39.828Z info [B] Message with label: B 2022-12-11T14:49:39.829Z info [A] test2: A // prev log was 'test1: A'
注:如果需要将最新日志排在最前面,可以收集日志到缓存后反向输出,或者使用控制台的反向打印逻辑,但常规日志输出是按时间顺序从上到下。
扩展优化
- 支持更多日志级别(warn、error等):复制
info方法的逻辑,调整级别字段即可。 - 自定义输出目标:将
console.log替换为写入文件、发送到日志服务等逻辑。 - 保留多条历史日志:将
lastLog改为数组,记录最近N条日志,输出时可显示更多上下文。
内容的提问来源于stack exchange,提问作者minicx
相关产品推荐
相关产品推荐

