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 +87 -472
- package/dist/format.d.ts +19 -8
- package/dist/format.js +123 -69
- package/dist/format.js.map +1 -1
- package/dist/logger.d.ts +4 -14
- package/dist/logger.js +85 -85
- package/dist/logger.js.map +1 -1
- package/dist/types.d.ts +20 -14
- package/dist/types.js.map +1 -1
- 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
|
-
|
|
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.
|
|
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
|
-
## 🚀
|
|
38
|
+
## 🚀 Quick Start
|
|
39
|
+
|
|
40
|
+
Get up and running in seconds:
|
|
41
41
|
|
|
42
42
|
```ts
|
|
43
|
-
|
|
44
|
-
import
|
|
43
|
+
import { createLogger, format } from 'scribelog';
|
|
44
|
+
import chalk from 'chalk';
|
|
45
45
|
|
|
46
|
-
//
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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
|
-
|
|
82
|
-
|
|
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
|
-
**
|
|
68
|
+
**Default Console Output (example):**
|
|
86
69
|
|
|
87
70
|
```bash
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
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
|
-
##
|
|
101
|
-
|
|
102
|
-
Create and configure your logger using `createLogger(options?: LoggerOptions)`.
|
|
80
|
+
## 📘 Full Documentation
|
|
103
81
|
|
|
104
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
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
|
-
|
|
90
|
+
Configure your logger via `createLogger(options)`. Key options:
|
|
235
91
|
|
|
236
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
]
|
|
114
|
+
],
|
|
115
|
+
defaultMeta: { service: 'file-writer' }
|
|
281
116
|
});
|
|
282
117
|
|
|
283
|
-
|
|
284
|
-
|
|
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
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
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.
|
|
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
|
|
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
|
|