scribelog 1.1.0 → 1.2.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/README.md CHANGED
@@ -3,31 +3,29 @@
3
3
 
4
4
  [![npm version](https://img.shields.io/npm/v/scribelog.svg)](https://www.npmjs.com/package/scribelog)
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
- [![Build Status](https://github.com/tolongames/scribelog/actions/workflows/node.js.yml/badge.svg)](https://github.com/tolongames/scribelog/actions/workflows/node.js.yml)
7
- <!-- Add other badges if you have them (e.g., coverage) -->
6
+ [![Build Status](https://github.com/tolongames/scribelog/actions/workflows/node.js.yml/badge.svg)](https://github.com/tolongames/scribelog/actions/workflows/node.js.yml) <!-- Zaktualizuj URL, jeśli trzeba -->
8
7
 
9
- **Scribelog** is an advanced, highly configurable logging library for Node.js applications, written in TypeScript. It offers flexible formatting, support for multiple destinations (transports), child loggers, automatic error catching, and printf-style interpolation, aiming for a great developer experience.
8
+ **Scribelog** is an advanced, highly configurable logging library for Node.js applications, written in TypeScript. It offers flexible formatting, support for multiple destinations (transports like Console and File), child loggers, automatic error catching, and printf-style interpolation, aiming for a great developer experience.
10
9
 
11
10
  ---
12
11
 
13
12
  ## ✨ Key Features
14
13
 
15
- * **Standard Logging Levels:** Uses familiar levels (`error`, `warn`, `info`, `http`, `verbose`, `debug`, `silly`).
16
- * **Highly Flexible Formatting:** Combine powerful formatters (`simple`, `json`, `timestamp`, `metadata`, `errors`, `splat`, etc.) using a composable API (`format.combine`). Customize timestamps, include/exclude metadata, and more.
17
- * **Printf-Style Logging:** Use `printf`-like placeholders (`%s`, `%d`, `%j`) for easy message interpolation.
18
- * **Console Color Support:** Automatic, readable colorization for the `simple` format in TTY environments.
14
+ **Standard & Custom Logging Levels:** Use familiar levels (`error`, `warn`, `info`, etc.) or define your own custom levels.
15
+ * **Highly Flexible Formatting:** Combine powerful formatters (`simple`, `json`, `timestamp`, `metadata`, `errors`, `splat`) using a composable API (`format.combine`). Customize outputs easily, including color themes.
16
+ * **Printf-Style Logging:** Use `printf`-like placeholders (`%s`, `%d`, `%j`) via `format.splat()` for easy message interpolation.
17
+ * **Console Color Support:** Automatic, readable colorization for the `simple` format in TTY environments, with customizable themes.
19
18
  * **Multiple Transports:** Log to different destinations. Built-in `ConsoleTransport` and `FileTransport` with rotation options.
20
19
  * **Child Loggers:** Easily create contextual loggers (`logger.child({...})`) that inherit settings but add specific metadata (like `requestId`).
21
20
  * **Automatic Error Handling:** Optionally catch and log `uncaughtException` and `unhandledRejection` events, including stack traces.
22
21
  * **TypeScript First:** Written entirely in TypeScript for type safety and excellent editor autocompletion.
23
22
 
24
- **Explore all features in the [Full Documentation](./DOCUMENTATION.md)!** ⬅
25
-
26
23
  ---
27
24
 
28
25
  ## 📦 Installation
29
26
 
30
27
  ```bash
28
+ # Core library
31
29
  npm install scribelog
32
30
  # or
33
31
  yarn add scribelog
@@ -37,511 +35,128 @@ pnpm add scribelog
37
35
 
38
36
  ---
39
37
 
40
- ## 🚀 Basic Usage
38
+ ## 🚀 Quick Start
39
+
40
+ Get up and running in seconds:
41
41
 
42
42
  ```ts
43
- // Import necessary functions and types
44
- import { createLogger, format, transports } from 'scribelog';
43
+ import { createLogger, format } from 'scribelog';
44
+ import chalk from 'chalk';
45
45
 
46
- // Create a logger with default settings:
47
- // - Level: 'info'
48
- // - Format: Simple, colored output to console (defaultSimpleFormat)
49
- // - Transport: Console
50
- const logger = createLogger();
51
-
52
- // Standard logging
53
- logger.info('Application started successfully.');
54
- logger.warn('Warning: Cache memory usage high.', { usage: '85%' }); // With metadata
55
-
56
- // Printf-style formatting (using the default format's built-in splat())
57
- const username = 'Alice';
58
- const userId = 123;
59
- logger.info('User %s (ID: %d) logged in.', username, userId);
60
-
61
- // Correct way to log Errors (pass error object in metadata)
62
- const dbError = new Error('Database connection timeout');
63
- (dbError as any).code = 'DB_TIMEOUT'; // Add custom properties
64
- logger.error('Database Error Occurred', { error: dbError }); // format.errors() will process this
65
-
66
- // Log to a file in JSON format
67
- const fileLogger = createLogger({
68
- level: 'debug', // Log more details to the file
69
- transports: [
70
- new transports.File({
71
- filename: 'app-%DATE%.log', // Filename pattern (date-fns)
72
- interval: '1d', // Rotate daily
73
- path: './logs', // Store logs in a 'logs' subfolder
74
- compress: 'gzip', // Compress rotated files
75
- maxFiles: 7, // Keep 7 days of logs
76
- format: format.defaultJsonFormat // Log as JSON to the file
46
+ // Logger with custom color theme and default settings
47
+ const logger = createLogger({
48
+ level: 'debug',
49
+ format: format.combine(
50
+ format.timestamp(),
51
+ format.simple({
52
+ colors: true,
53
+ levelColors: {
54
+ error: chalk.bgRed.white,
55
+ warn: chalk.yellow.bold,
56
+ info: chalk.green,
57
+ debug: chalk.blue,
58
+ },
77
59
  })
78
- ]
60
+ ),
79
61
  });
80
62
 
81
- fileLogger.debug('Writing detailed debug log to file.', { data: { complex: true }});
82
- fileLogger.info('User action logged to file.', { userId: 456 });
63
+ logger.info('Scribelog is ready!');
64
+ logger.warn('Something seems off...', { detail: 'Cache size exceeded limit' });
65
+ logger.error('An error occurred!', { error: new Error('Test error') });
83
66
  ```
84
67
 
85
- **Example Console Output (Default Simple Format with Colors):**
68
+ **Default Console Output (example):**
86
69
 
87
70
  ```bash
88
- # (Timestamps gray, Levels colored, Metadata inspected)
89
- 2024-05-01T10:00:00.123Z [INFO]: Application started successfully.
90
- 2024-05-01T10:00:01.456Z [WARN]: Warning: Cache memory usage high. { usage: '85%' }
91
- 2024-05-01T10:00:01.890Z [INFO]: User Alice (ID: 123) logged in.
92
- 2024-05-01T10:00:02.789Z [ERROR]: Database connection timeout { exception: true, eventType: undefined, errorName: 'Error', code: 'DB_TIMEOUT' }
93
- Error: Database connection timeout
94
- at <anonymous>:10:17
95
- ... (stack trace) ...
71
+ 2025-05-01T12:00:00.123Z [INFO]: Scribelog is ready!
72
+ 2025-05-01T12:00:00.125Z [WARN]: Something seems off... { detail: 'Cache size exceeded limit' }
73
+ 2025-05-01T12:00:00.127Z [ERROR]: An error occurred! { errorName: 'Error', exception: true }
74
+ Error: Test error
75
+ at <anonymous>:... (stack trace)
96
76
  ```
97
77
 
98
78
  ---
99
79
 
100
- ## ⚙️ Configuration
101
-
102
- Create and configure your logger using `createLogger(options?: LoggerOptions)`.
80
+ ## 📘 Full Documentation
103
81
 
104
- **`LoggerOptions` Interface:**
82
+ This README covers the basics. For a comprehensive guide covering **all configuration options, formatters (like `json`, custom `timestamp` formats), transports (`FileTransport` with rotation), child loggers, error handling details, and advanced examples**, please see the:
105
83
 
106
- | Option | Type | Default | Description |
107
- | :------------------ | :--------------------------- | :------------------------- | :-------------------------------------------------------------------------- |
108
- | `level` | `string` | `'info'` | Minimum level to log (e.g., 'debug', 'warn'). |
109
- | `format` | `LogFormat` | `format.defaultSimpleFormat` | Default formatter pipeline for the logger. |
110
- | `transports` | `Transport[]` | `[new transports.Console()]` | Array of transport instances (where to send logs). |
111
- | `defaultMeta` | `Record<string, any>` | `undefined` | Metadata automatically included in all logs from this instance. |
112
- | `handleExceptions` | `boolean` | `false` | Catch and log `uncaughtException` events. |
113
- | `handleRejections` | `boolean` | `false` | Catch and log `unhandledRejection` events. |
114
- | `exitOnError` | `boolean` | `true` | If handling exceptions/rejections, exit process (`process.exit(1)`) after logging. |
115
-
116
- **Example: Advanced Configuration**
117
-
118
- ```ts
119
- import { createLogger, format, transports, LogLevel } from 'scribelog';
120
-
121
- // Helper function to safely get log level from environment
122
- function getLogLevel(): LogLevel { /* ... (implementation from previous example) ... */ }
123
-
124
- const advancedLogger = createLogger({
125
- level: getLogLevel(),
126
- format: format.combine( // Custom format pipeline
127
- format.errors({ stack: true }),
128
- format.splat(), // Apply splat formatting early
129
- format.timestamp({ format: 'isoDateTime' }), // Use date-fns named format
130
- format.level(),
131
- format.message(),
132
- format.metadata({ alias: 'context' }), // Nest metadata
133
- format.json() // Output as JSON
134
- ),
135
- transports: [
136
- // Log info and above to console with simple format
137
- new transports.Console({
138
- level: 'info',
139
- format: format.defaultSimpleFormat // Override main format
140
- }),
141
- // Log everything to a rotating file
142
- new transports.File({
143
- filename: '/var/log/my-app/app.log',
144
- level: 'debug', // Log everything to file
145
- // format: // Inherits the JSON format from the logger
146
- size: '10M', // Rotate after 10 MB
147
- maxFiles: 5, // Keep 5 rotated files
148
- compress: 'gzip'
149
- })
150
- ],
151
- defaultMeta: {
152
- service: 'advanced-service',
153
- pid: process.pid,
154
- },
155
- handleExceptions: true,
156
- handleRejections: true,
157
- exitOnError: false // Don't exit automatically
158
- });
159
-
160
- advancedLogger.info('Advanced logger ready.');
161
- advancedLogger.debug('This goes only to the file transport as JSON.');
162
- advancedLogger.error('An error occurred!', { error: new Error("Config read failed"), critical: true });
163
- ```
84
+ ➡️ **[Detailed Documentation](./DOCUMENTATION.md)** ⬅️
164
85
 
165
86
  ---
166
87
 
167
- ## 📊 Logging Levels
168
-
169
- (Content is the same as before - list of levels and explanation)
170
-
171
- ```text
172
- error: 0, warn: 1, info: 2, http: 3, verbose: 4, debug: 5, silly: 6
173
- ```
174
- ---
175
-
176
- ## 🎨 Formatting
177
-
178
- Formatters transform the log `info` object. Chain them using `format.combine(...)`. The order matters!
179
-
180
- **How it Works:**
181
- `log(msg, ...args)` -> Creates `LogInfo { message, splat?, ... }` -> Passes to `format` -> `combine` applies chain -> Result passed to `transport.log()`.
182
-
183
- ### Available Formatters
184
-
185
- * **`format.timestamp(options?)`**: Adds/formats a timestamp (default: ISO).
186
- * `alias?: string` (default: `'timestamp'`)
187
- * `format?: string | ((date: Date) => string)` (`date-fns` format or function).
188
- * **`format.level(options?)`**: Adds the log level string.
189
- * `alias?: string` (default: `'level'`).
190
- * **`format.message(options?)`**: Adds the log message string (after potential `splat` formatting).
191
- * `alias?: string` (default: `'message'`).
192
- * **`format.splat()`**: Interpolates the `message` string using `util.format` and arguments found in `info.splat`. Place **after** `errors()` but **before** `message()` and `metadata()`.
193
- * **`format.errors(options?)`**: Extracts info from an `Error` object (expected at `info.error`). Adds `errorName`, `stack?`, etc. Place **early** in the chain.
194
- * `stack?: boolean` (default: `true`).
195
- * **`format.metadata(options?)`**: Gathers remaining properties. Excludes standard fields (`level`, `message`, `timestamp`, etc.) and error fields.
196
- * `alias?: string`: Nest metadata under this key.
197
- * `exclude?: string[]`: Additional keys to exclude.
198
- * **`format.json(options?)`**: **Terminal.** Serializes `info` to JSON.
199
- * `space?: string | number`: Pretty-print spaces.
200
- * **`format.simple(options?)`**: **Terminal.** Creates a human-readable string (colored if TTY). Includes `timestamp`, `level`, `message`, `{ metadata }`, and `stack` (new line).
201
- * `colors?: boolean`: Force colors (default: auto-detect).
202
-
203
- ### Combining Formatters (`format.combine`)
204
-
205
- ```ts
206
- import { createLogger, format } from 'scribelog';
207
-
208
- // Example: Simple format with printf-style interpolation first
209
- const printfSimpleFormat = format.combine(
210
- format.splat(), // Apply interpolation first
211
- format.errors({ stack: false }),
212
- format.timestamp({ format: 'HH:mm:ss' }),
213
- format.level(),
214
- format.message(), // Will use the result from splat()
215
- format.metadata(),
216
- format.simple()
217
- );
218
- const printfLogger = createLogger({ format: printfSimpleFormat });
219
- printfLogger.info('User %s logged in (ID: %d)', 'Bob', 42, { ip: '127.0.0.1' });
220
- // Output: 11:22:33 [INFO]: User Bob logged in (ID: 42) { ip: '127.0.0.1' }
221
- ```
222
-
223
- ### Predefined Formats
224
-
225
- * `format.defaultSimpleFormat`: `combine(errors(stack), splat(), timestamp(), level(), message(), metadata(), simple())`. **Default for `createLogger`.**
226
- * `format.defaultJsonFormat`: `combine(errors(stack), splat(), timestamp(), level(), message(), metadata(), json())`.
227
-
228
- ---
229
-
230
- ## 📤 Transports
231
-
232
- Define log destinations.
88
+ ## ⚙️ Basic Configuration (Overview)
233
89
 
234
- ### `transports.Console(options?: ConsoleTransportOptions)`
90
+ Configure your logger via `createLogger(options)`. Key options:
235
91
 
236
- Logs to `process.stdout` / `process.stderr`.
92
+ * `level`: `'info'` (default), `'debug'`, `'warn'`, etc., or **custom levels** (e.g., `'critical'`, `'trace'`).
93
+ * `format`: Use `format.combine(...)` with formatters like `format.simple()`, `format.json()`, `format.timestamp()`, `format.splat()`, `format.errors()`, `format.metadata()`. Default is `format.defaultSimpleFormat`. You can also define **custom color themes** for log levels.
94
+ * `transports`: Array of `new transports.Console({...})` or `new transports.File({...})`. Default is one Console transport.
95
+ * `defaultMeta`: An object with data to add to every log message.
96
+ * `handleExceptions`, `handleRejections`, `exitOnError`: For automatic error catching.
237
97
 
238
- * `level?: string`: Transport-specific minimum level.
239
- * `format?: LogFormat`: Transport-specific format.
240
- * `useStdErrLevels?: string[]`: Levels to log to `stderr` (default: `['error']`).
241
-
242
- ### `transports.File(options: FileTransportOptions)`
243
-
244
- Logs to a rotating file using [`rotating-file-stream`](https://github.com/iccicci/rotating-file-stream).
245
-
246
- * `filename: string`: Path/name of the log file (required). Can include date patterns like `%DATE%`.
247
- * `level?: string`: Transport-specific minimum level.
248
- * `format?: LogFormat`: Transport-specific format (defaults to `format.defaultJsonFormat`).
249
- * `size?: string`: Max file size before rotation (e.g., `'10M'`).
250
- * `interval?: string`: Rotation interval (e.g., `'1d'`, `'2h'`).
251
- * `path?: string`: Directory for rotated/archived files.
252
- * `compress?: string | boolean`: Compress rotated files (`'gzip'` or `true`).
253
- * `maxFiles?: number`: Max number of rotated files to keep.
254
- * `maxSize?: string`: Max total size of all log files.
255
- * `createPath?: boolean`: Create log directory if it doesn't exist (default: `true`).
256
- * `fsWriteStreamOptions?: object`: Options passed to `fs.createWriteStream`.
257
- * *(See `rotating-file-stream` docs for more options like `utc`, generators)*
258
-
259
- **Example: Logging to Console and File**
98
+ **Example 1: Logging JSON to a File**
260
99
 
261
100
  ```ts
262
101
  import { createLogger, format, transports } from 'scribelog';
263
102
 
264
- const fileAndConsoleLogger = createLogger({
103
+ const fileJsonLogger = createLogger({
265
104
  level: 'debug',
105
+ // Use the predefined JSON format (includes error handling, splat, timestamp etc.)
106
+ format: format.defaultJsonFormat,
266
107
  transports: [
267
- // Console for immediate feedback (info and above)
268
- new transports.Console({
269
- level: 'info',
270
- format: format.simple({ colors: true })
271
- }),
272
- // File for detailed logs (debug and above, JSON)
273
108
  new transports.File({
274
- filename: 'app-debug.log',
275
- level: 'debug',
276
- format: format.defaultJsonFormat,
277
- size: '5M', // Rotate every 5MB
278
- maxFiles: 3
109
+ filename: 'application.log', // Log to application.log
110
+ level: 'debug', // Log debug and above to the file
111
+ size: '10M', // Rotate at 10 MB
112
+ maxFiles: 5 // Keep 5 rotated files
279
113
  })
280
- ]
114
+ ],
115
+ defaultMeta: { service: 'file-writer' }
281
116
  });
282
117
 
283
- fileAndConsoleLogger.debug('Detailed info only in file');
284
- fileAndConsoleLogger.info('General info in console and file');
285
- fileAndConsoleLogger.error('Error in console and file', { error: new Error('Failure') });
286
- ```
287
-
288
- ---
289
-
290
- ## 🌱 Child Loggers
291
-
292
- ```ts
293
- import { createLogger } from 'scribelog';
294
-
295
- const baseLogger = createLogger({ level: 'debug', defaultMeta: { app: 'my-api' } });
296
-
297
- function processUserData(userId: string) {
298
- // Create a logger specific to this user's context
299
- const userLogger = baseLogger.child({ userId, module: 'userProcessing' });
300
-
301
- userLogger.debug('Starting data processing'); // Includes { app: 'my-api', userId: '...', module: '...' }
302
- // ...
303
- userLogger.info('Data processed');
304
- }
305
-
306
- function processAdminTask(adminId: string) {
307
- // Create a logger for admin tasks
308
- const adminLogger = baseLogger.child({ adminId, scope: 'admin' });
309
- adminLogger.info('Performing admin task');
310
- }
311
-
312
- processUserData('user-77');
313
- processAdminTask('admin-01');
118
+ fileJsonLogger.debug('Writing JSON log to file', { id: 1 });
119
+ fileJsonLogger.error('File write error occurred', { error: new Error('Disk full'), file: 'data.txt' });
314
120
  ```
315
121
 
316
- ---
317
-
318
- ## 🛠️ Error Handling
319
-
320
- Set `handleExceptions: true` and/or `handleRejections: true` in `createLogger` options to automatically log fatal errors.
122
+ **Example 2: Using Custom Levels and Colors**
321
123
 
322
124
  ```ts
323
125
  import { createLogger, format } from 'scribelog';
126
+ import chalk from 'chalk';
127
+
128
+ const customLevels = {
129
+ critical: 0,
130
+ error: 1,
131
+ warn: 2,
132
+ info: 3,
133
+ debug: 4,
134
+ trace: 5,
135
+ };
324
136
 
325
137
  const logger = createLogger({
326
- level: 'info',
327
- format: format.defaultJsonFormat, // Log errors as JSON for easier parsing
328
- handleExceptions: true,
329
- handleRejections: true,
330
- exitOnError: true // Default behavior: Exit after logging fatal error
138
+ levels: customLevels,
139
+ level: 'trace',
140
+ format: format.combine(
141
+ format.timestamp(),
142
+ format.simple({
143
+ colors: true,
144
+ levelColors: {
145
+ critical: chalk.bgRed.white.bold,
146
+ error: chalk.red,
147
+ warn: chalk.yellow,
148
+ info: chalk.green,
149
+ debug: chalk.blue,
150
+ trace: chalk.cyan,
151
+ },
152
+ })
153
+ ),
331
154
  });
332
155
 
333
- logger.info('Application running with error handlers.');
334
-
335
- // Example of what would be caught:
336
- // setTimeout(() => { throw new Error('Something broke badly!'); }, 50);
337
- // Output (JSON): {"level":"error","message":"Something broke badly!","timestamp":"...","exception":true,"eventType":"uncaughtException","errorName":"Error","stack":"..."}
338
- // ... and process exits
339
-
340
- // Example of what would be caught:
341
- // Promise.reject('Unhandled promise rejection reason');
342
- // Output (JSON): {"level":"error","message":"Unhandled promise rejection reason","timestamp":"...","exception":true,"eventType":"unhandledRejection","errorName":"Error","stack":"...","originalReason":"..."}
343
- // ... and process exits
156
+ logger.critical('Critical issue!');
157
+ logger.trace('Trace message for debugging.');
344
158
  ```
345
159
 
346
- The logger adds `{ exception: true, eventType: '...', ...errorDetails }` to the log metadata for these events, processed by the `format.errors()` formatter. Remember to have `format.errors()` in your format chain to see detailed error info.
347
-
348
- ---
349
-
350
- ## 💻 Showcase
351
-
352
- You can run this script to see a demonstration of various Scribelog features in action.
353
-
354
- <details>
355
- <summary>Click to show/hide showcase.ts code</summary>
356
-
357
- ```ts
358
- // showcase.ts
359
- // Import everything needed from scribelog
360
- import {
361
- createLogger,
362
- format, // Object containing formatters
363
- transports, // Object containing transports
364
- Logger, // Logger interface type
365
- LogLevel, // Log level type ('info', 'debug', etc.)
366
- LogFormat, // Formatter function type
367
- Transport, // Transport interface type
368
- LoggerOptions // Configuration options type
369
- } from 'scribelog'; // Import from your published package
370
- // Import 'process' for PID access
371
- import process from 'process';
372
- // Import 'crypto' for generating unique IDs
373
- import crypto from 'crypto';
374
- // Import 'date-fns' for custom date formatting (used in one example)
375
- import { format as formatDate } from 'date-fns';
376
- // Import chalk to demonstrate color control (optional for user)
377
- import chalk from 'chalk';
378
-
379
- // --- MAIN DEMO FUNCTION ---
380
- async function runShowcase() {
381
- console.log('\n===========================================');
382
- console.log('🚀 Scribelog Showcase - All Features Demo 🚀');
383
- console.log('===========================================\n');
384
-
385
- // === 1. Basic Configuration & Levels ===
386
- console.log('--- 1. Basic Configuration & Levels ---');
387
- const logger1 = createLogger({ level: 'debug' });
388
- logger1.info('Logger 1 (level: debug, format: simple)');
389
- logger1.warn('Warning from Logger 1');
390
- logger1.debug('Debug message from Logger 1 (should appear)');
391
- logger1.error('Error from Logger 1');
392
-
393
- // === 2. Different Formats ===
394
- console.log('\n--- 2. Different Formats ---');
395
-
396
- // 2a. JSON Format
397
- console.log('\n--- 2a. JSON Format ---');
398
- const logger2a = createLogger({ format: format.defaultJsonFormat, level: 'info' });
399
- logger2a.info('Log in JSON format.', { data: true, value: 123 });
400
- const jsonError = new Error("JSON Formatted Error");
401
- (jsonError as any).code = "E_JSON";
402
- logger2a.error('An error occurred (JSON)', { error: jsonError, user: 'admin' });
403
-
404
- // 2b. Custom Simple Format (Colored)
405
- console.log('\n--- 2b. Custom Simple Format (Colored) ---');
406
- const customSimpleFormat = format.combine(
407
- format.timestamp({ format: 'HH:mm:ss' }),
408
- format.level(),
409
- format.splat(), // Apply splat formatting
410
- format.message(),
411
- format.metadata({ exclude: ['pid'] }),
412
- format.errors({ stack: false }),
413
- format.simple({ colors: true })
414
- );
415
- const logger2b = createLogger({ format: customSimpleFormat, level: 'info' });
416
- const originalChalkLevel2b = chalk.level;
417
- chalk.level = 1; // Force colors
418
- logger2b.info('Custom simple format for %s', 'user', { pid: 12345, user: 'demo' }); // Use splat
419
- logger2b.error('Another error (custom simple)', { error: new Error("Simple format error")});
420
- chalk.level = originalChalkLevel2b; // Restore
421
-
422
- // 2c. Custom JSON Format with Aliases and Nesting
423
- console.log('\n--- 2c. Custom JSON Format (Aliases & Nesting) ---');
424
- const customJson = format.combine(
425
- format.errors({ stack: true }), // Handle errors first
426
- format.splat(), // Then splat
427
- format.timestamp({ alias: '@timestamp' }),
428
- format.level({ alias: 'severity' }),
429
- format.message(),
430
- format.metadata({ alias: 'details' }),
431
- format.json()
432
- );
433
- const logger2c = createLogger({ format: customJson, level: 'info' });
434
- logger2c.warn('Warn %s nested meta', 'with', { transactionId: 'xyz', status: 'WARN' }); // Use splat
435
- const nestedError = new Error("Nested Error");
436
- nestedError.stack = "Fake stack\n at place";
437
- logger2c.error("Error with nested meta", { error: nestedError, code: 503 });
438
-
439
-
440
- // === 3. Multiple Transports ===
441
- console.log('\n--- 3. Multiple Transports ---');
442
- const originalChalkLevel3 = chalk.level;
443
- chalk.level = 0; // Disable colors for comparison
444
- const logger3 = createLogger({
445
- level: 'debug',
446
- transports: [
447
- new transports.Console({
448
- level: 'info',
449
- format: format.defaultSimpleFormat, // Contains splat()
450
- useStdErrLevels: ['error']
451
- }),
452
- new transports.Console({
453
- level: 'debug',
454
- format: format.defaultJsonFormat, // Contains splat()
455
- useStdErrLevels: ['warn', 'error']
456
- })
457
- ]
458
- });
459
- logger3.debug('Debug log: %s', 'JSON only');
460
- logger3.info('Info log: %s', 'Simple & JSON');
461
- logger3.warn('Warn log: %s', 'Simple(stdout) & JSON(stderr)');
462
- logger3.error('Error log: %s', 'Simple(stderr) & JSON(stderr)');
463
- chalk.level = originalChalkLevel3; // Restore
464
-
465
- // === 4. Loggery Potomne (child) ===
466
- console.log('\n--- 4. Child Loggers ---');
467
- const parentLogger = createLogger({
468
- level: 'debug',
469
- format: format.simple({ colors: false }), // Use simple, no colors
470
- defaultMeta: { service: 'MainService' }
471
- });
472
- parentLogger.info('Parent log.');
473
- const childLogger1 = parentLogger.child({ module: 'ModuleA' });
474
- childLogger1.info('Child 1 log for action: %s', 'read'); // Use splat
475
- const childLogger2 = childLogger1.child({ function: 'doWork', module: 'OverrideModule' });
476
- childLogger2.debug('Child 2 log (debug).', { value: 42 });
477
-
478
- // === 5. logEntry ===
479
- console.log('\n--- 5. logEntry Method ---');
480
- const entryLogger = createLogger({ level: 'http' });
481
- entryLogger.logEntry({
482
- level: 'http',
483
- message: 'Manual %s entry with custom data %j', // Add splat placeholders
484
- splat: ['log', { status: 201 }], // Provide splat data
485
- method: 'POST', url: '/api/users', statusCode: 201,
486
- });
487
- entryLogger.logEntry({ level: 'info', message: 'This info entry will also show' });
488
-
489
- // === 6. Obsługa wyjątków i odrzuceń (Symulacja) ===
490
- // (Keep this section as in the previous example, it doesn't need _internalExit mock)
491
- console.log('\n--- 6. Exception/Rejection Handling (Simulating real events) ---');
492
- const handleErrorsAndExit = false;
493
- let errorHandlingLogger: Logger | undefined = undefined;
494
-
495
- console.log(`Creating logger with handleExceptions/Rejections, exitOnError: ${handleErrorsAndExit}`);
496
- errorHandlingLogger = createLogger({
497
- level: 'debug',
498
- transports: [new transports.Console({ format: format.defaultSimpleFormat })],
499
- handleExceptions: true,
500
- handleRejections: true,
501
- exitOnError: handleErrorsAndExit
502
- });
503
- errorHandlingLogger.info(`Error handlers active (exitOnError: ${handleErrorsAndExit}).`);
504
-
505
- console.log("Simulating unhandled rejection (will be logged)...");
506
- Promise.reject("Simulated rejection reason (handled by logger)");
507
-
508
- console.log("Simulating uncaught exception in 100ms (will be logged)...");
509
- const exceptionTimer = setTimeout(() => {
510
- try { throw new Error("Simulated uncaught exception (handled by logger)"); }
511
- catch (e) { process.emit('uncaughtException', e as Error); }
512
- if (!handleErrorsAndExit && errorHandlingLogger && typeof (errorHandlingLogger as any).removeExceptionHandlers === 'function') {
513
- (errorHandlingLogger as any).removeExceptionHandlers();
514
- console.log("Error handlers removed for no-exit logger.");
515
- }
516
- console.log('\n--- Showcase Finished (Error Handlers Tested) ---');
517
- }, 100);
518
-
519
- if (!handleErrorsAndExit) {
520
- await new Promise(resolve => setTimeout(resolve, 300));
521
- } else {
522
- // If we expect exit, keep the process running briefly
523
- // This usually isn't needed as process.exit stops everything
524
- // await new Promise(resolve => setTimeout(resolve, 1500));
525
- }
526
-
527
- } // End runShowcase
528
-
529
- runShowcase().catch(e => {
530
- console.error("!!! Unexpected error running showcase:", e);
531
- });
532
- ```
533
-
534
- </details>
535
-
536
- If you have any questions about scribelog or would like to know more about how to use any of the features. You can write to me on discord:
537
- theonlytolon
538
-
539
- ---
540
-
541
- ## 📘 Documentation
542
-
543
- For detailed documentation covering all features, configuration options, and advanced examples, please see the [**Full Documentation**](./DOCUMENTATION.md).
544
-
545
160
  ---
546
161
 
547
162
  ## 📚 Future Work
@@ -554,7 +169,7 @@ For detailed documentation covering all features, configuration options, and adv
554
169
 
555
170
  ## 🤝 Contributing
556
171
 
557
- Contributions are welcome! Please feel free to submit issues and pull requests. Check for any existing guidelines or open an issue to discuss larger changes.
172
+ Contributions are welcome! Please feel free to submit issues and pull requests on the [GitHub repository](https://github.com/tolongames/scribelog).
558
173
 
559
174
  ---
560
175