@ncoderz/log-m8 1.0.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/LICENSE +18 -0
- package/README.md +296 -0
- package/dist/browser/log-m8.global.js +1 -0
- package/dist/browser/log-m8.global.js.map +1 -0
- package/dist/index.cjs +1412 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1276 -0
- package/dist/index.d.ts +1276 -0
- package/dist/index.js +1384 -0
- package/dist/index.js.map +1 -0
- package/package.json +88 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,1276 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contextual metadata automatically included with all log events from a logger.
|
|
3
|
+
*
|
|
4
|
+
* LogContext provides a way to associate persistent metadata with logger instances
|
|
5
|
+
* that gets automatically included with every log event. This is useful for
|
|
6
|
+
* tracking request IDs, user sessions, service names, or any other contextual
|
|
7
|
+
* information that should be consistent across related log entries.
|
|
8
|
+
*
|
|
9
|
+
* Context is set via logger.setContext() and can contain both predefined
|
|
10
|
+
* properties and arbitrary key-value pairs. Formatters can access context
|
|
11
|
+
* properties using dot-path notation (e.g., {context.requestId}).
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* const logger = Logging.getLogger('api.auth');
|
|
16
|
+
*
|
|
17
|
+
* // Set context that applies to all subsequent log events
|
|
18
|
+
* logger.setContext({
|
|
19
|
+
* requestId: 'req-123',
|
|
20
|
+
* userId: 'user-456',
|
|
21
|
+
* sessionId: 'sess-789',
|
|
22
|
+
* service: 'authentication'
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* // All logs from this logger now include the context
|
|
26
|
+
* logger.info('User authentication started');
|
|
27
|
+
* logger.debug('Validating credentials');
|
|
28
|
+
* logger.info('Authentication successful');
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
interface LogContext {
|
|
32
|
+
/**
|
|
33
|
+
* Arbitrary context properties using string keys.
|
|
34
|
+
* Supports any serializable values for maximum flexibility.
|
|
35
|
+
*/
|
|
36
|
+
[key: string]: unknown;
|
|
37
|
+
/**
|
|
38
|
+
* User identifier for associating log events with specific users.
|
|
39
|
+
* Commonly used for security auditing and user behavior analysis.
|
|
40
|
+
*/
|
|
41
|
+
userId?: string;
|
|
42
|
+
/**
|
|
43
|
+
* Request identifier for tracing the complete lifecycle of a request.
|
|
44
|
+
* Essential for distributed tracing and debugging request flows.
|
|
45
|
+
*/
|
|
46
|
+
requestId?: string;
|
|
47
|
+
/**
|
|
48
|
+
* Correlation identifier for linking related events across service boundaries.
|
|
49
|
+
* Used in microservice architectures to track operations across multiple services.
|
|
50
|
+
*/
|
|
51
|
+
correlationId?: string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Enumeration of supported log severity levels in ascending order of verbosity.
|
|
56
|
+
*
|
|
57
|
+
* The logging system uses this hierarchy to determine which events to emit:
|
|
58
|
+
* - 'off': Disables all logging
|
|
59
|
+
* - 'fatal': Critical system failures requiring immediate intervention
|
|
60
|
+
* - 'error': Failures preventing normal operation
|
|
61
|
+
* - 'warn': Potentially problematic situations
|
|
62
|
+
* - 'info': General informational messages about normal operation
|
|
63
|
+
* - 'debug': Detailed diagnostic information for development
|
|
64
|
+
* - 'track': Analytics and user behavior tracking events
|
|
65
|
+
* - 'trace': Most detailed execution information for fine-grained debugging
|
|
66
|
+
*
|
|
67
|
+
* Events are emitted when their level index is <= logger's level index.
|
|
68
|
+
* The 'track' level is positioned between 'debug' and 'trace' to allow
|
|
69
|
+
* analytics collection without the verbosity of full trace logging.
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```typescript
|
|
73
|
+
* // Logger set to 'info' will emit: fatal, error, warn, info
|
|
74
|
+
* logger.setLevel('info');
|
|
75
|
+
* logger.debug('Not emitted'); // debug > info in hierarchy
|
|
76
|
+
* logger.info('Emitted'); // info <= info in hierarchy
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
declare const LogLevel: {
|
|
80
|
+
readonly off: "off";
|
|
81
|
+
readonly fatal: "fatal";
|
|
82
|
+
readonly error: "error";
|
|
83
|
+
readonly warn: "warn";
|
|
84
|
+
readonly info: "info";
|
|
85
|
+
readonly debug: "debug";
|
|
86
|
+
readonly track: "track";
|
|
87
|
+
readonly trace: "trace";
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Type representing a LogLevel enum value.
|
|
91
|
+
*/
|
|
92
|
+
type LogLevelType = (typeof LogLevel)[keyof typeof LogLevel];
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Interface for a hierarchical logger instance providing level-based logging methods.
|
|
96
|
+
*
|
|
97
|
+
* Logger instances are created via LogM8.getLogger() and provide methods for emitting
|
|
98
|
+
* log events at different severity levels. Each logger maintains its own context and
|
|
99
|
+
* can create child loggers using dot-separated naming conventions.
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```typescript
|
|
103
|
+
* const logger = Logging.getLogger('app.database');
|
|
104
|
+
* logger.setLevel('debug');
|
|
105
|
+
* logger.info('Connection established', { host: 'localhost' });
|
|
106
|
+
*
|
|
107
|
+
* // Create child logger
|
|
108
|
+
* const queryLogger = logger.getLogger('queries');
|
|
109
|
+
* queryLogger.debug('SELECT * FROM users'); // Name becomes 'app.database.queries'
|
|
110
|
+
*
|
|
111
|
+
* // Check if logging is enabled before expensive operations
|
|
112
|
+
* if (logger.isEnabled && logger.isDebug) {
|
|
113
|
+
* logger.debug('Expensive debug data', computeExpensiveDebugInfo());
|
|
114
|
+
* }
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
interface Log {
|
|
118
|
+
/**
|
|
119
|
+
* Logs a message at fatal severity level.
|
|
120
|
+
*
|
|
121
|
+
* Fatal events indicate critical system failures that typically require
|
|
122
|
+
* immediate intervention and may result in application termination.
|
|
123
|
+
*
|
|
124
|
+
* @param message - Primary message or serializable object to log
|
|
125
|
+
* @param data - Additional context data to include with the log event
|
|
126
|
+
*/
|
|
127
|
+
fatal(message: string | unknown, ...data: unknown[]): void;
|
|
128
|
+
/**
|
|
129
|
+
* Logs a message at error severity level.
|
|
130
|
+
*
|
|
131
|
+
* Error events indicate failures that prevent normal operation but
|
|
132
|
+
* don't necessarily require application termination.
|
|
133
|
+
*
|
|
134
|
+
* @param message - Primary message or serializable object to log
|
|
135
|
+
* @param data - Additional context data to include with the log event
|
|
136
|
+
*/
|
|
137
|
+
error(message: string | unknown, ...data: unknown[]): void;
|
|
138
|
+
/**
|
|
139
|
+
* Logs a message at warning severity level.
|
|
140
|
+
*
|
|
141
|
+
* Warning events indicate potentially problematic situations that
|
|
142
|
+
* don't prevent operation but may require attention.
|
|
143
|
+
*
|
|
144
|
+
* @param message - Primary message or serializable object to log
|
|
145
|
+
* @param data - Additional context data to include with the log event
|
|
146
|
+
*/
|
|
147
|
+
warn(message: string | unknown, ...data: unknown[]): void;
|
|
148
|
+
/**
|
|
149
|
+
* Logs a message at info severity level.
|
|
150
|
+
*
|
|
151
|
+
* Info events provide general informational messages about normal
|
|
152
|
+
* application operation and significant business events.
|
|
153
|
+
*
|
|
154
|
+
* @param message - Primary message or serializable object to log
|
|
155
|
+
* @param data - Additional context data to include with the log event
|
|
156
|
+
*/
|
|
157
|
+
info(message: string | unknown, ...data: unknown[]): void;
|
|
158
|
+
/**
|
|
159
|
+
* Logs a message at debug severity level.
|
|
160
|
+
*
|
|
161
|
+
* Debug events provide detailed diagnostic information useful during
|
|
162
|
+
* development and troubleshooting.
|
|
163
|
+
*
|
|
164
|
+
* @param message - Primary message or serializable object to log
|
|
165
|
+
* @param data - Additional context data to include with the log event
|
|
166
|
+
*/
|
|
167
|
+
debug(message: string | unknown, ...data: unknown[]): void;
|
|
168
|
+
/**
|
|
169
|
+
* Logs a message at track severity level.
|
|
170
|
+
*
|
|
171
|
+
* Track events are specifically designed for analytics and user behavior
|
|
172
|
+
* tracking, separate from operational logging concerns.
|
|
173
|
+
*
|
|
174
|
+
* @param message - Primary message or serializable object to log
|
|
175
|
+
* @param data - Additional context data to include with the log event
|
|
176
|
+
*/
|
|
177
|
+
track(message: string | unknown, ...data: unknown[]): void;
|
|
178
|
+
/**
|
|
179
|
+
* Logs a message at trace severity level.
|
|
180
|
+
*
|
|
181
|
+
* Trace events provide the most detailed execution information,
|
|
182
|
+
* typically used for fine-grained debugging and performance analysis.
|
|
183
|
+
*
|
|
184
|
+
* @param message - Primary message or serializable object to log
|
|
185
|
+
* @param data - Additional context data to include with the log event
|
|
186
|
+
*/
|
|
187
|
+
trace(message: string | unknown, ...data: unknown[]): void;
|
|
188
|
+
/**
|
|
189
|
+
* True when logger's current level enables fatal severity logging.
|
|
190
|
+
* When true, fatal() calls will emit log events.
|
|
191
|
+
*/
|
|
192
|
+
readonly isFatal: boolean;
|
|
193
|
+
/**
|
|
194
|
+
* True when logger's current level enables error severity logging.
|
|
195
|
+
* When true, error() calls will emit log events.
|
|
196
|
+
*/
|
|
197
|
+
readonly isError: boolean;
|
|
198
|
+
/**
|
|
199
|
+
* True when logger's current level enables warn severity logging.
|
|
200
|
+
* When true, warn() calls will emit log events.
|
|
201
|
+
*/
|
|
202
|
+
readonly isWarn: boolean;
|
|
203
|
+
/**
|
|
204
|
+
* True when logger's current level enables info severity logging.
|
|
205
|
+
* When true, info() calls will emit log events.
|
|
206
|
+
*/
|
|
207
|
+
readonly isInfo: boolean;
|
|
208
|
+
/**
|
|
209
|
+
* True when logger's current level enables debug severity logging.
|
|
210
|
+
* When true, debug() calls will emit log events.
|
|
211
|
+
*/
|
|
212
|
+
readonly isDebug: boolean;
|
|
213
|
+
/**
|
|
214
|
+
* True when logger's current level enables track severity logging.
|
|
215
|
+
* When true, track() calls will emit log events.
|
|
216
|
+
*/
|
|
217
|
+
readonly isTrack: boolean;
|
|
218
|
+
/**
|
|
219
|
+
* True when logger's current level enables trace severity logging.
|
|
220
|
+
* When true, trace() calls will emit log events.
|
|
221
|
+
*/
|
|
222
|
+
readonly isTrace: boolean;
|
|
223
|
+
/**
|
|
224
|
+
* True when logging is enabled for this logger.
|
|
225
|
+
* False only when the logger level is set to 'off', disabling all log output.
|
|
226
|
+
*/
|
|
227
|
+
readonly isEnabled: boolean;
|
|
228
|
+
/** The dot-separated hierarchical name of this logger instance. */
|
|
229
|
+
readonly name: string;
|
|
230
|
+
/** The current logging level determining which events are emitted. */
|
|
231
|
+
readonly level: LogLevelType;
|
|
232
|
+
/** Contextual data automatically included with all log events from this logger. */
|
|
233
|
+
readonly context: LogContext;
|
|
234
|
+
/**
|
|
235
|
+
* Updates the logger's severity level threshold.
|
|
236
|
+
*
|
|
237
|
+
* Events at or below this level will be emitted based on the level hierarchy:
|
|
238
|
+
* off < fatal < error < warn < info < debug < track < trace
|
|
239
|
+
*
|
|
240
|
+
* @param level - New logging level name (e.g., 'info', 'debug', 'off')
|
|
241
|
+
*/
|
|
242
|
+
setLevel(level: LogLevelType): void;
|
|
243
|
+
/**
|
|
244
|
+
* Replaces the logger's contextual data.
|
|
245
|
+
*
|
|
246
|
+
* Context is automatically included with all log events emitted by this logger,
|
|
247
|
+
* providing consistent metadata across related log entries.
|
|
248
|
+
*
|
|
249
|
+
* @param context - New context object to associate with this logger
|
|
250
|
+
*/
|
|
251
|
+
setContext(context: LogContext): void;
|
|
252
|
+
/**
|
|
253
|
+
* Creates or retrieves a child logger with hierarchical naming.
|
|
254
|
+
*
|
|
255
|
+
* Child loggers inherit configuration but can have independent levels and context.
|
|
256
|
+
* The child's name becomes 'parent.child' using dot notation.
|
|
257
|
+
*
|
|
258
|
+
* @param name - Name segment for the child logger
|
|
259
|
+
* @returns Child logger instance with name 'parent.child'
|
|
260
|
+
*
|
|
261
|
+
* @example
|
|
262
|
+
* ```typescript
|
|
263
|
+
* const parent = Logging.getLogger('app');
|
|
264
|
+
* const child = parent.getLogger('database'); // Name: 'app.database'
|
|
265
|
+
* const grandchild = child.getLogger('queries'); // Name: 'app.database.queries'
|
|
266
|
+
* ```
|
|
267
|
+
*/
|
|
268
|
+
getLogger(name: string): Log;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Configuration options for initializing a plugin.
|
|
273
|
+
*/
|
|
274
|
+
interface PluginConfig {
|
|
275
|
+
/**
|
|
276
|
+
* The plugin's unique name.
|
|
277
|
+
*/
|
|
278
|
+
name: string;
|
|
279
|
+
/**
|
|
280
|
+
* Additional plugin-specific settings.
|
|
281
|
+
*/
|
|
282
|
+
[key: string]: unknown;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Defines configuration options for a filter plugin.
|
|
287
|
+
* @extends PluginConfig
|
|
288
|
+
*/
|
|
289
|
+
interface FilterConfig extends PluginConfig {
|
|
290
|
+
/**
|
|
291
|
+
* Whether the filter is enabled.
|
|
292
|
+
*/
|
|
293
|
+
enabled?: boolean;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Defines configuration options for a formatter plugin.
|
|
298
|
+
* @extends PluginConfig
|
|
299
|
+
*/
|
|
300
|
+
interface FormatterConfig extends PluginConfig {
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Defines the configuration options for a log appender plugin.
|
|
305
|
+
*/
|
|
306
|
+
interface AppenderConfig extends PluginConfig {
|
|
307
|
+
/**
|
|
308
|
+
* Whether the appender is enabled.
|
|
309
|
+
*/
|
|
310
|
+
enabled?: boolean;
|
|
311
|
+
/**
|
|
312
|
+
* Priority determining execution order; higher values run first (descending order).
|
|
313
|
+
*/
|
|
314
|
+
priority?: number;
|
|
315
|
+
/**
|
|
316
|
+
* The formatter to apply to log events, specified by name or config object.
|
|
317
|
+
*/
|
|
318
|
+
formatter?: string | FormatterConfig;
|
|
319
|
+
/**
|
|
320
|
+
* Filters to apply to log events, specified by name or config objects.
|
|
321
|
+
*/
|
|
322
|
+
filters?: (string | FilterConfig)[];
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Primary configuration object for initializing the LogM8 logging system.
|
|
327
|
+
*
|
|
328
|
+
* Defines the overall logging behavior including default levels, per-logger
|
|
329
|
+
* overrides, and output destinations. Used as the parameter to LogM8.init()
|
|
330
|
+
* to configure the entire logging pipeline.
|
|
331
|
+
*
|
|
332
|
+
* If no configuration is provided, the system defaults to console output
|
|
333
|
+
* at 'info' level with the default formatter.
|
|
334
|
+
*
|
|
335
|
+
* @example
|
|
336
|
+
* ```typescript
|
|
337
|
+
* const config: LoggingConfig = {
|
|
338
|
+
* level: 'info',
|
|
339
|
+
* loggers: {
|
|
340
|
+
* 'app.database': 'debug', // More verbose for database operations
|
|
341
|
+
* 'app.security': 'warn', // Less verbose for security components
|
|
342
|
+
* 'app.performance': 'trace' // Maximum detail for performance monitoring
|
|
343
|
+
* },
|
|
344
|
+
* appenders: [
|
|
345
|
+
* {
|
|
346
|
+
* name: 'console',
|
|
347
|
+
* formatter: { name: 'default-formatter', color: true }
|
|
348
|
+
* },
|
|
349
|
+
* {
|
|
350
|
+
* name: 'file',
|
|
351
|
+
* filename: 'app.log',
|
|
352
|
+
* formatter: { name: 'json-formatter', pretty: true }
|
|
353
|
+
* }
|
|
354
|
+
* ]
|
|
355
|
+
* };
|
|
356
|
+
*
|
|
357
|
+
* Logging.init(config);
|
|
358
|
+
* ```
|
|
359
|
+
*/
|
|
360
|
+
interface LoggingConfig {
|
|
361
|
+
/**
|
|
362
|
+
* Default log level applied to all loggers unless overridden.
|
|
363
|
+
*
|
|
364
|
+
* Determines the minimum severity level that will be processed.
|
|
365
|
+
* Loggers will emit events at this level and all higher severity levels.
|
|
366
|
+
* Defaults to 'info' if not specified.
|
|
367
|
+
*/
|
|
368
|
+
level?: LogLevelType;
|
|
369
|
+
/**
|
|
370
|
+
* Per-logger level overrides by hierarchical name.
|
|
371
|
+
*
|
|
372
|
+
* Allows fine-grained control over logging verbosity for different
|
|
373
|
+
* parts of the application. Logger names use dot-separated hierarchical
|
|
374
|
+
* notation where child loggers inherit from parent configurations.
|
|
375
|
+
*
|
|
376
|
+
* @example
|
|
377
|
+
* ```typescript
|
|
378
|
+
* loggers: {
|
|
379
|
+
* 'app': 'info', // Base level for 'app' namespace
|
|
380
|
+
* 'app.database': 'debug', // More verbose for database operations
|
|
381
|
+
* 'app.database.queries': 'trace' // Maximum detail for query logging
|
|
382
|
+
* }
|
|
383
|
+
* ```
|
|
384
|
+
*/
|
|
385
|
+
loggers?: {
|
|
386
|
+
[key: string]: LogLevelType | undefined;
|
|
387
|
+
};
|
|
388
|
+
/**
|
|
389
|
+
* Output destination configurations.
|
|
390
|
+
*
|
|
391
|
+
* Defines where and how log events are written. Each appender can have
|
|
392
|
+
* its own formatter, filters, and specific configuration options.
|
|
393
|
+
* If not specified, defaults to a single console appender.
|
|
394
|
+
*
|
|
395
|
+
* Appenders are executed in priority order (highest first) for
|
|
396
|
+
* deterministic output behavior.
|
|
397
|
+
*/
|
|
398
|
+
appenders?: AppenderConfig[];
|
|
399
|
+
/**
|
|
400
|
+
* Global filters applied before any appender-specific processing.
|
|
401
|
+
*
|
|
402
|
+
* Each entry may be a string (filter factory name) or a full FilterConfig
|
|
403
|
+
* object. Global filters run first and can drop events entirely before they
|
|
404
|
+
* reach appenders. Appenders may also define their own filters via
|
|
405
|
+
* AppenderConfig.filters.
|
|
406
|
+
*/
|
|
407
|
+
filters?: (string | FilterConfig)[];
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Enumeration of plugin types supported by the LogM8 plugin system.
|
|
412
|
+
*
|
|
413
|
+
* The logging system uses a plugin architecture where functionality is
|
|
414
|
+
* provided by three categories of plugins:
|
|
415
|
+
*
|
|
416
|
+
* - **appender**: Output destinations that write formatted log events
|
|
417
|
+
* - **filter**: Event processors that determine which events to log
|
|
418
|
+
* - **formatter**: Event transformers that convert LogEvent objects to output format
|
|
419
|
+
*
|
|
420
|
+
* Each plugin factory must declare its kind to enable proper registration
|
|
421
|
+
* and instantiation during system initialization.
|
|
422
|
+
*
|
|
423
|
+
* @example
|
|
424
|
+
* ```typescript
|
|
425
|
+
* class CustomAppender implements Appender {
|
|
426
|
+
* kind = PluginKind.appender;
|
|
427
|
+
* // ... implementation
|
|
428
|
+
* }
|
|
429
|
+
*
|
|
430
|
+
* class CustomFilter implements Filter {
|
|
431
|
+
* kind = PluginKind.filter;
|
|
432
|
+
* // ... implementation
|
|
433
|
+
* }
|
|
434
|
+
* ```
|
|
435
|
+
*/
|
|
436
|
+
declare const PluginKind: {
|
|
437
|
+
readonly appender: "appender";
|
|
438
|
+
readonly filter: "filter";
|
|
439
|
+
readonly formatter: "formatter";
|
|
440
|
+
};
|
|
441
|
+
/**
|
|
442
|
+
* Type representing a PluginKind enum value.
|
|
443
|
+
*/
|
|
444
|
+
type PluginKindType = (typeof PluginKind)[keyof typeof PluginKind];
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Represents a plugin with identifying metadata and lifecycle methods.
|
|
448
|
+
*/
|
|
449
|
+
interface Plugin {
|
|
450
|
+
/** The unique plugin name. */
|
|
451
|
+
readonly name: string;
|
|
452
|
+
/** The plugin version in semver format. */
|
|
453
|
+
readonly version: string;
|
|
454
|
+
/** The kind of plugin, categorizing its behavior. */
|
|
455
|
+
readonly kind: PluginKindType;
|
|
456
|
+
/**
|
|
457
|
+
* Initializes the plugin with the given configuration.
|
|
458
|
+
* @param config - Plugin configuration options.
|
|
459
|
+
*/
|
|
460
|
+
init(config: PluginConfig): void;
|
|
461
|
+
/**
|
|
462
|
+
* Disposes the plugin, releasing any used resources.
|
|
463
|
+
*/
|
|
464
|
+
dispose(): void;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* Factory for creating plugin instances of a specific kind.
|
|
469
|
+
* @template C - Plugin configuration type.
|
|
470
|
+
* @template P - Plugin instance type.
|
|
471
|
+
*/
|
|
472
|
+
interface PluginFactory<C extends PluginConfig = PluginConfig, P extends Plugin = Plugin> {
|
|
473
|
+
/** The unique factory name. */
|
|
474
|
+
readonly name: string;
|
|
475
|
+
/** The factory version corresponding to plugin implementations. */
|
|
476
|
+
readonly version: string;
|
|
477
|
+
/** The kind of plugin this factory creates. */
|
|
478
|
+
readonly kind: PluginKindType;
|
|
479
|
+
/**
|
|
480
|
+
* Creates a plugin instance using the provided configuration.
|
|
481
|
+
* @param config - Configuration for the plugin.
|
|
482
|
+
* @returns A new plugin instance.
|
|
483
|
+
*/
|
|
484
|
+
create(config: C): P;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* Central logging manager providing hierarchical loggers and configurable output.
|
|
489
|
+
*
|
|
490
|
+
* LogM8 manages the complete logging lifecycle including:
|
|
491
|
+
* - Logger creation and configuration with hierarchical naming
|
|
492
|
+
* - Plugin-based appender, formatter, and filter system
|
|
493
|
+
* - Pre-initialization event buffering (up to 100 events)
|
|
494
|
+
* - Runtime appender and filter control (enable/disable/flush)
|
|
495
|
+
* - Built-in console and file appenders with customizable formatting
|
|
496
|
+
*
|
|
497
|
+
* The manager operates as a singleton export but can also be instantiated directly.
|
|
498
|
+
* Events logged before init() are buffered and flushed on first post-init log.
|
|
499
|
+
*
|
|
500
|
+
* @example
|
|
501
|
+
* ```typescript
|
|
502
|
+
* import { Logging } from 'log-m8';
|
|
503
|
+
*
|
|
504
|
+
* // Configure logging system
|
|
505
|
+
* Logging.init({
|
|
506
|
+
* level: 'info',
|
|
507
|
+
* loggers: { 'app.database': 'debug' },
|
|
508
|
+
* appenders: [
|
|
509
|
+
* { name: 'console', formatter: 'default-formatter' },
|
|
510
|
+
* { name: 'file', filename: 'app.log' }
|
|
511
|
+
* ]
|
|
512
|
+
* });
|
|
513
|
+
*
|
|
514
|
+
* // Use hierarchical loggers
|
|
515
|
+
* const logger = Logging.getLogger('app.service');
|
|
516
|
+
* logger.info('Service started');
|
|
517
|
+
*
|
|
518
|
+
* // Runtime control
|
|
519
|
+
* Logging.disableAppender('console');
|
|
520
|
+
* Logging.disableFilter('sensitive-data');
|
|
521
|
+
* Logging.flushAppenders();
|
|
522
|
+
* ```
|
|
523
|
+
*/
|
|
524
|
+
declare class LogM8 {
|
|
525
|
+
private _initialized;
|
|
526
|
+
private _pluginManager;
|
|
527
|
+
private _loggers;
|
|
528
|
+
private _appenders;
|
|
529
|
+
private _filters;
|
|
530
|
+
private _defaultLevel;
|
|
531
|
+
private _logLevelValues;
|
|
532
|
+
private _logLevelSet;
|
|
533
|
+
private _logBuffer;
|
|
534
|
+
constructor();
|
|
535
|
+
/**
|
|
536
|
+
* Initializes the logging system with configuration and flushes any buffered events.
|
|
537
|
+
*
|
|
538
|
+
* Sets up default and per-logger levels, creates configured appenders with their
|
|
539
|
+
* formatters and filters, and processes any events buffered before initialization.
|
|
540
|
+
* Appenders are sorted by priority (descending) for deterministic execution order.
|
|
541
|
+
*
|
|
542
|
+
* @param config - Logging configuration object
|
|
543
|
+
* @param config.level - Default log level for all loggers ('info' if not specified)
|
|
544
|
+
* @param config.loggers - Per-logger level overrides by name
|
|
545
|
+
* @param config.appenders - Appender configurations (defaults to console if not specified)
|
|
546
|
+
*
|
|
547
|
+
* @throws {Error} When referenced plugin factories are not registered
|
|
548
|
+
*
|
|
549
|
+
* @example
|
|
550
|
+
* ```typescript
|
|
551
|
+
* Logging.init({
|
|
552
|
+
* level: 'warn',
|
|
553
|
+
* loggers: { 'app.database': 'debug' },
|
|
554
|
+
* appenders: [{
|
|
555
|
+
* name: 'console',
|
|
556
|
+
* formatter: 'default-formatter',
|
|
557
|
+
* filters: ['sensitive-data']
|
|
558
|
+
* }]
|
|
559
|
+
* });
|
|
560
|
+
* ```
|
|
561
|
+
*/
|
|
562
|
+
init(config?: LoggingConfig): void;
|
|
563
|
+
/**
|
|
564
|
+
* Shuts down the logging system and releases all resources.
|
|
565
|
+
*
|
|
566
|
+
* Flushes all appenders, disposes plugin instances, clears logger registry,
|
|
567
|
+
* discards buffered events, and deregisters plugin factories. The system
|
|
568
|
+
* can be reinitialized after disposal.
|
|
569
|
+
*
|
|
570
|
+
* @example
|
|
571
|
+
* ```typescript
|
|
572
|
+
* // Graceful shutdown
|
|
573
|
+
* await new Promise(resolve => {
|
|
574
|
+
* Logging.flushAppenders();
|
|
575
|
+
* setTimeout(() => {
|
|
576
|
+
* Logging.dispose();
|
|
577
|
+
* resolve();
|
|
578
|
+
* }, 100);
|
|
579
|
+
* });
|
|
580
|
+
* ```
|
|
581
|
+
*/
|
|
582
|
+
dispose(): void;
|
|
583
|
+
/**
|
|
584
|
+
* Retrieves or creates a logger instance with hierarchical naming.
|
|
585
|
+
*
|
|
586
|
+
* Logger instances are cached and reused for the same name. Names can be
|
|
587
|
+
* provided as strings with dot-separation or as array segments that get
|
|
588
|
+
* joined. Each logger maintains independent level and context settings.
|
|
589
|
+
*
|
|
590
|
+
* @param name - Logger name as string ('app.service') or segments (['app', 'service'])
|
|
591
|
+
* @returns Logger instance for the specified name
|
|
592
|
+
*
|
|
593
|
+
* @example
|
|
594
|
+
* ```typescript
|
|
595
|
+
* const logger1 = Logging.getLogger('app.database');
|
|
596
|
+
* const logger2 = Logging.getLogger(['app', 'database']);
|
|
597
|
+
* // logger1 === logger2 (same instance)
|
|
598
|
+
*
|
|
599
|
+
* logger1.setLevel('debug');
|
|
600
|
+
* logger1.setContext({ service: 'postgres' });
|
|
601
|
+
* ```
|
|
602
|
+
*/
|
|
603
|
+
getLogger(name: string | string[]): Log;
|
|
604
|
+
/**
|
|
605
|
+
* Enables an appender to resume processing log events.
|
|
606
|
+
*
|
|
607
|
+
* @param name - Name of the appender to enable
|
|
608
|
+
*/
|
|
609
|
+
enableAppender(name: string): void;
|
|
610
|
+
/**
|
|
611
|
+
* Disables an appender to stop processing log events.
|
|
612
|
+
*
|
|
613
|
+
* @param name - Name of the appender to disable
|
|
614
|
+
*/
|
|
615
|
+
disableAppender(name: string): void;
|
|
616
|
+
/**
|
|
617
|
+
* Forces an appender to flush any buffered output.
|
|
618
|
+
*
|
|
619
|
+
* Catches and logs flush errors to console without interrupting operation.
|
|
620
|
+
* Useful for ensuring data persistence before shutdown or at intervals.
|
|
621
|
+
*
|
|
622
|
+
* @param name - Name of the appender to flush
|
|
623
|
+
*/
|
|
624
|
+
flushAppender(name: string): void;
|
|
625
|
+
/**
|
|
626
|
+
* Flushes all configured appenders.
|
|
627
|
+
*
|
|
628
|
+
* Iterates through all appenders calling flush on each, with individual
|
|
629
|
+
* error handling per appender.
|
|
630
|
+
*/
|
|
631
|
+
flushAppenders(): void;
|
|
632
|
+
/**
|
|
633
|
+
* Enables a filter to resume processing log events.
|
|
634
|
+
*
|
|
635
|
+
* When an appender name is provided, enables the filter only for that specific
|
|
636
|
+
* appender. When no appender is specified, enables the filter globally.
|
|
637
|
+
* Silently ignores requests for non-existent filters or appenders.
|
|
638
|
+
*
|
|
639
|
+
* @param name - Name of the filter to enable
|
|
640
|
+
* @param appenderName - Optional appender name to enable filter for specific appender only
|
|
641
|
+
*
|
|
642
|
+
* @example
|
|
643
|
+
* ```typescript
|
|
644
|
+
* // Enable filter globally
|
|
645
|
+
* Logging.enableFilter('sensitive-data');
|
|
646
|
+
*
|
|
647
|
+
* // Enable filter only for console appender
|
|
648
|
+
* Logging.enableFilter('debug-filter', 'console');
|
|
649
|
+
* ```
|
|
650
|
+
*/
|
|
651
|
+
enableFilter(name: string, appenderName?: string): void;
|
|
652
|
+
/**
|
|
653
|
+
* Disables a filter to stop processing log events.
|
|
654
|
+
*
|
|
655
|
+
* When an appender name is provided, disables the filter only for that specific
|
|
656
|
+
* appender. When no appender is specified, disables the filter globally.
|
|
657
|
+
* Silently ignores requests for non-existent filters or appenders.
|
|
658
|
+
*
|
|
659
|
+
* @param name - Name of the filter to disable
|
|
660
|
+
* @param appenderName - Optional appender name to disable filter for specific appender only
|
|
661
|
+
*
|
|
662
|
+
* @example
|
|
663
|
+
* ```typescript
|
|
664
|
+
* // Disable filter globally
|
|
665
|
+
* Logging.disableFilter('sensitive-data');
|
|
666
|
+
*
|
|
667
|
+
* // Disable filter only for file appender
|
|
668
|
+
* Logging.disableFilter('debug-filter', 'file');
|
|
669
|
+
* ```
|
|
670
|
+
*/
|
|
671
|
+
disableFilter(name: string, appenderName?: string): void;
|
|
672
|
+
/**
|
|
673
|
+
* Registers a custom plugin factory for appenders, formatters, or filters.
|
|
674
|
+
*
|
|
675
|
+
* Allows extending the logging system with custom implementations.
|
|
676
|
+
* Must be called before init() to be available during configuration.
|
|
677
|
+
*
|
|
678
|
+
* @param pluginFactory - Factory instance implementing the PluginFactory interface
|
|
679
|
+
*
|
|
680
|
+
* @example
|
|
681
|
+
* ```typescript
|
|
682
|
+
* class SlackAppenderFactory implements PluginFactory {
|
|
683
|
+
* name = 'slack';
|
|
684
|
+
* kind = PluginKind.appender;
|
|
685
|
+
* create(config) { return new SlackAppender(config); }
|
|
686
|
+
* }
|
|
687
|
+
*
|
|
688
|
+
* Logging.registerPluginFactory(new SlackAppenderFactory());
|
|
689
|
+
* ```
|
|
690
|
+
*/
|
|
691
|
+
registerPluginFactory(pluginFactory: PluginFactory): void;
|
|
692
|
+
private _log;
|
|
693
|
+
private _setLevel;
|
|
694
|
+
private _setContext;
|
|
695
|
+
private _processLogEvent;
|
|
696
|
+
private _getAppender;
|
|
697
|
+
private _sortAppenders;
|
|
698
|
+
private _getFilter;
|
|
699
|
+
private _reset;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
/**
|
|
703
|
+
* Structured representation of a single log entry containing all event data.
|
|
704
|
+
*
|
|
705
|
+
* LogEvent objects are created automatically when logger methods are called
|
|
706
|
+
* and contain the complete context needed for formatting and output by appenders.
|
|
707
|
+
* They are immutable once created and flow through the logging pipeline.
|
|
708
|
+
*
|
|
709
|
+
* @example
|
|
710
|
+
* ```typescript
|
|
711
|
+
* // Created automatically when calling:
|
|
712
|
+
* logger.info('User login', { userId: 123, ip: '192.168.1.1' });
|
|
713
|
+
*
|
|
714
|
+
* // Results in LogEvent:
|
|
715
|
+
* {
|
|
716
|
+
* logger: 'app.auth',
|
|
717
|
+
* level: 'info',
|
|
718
|
+
* message: 'User login',
|
|
719
|
+
* data: [{ userId: 123, ip: '192.168.1.1' }],
|
|
720
|
+
* context: { sessionId: 'sess-456' },
|
|
721
|
+
* timestamp: new Date('2025-08-04T14:23:45.123Z')
|
|
722
|
+
* }
|
|
723
|
+
* ```
|
|
724
|
+
*/
|
|
725
|
+
interface LogEvent {
|
|
726
|
+
/**
|
|
727
|
+
* Hierarchical name of the logger that generated this event.
|
|
728
|
+
* Used for filtering and routing by appenders and formatters.
|
|
729
|
+
*/
|
|
730
|
+
readonly logger: string;
|
|
731
|
+
/**
|
|
732
|
+
* Severity level determining event importance and routing.
|
|
733
|
+
* Must match one of the LogLevel enum values.
|
|
734
|
+
*/
|
|
735
|
+
readonly level: LogLevelType;
|
|
736
|
+
/**
|
|
737
|
+
* Primary log content - can be string, object, or any serializable value.
|
|
738
|
+
* Formatters determine how this is rendered in output.
|
|
739
|
+
*/
|
|
740
|
+
readonly message: string | unknown;
|
|
741
|
+
/**
|
|
742
|
+
* Additional arguments passed to the logging method.
|
|
743
|
+
* Typically contains context objects, error details, or supplementary data.
|
|
744
|
+
*/
|
|
745
|
+
readonly data: unknown[];
|
|
746
|
+
/**
|
|
747
|
+
* Logger's contextual metadata at the time of event creation.
|
|
748
|
+
* Automatically included from logger.setContext() calls.
|
|
749
|
+
*/
|
|
750
|
+
readonly context: LogContext;
|
|
751
|
+
/**
|
|
752
|
+
* Event creation timestamp for chronological ordering and time-based formatting.
|
|
753
|
+
* Set automatically when the log method is called.
|
|
754
|
+
*/
|
|
755
|
+
readonly timestamp: Date;
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
/**
|
|
759
|
+
* Represents a log event filter that can be initialized with specific configuration and determines whether a log event should be logged.
|
|
760
|
+
*/
|
|
761
|
+
interface Filter extends Plugin {
|
|
762
|
+
/**
|
|
763
|
+
* Runtime flag controlling whether this filter processes events.
|
|
764
|
+
*
|
|
765
|
+
* Can be toggled via LogM8.enableFilter()/disableFilter() for
|
|
766
|
+
* dynamic output control without full reconfiguration.
|
|
767
|
+
*/
|
|
768
|
+
enabled: boolean;
|
|
769
|
+
/**
|
|
770
|
+
* Initializes the filter with the specified configuration.
|
|
771
|
+
* @param config - Filter configuration options.
|
|
772
|
+
*/
|
|
773
|
+
init(config: FilterConfig): void;
|
|
774
|
+
/**
|
|
775
|
+
* Determines whether the given log event should be logged.
|
|
776
|
+
* @param logEvent - The log event to evaluate.
|
|
777
|
+
* @returns boolean indicating if the event should be logged.
|
|
778
|
+
*/
|
|
779
|
+
filter(logEvent: LogEvent): boolean;
|
|
780
|
+
/**
|
|
781
|
+
* Disposes of the filter, cleaning up any resources.
|
|
782
|
+
*
|
|
783
|
+
* Called during parent's dispose() to clean up the filter's resources.
|
|
784
|
+
*/
|
|
785
|
+
dispose(): void;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
/**
|
|
789
|
+
* Represents a log event formatter that initializes with configuration and converts log events into output tokens.
|
|
790
|
+
*/
|
|
791
|
+
interface Formatter extends Plugin {
|
|
792
|
+
/**
|
|
793
|
+
* Initializes the formatter with the specified configuration.
|
|
794
|
+
* @param config - Formatter configuration options.
|
|
795
|
+
*/
|
|
796
|
+
init(config: FormatterConfig): void;
|
|
797
|
+
/**
|
|
798
|
+
* Formats the given log event into an array of output tokens.
|
|
799
|
+
* @param logEvent - The log event to format.
|
|
800
|
+
* @returns An array of formatted output elements.
|
|
801
|
+
*/
|
|
802
|
+
format(logEvent: LogEvent): unknown[];
|
|
803
|
+
/**
|
|
804
|
+
* Disposes of the formatter, cleaning up any resources.
|
|
805
|
+
*
|
|
806
|
+
* Called during parent's dispose() to clean up the formatter's resources.
|
|
807
|
+
*/
|
|
808
|
+
dispose(): void;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
/**
|
|
812
|
+
* Plugin interface for log event output destinations.
|
|
813
|
+
*
|
|
814
|
+
* Appenders receive formatted log events and write them to specific outputs
|
|
815
|
+
* like console, files, network endpoints, or databases. They can be dynamically
|
|
816
|
+
* enabled/disabled and support priority-based execution ordering.
|
|
817
|
+
*
|
|
818
|
+
* Each appender declares which log levels it supports and can optionally
|
|
819
|
+
* use formatters to transform events and filters to determine eligibility.
|
|
820
|
+
*
|
|
821
|
+
* @example
|
|
822
|
+
* ```typescript
|
|
823
|
+
* class DatabaseAppender implements Appender {
|
|
824
|
+
* name = 'database';
|
|
825
|
+
* supportedLevels = new Set(['error', 'fatal']);
|
|
826
|
+
* enabled = true;
|
|
827
|
+
* priority = 10;
|
|
828
|
+
*
|
|
829
|
+
* init(config, formatter, filters) {
|
|
830
|
+
* this.db = new Database(config.connectionString);
|
|
831
|
+
* }
|
|
832
|
+
*
|
|
833
|
+
* write(event) {
|
|
834
|
+
* this.db.insert('logs', this.formatter.format(event));
|
|
835
|
+
* }
|
|
836
|
+
* }
|
|
837
|
+
* ```
|
|
838
|
+
*/
|
|
839
|
+
interface Appender extends Plugin {
|
|
840
|
+
/**
|
|
841
|
+
* Set of log levels this appender can process.
|
|
842
|
+
*
|
|
843
|
+
* Events with levels not in this set are automatically skipped.
|
|
844
|
+
* Use this to restrict appenders to specific severity ranges.
|
|
845
|
+
*/
|
|
846
|
+
readonly supportedLevels: Set<LogLevelType>;
|
|
847
|
+
/**
|
|
848
|
+
* Runtime flag controlling whether this appender processes events.
|
|
849
|
+
*
|
|
850
|
+
* Can be toggled via LogM8.enableAppender()/disableAppender() for
|
|
851
|
+
* dynamic output control without full reconfiguration.
|
|
852
|
+
*/
|
|
853
|
+
enabled: boolean;
|
|
854
|
+
/**
|
|
855
|
+
* Execution priority for deterministic appender ordering.
|
|
856
|
+
*
|
|
857
|
+
* Higher values execute first. Undefined/null treated as 0.
|
|
858
|
+
* Useful for ensuring critical appenders (like error alerting)
|
|
859
|
+
* process events before optional ones (like debug files).
|
|
860
|
+
*/
|
|
861
|
+
priority?: number;
|
|
862
|
+
/**
|
|
863
|
+
* Initializes the appender with configuration and optional processing components.
|
|
864
|
+
*
|
|
865
|
+
* Called once during LogM8.init() to set up the appender with its specific
|
|
866
|
+
* configuration, formatter for event transformation, and filters for event
|
|
867
|
+
* eligibility determination.
|
|
868
|
+
*
|
|
869
|
+
* @param config - Appender-specific configuration options
|
|
870
|
+
* @param formatter - Optional formatter to transform log events before output
|
|
871
|
+
* @param filters - Optional filters to determine which events to process
|
|
872
|
+
*/
|
|
873
|
+
init(config: AppenderConfig, formatter?: Formatter, filters?: Filter[]): void;
|
|
874
|
+
/**
|
|
875
|
+
* Processes a single log event for output.
|
|
876
|
+
*
|
|
877
|
+
* Called for each log event that passes level and filter checks.
|
|
878
|
+
* Implementations should handle formatting (if no formatter provided)
|
|
879
|
+
* and write to their specific output destination.
|
|
880
|
+
*
|
|
881
|
+
* @param logEvent - The log event to be processed and output
|
|
882
|
+
*/
|
|
883
|
+
write(logEvent: LogEvent): void;
|
|
884
|
+
/**
|
|
885
|
+
* Forces immediate output of any buffered log events.
|
|
886
|
+
*
|
|
887
|
+
* Called during appender shutdown or when explicitly requested via
|
|
888
|
+
* LogM8.flushAppender(). Implementations should ensure data persistence.
|
|
889
|
+
*/
|
|
890
|
+
flush(): void;
|
|
891
|
+
/**
|
|
892
|
+
* Disposes of the appender and releases any resources.
|
|
893
|
+
*
|
|
894
|
+
* Called during LogM8.dispose() to clean up the appender's resources.
|
|
895
|
+
* Implementations should ensure all buffered events are flushed before disposal.
|
|
896
|
+
*/
|
|
897
|
+
dispose(): void;
|
|
898
|
+
/**
|
|
899
|
+
* Enables the specified filter for this appender.
|
|
900
|
+
*
|
|
901
|
+
* @param filterName - The name of the filter to enable
|
|
902
|
+
*/
|
|
903
|
+
enableFilter(filterName: string): void;
|
|
904
|
+
/**
|
|
905
|
+
* Disables the specified filter for this appender.
|
|
906
|
+
*
|
|
907
|
+
* @param filterName - The name of the filter to disable
|
|
908
|
+
*/
|
|
909
|
+
disableFilter(filterName: string): void;
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
/**
|
|
913
|
+
* Configuration interface for console appender.
|
|
914
|
+
* Currently extends base AppenderConfig without additional options.
|
|
915
|
+
*/
|
|
916
|
+
interface ConsoleAppenderConfig extends AppenderConfig {
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
/**
|
|
920
|
+
* Configuration options for the file appender.
|
|
921
|
+
*
|
|
922
|
+
* - filename: Destination file path. The file is opened on init.
|
|
923
|
+
* - append: When true, appends to the existing file; otherwise it is truncated.
|
|
924
|
+
*/
|
|
925
|
+
interface FileAppenderConfig extends AppenderConfig {
|
|
926
|
+
/** Destination file path to write logs into. */
|
|
927
|
+
filename: string;
|
|
928
|
+
/** Append to existing file (true) or overwrite on startup (false). Default: false */
|
|
929
|
+
append?: boolean;
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
/**
|
|
933
|
+
* Configuration for MatchFilter.
|
|
934
|
+
*
|
|
935
|
+
* Provides simple allow/deny rule maps where each key is a dot-path into the LogEvent
|
|
936
|
+
* (supports array bracket notation like `data[0].items[2]`) and each value is the value
|
|
937
|
+
* that must match for the rule to apply.
|
|
938
|
+
*
|
|
939
|
+
* Behavior:
|
|
940
|
+
* - allow: If provided and non-empty, an event must satisfy ALL allow rules to pass.
|
|
941
|
+
* - deny: If provided, an event that satisfies ANY deny rule will be blocked.
|
|
942
|
+
* - Precedence: deny rules take precedence over allow; i.e., an event that passes allow
|
|
943
|
+
* but matches a deny rule will be denied.
|
|
944
|
+
*
|
|
945
|
+
* Examples:
|
|
946
|
+
* ```ts
|
|
947
|
+
* // Only allow events from a specific logger AND with a specific data value
|
|
948
|
+
* { name: 'match-filter', allow: { 'logger': 'app.service', 'data[0].type': 'audit' } }
|
|
949
|
+
*
|
|
950
|
+
* // Deny events for a user id regardless of other matches
|
|
951
|
+
* { name: 'match-filter', deny: { 'context.userId': '1234' } }
|
|
952
|
+
*
|
|
953
|
+
* // Combined example
|
|
954
|
+
* {
|
|
955
|
+
* name: 'match-filter',
|
|
956
|
+
* allow: { 'logger': 'allow.this.logger', 'data[0].custom[3].path': 4 },
|
|
957
|
+
* deny: { 'logger': 'block.this.logger', 'context.userId': '1234' }
|
|
958
|
+
* }
|
|
959
|
+
* ```
|
|
960
|
+
*/
|
|
961
|
+
interface MatchFilterConfig extends FilterConfig {
|
|
962
|
+
/** All rules in this map must match for the event to be allowed (AND). */
|
|
963
|
+
allow?: Record<string, unknown>;
|
|
964
|
+
/** If any rule in this map matches, the event will be denied (OR). */
|
|
965
|
+
deny?: Record<string, unknown>;
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
/**
|
|
969
|
+
* Configuration for the default text formatter.
|
|
970
|
+
*
|
|
971
|
+
* Extends the base FormatterConfig with options for template customization,
|
|
972
|
+
* timestamp formatting, and optional colorization.
|
|
973
|
+
*/
|
|
974
|
+
interface DefaultFormatterConfig extends FormatterConfig {
|
|
975
|
+
/**
|
|
976
|
+
* Custom format template(s) using token syntax.
|
|
977
|
+
* Provide a single template string or an array of template strings for multi-line output.
|
|
978
|
+
* Defaults to a readable text format: ['{timestamp} {LEVEL} [{logger}]', '{message}', '{data}'].
|
|
979
|
+
*/
|
|
980
|
+
format?: string | string[];
|
|
981
|
+
/**
|
|
982
|
+
* Timestamp format pattern or preset.
|
|
983
|
+
* Supports 'iso', 'locale', or custom token patterns (yyyy-MM-dd hh:mm:ss).
|
|
984
|
+
*/
|
|
985
|
+
timestampFormat?: string;
|
|
986
|
+
/**
|
|
987
|
+
* Enable colorized output for level tokens.
|
|
988
|
+
*
|
|
989
|
+
* - Node.js: Applies ANSI escape codes.
|
|
990
|
+
* - Browser: Returns a tuple ['%cLEVEL', css] suitable for console.log('%c..', ..)
|
|
991
|
+
* when {LEVEL} is resolved; appenders may pass tokens straight to console APIs.
|
|
992
|
+
*
|
|
993
|
+
* Set to true to enable; environment detection is used only to decide ANSI vs CSS.
|
|
994
|
+
*/
|
|
995
|
+
color?: boolean;
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
interface StringifyLogOptions {
|
|
999
|
+
/** Max object/array nesting depth to descend into (default 3). */
|
|
1000
|
+
maxDepth?: number;
|
|
1001
|
+
/** Truncate long string values to this length (default 200). */
|
|
1002
|
+
maxStringLength?: number;
|
|
1003
|
+
/** Truncate long arrays to this length (default: 100) */
|
|
1004
|
+
maxArrayLength?: number;
|
|
1005
|
+
}
|
|
1006
|
+
interface SerializedError {
|
|
1007
|
+
name: string;
|
|
1008
|
+
message: string;
|
|
1009
|
+
stack?: string;
|
|
1010
|
+
cause?: SerializedError | null;
|
|
1011
|
+
[key: string]: unknown;
|
|
1012
|
+
}
|
|
1013
|
+
/**
|
|
1014
|
+
* Utility functions for timestamp formatting and object property access.
|
|
1015
|
+
*
|
|
1016
|
+
* Provides environment detection, nested property traversal, and flexible
|
|
1017
|
+
* timestamp formatting with support for custom tokens, ISO formats, and
|
|
1018
|
+
* locale-specific output.
|
|
1019
|
+
*/
|
|
1020
|
+
declare class LogM8Utils {
|
|
1021
|
+
/**
|
|
1022
|
+
* Detects browser environment for feature compatibility.
|
|
1023
|
+
*
|
|
1024
|
+
* @returns True when both window and document global objects are available
|
|
1025
|
+
*/
|
|
1026
|
+
static isBrowser(): boolean;
|
|
1027
|
+
/**
|
|
1028
|
+
* Check if an object is a string.
|
|
1029
|
+
*
|
|
1030
|
+
* @param obj - The object to check.
|
|
1031
|
+
* @returns true if the object is a string, otherwise false.
|
|
1032
|
+
*/
|
|
1033
|
+
static isString(obj: unknown): boolean;
|
|
1034
|
+
/**
|
|
1035
|
+
* Traverses nested object properties using dot-separated path notation.
|
|
1036
|
+
*
|
|
1037
|
+
* Supports both object property access and array indexing with numeric keys.
|
|
1038
|
+
* Also supports bracket notation for array indices which is normalized internally
|
|
1039
|
+
* (e.g., `data[0].items[2]` becomes `data.0.items.2`).
|
|
1040
|
+
* Safe navigation that returns undefined for invalid paths rather than throwing.
|
|
1041
|
+
*
|
|
1042
|
+
* @param obj - Source object to traverse
|
|
1043
|
+
* @param path - Dot-separated property path (e.g., 'user.profile.name', 'items.0.id')
|
|
1044
|
+
* or a path with bracket indices (e.g., 'items[0].id')
|
|
1045
|
+
* @returns Property value at the specified path, or undefined if not found
|
|
1046
|
+
*
|
|
1047
|
+
* @example
|
|
1048
|
+
* ```typescript
|
|
1049
|
+
* const data = { user: { profile: { name: 'John' } }, items: [{ id: 1 }, { id: 2 }] };
|
|
1050
|
+
* getPropertyByPath(data, 'user.profile.name'); // 'John'
|
|
1051
|
+
* getPropertyByPath(data, 'items.0.id'); // 1
|
|
1052
|
+
* getPropertyByPath(data, 'items[1].id'); // 2 (bracket notation)
|
|
1053
|
+
* getPropertyByPath(data, 'missing.path'); // undefined
|
|
1054
|
+
* ```
|
|
1055
|
+
*/
|
|
1056
|
+
static getPropertyByPath(obj: unknown, path: string): unknown;
|
|
1057
|
+
/**
|
|
1058
|
+
* Formats Date objects using preset formats or custom token patterns.
|
|
1059
|
+
*
|
|
1060
|
+
* Supports common presets ('iso', 'locale') and flexible token-based formatting
|
|
1061
|
+
* for complete control over timestamp appearance. Tokens are replaced with
|
|
1062
|
+
* corresponding date/time components, while non-token text is preserved literally.
|
|
1063
|
+
*
|
|
1064
|
+
* Supported format tokens:
|
|
1065
|
+
* - yyyy: 4-digit year (2025)
|
|
1066
|
+
* - yy: 2-digit year (25)
|
|
1067
|
+
* - MM: month with leading zero (01-12)
|
|
1068
|
+
* - dd: day with leading zero (01-31)
|
|
1069
|
+
* - hh: 24-hour format hour with leading zero (00-23)
|
|
1070
|
+
* - h: 12-hour format hour (1-12)
|
|
1071
|
+
* - mm: minutes with leading zero (00-59)
|
|
1072
|
+
* - ss: seconds with leading zero (00-59)
|
|
1073
|
+
* - SSS: milliseconds with leading zeros (000-999)
|
|
1074
|
+
* - SS: centiseconds with leading zero (00-99)
|
|
1075
|
+
* - S: deciseconds (0-9)
|
|
1076
|
+
* - A: uppercase AM/PM
|
|
1077
|
+
* - a: lowercase am/pm
|
|
1078
|
+
* - z: timezone offset with colon (±HH:MM)
|
|
1079
|
+
* - zz: timezone offset without colon (±HHMM)
|
|
1080
|
+
*
|
|
1081
|
+
* @param date - Date instance to format
|
|
1082
|
+
* @param fmt - Format preset ('iso'|'locale') or custom token pattern
|
|
1083
|
+
* @returns Formatted timestamp string
|
|
1084
|
+
*
|
|
1085
|
+
* @example
|
|
1086
|
+
* ```typescript
|
|
1087
|
+
* const date = new Date('2025-08-04T14:23:45.123Z');
|
|
1088
|
+
*
|
|
1089
|
+
* // Presets
|
|
1090
|
+
* formatTimestamp(date, 'iso'); // '2025-08-04T14:23:45.123Z'
|
|
1091
|
+
* formatTimestamp(date, 'locale'); // '8/4/2025, 2:23:45 PM' (locale-dependent)
|
|
1092
|
+
*
|
|
1093
|
+
* // Custom patterns
|
|
1094
|
+
* formatTimestamp(date, 'yyyy-MM-dd hh:mm:ss'); // '2025-08-04 14:23:45'
|
|
1095
|
+
* formatTimestamp(date, 'MM/dd/yyyy h:mm A'); // '08/04/2025 2:23 PM'
|
|
1096
|
+
* formatTimestamp(date, 'hh:mm:ss.SSS'); // '14:23:45.123'
|
|
1097
|
+
* formatTimestamp(date, 'yyyy-MM-dd hh:mm:ss z'); // '2025-08-04 14:23:45 +00:00'
|
|
1098
|
+
* ```
|
|
1099
|
+
*/
|
|
1100
|
+
static formatTimestamp(date: Date, fmt?: string): string;
|
|
1101
|
+
/**
|
|
1102
|
+
* Converts arbitrary values into JSON strings optimized for logging systems.
|
|
1103
|
+
*
|
|
1104
|
+
* This utility ensures that any JavaScript value can be safely logged without causing
|
|
1105
|
+
* serialization errors or producing excessively large output. It's designed specifically
|
|
1106
|
+
* for logging contexts where reliability and readability are more important than
|
|
1107
|
+
* perfect fidelity.
|
|
1108
|
+
*
|
|
1109
|
+
* ## Key Features
|
|
1110
|
+
*
|
|
1111
|
+
* **Depth Protection**: Prevents stack overflows and excessive output by limiting
|
|
1112
|
+
* object traversal depth. Objects/arrays beyond the limit are replaced with
|
|
1113
|
+
* "[Object]" or "[Array]" placeholders.
|
|
1114
|
+
*
|
|
1115
|
+
* **Array Length Limiting**: Automatically truncates arrays that exceed the maximum
|
|
1116
|
+
* length threshold. Truncated arrays include a message indicating how many additional
|
|
1117
|
+
* items were omitted.
|
|
1118
|
+
*
|
|
1119
|
+
* **String Truncation**: Automatically truncates long strings to prevent log flooding.
|
|
1120
|
+
* Truncated strings end with an ellipsis (…) character.
|
|
1121
|
+
*
|
|
1122
|
+
* **Type Safety**: Handles problematic JavaScript types that would normally cause
|
|
1123
|
+
* JSON.stringify to throw:
|
|
1124
|
+
* - BigInt values are converted to strings
|
|
1125
|
+
* - Date objects are normalized to ISO 8601 format
|
|
1126
|
+
* - Error instances are serialized to structured objects via {@link LogM8Utils.serializeError}
|
|
1127
|
+
*
|
|
1128
|
+
* ## Implementation Details
|
|
1129
|
+
*
|
|
1130
|
+
* - Uses a WeakMap to track traversal depth per object, preventing revisits to the
|
|
1131
|
+
* same instance at different depths
|
|
1132
|
+
* - Respects existing `toJSON()` methods on objects
|
|
1133
|
+
* - Not designed for full cycle detection - cyclic references are handled by the
|
|
1134
|
+
* depth limit rather than explicit cycle breaking
|
|
1135
|
+
* - The replacer function executes in the context of the parent object, enabling
|
|
1136
|
+
* depth tracking through the traversal
|
|
1137
|
+
*
|
|
1138
|
+
* @param value - Any JavaScript value to stringify for logging (events, contexts, errors, etc.)
|
|
1139
|
+
* @param options - Configuration for controlling output size and complexity
|
|
1140
|
+
* @param options.maxDepth - Maximum nesting depth for objects/arrays (default: 3).
|
|
1141
|
+
* Level 0 = primitive values only,
|
|
1142
|
+
* Level 1 = top-level properties,
|
|
1143
|
+
* Level 2 = nested properties, etc.
|
|
1144
|
+
* @param options.maxArrayLength - Maximum number of array elements to include before truncation (default: 100).
|
|
1145
|
+
* Arrays exceeding this limit will be truncated with a message
|
|
1146
|
+
* indicating the number of omitted items.
|
|
1147
|
+
* @param options.maxStringLength - Maximum character length for strings before truncation (default: 200)
|
|
1148
|
+
* @param space - Indentation for pretty-printing. Can be a number (spaces) or string (e.g., '\t').
|
|
1149
|
+
* Pass undefined for compact output (recommended for production logs).
|
|
1150
|
+
*
|
|
1151
|
+
* @returns A JSON string that is guaranteed to be safe for logging systems
|
|
1152
|
+
*
|
|
1153
|
+
* @example
|
|
1154
|
+
* // Basic usage with default options
|
|
1155
|
+
* const json = LogM8Utils.stringifyLog({ message: 'User logged in', userId: 12345 });
|
|
1156
|
+
* // => '{"message":"User logged in","userId":12345}'
|
|
1157
|
+
*
|
|
1158
|
+
* @example
|
|
1159
|
+
* // Handling problematic types
|
|
1160
|
+
* const data = {
|
|
1161
|
+
* bigNumber: 123456789012345678901234567890n,
|
|
1162
|
+
* timestamp: new Date('2024-01-15T10:30:00Z'),
|
|
1163
|
+
* error: new Error('Connection failed'),
|
|
1164
|
+
* longText: 'x'.repeat(500)
|
|
1165
|
+
* };
|
|
1166
|
+
* const json = LogM8Utils.stringifyLog(data);
|
|
1167
|
+
* // => '{"bigNumber":"123456789012345678901234567890","timestamp":"2024-01-15T10:30:00.000Z","error":{...},"longText":"xxx...xxx…"}'
|
|
1168
|
+
*
|
|
1169
|
+
* @example
|
|
1170
|
+
* // Array length limiting for large arrays
|
|
1171
|
+
* const largeData = {
|
|
1172
|
+
* items: new Array(1000).fill({ id: 1, name: 'item' }),
|
|
1173
|
+
* values: Array.from({ length: 500 }, (_, i) => i)
|
|
1174
|
+
* };
|
|
1175
|
+
* const json = LogM8Utils.stringifyLog(largeData, { maxArrayLength: 50 });
|
|
1176
|
+
* // => '{"items":[{...},{...},...,"... 950 more items"],"values":[0,1,2,...,"... 450 more items"]}'
|
|
1177
|
+
*
|
|
1178
|
+
* @example
|
|
1179
|
+
* // Depth limiting for deeply nested objects
|
|
1180
|
+
* const deepObj = {
|
|
1181
|
+
* level1: {
|
|
1182
|
+
* level2: {
|
|
1183
|
+
* level3: {
|
|
1184
|
+
* level4: {
|
|
1185
|
+
* level5: 'too deep'
|
|
1186
|
+
* }
|
|
1187
|
+
* }
|
|
1188
|
+
* }
|
|
1189
|
+
* }
|
|
1190
|
+
* };
|
|
1191
|
+
* const json = LogM8Utils.stringifyLog(deepObj, { maxDepth: 3 });
|
|
1192
|
+
* // => '{"level1":{"level2":{"level3":{"level4":"[Object]"}}}}'
|
|
1193
|
+
*
|
|
1194
|
+
* @example
|
|
1195
|
+
* // Custom options for verbose debugging
|
|
1196
|
+
* const debugJson = LogM8Utils.stringifyLog(
|
|
1197
|
+
* complexObject,
|
|
1198
|
+
* { maxDepth: 5, maxArrayLength: 500, maxStringLength: 1000 },
|
|
1199
|
+
* 2 // Pretty print with 2 spaces
|
|
1200
|
+
* );
|
|
1201
|
+
*
|
|
1202
|
+
* @example
|
|
1203
|
+
* // Production logging with minimal output
|
|
1204
|
+
* const prodJson = LogM8Utils.stringifyLog(
|
|
1205
|
+
* userEvent,
|
|
1206
|
+
* { maxDepth: 2, maxArrayLength: 20, maxStringLength: 100 } // Aggressive truncation for high-volume logs
|
|
1207
|
+
* );
|
|
1208
|
+
*
|
|
1209
|
+
* @example
|
|
1210
|
+
* // Handling arrays with mixed content
|
|
1211
|
+
* const mixedArray = {
|
|
1212
|
+
* results: [
|
|
1213
|
+
* { id: 1, data: 'first' },
|
|
1214
|
+
* { id: 2, data: 'second' },
|
|
1215
|
+
* ...Array(200).fill({ id: 999, data: 'bulk' })
|
|
1216
|
+
* ]
|
|
1217
|
+
* };
|
|
1218
|
+
* const json = LogM8Utils.stringifyLog(mixedArray, { maxArrayLength: 10 });
|
|
1219
|
+
* // First 10 items preserved, then truncation message
|
|
1220
|
+
*
|
|
1221
|
+
* @see {@link LogM8Utils.serializeError} - For Error serialization details
|
|
1222
|
+
*/
|
|
1223
|
+
static stringifyLog(value: unknown, { maxDepth, maxStringLength, maxArrayLength }?: StringifyLogOptions, space?: number | string): string;
|
|
1224
|
+
/**
|
|
1225
|
+
* Serializes an Error (or Error-like) into a plain, JSON-safe object.
|
|
1226
|
+
*
|
|
1227
|
+
* Behavior:
|
|
1228
|
+
* - Returns null for falsy inputs.
|
|
1229
|
+
* - If the object provides a custom toJSON(), that result is used verbatim to
|
|
1230
|
+
* honor caller-defined serialization.
|
|
1231
|
+
* - Otherwise includes standard fields: name, message, stack.
|
|
1232
|
+
* - Recursively serializes the optional error.cause chain using the same rules.
|
|
1233
|
+
* - Handles circular references in the cause chain safely.
|
|
1234
|
+
* - Copies other own enumerable properties (excluding name, message, stack, cause),
|
|
1235
|
+
* skipping properties that throw on access or are not JSON-serializable.
|
|
1236
|
+
* - Optionally includes common non-enumerable properties like 'code' if present.
|
|
1237
|
+
*
|
|
1238
|
+
* Important:
|
|
1239
|
+
* - This function does not attempt to preserve all non-enumerable properties.
|
|
1240
|
+
* - Circular references in the cause chain are detected and handled gracefully.
|
|
1241
|
+
*
|
|
1242
|
+
* @param error - Unknown error input (Error instance or compatible object).
|
|
1243
|
+
* @returns Structured error data suitable for logging, or null when input is falsy.
|
|
1244
|
+
*
|
|
1245
|
+
* @example
|
|
1246
|
+
* try {
|
|
1247
|
+
* throw new Error('Boom');
|
|
1248
|
+
* } catch (e) {
|
|
1249
|
+
* const payload = LogM8Utils.serializeError(e);
|
|
1250
|
+
* // { name: 'Error', message: 'Boom', stack: '...', ... }
|
|
1251
|
+
* }
|
|
1252
|
+
*/
|
|
1253
|
+
static serializeError(error: unknown): SerializedError | null;
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
/**
|
|
1257
|
+
* Default singleton instance of the LogM8 logging manager.
|
|
1258
|
+
*
|
|
1259
|
+
* Pre-configured with built-in appenders and formatters for immediate use.
|
|
1260
|
+
* Most applications should use this export rather than creating new LogM8 instances.
|
|
1261
|
+
*
|
|
1262
|
+
* @example
|
|
1263
|
+
* ```typescript
|
|
1264
|
+
* import { Logging } from 'log-m8';
|
|
1265
|
+
*
|
|
1266
|
+
* // Initialize with default console output
|
|
1267
|
+
* Logging.init();
|
|
1268
|
+
*
|
|
1269
|
+
* // Get a logger and start logging
|
|
1270
|
+
* const logger = Logging.getLogger('app');
|
|
1271
|
+
* logger.info('Application started');
|
|
1272
|
+
* ```
|
|
1273
|
+
*/
|
|
1274
|
+
declare const Logging: LogM8;
|
|
1275
|
+
|
|
1276
|
+
export { type Appender, type AppenderConfig, type ConsoleAppenderConfig, type DefaultFormatterConfig, type FileAppenderConfig, type Filter, type FilterConfig, type Formatter, type FormatterConfig, type Log, type LogContext, LogLevel, type LogLevelType, LogM8Utils, Logging, type LoggingConfig, type MatchFilterConfig, type Plugin, type PluginConfig, type PluginFactory, PluginKind, type PluginKindType };
|