Compare commits

..

2 Commits

Author SHA1 Message Date
7f2d9a9b0f
v2.4.0 2023-07-05 16:38:26 +03:00
c37ebbe7bb
Prune log entries older than x days (pruneDays) 2023-07-05 16:37:47 +03:00
3 changed files with 40 additions and 4 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "@navy.gif/logger", "name": "@navy.gif/logger",
"version": "2.3.4", "version": "2.4.0",
"description": "Logging thing", "description": "Logging thing",
"author": "Navy.gif", "author": "Navy.gif",
"license": "MIT", "license": "MIT",

View File

@ -43,6 +43,7 @@ const customStreams: string[] = [];
const customTypes: string[] = []; const customTypes: string[] = [];
const guard = '_logger'; const guard = '_logger';
const webhook: { url?: string, id?: string, token?: string } = {}; const webhook: { url?: string, id?: string, token?: string } = {};
const pruneDays = 3;
type LogLevelType = { type LogLevelType = {
debug: LogLevel, debug: LogLevel,
@ -82,6 +83,7 @@ export type LoggerMasterOptions = SharedOptionsType & {
customColours?: { [key: string]: number | string }, customColours?: { [key: string]: number | string },
broadcastLevel?: number, broadcastLevel?: number,
webhook?: WebhookClientOptions, webhook?: WebhookClientOptions,
pruneDays?: number
} }
const MasterOptions: LoggerMasterOptions = { const MasterOptions: LoggerMasterOptions = {
@ -93,6 +95,7 @@ const MasterOptions: LoggerMasterOptions = {
customColours, customColours,
broadcastLevel: 4, broadcastLevel: 4,
webhook, webhook,
pruneDays
}; };
export type LoggerClientOptions = SharedOptionsType; export type LoggerClientOptions = SharedOptionsType;

View File

@ -49,6 +49,8 @@ class MasterLogger implements Logger
#rotationFreq: number; #rotationFreq: number;
#startDay: number; #startDay: number;
#rotateTO: NodeJS.Timeout; #rotateTO: NodeJS.Timeout;
#pruneInterval: NodeJS.Timer;
#pruneDays: number;
constructor (config = Defaults.MasterOptions) constructor (config = Defaults.MasterOptions)
{ {
@ -56,7 +58,7 @@ class MasterLogger implements Logger
const { const {
directory, customTypes = [], customStreams = [], customTypeMapping, directory, customTypes = [], customStreams = [], customTypeMapping,
customColours, guard, fileRotationFreq, logLevel, logLevelMapping, customColours, guard, fileRotationFreq, logLevel, logLevelMapping,
webhook, broadcastLevel webhook, broadcastLevel, pruneDays
} = { ...Defaults.MasterOptions, ...config }; } = { ...Defaults.MasterOptions, ...config };
if (!directory) if (!directory)
@ -64,6 +66,7 @@ class MasterLogger implements Logger
this.#directory = path.resolve(directory); this.#directory = path.resolve(directory);
if (!fs.existsSync(this.#directory)) if (!fs.existsSync(this.#directory))
fs.mkdirSync(this.#directory, { recursive: true }); fs.mkdirSync(this.#directory, { recursive: true });
this.#_broadcastLevel = broadcastLevel as number; this.#_broadcastLevel = broadcastLevel as number;
this.#_logLevel = logLevel as number; this.#_logLevel = logLevel as number;
this.#_logLevelMapping = { ...Defaults.MasterOptions.logLevelMapping, ...logLevelMapping }; this.#_logLevelMapping = { ...Defaults.MasterOptions.logLevelMapping, ...logLevelMapping };
@ -102,7 +105,7 @@ class MasterLogger implements Logger
this.#streamTypes = [ ...customStreams, 'error', 'default' ]; this.#streamTypes = [ ...customStreams, 'error', 'default' ];
this.#streamTypeMapping = { ...Defaults.TypeStream, ...customTypeMapping }; this.#streamTypeMapping = { ...Defaults.TypeStream, ...customTypeMapping };
this.#writeStreams = this.#streamTypes.reduce((acc, type) => this.#writeStreams = this.#streamTypes.reduce((acc, type) =>
{ {
acc[type] = this.loadFile(type); acc[type] = this.loadFile(type);
return acc; return acc;
@ -112,8 +115,11 @@ class MasterLogger implements Logger
this.#rotationFreq = fileRotationFreq as number * DAY; this.#rotationFreq = fileRotationFreq as number * DAY;
this.#startDay = Math.floor(Date.now() / this.#rotationFreq) * this.#rotationFreq; this.#startDay = Math.floor(Date.now() / this.#rotationFreq) * this.#rotationFreq;
this.#rotateTO = setTimeout(this.rotateLogFiles.bind(this), this.#startDay + this.#rotationFreq - Date.now()); this.#rotateTO = setTimeout(this.rotateLogFiles.bind(this), this.#startDay + this.#rotationFreq - Date.now());
this.#pruneDays = pruneDays as number;
this.#pruneInterval = setInterval(this.pruneLogFiles.bind(this), 60 * 60 * 1000);
this.pruneLogFiles();
if (webhook && webhook.url) if (webhook && webhook.url)
{ {
this.#webhook = new DiscordWebhook(webhook); this.#webhook = new DiscordWebhook(webhook);
this.#webhook.fetch(); this.#webhook.fetch();
@ -121,6 +127,16 @@ class MasterLogger implements Logger
} }
close ()
{
clearInterval(this.#pruneInterval);
const streams = Object.keys(this.#writeStreams);
for (const type of streams)
this.#writeStreams[type].end();
clearTimeout(this.#rotateTO);
}
get guard () get guard ()
{ {
return this.#_guard; return this.#_guard;
@ -136,6 +152,23 @@ class MasterLogger implements Logger
return Object.keys(this.#_logLevelMapping); return Object.keys(this.#_logLevelMapping);
} }
pruneLogFiles ()
{
const directory = fs.readdirSync(this.#directory, { withFileTypes: true });
const now = Date.now();
const limit = this.#pruneDays * 24 * 60 * 60 * 1000;
for (const entry of directory)
{
if (!entry.isFile() || !(/\d{4}-\d{2}-\d{2}-[a-z]+\.log/u).test(entry.name))
continue;
const [ year, month, day ] = entry.name.split('-');
const date = new Date(parseInt(year), parseInt(month) - 1, parseInt(day)).getTime();
if ((now - date) < limit)
continue;
fs.unlinkSync(path.join(this.#directory, entry.name));
}
}
setLogLevel (level: number) setLogLevel (level: number)
{ {
if (LogLevel[level] in this.#_logLevelMapping) if (LogLevel[level] in this.#_logLevelMapping)