@qubit-ltd/logging 1.4.4 → 1.4.6

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/README.md CHANGED
@@ -11,6 +11,16 @@ logging capabilities through decorators for class methods and properties.
11
11
  This library is designed to seamlessly integrate with [Vue.js class components],
12
12
  offering an elegant solution for handling logging in your JavaScript projects.
13
13
 
14
+ ## Features
15
+
16
+ - 📝 Simple and flexible logging interface with different log levels
17
+ - 🔍 Support for formatted log messages with placeholders
18
+ - 🎯 Decorators for automatic method logging and class logger integration
19
+ - 🔄 Seamless integration with Vue.js class components
20
+ - 🎛️ Configurable logging levels and appenders
21
+ - 🌐 Global and individual logger management
22
+ - 📋 Browser console and custom appender support
23
+
14
24
  ## Installation
15
25
 
16
26
  To install the library, use either npm or yarn:
@@ -42,6 +52,28 @@ You can retrieve a `Logger` instance by calling the static method
42
52
  of the logger will be used, or the default logging level will be assigned to
43
53
  a new logger.
44
54
 
55
+ Example:
56
+
57
+ ```javascript
58
+ import Logger from '@qubit-ltd/logging';
59
+
60
+ // Create a logger with default settings
61
+ const logger1 = Logger.getLogger('MyLogger');
62
+
63
+ // Create a logger with custom level
64
+ const logger2 = Logger.getLogger('DebugLogger', { level: 'DEBUG' });
65
+
66
+ // Create a logger with custom appender
67
+ const customAppender = {
68
+ trace: (message, ...args) => { /* custom trace implementation */ },
69
+ debug: (message, ...args) => { /* custom debug implementation */ },
70
+ info: (message, ...args) => { /* custom info implementation */ },
71
+ warn: (message, ...args) => { /* custom warn implementation */ },
72
+ error: (message, ...args) => { /* custom error implementation */ },
73
+ };
74
+ const logger3 = Logger.getLogger('CustomLogger', { appender: customAppender, level: 'INFO' });
75
+ ```
76
+
45
77
  ### Logging Messages
46
78
 
47
79
  - `logger.trace(message, ...args)`: Logs a trace-level message.
@@ -82,7 +114,33 @@ logger.log(level, 'This is an %s message with argument %s and argument %o', leve
82
114
 
83
115
  Adjust the logging level for a logger using `logger.setLevel(level)`.
84
116
 
85
- Available levels: `TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR`, `NONE` (case-insensitive).
117
+ Available levels (from most to least verbose):
118
+ - `TRACE`: Most detailed information for debugging purposes
119
+ - `DEBUG`: General debugging information
120
+ - `INFO`: General information about application progress
121
+ - `WARN`: Warning situations that might require attention
122
+ - `ERROR`: Error conditions that need handling
123
+ - `NONE`: Completely disable logging
124
+
125
+ All level names are case-insensitive.
126
+
127
+ Example:
128
+
129
+ ```javascript
130
+ const logger = Logger.getLogger('MyClass');
131
+
132
+ // Change the level to only show warnings and errors
133
+ logger.setLevel('WARN');
134
+
135
+ // These won't be displayed because they're below the WARN level
136
+ logger.trace('This trace message will not be displayed');
137
+ logger.debug('This debug message will not be displayed');
138
+ logger.info('This info message will not be displayed');
139
+
140
+ // These will be displayed
141
+ logger.warn('This warning message will be displayed');
142
+ logger.error('This error message will be displayed');
143
+ ```
86
144
 
87
145
  ### Set the Logging Appender
88
146
 
@@ -98,6 +156,16 @@ Example:
98
156
  ```javascript
99
157
  const logger = Logger.getLogger('MyClass');
100
158
  logger.setAppender(console); // Outputs log messages to the console.
159
+
160
+ // Or create a custom appender that adds timestamps to all logs
161
+ const timestampAppender = {
162
+ trace: (message, ...args) => console.trace(`[${new Date().toISOString()}] ${message}`, ...args),
163
+ debug: (message, ...args) => console.debug(`[${new Date().toISOString()}] ${message}`, ...args),
164
+ info: (message, ...args) => console.info(`[${new Date().toISOString()}] ${message}`, ...args),
165
+ warn: (message, ...args) => console.warn(`[${new Date().toISOString()}] ${message}`, ...args),
166
+ error: (message, ...args) => console.error(`[${new Date().toISOString()}] ${message}`, ...args),
167
+ };
168
+ logger.setAppender(timestampAppender);
101
169
  ```
102
170
 
103
171
  ### Enable or Disable Logging
@@ -106,12 +174,50 @@ logger.setAppender(console); // Outputs log messages to the console.
106
174
  - `logger.disable()`: Disable logging.
107
175
  - `logger.setEnabled(enabled)`: Dynamically control logging.
108
176
 
177
+ Example:
178
+
179
+ ```javascript
180
+ const logger = Logger.getLogger('MyClass');
181
+
182
+ // Disable all logging temporarily
183
+ logger.disable();
184
+ logger.info('This message will not be logged');
185
+
186
+ // Re-enable logging
187
+ logger.enable();
188
+ logger.info('This message will be logged');
189
+
190
+ // Use a condition to control logging
191
+ const debugMode = process.env.NODE_ENV === 'development';
192
+ logger.setEnabled(debugMode);
193
+ ```
194
+
109
195
  ### Managing Loggers
110
196
 
111
197
  - `Logger.clearAllLoggers()`: Clears all registered loggers.
112
198
  - `Logger.getLevel(name)`: Retrieves the logging level for a specific logger.
113
199
  - `Logger.setLevel(name, level)`: Sets the logging level for a specific logger.
114
200
 
201
+ Example:
202
+
203
+ ```javascript
204
+ // Create multiple loggers
205
+ const apiLogger = Logger.getLogger('API');
206
+ const uiLogger = Logger.getLogger('UI');
207
+ const dbLogger = Logger.getLogger('Database');
208
+
209
+ // Change a specific logger's level without accessing its instance
210
+ Logger.setLevel('API', 'DEBUG');
211
+ Logger.setLevel('Database', 'ERROR');
212
+
213
+ // Get a logger's current level
214
+ const uiLevel = Logger.getLevel('UI');
215
+ console.log(`UI Logger level: ${uiLevel}`);
216
+
217
+ // Clear all loggers when shutting down the application
218
+ Logger.clearAllLoggers();
219
+ ```
220
+
115
221
  ### Default Levels and Appenders
116
222
 
117
223
  The default logging levels and appenders are used when creating a new logger
@@ -126,6 +232,23 @@ without specifying the level or appender.
126
232
  - `Logger.resetDefaultAppender()`: Resets the default logging appender to the
127
233
  factory value.
128
234
 
235
+ Example:
236
+
237
+ ```javascript
238
+ // Get the current default level
239
+ const defaultLevel = Logger.getDefaultLevel();
240
+ console.log(`Default logging level: ${defaultLevel}`);
241
+
242
+ // Change the default level for all new loggers
243
+ Logger.setDefaultLevel('DEBUG');
244
+
245
+ // All new loggers will now have DEBUG level by default
246
+ const logger = Logger.getLogger('NewLogger'); // Will have DEBUG level
247
+
248
+ // Reset to the original factory default level
249
+ Logger.resetDefaultLevel();
250
+ ```
251
+
129
252
  ### Global Loggers Management
130
253
 
131
254
  - `Logger.setAllLevels(level)`: Applies a logging level to all existing loggers.
@@ -136,12 +259,44 @@ without specifying the level or appender.
136
259
  - `Logger.resetAllAppenders()`: Resets the logging appender of all existing loggers
137
260
  to the default logging appender.
138
261
 
262
+ Example:
263
+
264
+ ```javascript
265
+ // Create several loggers with different levels
266
+ const logger1 = Logger.getLogger('Logger1', { level: 'TRACE' });
267
+ const logger2 = Logger.getLogger('Logger2', { level: 'INFO' });
268
+ const logger3 = Logger.getLogger('Logger3', { level: 'ERROR' });
269
+
270
+ // Change all loggers to WARNING level at once
271
+ Logger.setAllLevels('WARN');
272
+
273
+ // Now all loggers will only display WARN and ERROR messages
274
+ logger1.info('This won't be displayed');
275
+ logger2.warn('This will be displayed');
276
+ logger3.error('This will be displayed');
277
+
278
+ // Reset all loggers to use the default level
279
+ Logger.resetAllLevels();
280
+
281
+ // Apply a custom appender to all existing loggers
282
+ const fileAppender = { /* ... implementation of logging to a file ... */ };
283
+ Logger.setAllAppenders(fileAppender);
284
+ ```
285
+
139
286
  ### Reset to Factory Defaults
140
287
 
141
288
  - `Logger.reset()`: Resets all loggers to the factory default settings. This
142
289
  includes clearing all existing loggers, and resetting the default logging
143
290
  level and the default logging appender.
144
291
 
292
+ Example:
293
+
294
+ ```javascript
295
+ // After making many modifications to loggers and defaults
296
+ // This single call resets everything to factory settings
297
+ Logger.reset();
298
+ ```
299
+
145
300
  ## The `@Log` Decorator
146
301
 
147
302
  The `@Log` decorator automatically logs the method signature, including the
@@ -156,17 +311,29 @@ class Person {
156
311
  @Log
157
312
  eat(meal) {
158
313
  // method implementation
314
+ return `Eating ${meal.name}`;
315
+ }
316
+
317
+ // Custom options for the Log decorator
318
+ @Log({ level: 'INFO', withResult: true })
319
+ calculateCalories(food, amount) {
320
+ const calories = food.caloriesPerUnit * amount;
321
+ return calories;
159
322
  }
160
323
  }
161
324
 
162
325
  const person = new Person();
163
- const meal = new Meal();
164
- person.eat(meal); // The log will print the method calling signature
326
+ const meal = { name: 'Breakfast', type: 'healthy' };
327
+ person.eat(meal);
328
+ // Logs: "Person.eat({"name":"Breakfast","type":"healthy"})"
329
+
330
+ const calories = person.calculateCalories({ caloriesPerUnit: 50 }, 4);
331
+ // Logs: "Person.calculateCalories({"caloriesPerUnit":50}, 4) => 200"
165
332
  ```
166
333
 
167
334
  ## The `@HasLogger` Decorator
168
335
 
169
- The `@HasLogger` decorator adds a named logger to a class, which is accessibl
336
+ The `@HasLogger` decorator adds a named logger to a class, which is accessible
170
337
  via the `logger` property.
171
338
 
172
339
  Example:
@@ -179,7 +346,20 @@ class MyClass {
179
346
  foo() {
180
347
  this.logger.debug('This is MyClass.foo()');
181
348
  }
349
+
350
+ bar(param) {
351
+ this.logger.info('Processing with parameter: %o', param);
352
+ // do something with param
353
+ if (param.value < 0) {
354
+ this.logger.warn('Negative value detected: %d', param.value);
355
+ }
356
+ return param.value * 2;
357
+ }
182
358
  }
359
+
360
+ const instance = new MyClass();
361
+ instance.foo();
362
+ instance.bar({ value: -5 });
183
363
  ```
184
364
 
185
365
  ## Using with Vue.js Class Components
@@ -201,6 +381,21 @@ class MyComponent {
201
381
  @Log
202
382
  foo() {
203
383
  this.logger.debug('This is MyComponent.foo()');
384
+ this.message = 'clicked at ' + new Date().toLocaleTimeString();
385
+ }
386
+
387
+ @Log({ level: 'INFO' })
388
+ async fetchData() {
389
+ try {
390
+ this.logger.info('Fetching data from API...');
391
+ const response = await fetch('/api/data');
392
+ const data = await response.json();
393
+ this.logger.info('Data received: %o', data);
394
+ return data;
395
+ } catch (error) {
396
+ this.logger.error('Failed to fetch data: %o', error);
397
+ throw error;
398
+ }
204
399
  }
205
400
  }
206
401
 
@@ -209,11 +404,77 @@ export default toVue(MyComponent);
209
404
 
210
405
  **Note**: The `@HasLogger` decorator must be placed **after** the `@Component` decorator.
211
406
 
407
+ ## Advanced Usage
408
+
409
+ ### Creating a Custom Appender
410
+
411
+ You can create custom appenders to direct logs to different destinations:
412
+
413
+ ```javascript
414
+ // File logging appender (Node.js example)
415
+ import fs from 'fs';
416
+
417
+ const fileAppender = {
418
+ _writeToFile(level, message, ...args) {
419
+ const formattedArgs = args.map(arg =>
420
+ typeof arg === 'object' ? JSON.stringify(arg) : String(arg)
421
+ );
422
+ const logEntry = `[${new Date().toISOString()}] [${level}] ${message} ${formattedArgs.join(' ')}\n`;
423
+ fs.appendFileSync('application.log', logEntry);
424
+ },
425
+ trace: function(message, ...args) { this._writeToFile('TRACE', message, ...args); },
426
+ debug: function(message, ...args) { this._writeToFile('DEBUG', message, ...args); },
427
+ info: function(message, ...args) { this._writeToFile('INFO', message, ...args); },
428
+ warn: function(message, ...args) { this._writeToFile('WARN', message, ...args); },
429
+ error: function(message, ...args) { this._writeToFile('ERROR', message, ...args); }
430
+ };
431
+
432
+ // Use the custom appender
433
+ const logger = Logger.getLogger('AppLogger', { appender: fileAppender });
434
+ ```
435
+
436
+ ### Conditional Logging
437
+
438
+ ```javascript
439
+ import Logger from '@qubit-ltd/logging';
440
+
441
+ function processData(data, options = {}) {
442
+ const logger = Logger.getLogger('DataProcessor');
443
+
444
+ // Enable debug logging only when explicitly requested
445
+ if (options.debug) {
446
+ logger.setLevel('DEBUG');
447
+ } else {
448
+ logger.setLevel('INFO');
449
+ }
450
+
451
+ logger.debug('Processing data with options: %o', options);
452
+ // rest of the function
453
+ }
454
+ ```
455
+
212
456
  ## <span id="contributing">Contributing</span>
213
457
 
214
458
  If you find any issues or have suggestions for improvements, please feel free
215
459
  to open an issue or submit a pull request to the [GitHub repository].
216
460
 
461
+ ### Development Setup
462
+
463
+ ```bash
464
+ # Clone the repository
465
+ git clone https://github.com/Haixing-Hu/js-logging.git
466
+ cd js-logging
467
+
468
+ # Install dependencies
469
+ yarn install
470
+
471
+ # Run tests
472
+ yarn test
473
+
474
+ # Build the library
475
+ yarn build
476
+ ```
477
+
217
478
  ## <span id="license">License</span>
218
479
 
219
480
  [@qubit-ltd/logging] is distributed under the Apache 2.0 license.