metalog 3.1.16 → 3.1.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/metalog.d.ts +30 -2
  2. package/metalog.js +46 -15
  3. package/package.json +9 -9
package/metalog.d.ts CHANGED
@@ -11,6 +11,28 @@ interface LoggerOptions {
11
11
  json?: boolean;
12
12
  toFile?: Array<string>;
13
13
  toStdout?: Array<string>;
14
+ crash?: string;
15
+ }
16
+
17
+ interface Console {
18
+ assert(assertion: unknown, ...args: unknown[]): void;
19
+ clear(): void;
20
+ count(label?: string): void;
21
+ countReset(label?: string): void;
22
+ debug(...args: unknown[]): void;
23
+ dir(...args: unknown[]): void;
24
+ trace(...args: unknown[]): void;
25
+ info(...args: unknown[]): void;
26
+ log(...args: unknown[]): void;
27
+ warn(...args: unknown[]): void;
28
+ error(...args: unknown[]): void;
29
+ group(...args: unknown[]): void;
30
+ groupCollapsed(...args: unknown[]): void;
31
+ groupEnd(): void;
32
+ table(tabularData: unknown): void;
33
+ time(label?: string): void;
34
+ timeEnd(label?: string): void;
35
+ timeLog(label: string, ...args: unknown[]): void;
14
36
  }
15
37
 
16
38
  export class Logger extends EventEmitter {
@@ -22,6 +44,7 @@ export class Logger extends EventEmitter {
22
44
  writeBuffer: number;
23
45
  keepDays: number;
24
46
  home: string;
47
+ json: boolean;
25
48
  stream: NodeJS.WritableStream;
26
49
  reopenTimer: NodeJS.Timer;
27
50
  flushTimer: NodeJS.Timer;
@@ -38,9 +61,14 @@ export class Logger extends EventEmitter {
38
61
  open(): Promise<Logger>;
39
62
  close(): Promise<void>;
40
63
  rotate(): Promise<void>;
41
- write(type: string, s: string): void;
42
- flush(callback: Function): void;
64
+ format(type: string, indent: number, ...args: unknown[]): string;
65
+ formatPretty(type: string, indent: number, ...args: unknown[]): string;
66
+ formatFile(type: string, indent: number, ...args: unknown[]): string;
67
+ formatJson(type: string, indent: number, ...args: unknown[]): string;
68
+ write(type: string, indent: number, ...args: unknown[]): void;
69
+ flush(callback?: (err?: Error) => void): void;
43
70
  normalizeStack(stack: string): string;
71
+ expandError(err: Error): unknown;
44
72
  }
45
73
 
46
74
  export function openLog(args: LoggerOptions): Promise<Logger>;
package/metalog.js CHANGED
@@ -89,10 +89,10 @@ class Console {
89
89
  }
90
90
 
91
91
  assert(assertion, ...args) {
92
- try {
93
- console.assert(assertion, ...args);
94
- } catch (err) {
95
- this.#write('error', this.#groupIndent, err.stack);
92
+ if (!assertion) {
93
+ const noArgs = args.length === 0;
94
+ const message = noArgs ? 'Assertion failed' : util.format(...args);
95
+ this.#write('error', this.#groupIndent, message);
96
96
  }
97
97
  }
98
98
 
@@ -152,7 +152,7 @@ class Console {
152
152
  }
153
153
 
154
154
  groupEnd() {
155
- if (this.#groupIndent.length === 0) return;
155
+ if (this.#groupIndent === 0) return;
156
156
  this.#groupIndent -= INDENT;
157
157
  }
158
158
 
@@ -184,19 +184,20 @@ class Console {
184
184
  }
185
185
 
186
186
  class Logger extends events.EventEmitter {
187
- constructor(args) {
187
+ constructor(options) {
188
188
  super();
189
- const { workerId = 0, createStream = fs.createWriteStream } = args;
190
- const { writeInterval, writeBuffer, keepDays, home, json } = args;
191
- const { toFile = LOG_TYPES, toStdout = LOG_TYPES } = args;
189
+ const { workerId = 0, createStream = fs.createWriteStream } = options;
190
+ const { writeInterval, writeBuffer, keepDays, home, json } = options;
191
+ const { toFile = LOG_TYPES, toStdout = LOG_TYPES, crash } = options;
192
192
  this.active = false;
193
- this.path = args.path;
193
+ this.path = options.path;
194
+ this.path = path.resolve(options.path);
194
195
  this.workerId = `W${workerId}`;
195
196
  this.createStream = createStream;
196
197
  this.writeInterval = writeInterval || DEFAULT_WRITE_INTERVAL;
197
198
  this.writeBuffer = writeBuffer || DEFAULT_BUFFER_SIZE;
198
199
  this.keepDays = keepDays || DEFAULT_KEEP_DAYS;
199
- this.home = home;
200
+ this.home = home ? path.resolve(home) : undefined;
200
201
  this.json = Boolean(json);
201
202
  this.stream = null;
202
203
  this.reopenTimer = null;
@@ -209,6 +210,7 @@ class Logger extends events.EventEmitter {
209
210
  this.fsEnabled = toFile.length !== 0;
210
211
  this.toStdout = logTypes(toStdout);
211
212
  this.console = new Console((...args) => this.write(...args));
213
+ if (crash === 'flush') this.#setupCrashHandling();
212
214
  return this.open();
213
215
  }
214
216
 
@@ -304,9 +306,11 @@ class Logger extends events.EventEmitter {
304
306
  if (metautil.fileExt(fileName) !== 'log') continue;
305
307
  const fileAge = now - nameToDays(fileName);
306
308
  if (fileAge < this.keepDays) continue;
307
- finish.push(fsp.unlink(path.join(this.path, fileName)));
309
+ const filePath = path.join(this.path, fileName);
310
+ const promise = fsp.unlink(filePath).catch(() => {});
311
+ finish.push(promise);
308
312
  }
309
- await Promise.all(finish);
313
+ await Promise.allSettled(finish);
310
314
  } catch (err) {
311
315
  process.stdout.write(`${err.stack}\n`);
312
316
  this.emit('error', err);
@@ -386,7 +390,13 @@ class Logger extends events.EventEmitter {
386
390
  return;
387
391
  }
388
392
  if (!this.active) {
389
- const err = new Error('Cannot flush log buffer: logger is not opened');
393
+ const err = new Error('Cannot flush log buffer: logger is not active');
394
+ this.emit('error', err);
395
+ if (callback) callback(err);
396
+ return;
397
+ }
398
+ if (!this.stream || this.stream.destroyed || this.stream.closed) {
399
+ const err = new Error('Cannot flush log buffer: stream is not available');
390
400
  this.emit('error', err);
391
401
  if (callback) callback(err);
392
402
  return;
@@ -416,8 +426,29 @@ class Logger extends events.EventEmitter {
416
426
  ...err,
417
427
  };
418
428
  }
429
+
430
+ #setupCrashHandling() {
431
+ const exitHandler = () => {
432
+ this.flush();
433
+ };
434
+ process.on('SIGTERM', exitHandler);
435
+ process.on('SIGINT', exitHandler);
436
+ process.on('SIGUSR1', exitHandler);
437
+ process.on('SIGUSR2', exitHandler);
438
+ process.on('uncaughtException', (err) => {
439
+ this.write('error', 0, 'Uncaught Exception:', err);
440
+ this.flush();
441
+ });
442
+ process.on('unhandledRejection', (reason) => {
443
+ this.write('error', 0, 'Unhandled Rejection:', reason);
444
+ this.flush();
445
+ });
446
+ process.on('exit', () => {
447
+ this.flush();
448
+ });
449
+ }
419
450
  }
420
451
 
421
- const openLog = async (args) => new Logger(args);
452
+ const openLog = async (options) => new Logger(options);
422
453
 
423
454
  module.exports = { Logger, openLog };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "metalog",
3
- "version": "3.1.16",
3
+ "version": "3.1.18",
4
4
  "author": "Timur Shemsedinov <timur.shemsedinov@gmail.com>",
5
5
  "description": "Logger for Metarhia",
6
6
  "license": "MIT",
@@ -49,17 +49,17 @@
49
49
  "fix": "eslint . --fix && prettier --write \"**/*.js\" \"**/*.json\" \"**/*.md\" \"**/*.ts\""
50
50
  },
51
51
  "engines": {
52
- "node": "18 || 20 || 21 || 22 || 23 || 24"
52
+ "node": ">=18"
53
53
  },
54
54
  "dependencies": {
55
- "concolor": "^1.1.2",
56
- "metautil": "^5.2.5"
55
+ "concolor": "^1.1.3",
56
+ "metautil": "^5.3.0"
57
57
  },
58
58
  "devDependencies": {
59
- "@types/node": "^22.15.21",
60
- "eslint": "^9.27.0",
61
- "eslint-config-metarhia": "^9.1.1",
62
- "prettier": "^3.5.3",
63
- "typescript": "^5.8.3"
59
+ "@types/node": "^24.3.0",
60
+ "eslint": "^9.34.0",
61
+ "eslint-config-metarhia": "^9.1.3",
62
+ "prettier": "^3.6.2",
63
+ "typescript": "^5.9.2"
64
64
  }
65
65
  }