@decaf-ts/logging 0.2.3 → 0.3.0

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.md CHANGED
File without changes
package/README.md CHANGED
@@ -2,8 +2,7 @@
2
2
 
3
3
  ## Decaf's Logging
4
4
 
5
- Wimple winston like wrapper for decaf usage
6
-
5
+ A comprehensive, flexible, and type-safe logging library for TypeScript applications that provides hierarchical context-aware logging, configurable styling, multiple output formats, and method decorators. It offers a lightweight built-in logger and seamless Winston integration, enabling developers to easily add structured logging with different verbosity levels to their applications.
7
6
 
8
7
 
9
8
  ![Licence](https://img.shields.io/github/license/decaf-ts/logging.svg?style=plastic)
@@ -37,6 +36,83 @@ Documentation available [here](https://decaf-ts.github.io/logging/)
37
36
 
38
37
  ### Description
39
38
 
39
+ Decaf's Logging is a powerful TypeScript logging library designed to provide flexible, context-aware logging capabilities for applications of any size. The library is built with a focus on type safety, configurability, and ease of use.
40
+
41
+ #### Core Architecture
42
+
43
+ The library follows a modular architecture with several key components:
44
+
45
+ 1. **Logging System**:
46
+ - `Logging`: A static class that serves as the central entry point for the logging system. It manages global configuration, provides factory methods for creating loggers, and offers static logging methods.
47
+ - `MiniLogger`: A lightweight logger implementation that provides the core logging functionality with support for different log levels, context-aware logging, and customizable formatting.
48
+ - `Logger` interface: Defines the standard methods that all logger implementations must provide, ensuring consistency across different logger types.
49
+
50
+ 2. **Configuration System**:
51
+ - `LoggingConfig`: Defines configuration options for the logging system, including log level, verbosity, styling, timestamp format, and more.
52
+ - `DefaultLoggingConfig`: Provides sensible default settings that can be overridden as needed.
53
+
54
+ 3. **Log Levels**:
55
+ - `LogLevel` enum: Defines standard log levels (error, info, verbose, debug, silly) for categorizing log messages.
56
+ - `NumericLogLevels`: Maps log levels to numeric values for comparison and filtering.
57
+
58
+ 4. **Styling System**:
59
+ - `Theme` interface: Defines a comprehensive theming system for styling log output with colors and formatting.
60
+ - `DefaultTheme`: Provides a default color scheme for log output.
61
+ - `LoggingMode` enum: Supports different output formats (RAW, JSON) for log messages.
62
+
63
+ 5. **Decorator System**:
64
+ - Method decorators (`@log`, `@debug`, `@info`, `@verbose`, `@silly`): Allow for easy integration of logging into class methods with options for benchmarking and verbosity control.
65
+
66
+ 6. **Winston Integration**:
67
+ - `WinstonLogger`: Extends the core logging functionality to leverage the Winston logging library.
68
+ - `WinstonFactory`: A factory function for creating Winston-based loggers.
69
+
70
+ #### Key Features
71
+
72
+ 1. **Hierarchical Context-Aware Logging**:
73
+ The library allows creating loggers for specific classes and methods, maintaining a hierarchy of contexts. This makes it easy to trace log messages back to their source and filter logs by context.
74
+
75
+ 2. **Configurable Styling**:
76
+ Extensive support for styling log output with colors and formatting, with a theme system that allows customizing the appearance of different log components.
77
+
78
+ 3. **Multiple Output Formats**:
79
+ Support for both human-readable (RAW) and machine-parseable (JSON) output formats.
80
+
81
+ 4. **Method Decorators**:
82
+ Easy-to-use decorators for adding logging to class methods, with support for benchmarking execution time.
83
+
84
+ 5. **Verbosity Control**:
85
+ Fine-grained control over log verbosity, allowing developers to adjust the detail level of logs without changing code.
86
+
87
+ 6. **Type Safety**:
88
+ Comprehensive TypeScript type definitions ensure type safety and enable IDE autocompletion.
89
+
90
+ 7. **Winston Integration**:
91
+ Seamless integration with the popular Winston logging library, providing access to its advanced features while maintaining the same interface.
92
+
93
+ 8. **Error Handling**:
94
+ Special support for logging errors with stack traces for better debugging.
95
+
96
+ #### Usage Patterns
97
+
98
+ The library supports several usage patterns:
99
+
100
+ 1. **Global Logging**:
101
+ Using the static `Logging` class methods for simple, application-wide logging.
102
+
103
+ 2. **Class-Specific Logging**:
104
+ Creating loggers for specific classes to provide context for log messages.
105
+
106
+ 3. **Method-Specific Logging**:
107
+ Creating child loggers for specific methods to further refine the context.
108
+
109
+ 4. **Decorator-Based Logging**:
110
+ Using method decorators to automatically log method calls and execution times.
111
+
112
+ 5. **Winston-Based Logging**:
113
+ Leveraging Winston's advanced features while maintaining the same interface.
114
+
115
+ This flexible design makes the library suitable for a wide range of applications, from simple scripts to complex enterprise systems.
40
116
 
41
117
 
42
118
  ### How to Use
@@ -44,7 +120,292 @@ Documentation available [here](https://decaf-ts.github.io/logging/)
44
120
  - [Initial Setup](./tutorials/For%20Developers.md#_initial-setup_)
45
121
  - [Installation](./tutorials/For%20Developers.md#installation)
46
122
 
123
+ ## Basic Usage
124
+
125
+ ### Global Logging
126
+
127
+ The simplest way to use the library is through the static `Logging` class:
128
+
129
+ ```typescript
130
+ import { Logging, LogLevel } from 'decaf-logging';
131
+
132
+ // Configure global logging settings
133
+ Logging.setConfig({
134
+ level: LogLevel.debug,
135
+ style: true,
136
+ timestamp: true
137
+ });
138
+
139
+ // Log messages at different levels
140
+ Logging.info('Application started');
141
+ Logging.debug('Debug information');
142
+ Logging.error('An error occurred');
143
+ Logging.verbose('Detailed information', 1); // With verbosity level
144
+ ```
145
+
146
+ ### Class-Specific Logging
147
+
148
+ For more context-aware logging, create loggers for specific classes:
149
+
150
+ ```typescript
151
+ import { Logging, Logger } from 'decaf-logging';
152
+
153
+ class UserService {
154
+ private logger: Logger;
155
+
156
+ constructor() {
157
+ // Create a logger for this class
158
+ this.logger = Logging.for(UserService);
159
+ // Or with string name: Logging.for('UserService');
160
+ }
161
+
162
+ getUser(id: string) {
163
+ this.logger.info(`Getting user with ID: ${id}`);
164
+ // ... implementation
165
+ this.logger.debug('User retrieved successfully');
166
+ }
167
+
168
+ updateUser(id: string, data: any) {
169
+ try {
170
+ this.logger.info(`Updating user with ID: ${id}`);
171
+ // ... implementation
172
+ this.logger.debug('User updated successfully');
173
+ } catch (error) {
174
+ this.logger.error(error); // Logs error with stack trace
175
+ }
176
+ }
177
+ }
178
+ ```
179
+
180
+ ### Method-Specific Logging
181
+
182
+ Create child loggers for specific methods to further refine the context:
183
+
184
+ ```typescript
185
+ import { Logging, Logger } from 'decaf-logging';
47
186
 
187
+ class DataProcessor {
188
+ private logger: Logger;
189
+
190
+ constructor() {
191
+ this.logger = Logging.for(DataProcessor);
192
+ }
193
+
194
+ processData(data: any[]) {
195
+ // Create a method-specific logger
196
+ const methodLogger = this.logger.for('processData');
197
+
198
+ methodLogger.info(`Processing ${data.length} items`);
199
+
200
+ // With custom configuration
201
+ const verboseLogger = methodLogger.for('details', { verbose: 2 });
202
+ verboseLogger.verbose('Starting detailed processing', 1);
203
+
204
+ // ... implementation
205
+ }
206
+ }
207
+ ```
208
+
209
+ ### Using Decorators
210
+
211
+ Decorators provide an easy way to add logging to class methods:
212
+
213
+ ```typescript
214
+ import { debug, info, log, LogLevel, verbose } from 'decaf-logging';
215
+
216
+ class PaymentProcessor {
217
+ // Basic logging with info level
218
+ @info()
219
+ processPayment(amount: number, userId: string) {
220
+ // Method implementation
221
+ return true;
222
+ }
223
+
224
+ // Debug level logging with benchmarking
225
+ @debug(true)
226
+ validatePayment(paymentData: any) {
227
+ // Method implementation
228
+ return true;
229
+ }
230
+
231
+ // Verbose logging with custom verbosity
232
+ @verbose(2)
233
+ recordTransaction(transactionData: any) {
234
+ // Method implementation
235
+ }
236
+
237
+ // Custom log level with benchmarking and verbosity
238
+ @log(LogLevel.error, true, 1)
239
+ handleFailure(error: Error) {
240
+ // Method implementation
241
+ }
242
+ }
243
+ ```
244
+
245
+ ### Winston Integration
246
+
247
+ To use Winston for logging:
248
+
249
+ ```typescript
250
+ import { Logging, LogLevel } from 'decaf-logging';
251
+ import { WinstonFactory } from 'decaf-logging/winston';
252
+ import winston from 'winston';
253
+
254
+ // Configure Winston transports
255
+ const transports = [
256
+ new winston.transports.Console(),
257
+ new winston.transports.File({ filename: 'app.log' })
258
+ ];
259
+
260
+ // Set Winston as the logger factory
261
+ Logging.setFactory(WinstonFactory);
262
+
263
+ // Configure global logging
264
+ Logging.setConfig({
265
+ level: LogLevel.info,
266
+ timestamp: true,
267
+ timestampFormat: 'YYYY-MM-DD HH:mm:ss'
268
+ });
269
+
270
+ // Create a Winston logger for a class
271
+ const logger = Logging.for('MyService');
272
+ logger.info('Service initialized');
273
+ ```
274
+
275
+ ## Advanced Usage
276
+
277
+ ### Custom Styling
278
+
279
+ Configure custom styling for log output:
280
+
281
+ ```typescript
282
+ import { Logging, LogLevel, Theme } from 'decaf-logging';
283
+
284
+ // Define a custom theme
285
+ const customTheme: Theme = {
286
+ class: {
287
+ fg: 35, // Magenta
288
+ },
289
+ id: {
290
+ fg: 36, // Cyan
291
+ },
292
+ stack: {},
293
+ timestamp: {
294
+ fg: 90, // Gray
295
+ },
296
+ message: {
297
+ error: {
298
+ fg: 31, // Red
299
+ style: ['bold'],
300
+ },
301
+ },
302
+ method: {},
303
+ logLevel: {
304
+ error: {
305
+ fg: 31, // Red
306
+ style: ['bold'],
307
+ },
308
+ info: {
309
+ fg: 32, // Green
310
+ },
311
+ verbose: {
312
+ fg: 34, // Blue
313
+ },
314
+ debug: {
315
+ fg: 33, // Yellow
316
+ },
317
+ },
318
+ };
319
+
320
+ // Apply the custom theme
321
+ Logging.setConfig({
322
+ style: true,
323
+ theme: customTheme
324
+ });
325
+ ```
326
+
327
+ ### Correlation IDs
328
+
329
+ Track related log messages with correlation IDs:
330
+
331
+ ```typescript
332
+ import { Logging } from 'decaf-logging';
333
+
334
+ function processRequest(requestId: string, data: any) {
335
+ // Create a logger with correlation ID
336
+ const logger = Logging.for('RequestProcessor', {
337
+ correlationId: requestId
338
+ });
339
+
340
+ logger.info('Processing request');
341
+
342
+ // All log messages from this logger will include the correlation ID
343
+ processRequestData(data, logger);
344
+
345
+ logger.info('Request processing completed');
346
+ }
347
+
348
+ function processRequestData(data: any, logger: Logger) {
349
+ // Child loggers inherit the correlation ID
350
+ const dataLogger = logger.for('DataProcessor');
351
+ dataLogger.debug('Processing data');
352
+ // ...
353
+ }
354
+ ```
355
+
356
+ ### JSON Output Mode
357
+
358
+ For machine-readable logs:
359
+
360
+ ```typescript
361
+ import { Logging, LoggingMode } from 'decaf-logging';
362
+
363
+ // Configure for JSON output
364
+ Logging.setConfig({
365
+ mode: LoggingMode.JSON,
366
+ timestamp: true
367
+ });
368
+
369
+ Logging.info('This will be output in JSON format');
370
+ ```
371
+
372
+ ### Custom Logger Factory
373
+
374
+ Create a custom logger implementation:
375
+
376
+ ```typescript
377
+ import { Logger, LoggerFactory, Logging, MiniLogger } from 'decaf-logging';
378
+
379
+ // Custom logger that adds prefix to all messages
380
+ class PrefixedLogger extends MiniLogger {
381
+ constructor(context: string, prefix: string, conf?: Partial<LoggingConfig>) {
382
+ super(context, conf);
383
+ this.prefix = prefix;
384
+ }
385
+
386
+ private prefix: string;
387
+
388
+ protected override createLog(level: LogLevel, message: StringLike | Error, stack?: string): string {
389
+ const msg = typeof message === 'string' ? message : message.message;
390
+ const prefixedMsg = `${this.prefix}: ${msg}`;
391
+ return super.createLog(level, prefixedMsg, stack);
392
+ }
393
+ }
394
+
395
+ // Custom factory function
396
+ const PrefixedLoggerFactory: LoggerFactory = (
397
+ context: string,
398
+ conf?: Partial<LoggingConfig>,
399
+ ...args: any[]
400
+ ) => new PrefixedLogger(context, args[0] || '[APP]', conf);
401
+
402
+ // Set the custom factory
403
+ Logging.setFactory(PrefixedLoggerFactory);
404
+
405
+ // Create a logger with the custom factory
406
+ const logger = Logging.for('MyClass', undefined, '[CUSTOM]');
407
+ logger.info('Hello world'); // Outputs: "[CUSTOM]: Hello world"
408
+ ```
48
409
 
49
410
 
50
411
  ### Related