UNPKG

kaven-utils

Version:

Utils for Node.js.

168 lines (167 loc) 5.58 kB
/******************************************************************** * @author: Kaven * @email: kaven@wuwenkai.com * @website: http://blog.kaven.xyz * @file: [Kaven-Utils] /src/KavenLogger.ts * @create: 2020-01-19 14:55:07.833 * @modify: 2024-11-01 10:48:07.333 * @version: 5.4.5 * @times: 55 * @lines: 206 * @copyright: Copyright © 2020-2024 Kaven. All Rights Reserved. * @description: [description] * @license: [license] ********************************************************************/ import { AnsiColors_Blue, AnsiColors_Red, AnsiColors_Yellow, CombinePath, DeleteKeyValuePair, FindKeyValuePair, KavenLog, LogLevel, StartTimer } from "kaven-basic"; import { EOL } from "node:os"; import { format } from "node:util"; import { KavenLoggerFile } from "./KavenLoggerFile.js"; import { ResetLogFileIf } from "./KavenUtility.js"; import { GetEntryDirectory } from "./KavenUtility.Constant.js"; /** * @since 4.3.0 * @version 2022-06-26 */ export class KavenLogger { // #region Static static _loggers = {}; static _logger; static get Default() { if (!KavenLogger._logger) { KavenLogger._logger = new KavenLogger(KavenLogger.DefaultLogFile); } return KavenLogger._logger; } static set Default(logger) { KavenLogger._logger = logger; } static get DefaultLogFile() { const dir = GetEntryDirectory(); return CombinePath(dir, "logs", "log.txt"); } static AddLogger(name, logger) { this.RemoveLogger(name)?.Stop(); this._loggers[name] = logger; } static GetLogger(name) { const pair = FindKeyValuePair(this._loggers, name, true); return pair?.value; } static RemoveLogger(name) { const pair = DeleteKeyValuePair(this._loggers, name, true); return pair?.value; } // #endregion logFiles = []; options; timer; addLoggerFile(options) { const file = new KavenLoggerFile(options); if (this.logFiles.some(p => p.File === file.File)) { throw new Error(`Duplicate file: ${file.File}`); } this.logFiles.push(file); } constructor(p1, p2) { const file = typeof p1 === "string" ? p1 : undefined; const options = (typeof p1 !== "string" ? p1 : undefined) ?? p2; if (file) { this.addLoggerFile({ file, }); } this.options = options ?? {}; if (this.options.resetSizeInBytes === undefined) { this.options.resetSizeInBytes = 5 * 1024 * 1024; } if (this.options.resetInterval === undefined) { this.options.resetInterval = { hours: 1 }; } if (this.options.files) { for (const f of this.options.files) { this.addLoggerFile(f); } } if (this.logFiles.length === 0) { throw new Error("Please specify at least one log file."); } } EnableConsole = true; EnableAnsiColorForConsole = true; SaveWithAnsiColor = true; AnsiColorInfo = { All: AnsiColors_Blue, }; AnsiColorWarn = { All: AnsiColors_Yellow, }; AnsiColorError = { All: AnsiColors_Red, }; Log(log) { if (!log.Colors) { if (log.Level === LogLevel.Info) { log.Colors = this.AnsiColorInfo; } else if (log.Level === LogLevel.Warn) { log.Colors = this.AnsiColorWarn; } else if (log.Level === LogLevel.Error) { log.Colors = this.AnsiColorError; } } if (this.EnableConsole && log.NeedWriteToConsole) { if (this.EnableAnsiColorForConsole) { log.WriteToConsole(); } else { log.WriteToConsole(false); } } if (log.NeedSave) { for (const file of this.logFiles) { if (file.Has(log.Level)) { const line = log.ToString(file.SaveWithAnsiColor ?? this.SaveWithAnsiColor) + EOL; file.Stream?.write(line, "utf8"); } } } } Info(...args) { const message = format(args.shift(), ...args); const log = KavenLog.CreateInfo(message); this.Log(log); } Warn(...args) { const message = format(args.shift(), ...args); const log = KavenLog.CreateWarn(message); this.Log(log); } Error(...args) { const message = format(args.shift(), ...args); const log = KavenLog.CreateError(message); this.Log(log); } async Start() { await Promise.all(this.logFiles.map(p => p.Open())); for (const file of this.logFiles) { this.Info(`Start logger: ${file.ToString()}`); } if (!this.timer) { if (this.options.resetInterval) { this.timer = StartTimer(async () => { await this.ResetIfNecessary(); }, this.options.resetInterval); KavenLogger.Default.Info(`Next log reset date: ${this.timer.NextInvocationDateTime}`); } } } async ResetIfNecessary() { await Promise.all(this.logFiles.map(p => ResetLogFileIf(this.options.resetSizeInBytes, p.File))); } async Stop() { this.timer?.Stop(); this.timer = undefined; await Promise.all(this.logFiles.map(p => p.Close())); } }