kaven-utils
Version:
Utils for Node.js.
168 lines (167 loc) • 5.58 kB
JavaScript
/********************************************************************
* @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()));
}
}