scribelog 1.1.0 → 1.1.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/README.md +54 -477
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,31 +3,29 @@
|
|
|
3
3
|
|
|
4
4
|
[](https://www.npmjs.com/package/scribelog)
|
|
5
5
|
[](https://opensource.org/licenses/MIT)
|
|
6
|
-
[](https://github.com/tolongames/scribelog/actions/workflows/node.js.yml)
|
|
7
|
-
<!-- Add other badges if you have them (e.g., coverage) -->
|
|
6
|
+
[](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
14
|
* **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
|
|
17
|
-
* **Printf-Style Logging:** Use `printf`-like placeholders (`%s`, `%d`, `%j`) for easy message interpolation.
|
|
15
|
+
* **Highly Flexible Formatting:** Combine powerful formatters (`simple`, `json`, `timestamp`, `metadata`, `errors`, `splat`) using a composable API (`format.combine`). Customize outputs easily.
|
|
16
|
+
* **Printf-Style Logging:** Use `printf`-like placeholders (`%s`, `%d`, `%j`) via `format.splat()` for easy message interpolation.
|
|
18
17
|
* **Console Color Support:** Automatic, readable colorization for the `simple` format in TTY environments.
|
|
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,90 @@ pnpm add scribelog
|
|
|
37
35
|
|
|
38
36
|
---
|
|
39
37
|
|
|
40
|
-
## 🚀
|
|
38
|
+
## 🚀 Quick Start
|
|
39
|
+
|
|
40
|
+
Get up and running in seconds:
|
|
41
41
|
|
|
42
42
|
```ts
|
|
43
|
-
|
|
44
|
-
import { createLogger, format, transports } from 'scribelog';
|
|
43
|
+
import { createLogger } from 'scribelog';
|
|
45
44
|
|
|
46
|
-
//
|
|
45
|
+
// Logger with default settings:
|
|
47
46
|
// - Level: 'info'
|
|
48
|
-
// - Format: Simple, colored output
|
|
47
|
+
// - Format: Simple, colored output (if TTY)
|
|
49
48
|
// - Transport: Console
|
|
50
49
|
const logger = createLogger();
|
|
51
50
|
|
|
52
|
-
|
|
53
|
-
logger.
|
|
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);
|
|
51
|
+
logger.info('Scribelog is ready!');
|
|
52
|
+
logger.warn('Something seems off...', { detail: 'Cache size exceeded limit' });
|
|
60
53
|
|
|
61
|
-
|
|
62
|
-
const
|
|
63
|
-
(
|
|
64
|
-
logger.error('Database Error Occurred', { error: dbError }); // format.errors() will process this
|
|
54
|
+
const userId = 'user-42';
|
|
55
|
+
const action = 'login';
|
|
56
|
+
logger.info('User %s performed action: %s', userId, action); // Printf-style
|
|
65
57
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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
|
|
77
|
-
})
|
|
78
|
-
]
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
fileLogger.debug('Writing detailed debug log to file.', { data: { complex: true }});
|
|
82
|
-
fileLogger.info('User action logged to file.', { userId: 456 });
|
|
58
|
+
try {
|
|
59
|
+
// Simulate an error
|
|
60
|
+
throw new Error('Failed to retrieve data');
|
|
61
|
+
} catch(error) {
|
|
62
|
+
// Log the error object correctly
|
|
63
|
+
logger.error('Data retrieval failed', { error: error as Error });
|
|
64
|
+
}
|
|
83
65
|
```
|
|
84
66
|
|
|
85
|
-
**
|
|
67
|
+
**Default Console Output (example):**
|
|
86
68
|
|
|
87
69
|
```bash
|
|
88
|
-
|
|
89
|
-
2024-05-
|
|
90
|
-
2024-05-
|
|
91
|
-
2024-05-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
at <anonymous>:10:17
|
|
95
|
-
... (stack trace) ...
|
|
70
|
+
2024-05-01T12:00:00.123Z [INFO]: Scribelog is ready!
|
|
71
|
+
2024-05-01T12:00:00.125Z [WARN]: Something seems off... { detail: 'Cache size exceeded limit' }
|
|
72
|
+
2024-05-01T12:00:00.127Z [INFO]: User user-42 performed action: login
|
|
73
|
+
2024-05-01T12:00:00.129Z [ERROR]: Failed to retrieve data { errorName: 'Error', exception: true }
|
|
74
|
+
Error: Failed to retrieve data
|
|
75
|
+
at <anonymous>:... (stack trace)
|
|
96
76
|
```
|
|
97
77
|
|
|
98
78
|
---
|
|
99
79
|
|
|
100
|
-
##
|
|
101
|
-
|
|
102
|
-
Create and configure your logger using `createLogger(options?: LoggerOptions)`.
|
|
103
|
-
|
|
104
|
-
**`LoggerOptions` Interface:**
|
|
105
|
-
|
|
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
|
-
```
|
|
164
|
-
|
|
165
|
-
---
|
|
80
|
+
## 📘 Full Documentation
|
|
166
81
|
|
|
167
|
-
|
|
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:
|
|
168
83
|
|
|
169
|
-
|
|
84
|
+
➡️ **[Detailed Documentation](./DOCUMENTATION.md)** ⬅️
|
|
170
85
|
|
|
171
|
-
```text
|
|
172
|
-
error: 0, warn: 1, info: 2, http: 3, verbose: 4, debug: 5, silly: 6
|
|
173
|
-
```
|
|
174
86
|
---
|
|
175
87
|
|
|
176
|
-
##
|
|
177
|
-
|
|
178
|
-
Formatters transform the log `info` object. Chain them using `format.combine(...)`. The order matters!
|
|
88
|
+
## ⚙️ Basic Configuration (Overview)
|
|
179
89
|
|
|
180
|
-
|
|
181
|
-
`log(msg, ...args)` -> Creates `LogInfo { message, splat?, ... }` -> Passes to `format` -> `combine` applies chain -> Result passed to `transport.log()`.
|
|
90
|
+
Configure your logger via `createLogger(options)`. Key options:
|
|
182
91
|
|
|
183
|
-
|
|
92
|
+
* `level`: `'info'` (default), `'debug'`, `'warn'`, etc.
|
|
93
|
+
* `format`: Use `format.combine(...)` with formatters like `format.simple()`, `format.json()`, `format.timestamp()`, `format.splat()`, `format.errors()`, `format.metadata()`. Default is `format.defaultSimpleFormat`.
|
|
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.
|
|
184
97
|
|
|
185
|
-
|
|
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.
|
|
233
|
-
|
|
234
|
-
### `transports.Console(options?: ConsoleTransportOptions)`
|
|
235
|
-
|
|
236
|
-
Logs to `process.stdout` / `process.stderr`.
|
|
237
|
-
|
|
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: Logging JSON to a File**
|
|
260
99
|
|
|
261
100
|
```ts
|
|
262
101
|
import { createLogger, format, transports } from 'scribelog';
|
|
263
102
|
|
|
264
|
-
const
|
|
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: '
|
|
275
|
-
level: 'debug',
|
|
276
|
-
|
|
277
|
-
|
|
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
|
-
]
|
|
281
|
-
}
|
|
282
|
-
|
|
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');
|
|
314
|
-
```
|
|
315
|
-
|
|
316
|
-
---
|
|
317
|
-
|
|
318
|
-
## 🛠️ Error Handling
|
|
319
|
-
|
|
320
|
-
Set `handleExceptions: true` and/or `handleRejections: true` in `createLogger` options to automatically log fatal errors.
|
|
321
|
-
|
|
322
|
-
```ts
|
|
323
|
-
import { createLogger, format } from 'scribelog';
|
|
324
|
-
|
|
325
|
-
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
|
|
114
|
+
],
|
|
115
|
+
defaultMeta: { service: 'file-writer' }
|
|
331
116
|
});
|
|
332
117
|
|
|
333
|
-
|
|
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
|
|
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'});
|
|
344
120
|
```
|
|
345
121
|
|
|
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
122
|
---
|
|
546
123
|
|
|
547
124
|
## 📚 Future Work
|
|
@@ -554,12 +131,12 @@ For detailed documentation covering all features, configuration options, and adv
|
|
|
554
131
|
|
|
555
132
|
## 🤝 Contributing
|
|
556
133
|
|
|
557
|
-
Contributions are welcome! Please feel free to submit issues and pull requests
|
|
134
|
+
Contributions are welcome! Please feel free to submit issues and pull requests on the [GitHub repository](https://github.com/tolongames/scribelog).
|
|
558
135
|
|
|
559
136
|
---
|
|
560
137
|
|
|
561
138
|
## 📄 License
|
|
562
139
|
|
|
563
140
|
MIT License
|
|
564
|
-
Copyright (c)
|
|
141
|
+
Copyright (c) 2024 tolongames
|
|
565
142
|
See [LICENSE](./LICENSE) for details.
|