@nu-art/logger 0.401.1
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.
- package/BeLogged.d.ts +92 -0
- package/BeLogged.js +124 -0
- package/LogClient.d.ts +126 -0
- package/LogClient.js +143 -0
- package/LogClient_BaseRotate.d.ts +91 -0
- package/LogClient_BaseRotate.js +109 -0
- package/LogClient_Browser.d.ts +38 -0
- package/LogClient_Browser.js +92 -0
- package/LogClient_BrowserGroups.d.ts +50 -0
- package/LogClient_BrowserGroups.js +112 -0
- package/LogClient_ConsoleProxy.d.ts +108 -0
- package/LogClient_ConsoleProxy.js +179 -0
- package/LogClient_File.d.ts +58 -0
- package/LogClient_File.js +89 -0
- package/LogClient_Function.d.ts +31 -0
- package/LogClient_Function.js +63 -0
- package/LogClient_MemBuffer.d.ts +88 -0
- package/LogClient_MemBuffer.js +139 -0
- package/LogClient_Terminal.d.ts +49 -0
- package/LogClient_Terminal.js +81 -0
- package/Logger.d.ts +237 -0
- package/Logger.js +316 -0
- package/debug-flags.d.ts +145 -0
- package/debug-flags.js +196 -0
- package/get-log-style.d.ts +27 -0
- package/get-log-style.js +29 -0
- package/index.d.ts +15 -0
- package/index.js +20 -0
- package/package.json +52 -0
- package/types.d.ts +32 -0
- package/types.js +30 -0
- package/utils.d.ts +49 -0
- package/utils.js +106 -0
package/BeLogged.d.ts
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { LogClient } from './LogClient.js';
|
|
2
|
+
import { LogLevel, LogParam } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Central logging manager that distributes log messages to all registered log clients.
|
|
5
|
+
*
|
|
6
|
+
* BeLogged acts as a dispatcher - when a log message is sent, it forwards it to all
|
|
7
|
+
* registered LogClient instances. This allows multiple output destinations simultaneously
|
|
8
|
+
* (e.g., console + file + remote logging).
|
|
9
|
+
*
|
|
10
|
+
* Log clients are added via `addClient()` and can be removed via `removeClient()`.
|
|
11
|
+
* Each client can have its own filter and prefix composer.
|
|
12
|
+
*/
|
|
13
|
+
declare class BeLogged_Class {
|
|
14
|
+
/** Array of registered log clients */
|
|
15
|
+
private clients;
|
|
16
|
+
/** Line count for console rewriting (used by some clients) */
|
|
17
|
+
private lineCount;
|
|
18
|
+
/**
|
|
19
|
+
* Registers a log client to receive all log messages.
|
|
20
|
+
*
|
|
21
|
+
* The client's `init()` method is called immediately. If the client is already
|
|
22
|
+
* registered, this method does nothing (no duplicate registration).
|
|
23
|
+
*
|
|
24
|
+
* @param client - LogClient instance to register
|
|
25
|
+
*/
|
|
26
|
+
addClient<Client extends LogClient>(client: Client): void;
|
|
27
|
+
/**
|
|
28
|
+
* Removes a log client (alias for removeClient for backwards compatibility).
|
|
29
|
+
*
|
|
30
|
+
* @param client - LogClient instance to remove
|
|
31
|
+
*/
|
|
32
|
+
removeConsole<Client extends LogClient>(client: Client): void;
|
|
33
|
+
/**
|
|
34
|
+
* Removes a log client from the registry.
|
|
35
|
+
*
|
|
36
|
+
* The client's `stop()` method is called for cleanup. If the client is not
|
|
37
|
+
* registered, this method does nothing.
|
|
38
|
+
*
|
|
39
|
+
* @param client - LogClient instance to remove
|
|
40
|
+
*/
|
|
41
|
+
removeClient<Client extends LogClient>(client: Client): void;
|
|
42
|
+
/**
|
|
43
|
+
* Logs a message to all registered clients.
|
|
44
|
+
*
|
|
45
|
+
* @param tag - Logger tag/identifier
|
|
46
|
+
* @param level - Log level
|
|
47
|
+
* @param bold - Whether to apply bold formatting
|
|
48
|
+
* @param toLog - Values to log (spread arguments)
|
|
49
|
+
*/
|
|
50
|
+
log(tag: string, level: LogLevel, bold: boolean, ...toLog: LogParam[]): void;
|
|
51
|
+
/**
|
|
52
|
+
* Internal implementation that distributes the log message to all clients.
|
|
53
|
+
*
|
|
54
|
+
* Creates a copy of the toLog array for each client to prevent mutation issues.
|
|
55
|
+
*
|
|
56
|
+
* @param tag - Logger tag/identifier
|
|
57
|
+
* @param level - Log level
|
|
58
|
+
* @param bold - Whether to apply bold formatting
|
|
59
|
+
* @param toLog - Array of values to log
|
|
60
|
+
*/
|
|
61
|
+
private logImpl;
|
|
62
|
+
/**
|
|
63
|
+
* Clears footer lines from console output.
|
|
64
|
+
*
|
|
65
|
+
* Used by console-based log clients to clear previously written footer content.
|
|
66
|
+
* Writes newlines to stdout to clear the specified number of lines.
|
|
67
|
+
*/
|
|
68
|
+
clearFooter(): void;
|
|
69
|
+
/**
|
|
70
|
+
* Sets the line count for console rewriting operations.
|
|
71
|
+
*
|
|
72
|
+
* Used by log clients that rewrite console output (e.g., progress indicators).
|
|
73
|
+
*
|
|
74
|
+
* @param lineCount - Number of lines to track for rewriting
|
|
75
|
+
*/
|
|
76
|
+
rewriteConsole(lineCount: number): void;
|
|
77
|
+
/**
|
|
78
|
+
* Removes all registered log clients and stops them.
|
|
79
|
+
*
|
|
80
|
+
* Useful for test cleanup to ensure no clients remain active.
|
|
81
|
+
*/
|
|
82
|
+
removeAllClients(): void;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Singleton instance of the logging manager.
|
|
86
|
+
*
|
|
87
|
+
* This is the central entry point for all logging. Logger instances call
|
|
88
|
+
* `BeLogged.logImpl()` to output messages, which are then distributed to
|
|
89
|
+
* all registered log clients.
|
|
90
|
+
*/
|
|
91
|
+
export declare const BeLogged: BeLogged_Class;
|
|
92
|
+
export {};
|
package/BeLogged.js
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @nu-art/logger - Flexible logging infrastructure with multiple output targets
|
|
3
|
+
* Copyright (C) 2024 Adam van der Kruk aka TacB0sS
|
|
4
|
+
* Licensed under the Apache License, Version 2.0
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Central logging manager that distributes log messages to all registered log clients.
|
|
8
|
+
*
|
|
9
|
+
* BeLogged acts as a dispatcher - when a log message is sent, it forwards it to all
|
|
10
|
+
* registered LogClient instances. This allows multiple output destinations simultaneously
|
|
11
|
+
* (e.g., console + file + remote logging).
|
|
12
|
+
*
|
|
13
|
+
* Log clients are added via `addClient()` and can be removed via `removeClient()`.
|
|
14
|
+
* Each client can have its own filter and prefix composer.
|
|
15
|
+
*/
|
|
16
|
+
class BeLogged_Class {
|
|
17
|
+
/** Array of registered log clients */
|
|
18
|
+
clients = [];
|
|
19
|
+
/** Line count for console rewriting (used by some clients) */
|
|
20
|
+
lineCount = 0;
|
|
21
|
+
/**
|
|
22
|
+
* Registers a log client to receive all log messages.
|
|
23
|
+
*
|
|
24
|
+
* The client's `init()` method is called immediately. If the client is already
|
|
25
|
+
* registered, this method does nothing (no duplicate registration).
|
|
26
|
+
*
|
|
27
|
+
* @param client - LogClient instance to register
|
|
28
|
+
*/
|
|
29
|
+
addClient(client) {
|
|
30
|
+
if (this.clients.indexOf(client) !== -1)
|
|
31
|
+
return;
|
|
32
|
+
client.init();
|
|
33
|
+
this.clients.push(client);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Removes a log client (alias for removeClient for backwards compatibility).
|
|
37
|
+
*
|
|
38
|
+
* @param client - LogClient instance to remove
|
|
39
|
+
*/
|
|
40
|
+
removeConsole(client) {
|
|
41
|
+
this.removeClient(client);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Removes a log client from the registry.
|
|
45
|
+
*
|
|
46
|
+
* The client's `stop()` method is called for cleanup. If the client is not
|
|
47
|
+
* registered, this method does nothing.
|
|
48
|
+
*
|
|
49
|
+
* @param client - LogClient instance to remove
|
|
50
|
+
*/
|
|
51
|
+
removeClient(client) {
|
|
52
|
+
const index = this.clients.indexOf(client);
|
|
53
|
+
if (index === -1)
|
|
54
|
+
return;
|
|
55
|
+
this.clients.splice(index, 1);
|
|
56
|
+
client.stop();
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Logs a message to all registered clients.
|
|
60
|
+
*
|
|
61
|
+
* @param tag - Logger tag/identifier
|
|
62
|
+
* @param level - Log level
|
|
63
|
+
* @param bold - Whether to apply bold formatting
|
|
64
|
+
* @param toLog - Values to log (spread arguments)
|
|
65
|
+
*/
|
|
66
|
+
log(tag, level, bold, ...toLog) {
|
|
67
|
+
this.logImpl(tag, level, bold, toLog);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Internal implementation that distributes the log message to all clients.
|
|
71
|
+
*
|
|
72
|
+
* Creates a copy of the toLog array for each client to prevent mutation issues.
|
|
73
|
+
*
|
|
74
|
+
* @param tag - Logger tag/identifier
|
|
75
|
+
* @param level - Log level
|
|
76
|
+
* @param bold - Whether to apply bold formatting
|
|
77
|
+
* @param toLog - Array of values to log
|
|
78
|
+
*/
|
|
79
|
+
logImpl(tag, level, bold, toLog) {
|
|
80
|
+
for (const client of this.clients) {
|
|
81
|
+
client.log(tag, level, bold, [...toLog]);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Clears footer lines from console output.
|
|
86
|
+
*
|
|
87
|
+
* Used by console-based log clients to clear previously written footer content.
|
|
88
|
+
* Writes newlines to stdout to clear the specified number of lines.
|
|
89
|
+
*/
|
|
90
|
+
clearFooter() {
|
|
91
|
+
for (let i = 0; i < this.lineCount + 3; i++) {
|
|
92
|
+
process.stdout.write(`\n`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Sets the line count for console rewriting operations.
|
|
97
|
+
*
|
|
98
|
+
* Used by log clients that rewrite console output (e.g., progress indicators).
|
|
99
|
+
*
|
|
100
|
+
* @param lineCount - Number of lines to track for rewriting
|
|
101
|
+
*/
|
|
102
|
+
rewriteConsole(lineCount) {
|
|
103
|
+
this.lineCount = lineCount;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Removes all registered log clients and stops them.
|
|
107
|
+
*
|
|
108
|
+
* Useful for test cleanup to ensure no clients remain active.
|
|
109
|
+
*/
|
|
110
|
+
removeAllClients() {
|
|
111
|
+
const clients = [...this.clients];
|
|
112
|
+
for (const client of clients) {
|
|
113
|
+
this.removeClient(client);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Singleton instance of the logging manager.
|
|
119
|
+
*
|
|
120
|
+
* This is the central entry point for all logging. Logger instances call
|
|
121
|
+
* `BeLogged.logImpl()` to output messages, which are then distributed to
|
|
122
|
+
* all registered log clients.
|
|
123
|
+
*/
|
|
124
|
+
export const BeLogged = new BeLogged_Class();
|
package/LogClient.d.ts
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { LogLevel, LogParam, LogPrefixComposer } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Filter function type for controlling which log messages are output.
|
|
4
|
+
*
|
|
5
|
+
* Returns true if the message should be logged, false to suppress it.
|
|
6
|
+
*/
|
|
7
|
+
export type LogFilter = (level: LogLevel, tag: string) => boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Abstract base class for all log client implementations.
|
|
10
|
+
*
|
|
11
|
+
* LogClient defines the interface for outputting log messages. Each implementation
|
|
12
|
+
* handles the actual output mechanism (console, file, browser, etc.). The base class
|
|
13
|
+
* provides:
|
|
14
|
+
* - Prefix composition (timestamp, level, tag formatting)
|
|
15
|
+
* - Filtering (optional per-client filtering)
|
|
16
|
+
* - Lifecycle management (init/stop)
|
|
17
|
+
*
|
|
18
|
+
* Concrete implementations must override `logMessage()` to perform the actual output.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* class CustomLogClient extends LogClient {
|
|
23
|
+
* protected logMessage(level: LogLevel, bold: boolean, prefix: string, ...toLog: LogParam[]) {
|
|
24
|
+
* // Custom output logic
|
|
25
|
+
* console.log(prefix, ...toLog);
|
|
26
|
+
* }
|
|
27
|
+
* }
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare abstract class LogClient {
|
|
31
|
+
/** Function that composes the log prefix (timestamp, level, tag) */
|
|
32
|
+
private prefixComposer;
|
|
33
|
+
/** Optional filter function to suppress certain log messages */
|
|
34
|
+
private filter;
|
|
35
|
+
/**
|
|
36
|
+
* Abstract method that concrete implementations must override.
|
|
37
|
+
*
|
|
38
|
+
* Performs the actual output of the log message. The prefix is already composed,
|
|
39
|
+
* and filtering has already been applied.
|
|
40
|
+
*
|
|
41
|
+
* @param level - Log level
|
|
42
|
+
* @param bold - Whether to apply bold formatting
|
|
43
|
+
* @param prefix - Composed prefix string (timestamp, level indicator, tag)
|
|
44
|
+
* @param toLog - Array of values to log
|
|
45
|
+
*/
|
|
46
|
+
protected abstract logMessage(level: LogLevel, bold: boolean, prefix: string, toLog: LogParam[]): void;
|
|
47
|
+
/**
|
|
48
|
+
* Sets a custom prefix composer for this log client.
|
|
49
|
+
*
|
|
50
|
+
* The composer function generates the prefix string that appears before each log message.
|
|
51
|
+
*
|
|
52
|
+
* @param logComposer - Function that generates the prefix from tag and level
|
|
53
|
+
*/
|
|
54
|
+
setComposer(logComposer: LogPrefixComposer): void;
|
|
55
|
+
/**
|
|
56
|
+
* Lifecycle hook called when the log client is added to BeLogged.
|
|
57
|
+
*
|
|
58
|
+
* Override to perform initialization (e.g., open files, set up connections).
|
|
59
|
+
*/
|
|
60
|
+
init(): void;
|
|
61
|
+
/**
|
|
62
|
+
* Lifecycle hook called when the log client is removed from BeLogged.
|
|
63
|
+
*
|
|
64
|
+
* Override to perform cleanup (e.g., close files, clean up resources).
|
|
65
|
+
*/
|
|
66
|
+
stop(): void;
|
|
67
|
+
/**
|
|
68
|
+
* Sets a filter function for this log client.
|
|
69
|
+
*
|
|
70
|
+
* The filter is applied before `logMessage()` is called. If the filter returns
|
|
71
|
+
* false, the message is not output by this client.
|
|
72
|
+
*
|
|
73
|
+
* @param filter - Function that returns true to log, false to suppress
|
|
74
|
+
* @returns This instance for method chaining
|
|
75
|
+
*/
|
|
76
|
+
setFilter(filter: LogFilter): this;
|
|
77
|
+
/**
|
|
78
|
+
* Logs a message through this client.
|
|
79
|
+
*
|
|
80
|
+
* Applies the filter, composes the prefix, and calls `logMessage()` if the
|
|
81
|
+
* message passes the filter.
|
|
82
|
+
*
|
|
83
|
+
* @param tag - Logger tag/identifier
|
|
84
|
+
* @param level - Log level
|
|
85
|
+
* @param bold - Whether to apply bold formatting
|
|
86
|
+
* @param toLog - Array of values to log
|
|
87
|
+
*/
|
|
88
|
+
log(tag: string, level: LogLevel, bold: boolean, toLog: LogParam[]): void;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Timezone offset in milliseconds, calculated once at module load.
|
|
92
|
+
*
|
|
93
|
+
* Used to adjust timestamps to local timezone in log prefixes.
|
|
94
|
+
*/
|
|
95
|
+
export declare const _logger_timezoneOffset: number;
|
|
96
|
+
/**
|
|
97
|
+
* Reusable Date object for timestamp formatting (mutated, not recreated for performance).
|
|
98
|
+
*
|
|
99
|
+
* **Performance Note**: This Date object is mutated on every log call to avoid creating
|
|
100
|
+
* new Date instances. This is safe in Node.js's single-threaded execution model but
|
|
101
|
+
* would not be thread-safe in a multi-threaded environment.
|
|
102
|
+
*/
|
|
103
|
+
export declare const _logger_finalDate: Date;
|
|
104
|
+
/**
|
|
105
|
+
* Array of log level prefix indicators.
|
|
106
|
+
*
|
|
107
|
+
* Maps log levels to their string representations: '---' (unknown), '-V-' (Verbose),
|
|
108
|
+
* '-D-' (Debug), '-I-' (Info), '-W-' (Warning), '-E-' (Error).
|
|
109
|
+
*/
|
|
110
|
+
export declare const _logger_logPrefixes: readonly ["---", "-V-", "-D-", "-I-", "-W-", "-E-"];
|
|
111
|
+
/**
|
|
112
|
+
* Gets the prefix indicator for a log level.
|
|
113
|
+
*
|
|
114
|
+
* @param level - Log level
|
|
115
|
+
* @returns Prefix string ('-V-' for Verbose, '-D-' for Debug, etc.)
|
|
116
|
+
*/
|
|
117
|
+
export declare function _logger_getPrefix(level: LogLevel): typeof _logger_logPrefixes[number];
|
|
118
|
+
/**
|
|
119
|
+
* Default prefix composer that generates timestamps and level indicators.
|
|
120
|
+
*
|
|
121
|
+
* Format: ` YYYY-MM-DD_HH:mm:ss.SSS -X- Tag: `
|
|
122
|
+
*
|
|
123
|
+
* **Note**: Mutates the shared `_logger_finalDate` object for performance.
|
|
124
|
+
* Uses timezone offset to adjust timestamps.
|
|
125
|
+
*/
|
|
126
|
+
export declare const DefaultLogPrefixComposer: LogPrefixComposer;
|
package/LogClient.js
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @nu-art/logger - Flexible logging infrastructure with multiple output targets
|
|
3
|
+
* Copyright (C) 2024 Adam van der Kruk aka TacB0sS
|
|
4
|
+
* Licensed under the Apache License, Version 2.0
|
|
5
|
+
*/
|
|
6
|
+
import { LogLevel } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Abstract base class for all log client implementations.
|
|
9
|
+
*
|
|
10
|
+
* LogClient defines the interface for outputting log messages. Each implementation
|
|
11
|
+
* handles the actual output mechanism (console, file, browser, etc.). The base class
|
|
12
|
+
* provides:
|
|
13
|
+
* - Prefix composition (timestamp, level, tag formatting)
|
|
14
|
+
* - Filtering (optional per-client filtering)
|
|
15
|
+
* - Lifecycle management (init/stop)
|
|
16
|
+
*
|
|
17
|
+
* Concrete implementations must override `logMessage()` to perform the actual output.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* class CustomLogClient extends LogClient {
|
|
22
|
+
* protected logMessage(level: LogLevel, bold: boolean, prefix: string, ...toLog: LogParam[]) {
|
|
23
|
+
* // Custom output logic
|
|
24
|
+
* console.log(prefix, ...toLog);
|
|
25
|
+
* }
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export class LogClient {
|
|
30
|
+
/** Function that composes the log prefix (timestamp, level, tag) */
|
|
31
|
+
prefixComposer = DefaultLogPrefixComposer;
|
|
32
|
+
/** Optional filter function to suppress certain log messages */
|
|
33
|
+
filter = () => true;
|
|
34
|
+
/**
|
|
35
|
+
* Sets a custom prefix composer for this log client.
|
|
36
|
+
*
|
|
37
|
+
* The composer function generates the prefix string that appears before each log message.
|
|
38
|
+
*
|
|
39
|
+
* @param logComposer - Function that generates the prefix from tag and level
|
|
40
|
+
*/
|
|
41
|
+
setComposer(logComposer) {
|
|
42
|
+
this.prefixComposer = logComposer;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Lifecycle hook called when the log client is added to BeLogged.
|
|
46
|
+
*
|
|
47
|
+
* Override to perform initialization (e.g., open files, set up connections).
|
|
48
|
+
*/
|
|
49
|
+
init() {
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Lifecycle hook called when the log client is removed from BeLogged.
|
|
53
|
+
*
|
|
54
|
+
* Override to perform cleanup (e.g., close files, clean up resources).
|
|
55
|
+
*/
|
|
56
|
+
stop() {
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Sets a filter function for this log client.
|
|
60
|
+
*
|
|
61
|
+
* The filter is applied before `logMessage()` is called. If the filter returns
|
|
62
|
+
* false, the message is not output by this client.
|
|
63
|
+
*
|
|
64
|
+
* @param filter - Function that returns true to log, false to suppress
|
|
65
|
+
* @returns This instance for method chaining
|
|
66
|
+
*/
|
|
67
|
+
setFilter(filter) {
|
|
68
|
+
this.filter = filter;
|
|
69
|
+
return this;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Logs a message through this client.
|
|
73
|
+
*
|
|
74
|
+
* Applies the filter, composes the prefix, and calls `logMessage()` if the
|
|
75
|
+
* message passes the filter.
|
|
76
|
+
*
|
|
77
|
+
* @param tag - Logger tag/identifier
|
|
78
|
+
* @param level - Log level
|
|
79
|
+
* @param bold - Whether to apply bold formatting
|
|
80
|
+
* @param toLog - Array of values to log
|
|
81
|
+
*/
|
|
82
|
+
log(tag, level, bold, toLog) {
|
|
83
|
+
if (!this.filter(level, tag))
|
|
84
|
+
return;
|
|
85
|
+
this.logMessage(level, bold, this.prefixComposer(tag, level), toLog);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Timezone offset in milliseconds, calculated once at module load.
|
|
90
|
+
*
|
|
91
|
+
* Used to adjust timestamps to local timezone in log prefixes.
|
|
92
|
+
*/
|
|
93
|
+
export const _logger_timezoneOffset = new Date().getTimezoneOffset() * 60000; //offset in milliseconds
|
|
94
|
+
/**
|
|
95
|
+
* Reusable Date object for timestamp formatting (mutated, not recreated for performance).
|
|
96
|
+
*
|
|
97
|
+
* **Performance Note**: This Date object is mutated on every log call to avoid creating
|
|
98
|
+
* new Date instances. This is safe in Node.js's single-threaded execution model but
|
|
99
|
+
* would not be thread-safe in a multi-threaded environment.
|
|
100
|
+
*/
|
|
101
|
+
export const _logger_finalDate = new Date();
|
|
102
|
+
/**
|
|
103
|
+
* Array of log level prefix indicators.
|
|
104
|
+
*
|
|
105
|
+
* Maps log levels to their string representations: '---' (unknown), '-V-' (Verbose),
|
|
106
|
+
* '-D-' (Debug), '-I-' (Info), '-W-' (Warning), '-E-' (Error).
|
|
107
|
+
*/
|
|
108
|
+
export const _logger_logPrefixes = ['---', '-V-', '-D-', '-I-', '-W-', '-E-'];
|
|
109
|
+
/**
|
|
110
|
+
* Gets the prefix indicator for a log level.
|
|
111
|
+
*
|
|
112
|
+
* @param level - Log level
|
|
113
|
+
* @returns Prefix string ('-V-' for Verbose, '-D-' for Debug, etc.)
|
|
114
|
+
*/
|
|
115
|
+
export function _logger_getPrefix(level) {
|
|
116
|
+
switch (level) {
|
|
117
|
+
case LogLevel.Verbose:
|
|
118
|
+
return '-V-';
|
|
119
|
+
case LogLevel.Debug:
|
|
120
|
+
return '-D-';
|
|
121
|
+
case LogLevel.Info:
|
|
122
|
+
return '-I-';
|
|
123
|
+
case LogLevel.Warning:
|
|
124
|
+
return '-W-';
|
|
125
|
+
case LogLevel.Error:
|
|
126
|
+
return '-E-';
|
|
127
|
+
default:
|
|
128
|
+
return '---';
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Default prefix composer that generates timestamps and level indicators.
|
|
133
|
+
*
|
|
134
|
+
* Format: ` YYYY-MM-DD_HH:mm:ss.SSS -X- Tag: `
|
|
135
|
+
*
|
|
136
|
+
* **Note**: Mutates the shared `_logger_finalDate` object for performance.
|
|
137
|
+
* Uses timezone offset to adjust timestamps.
|
|
138
|
+
*/
|
|
139
|
+
export const DefaultLogPrefixComposer = (tag, level) => {
|
|
140
|
+
_logger_finalDate.setTime(Date.now() - _logger_timezoneOffset);
|
|
141
|
+
const date = _logger_finalDate.toISOString().replace(/T/, '_').replace(/Z/, '').substring(0, 23);
|
|
142
|
+
return ` ${date} ${_logger_getPrefix(level)} ${tag}: `;
|
|
143
|
+
};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { LogClient } from './LogClient.js';
|
|
2
|
+
import { LogLevel, LogParam } from './types.js';
|
|
3
|
+
/** Callback function type for log rotation events */
|
|
4
|
+
type LogRotateListener = () => void;
|
|
5
|
+
/**
|
|
6
|
+
* Base class for log clients that support log rotation.
|
|
7
|
+
*
|
|
8
|
+
* Automatically rotates logs when the buffer size exceeds `maxSize`. Rotation works
|
|
9
|
+
* by shifting existing log files/buffers (e.g., log-0.txt → log-1.txt, log-1.txt → log-2.txt)
|
|
10
|
+
* and creating a new current log file/buffer. Oldest logs beyond `maxEntries` are deleted.
|
|
11
|
+
*
|
|
12
|
+
* Subclasses must implement:
|
|
13
|
+
* - `printLogMessage()` - How to output the log
|
|
14
|
+
* - `prepare()` - Initialize the buffer/file
|
|
15
|
+
* - `cleanup()` - Clean up old logs
|
|
16
|
+
* - `rotateBuffer()` - Move log from one index to another
|
|
17
|
+
*/
|
|
18
|
+
export declare abstract class LogClient_BaseRotate extends LogClient {
|
|
19
|
+
/** Name identifier for this log client (used in filenames) */
|
|
20
|
+
readonly name: string;
|
|
21
|
+
/** Maximum number of rotated log files/buffers to keep */
|
|
22
|
+
readonly maxEntries: number;
|
|
23
|
+
/** Maximum size in bytes before rotation is triggered */
|
|
24
|
+
readonly maxSize: number;
|
|
25
|
+
/** Current size of the buffer in bytes */
|
|
26
|
+
protected bufferSize: number;
|
|
27
|
+
/** Optional callback invoked when rotation occurs */
|
|
28
|
+
private rotationListener?;
|
|
29
|
+
/**
|
|
30
|
+
* Creates a new rotating log client.
|
|
31
|
+
*
|
|
32
|
+
* @param name - Identifier for this log client (used in filenames)
|
|
33
|
+
* @param maxEntries - Maximum number of rotated logs to keep (default: 10)
|
|
34
|
+
* @param maxSize - Maximum buffer size in bytes before rotation (default: 1MB)
|
|
35
|
+
*/
|
|
36
|
+
protected constructor(name: string, maxEntries?: number, maxSize?: number);
|
|
37
|
+
/**
|
|
38
|
+
* Processes and outputs a log message, checking for rotation.
|
|
39
|
+
*
|
|
40
|
+
* Checks if rotation is needed before writing. Tracks buffer size and triggers
|
|
41
|
+
* rotation when the threshold is exceeded.
|
|
42
|
+
*
|
|
43
|
+
* @param level - Log level
|
|
44
|
+
* @param bold - Whether to apply bold formatting
|
|
45
|
+
* @param prefix - Composed prefix string
|
|
46
|
+
* @param toLog - Array of values to log
|
|
47
|
+
*/
|
|
48
|
+
protected logMessage(level: LogLevel, bold: boolean, prefix: string, toLog: LogParam[]): void;
|
|
49
|
+
/**
|
|
50
|
+
* Processes log parameters into a formatted string.
|
|
51
|
+
*
|
|
52
|
+
* Can be overridden by subclasses to customize formatting.
|
|
53
|
+
*
|
|
54
|
+
* @param level - Log level
|
|
55
|
+
* @param bold - Whether to apply bold formatting
|
|
56
|
+
* @param prefix - Composed prefix string
|
|
57
|
+
* @param toLog - Array of values to log
|
|
58
|
+
* @returns Formatted log string
|
|
59
|
+
*/
|
|
60
|
+
protected processLogMessage(level: LogLevel, bold: boolean, prefix: string, toLog: LogParam[]): string;
|
|
61
|
+
/**
|
|
62
|
+
* Sets a callback to be invoked when log rotation occurs.
|
|
63
|
+
*
|
|
64
|
+
* @param rotationListener - Function to call on rotation
|
|
65
|
+
* @returns This instance for method chaining
|
|
66
|
+
*/
|
|
67
|
+
setRotationListener(rotationListener: LogRotateListener): this;
|
|
68
|
+
/**
|
|
69
|
+
* Outputs the formatted log message.
|
|
70
|
+
*
|
|
71
|
+
* Must be implemented by subclasses to define the actual output mechanism.
|
|
72
|
+
*
|
|
73
|
+
* @param log - Formatted log string (includes newline)
|
|
74
|
+
*/
|
|
75
|
+
protected abstract printLogMessage(log: string): void;
|
|
76
|
+
/**
|
|
77
|
+
* Checks if rotation is needed and performs it if the buffer size exceeds maxSize.
|
|
78
|
+
*
|
|
79
|
+
* Rotation process:
|
|
80
|
+
* 1. Deletes the oldest log (cleanup)
|
|
81
|
+
* 2. Shifts all logs one position (rotateBuffer)
|
|
82
|
+
* 3. Creates a new current log (prepare)
|
|
83
|
+
* 4. Resets buffer size counter
|
|
84
|
+
* 5. Invokes rotation listener if set
|
|
85
|
+
*/
|
|
86
|
+
private rotate;
|
|
87
|
+
protected abstract cleanup(): void;
|
|
88
|
+
protected abstract prepare(): void;
|
|
89
|
+
protected abstract rotateBuffer(fromIndex: number, toIndex: number): void;
|
|
90
|
+
}
|
|
91
|
+
export {};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @nu-art/logger - Flexible logging infrastructure with multiple output targets
|
|
3
|
+
* Copyright (C) 2024 Adam van der Kruk aka TacB0sS
|
|
4
|
+
* Licensed under the Apache License, Version 2.0
|
|
5
|
+
*/
|
|
6
|
+
import { LogClient } from './LogClient.js';
|
|
7
|
+
import { _logger_convertLogParamsToStrings, _logger_indentNewLineBy } from './utils.js';
|
|
8
|
+
/**
|
|
9
|
+
* Base class for log clients that support log rotation.
|
|
10
|
+
*
|
|
11
|
+
* Automatically rotates logs when the buffer size exceeds `maxSize`. Rotation works
|
|
12
|
+
* by shifting existing log files/buffers (e.g., log-0.txt → log-1.txt, log-1.txt → log-2.txt)
|
|
13
|
+
* and creating a new current log file/buffer. Oldest logs beyond `maxEntries` are deleted.
|
|
14
|
+
*
|
|
15
|
+
* Subclasses must implement:
|
|
16
|
+
* - `printLogMessage()` - How to output the log
|
|
17
|
+
* - `prepare()` - Initialize the buffer/file
|
|
18
|
+
* - `cleanup()` - Clean up old logs
|
|
19
|
+
* - `rotateBuffer()` - Move log from one index to another
|
|
20
|
+
*/
|
|
21
|
+
export class LogClient_BaseRotate extends LogClient {
|
|
22
|
+
/** Name identifier for this log client (used in filenames) */
|
|
23
|
+
name;
|
|
24
|
+
/** Maximum number of rotated log files/buffers to keep */
|
|
25
|
+
maxEntries;
|
|
26
|
+
/** Maximum size in bytes before rotation is triggered */
|
|
27
|
+
maxSize;
|
|
28
|
+
/** Current size of the buffer in bytes */
|
|
29
|
+
bufferSize = 0;
|
|
30
|
+
/** Optional callback invoked when rotation occurs */
|
|
31
|
+
rotationListener;
|
|
32
|
+
/**
|
|
33
|
+
* Creates a new rotating log client.
|
|
34
|
+
*
|
|
35
|
+
* @param name - Identifier for this log client (used in filenames)
|
|
36
|
+
* @param maxEntries - Maximum number of rotated logs to keep (default: 10)
|
|
37
|
+
* @param maxSize - Maximum buffer size in bytes before rotation (default: 1MB)
|
|
38
|
+
*/
|
|
39
|
+
constructor(name, maxEntries = 10, maxSize = 1024 * 1024) {
|
|
40
|
+
super();
|
|
41
|
+
this.name = name;
|
|
42
|
+
this.maxSize = maxSize;
|
|
43
|
+
this.maxEntries = maxEntries;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Processes and outputs a log message, checking for rotation.
|
|
47
|
+
*
|
|
48
|
+
* Checks if rotation is needed before writing. Tracks buffer size and triggers
|
|
49
|
+
* rotation when the threshold is exceeded.
|
|
50
|
+
*
|
|
51
|
+
* @param level - Log level
|
|
52
|
+
* @param bold - Whether to apply bold formatting
|
|
53
|
+
* @param prefix - Composed prefix string
|
|
54
|
+
* @param toLog - Array of values to log
|
|
55
|
+
*/
|
|
56
|
+
logMessage(level, bold, prefix, toLog) {
|
|
57
|
+
const log = this.processLogMessage(level, bold, prefix, toLog);
|
|
58
|
+
this.rotate();
|
|
59
|
+
const finalLog = log + '\n';
|
|
60
|
+
this.printLogMessage(finalLog);
|
|
61
|
+
this.bufferSize += finalLog.length;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Processes log parameters into a formatted string.
|
|
65
|
+
*
|
|
66
|
+
* Can be overridden by subclasses to customize formatting.
|
|
67
|
+
*
|
|
68
|
+
* @param level - Log level
|
|
69
|
+
* @param bold - Whether to apply bold formatting
|
|
70
|
+
* @param prefix - Composed prefix string
|
|
71
|
+
* @param toLog - Array of values to log
|
|
72
|
+
* @returns Formatted log string
|
|
73
|
+
*/
|
|
74
|
+
processLogMessage(level, bold, prefix, toLog) {
|
|
75
|
+
const paramsAsStrings = _logger_convertLogParamsToStrings(toLog);
|
|
76
|
+
return _logger_indentNewLineBy(prefix, paramsAsStrings.join(' '));
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Sets a callback to be invoked when log rotation occurs.
|
|
80
|
+
*
|
|
81
|
+
* @param rotationListener - Function to call on rotation
|
|
82
|
+
* @returns This instance for method chaining
|
|
83
|
+
*/
|
|
84
|
+
setRotationListener(rotationListener) {
|
|
85
|
+
this.rotationListener = rotationListener;
|
|
86
|
+
return this;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Checks if rotation is needed and performs it if the buffer size exceeds maxSize.
|
|
90
|
+
*
|
|
91
|
+
* Rotation process:
|
|
92
|
+
* 1. Deletes the oldest log (cleanup)
|
|
93
|
+
* 2. Shifts all logs one position (rotateBuffer)
|
|
94
|
+
* 3. Creates a new current log (prepare)
|
|
95
|
+
* 4. Resets buffer size counter
|
|
96
|
+
* 5. Invokes rotation listener if set
|
|
97
|
+
*/
|
|
98
|
+
rotate() {
|
|
99
|
+
if (this.bufferSize < this.maxSize)
|
|
100
|
+
return;
|
|
101
|
+
this.cleanup();
|
|
102
|
+
for (let i = this.maxEntries - 1; i > 0; i--) {
|
|
103
|
+
this.rotateBuffer(i - 1, i);
|
|
104
|
+
}
|
|
105
|
+
this.rotationListener?.();
|
|
106
|
+
this.bufferSize = 0;
|
|
107
|
+
this.prepare();
|
|
108
|
+
}
|
|
109
|
+
}
|