zario 0.3.5 → 0.4.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 +102 -359
- package/dist/cjs/aggregation/LogAggregator.js +60 -31
- package/dist/cjs/core/Formatter.js +3 -4
- package/dist/cjs/core/Logger.js +41 -24
- package/dist/cjs/filters/Filter.js +52 -18
- package/dist/cjs/filters/index.js +0 -1
- package/dist/cjs/index.js +6 -1
- package/dist/cjs/transports/CircuitBreakerTransport.js +171 -0
- package/dist/cjs/transports/DeadLetterQueue.js +129 -0
- package/dist/cjs/transports/FileTransport.js +78 -7
- package/dist/cjs/transports/HttpTransport.js +15 -3
- package/dist/cjs/transports/RetryTransport.js +199 -0
- package/dist/cjs/transports/index.js +3 -0
- package/dist/cjs/types/TypeInterfaces.js +2 -0
- package/dist/cjs/utils/index.js +78 -0
- package/dist/esm/aggregation/LogAggregator.d.ts +8 -29
- package/dist/esm/aggregation/LogAggregator.js +60 -31
- package/dist/esm/core/Formatter.js +1 -2
- package/dist/esm/core/Logger.d.ts +13 -3
- package/dist/esm/core/Logger.js +40 -23
- package/dist/esm/filters/Filter.d.ts +24 -22
- package/dist/esm/filters/Filter.js +47 -17
- package/dist/esm/filters/index.d.ts +0 -1
- package/dist/esm/filters/index.js +0 -1
- package/dist/esm/index.d.ts +3 -2
- package/dist/esm/index.js +6 -3
- package/dist/esm/transports/CircuitBreakerTransport.d.ts +43 -0
- package/dist/esm/transports/CircuitBreakerTransport.js +167 -0
- package/dist/esm/transports/DeadLetterQueue.d.ts +34 -0
- package/dist/esm/transports/DeadLetterQueue.js +92 -0
- package/dist/esm/transports/FileTransport.d.ts +4 -0
- package/dist/esm/transports/FileTransport.js +78 -7
- package/dist/esm/transports/HttpTransport.d.ts +2 -0
- package/dist/esm/transports/HttpTransport.js +15 -3
- package/dist/esm/transports/RetryTransport.d.ts +67 -0
- package/dist/esm/transports/RetryTransport.js +195 -0
- package/dist/esm/transports/Transport.d.ts +1 -0
- package/dist/esm/transports/index.d.ts +3 -0
- package/dist/esm/transports/index.js +3 -0
- package/dist/esm/types/TypeInterfaces.d.ts +7 -0
- package/dist/esm/types/TypeInterfaces.js +1 -0
- package/dist/esm/utils/index.d.ts +15 -0
- package/dist/esm/utils/index.js +72 -0
- package/package.json +87 -71
- package/dist/cjs/filters/SpecificFilters.js +0 -71
- package/dist/cjs/utils/ColorUtil.js +0 -42
- package/dist/cjs/utils/TimeUtil.js +0 -26
- package/dist/cjs/utils/Timerutil.js +0 -22
- package/dist/esm/filters/SpecificFilters.d.ts +0 -41
- package/dist/esm/filters/SpecificFilters.js +0 -64
- package/dist/esm/utils/ColorUtil.d.ts +0 -4
- package/dist/esm/utils/ColorUtil.js +0 -38
- package/dist/esm/utils/TimeUtil.d.ts +0 -3
- package/dist/esm/utils/TimeUtil.js +0 -22
- package/dist/esm/utils/Timerutil.d.ts +0 -8
- package/dist/esm/utils/Timerutil.js +0 -18
package/README.md
CHANGED
|
@@ -1,359 +1,102 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
|
72
|
-
|
|
|
73
|
-
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
})
|
|
104
|
-
]
|
|
105
|
-
});
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
#### HTTP Transport
|
|
109
|
-
|
|
110
|
-
```js
|
|
111
|
-
import { Logger, HttpTransport } from "zario";
|
|
112
|
-
|
|
113
|
-
const logger = new Logger({
|
|
114
|
-
transports: [
|
|
115
|
-
new HttpTransport({
|
|
116
|
-
url: 'https://api.example.com/logs',
|
|
117
|
-
method: 'POST',
|
|
118
|
-
headers: {
|
|
119
|
-
'Content-Type': 'application/json',
|
|
120
|
-
'Authorization': 'Bearer your-token-here'
|
|
121
|
-
},
|
|
122
|
-
timeout: 10000, // Request timeout in ms
|
|
123
|
-
retries: 3 // Number of retry attempts
|
|
124
|
-
})
|
|
125
|
-
]
|
|
126
|
-
});
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
### Advanced Filtering
|
|
130
|
-
|
|
131
|
-
Filter logs based on various criteria using built-in filter classes:
|
|
132
|
-
|
|
133
|
-
```js
|
|
134
|
-
import {
|
|
135
|
-
Logger,
|
|
136
|
-
ConsoleTransport,
|
|
137
|
-
LevelFilter,
|
|
138
|
-
PrefixFilter,
|
|
139
|
-
MetadataFilter,
|
|
140
|
-
CompositeFilter,
|
|
141
|
-
OrFilter,
|
|
142
|
-
PredicateFilter
|
|
143
|
-
} from "zario";
|
|
144
|
-
|
|
145
|
-
// Level filter - only allow specific log levels
|
|
146
|
-
const levelFilter = new LevelFilter(['info', 'error']);
|
|
147
|
-
|
|
148
|
-
// Prefix filter - only allow logs with specific prefixes
|
|
149
|
-
const prefixFilter = new PrefixFilter(['[API]', '[DB]']);
|
|
150
|
-
|
|
151
|
-
// Metadata filter - only allow logs with specific metadata
|
|
152
|
-
const metadataFilter = new MetadataFilter({ userId: 123 });
|
|
153
|
-
|
|
154
|
-
// Composite filter - combines multiple filters with AND logic
|
|
155
|
-
// Note: With an empty array, CompositeFilter allows all logs (vacuous truth)
|
|
156
|
-
const compositeFilter = new CompositeFilter([levelFilter, prefixFilter]);
|
|
157
|
-
|
|
158
|
-
// Or filter - combines multiple filters with OR logic
|
|
159
|
-
// Note: With an empty array, OrFilter blocks all logs (no matching conditions)
|
|
160
|
-
const orFilter = new OrFilter([levelFilter, metadataFilter]);
|
|
161
|
-
|
|
162
|
-
// Predicate filter - custom filtering function
|
|
163
|
-
const predicateFilter = new PredicateFilter((logData) => {
|
|
164
|
-
return logData.level !== 'debug'; // Filter out debug messages
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
// Create logger with filters
|
|
168
|
-
const filteredLogger = new Logger({
|
|
169
|
-
level: 'debug',
|
|
170
|
-
transports: [new ConsoleTransport()],
|
|
171
|
-
filters: [compositeFilter, predicateFilter] // Apply multiple filters
|
|
172
|
-
});
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
### Structured Logging Extensions
|
|
176
|
-
|
|
177
|
-
Enhance your logs with additional metadata using structured logging extensions:
|
|
178
|
-
|
|
179
|
-
```js
|
|
180
|
-
import {
|
|
181
|
-
Logger,
|
|
182
|
-
ConsoleTransport,
|
|
183
|
-
LogEnrichmentPipeline,
|
|
184
|
-
MetadataEnricher
|
|
185
|
-
} from "zario";
|
|
186
|
-
|
|
187
|
-
// Create enrichers to add metadata to logs
|
|
188
|
-
const staticEnricher = MetadataEnricher.addStaticFields({
|
|
189
|
-
service: 'user-service',
|
|
190
|
-
version: '1.0.0'
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
const dynamicEnricher = MetadataEnricher.addDynamicFields(() => ({
|
|
194
|
-
processId: process.pid,
|
|
195
|
-
memoryUsage: process.memoryUsage().heapUsed
|
|
196
|
-
}));
|
|
197
|
-
|
|
198
|
-
const processEnricher = MetadataEnricher.addProcessInfo();
|
|
199
|
-
const envEnricher = MetadataEnricher.addEnvironmentInfo();
|
|
200
|
-
|
|
201
|
-
// Create a pipeline with multiple enrichers
|
|
202
|
-
const enricherPipeline = new LogEnrichmentPipeline([
|
|
203
|
-
staticEnricher,
|
|
204
|
-
dynamicEnricher,
|
|
205
|
-
processEnricher,
|
|
206
|
-
envEnricher
|
|
207
|
-
]);
|
|
208
|
-
|
|
209
|
-
// Create logger with enrichers
|
|
210
|
-
const enrichedLogger = new Logger({
|
|
211
|
-
level: 'info',
|
|
212
|
-
transports: [new ConsoleTransport()],
|
|
213
|
-
enrichers: enricherPipeline
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
enrichedLogger.info('User login', { userId: 123 });
|
|
217
|
-
// Output will include additional metadata fields
|
|
218
|
-
|
|
219
|
-
// Add enrichers dynamically
|
|
220
|
-
enrichedLogger.addEnricher((logData) => {
|
|
221
|
-
return {
|
|
222
|
-
...logData,
|
|
223
|
-
timestamp: new Date().toISOString(),
|
|
224
|
-
additionalField: 'some-value'
|
|
225
|
-
};
|
|
226
|
-
});
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
### Log Aggregation
|
|
230
|
-
|
|
231
|
-
Aggregate logs in batches or based on time intervals:
|
|
232
|
-
|
|
233
|
-
```js
|
|
234
|
-
import {
|
|
235
|
-
Logger,
|
|
236
|
-
ConsoleTransport,
|
|
237
|
-
BatchAggregator,
|
|
238
|
-
TimeBasedAggregator,
|
|
239
|
-
CompositeAggregator
|
|
240
|
-
} from "zario";
|
|
241
|
-
|
|
242
|
-
// Batch aggregator - flushes when batch size is reached
|
|
243
|
-
const batchAggregator = new BatchAggregator(10, (logs) => {
|
|
244
|
-
// Process batch of 10 logs
|
|
245
|
-
console.log(`Processing ${logs.length} logs`);
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
// Time-based aggregator - flushes after time interval
|
|
249
|
-
const timeAggregator = new TimeBasedAggregator(5000, (logs) => {
|
|
250
|
-
// Process logs every 5 seconds
|
|
251
|
-
console.log(`Processing ${logs.length} logs`);
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
// Create logger with aggregators
|
|
255
|
-
const aggregatedLogger = new Logger({
|
|
256
|
-
level: 'info',
|
|
257
|
-
transports: [new ConsoleTransport()],
|
|
258
|
-
aggregators: [batchAggregator]
|
|
259
|
-
});
|
|
260
|
-
|
|
261
|
-
// Manually flush aggregators
|
|
262
|
-
aggregatedLogger.flushAggregators();
|
|
263
|
-
|
|
264
|
-
// Stop time-based aggregator timer
|
|
265
|
-
// timeAggregator.stop(); // Available for TimeBasedAggregator
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
### Methods
|
|
269
|
-
|
|
270
|
-
- `logger.debug(message, metadata?)` - Debug level logging
|
|
271
|
-
- `logger.info(message, metadata?)` - Info level logging
|
|
272
|
-
- `logger.warn(message, metadata?)` - Warning level logging
|
|
273
|
-
- `logger.error(message, metadata?)` - Error level logging
|
|
274
|
-
- `logger.logWithLevel(level, message, metadata?)` - Log a message at an arbitrary/custom level
|
|
275
|
-
- `logger.createChild(options)` - Creates a child logger with inherited settings
|
|
276
|
-
- `logger.setLevel(level)` - Change the logger level at runtime
|
|
277
|
-
- `logger.setFormat(format)` - Set the output format to text or json
|
|
278
|
-
- `logger.addFilter(filter)` - Add a filter to the logger (LevelFilter, PrefixFilter, MetadataFilter, etc.)
|
|
279
|
-
- `logger.removeFilter(filter)` - Remove a filter from the logger
|
|
280
|
-
- `logger.addAggregator(aggregator)` - Add an aggregator to the logger (BatchAggregator, TimeBasedAggregator, etc.)
|
|
281
|
-
- `logger.removeAggregator(aggregator)` - Remove an aggregator from the logger
|
|
282
|
-
- `logger.flushAggregators()` - Manually flush all aggregators
|
|
283
|
-
- `logger.addEnricher(enricher)` - Add an enricher to the logger for structured logging
|
|
284
|
-
- `logger.startTimer(name)` - Create a performance timer
|
|
285
|
-
|
|
286
|
-
## Usage Examples
|
|
287
|
-
|
|
288
|
-
### Basic Usage
|
|
289
|
-
|
|
290
|
-
```js
|
|
291
|
-
import { Logger, ConsoleTransport } from "zario";
|
|
292
|
-
|
|
293
|
-
const logger = new Logger({
|
|
294
|
-
level: "info",
|
|
295
|
-
colorize: true,
|
|
296
|
-
transports: [new ConsoleTransport()]
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
logger.info("Application started");
|
|
300
|
-
logger.error("Something went wrong", { userId: 123 });
|
|
301
|
-
```
|
|
302
|
-
|
|
303
|
-
### JSON Format
|
|
304
|
-
|
|
305
|
-
```js
|
|
306
|
-
const logger = new Logger({ json: true });
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
### Custom Levels & Colors
|
|
310
|
-
|
|
311
|
-
```js
|
|
312
|
-
import { Logger, ConsoleTransport } from "zario";
|
|
313
|
-
|
|
314
|
-
const logger = new Logger({
|
|
315
|
-
level: 'info',
|
|
316
|
-
customLevels: {
|
|
317
|
-
'success': 6, // Higher priority than error (5).
|
|
318
|
-
'verbose': 1, // Lower priority than debug (2).
|
|
319
|
-
'critical': 7, // Highest priority.
|
|
320
|
-
},
|
|
321
|
-
customColors: {
|
|
322
|
-
'success': 'green',
|
|
323
|
-
'verbose': 'cyan',
|
|
324
|
-
'critical': 'brightRed',
|
|
325
|
-
},
|
|
326
|
-
transports: [
|
|
327
|
-
new ConsoleTransport()
|
|
328
|
-
]
|
|
329
|
-
});
|
|
330
|
-
|
|
331
|
-
// Using custom levels.
|
|
332
|
-
logger.logWithLevel('success', 'This is a success message in green!');
|
|
333
|
-
logger.logWithLevel('verbose', 'This is a verbose message in cyan');
|
|
334
|
-
logger.logWithLevel('critical', 'This is a critical message in bright red');
|
|
335
|
-
```
|
|
336
|
-
|
|
337
|
-
### Child Loggers
|
|
338
|
-
|
|
339
|
-
```js
|
|
340
|
-
const main = new Logger({ prefix: "[APP]" });
|
|
341
|
-
const db = main.createChild({ prefix: "[DB]" });
|
|
342
|
-
|
|
343
|
-
main.info("App initialized");
|
|
344
|
-
db.error("Connection timeout");
|
|
345
|
-
```
|
|
346
|
-
|
|
347
|
-
### Multiple Transports
|
|
348
|
-
|
|
349
|
-
```js
|
|
350
|
-
import { Logger, ConsoleTransport, FileTransport } from "zario";
|
|
351
|
-
|
|
352
|
-
const logger = new Logger({
|
|
353
|
-
level: 'info',
|
|
354
|
-
transports: [
|
|
355
|
-
new ConsoleTransport(),
|
|
356
|
-
new FileTransport({ path: './logs/app.log' })
|
|
357
|
-
]
|
|
358
|
-
});
|
|
359
|
-
```
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<a id="top"></a>
|
|
4
|
+
|
|
5
|
+
# 📝 Zario
|
|
6
|
+
|
|
7
|
+
### A Minimal Logging Solution for TypeScript
|
|
8
|
+
|
|
9
|
+
[](https://www.npmjs.com/package/zario)
|
|
10
|
+
[](./LICENSE)
|
|
11
|
+
[](https://www.npmjs.com/package/zario)
|
|
12
|
+
[](https://bundlephobia.com/package/zario)
|
|
13
|
+
](https://github.com/Dev-Dami/zario/actions)
|
|
14
|
+
|
|
15
|
+
**Built on January 8, 2026**
|
|
16
|
+
|
|
17
|
+
<br/>
|
|
18
|
+
|
|
19
|
+
**Fast** • **Lightweight** • **Zero Dependencies** • **TypeScript Native**
|
|
20
|
+
|
|
21
|
+
<br/>
|
|
22
|
+
|
|
23
|
+
[📖 Documentation](#-documentation) · [⚡ Quick Start](#-quick-start) · [✨ Features](#-features) · [🤝 Contributing](#-contributing)
|
|
24
|
+
|
|
25
|
+
<br/>
|
|
26
|
+
|
|
27
|
+

|
|
28
|
+
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
<br/>
|
|
32
|
+
|
|
33
|
+
## Features
|
|
34
|
+
|
|
35
|
+
- **Lightweight** — minimal footprint, fast execution
|
|
36
|
+
- **Simple API** — intuitive methods like `info()`, `warn()`, `error()`
|
|
37
|
+
- **Flexible formatting** — plain text or structured JSON
|
|
38
|
+
- **Multiple transports** — Console, File (streaming rotation), HTTP (async retry), CircuitBreaker, and DeadLetterQueue
|
|
39
|
+
- **Child loggers** — scoped logging for modules or requests
|
|
40
|
+
- **Async mode** — non-blocking writes for high-performance applications
|
|
41
|
+
- **Memory safe** — bounded queues and memory-efficient streaming
|
|
42
|
+
- **Customizable** — custom log levels, colors, and filtering
|
|
43
|
+
|
|
44
|
+
## 📦 Installation
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npm install zario
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## 🚀 Quick Start
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
import { Logger, ConsoleTransport } from "zario";
|
|
54
|
+
|
|
55
|
+
const logger = new Logger({
|
|
56
|
+
level: "info",
|
|
57
|
+
colorize: true,
|
|
58
|
+
transports: [new ConsoleTransport()],
|
|
59
|
+
prefix: "[MyApp]",
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
logger.info("🚀 Server started on port 3000");
|
|
63
|
+
logger.warn("⚠️ High memory usage detected");
|
|
64
|
+
logger.error("❌ Database connection failed", { code: 500 });
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## 📖 Documentation
|
|
68
|
+
|
|
69
|
+
Documentation:
|
|
70
|
+
|
|
71
|
+
| Section | Description |
|
|
72
|
+
| --------------------------------------------------- | ----------------------------------------------------------------------------- |
|
|
73
|
+
| [📘 **Introduction**](./docs/introduction.md) | Philosophy, core features, and common use cases. |
|
|
74
|
+
| [🚀 **Getting Started**](./docs/getting-started.md) | Detailed installation and environment auto-configuration. |
|
|
75
|
+
| [⚙️ **Configuration**](./docs/configuration.md) | Full reference for all logger options, custom levels, and colors. |
|
|
76
|
+
| [📖 **API Reference**](./docs/api-reference.md) | Detailed API documentation for the Logger class and utilities. |
|
|
77
|
+
| [📁 **Transports**](./docs/transports.md) | Guide to Console, File, HTTP, CircuitBreaker, and DeadLetterQueue transports. |
|
|
78
|
+
| [🧩 **Advanced Usage**](./docs/advanced-usage.md) | Filters, Enrichers (Structured Logging), and Aggregators. |
|
|
79
|
+
| [📊 **Log Formats**](./docs/log-formats.md) | Specification for Text and JSON output formats. |
|
|
80
|
+
| [🗺️ **Roadmap**](./docs/roadmap.md) | Future plans and upcoming features. |
|
|
81
|
+
|
|
82
|
+
## 🤝 Contributing
|
|
83
|
+
|
|
84
|
+
We welcome contributions! Whether it's bug reports, feature requests, or code contributions. Please see our [Contributing Guide](./CONTRIBUTING.md) for more details.
|
|
85
|
+
|
|
86
|
+
## 📄 License
|
|
87
|
+
|
|
88
|
+
This project is licensed under the **MIT License** - see the [LICENSE](./LICENSE) file for full details.
|
|
89
|
+
|
|
90
|
+
<br/>
|
|
91
|
+
|
|
92
|
+
<div align="center">
|
|
93
|
+
|
|
94
|
+
### Developed for developers
|
|
95
|
+
|
|
96
|
+
⭐ Star this repository to show your support
|
|
97
|
+
|
|
98
|
+
</div>
|
|
99
|
+
|
|
100
|
+
<br/>
|
|
101
|
+
|
|
102
|
+
[⬆ Back to Top](#top)
|
|
@@ -1,57 +1,77 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.CompositeAggregator = exports.TimeBasedAggregator = exports.BatchAggregator = void 0;
|
|
4
|
-
|
|
5
|
-
* Aggregates logs in memory and flushes them in batches
|
|
6
|
-
*/
|
|
4
|
+
//Aggregates logs in memory and flushes them in batches
|
|
7
5
|
class BatchAggregator {
|
|
8
|
-
constructor(maxSize = 100, flushCallback) {
|
|
6
|
+
constructor(maxSize = 100, flushCallback, maxQueueSize = 10000) {
|
|
9
7
|
this.logs = [];
|
|
8
|
+
this.pendingFlush = null;
|
|
10
9
|
this.maxSize = maxSize;
|
|
10
|
+
this.maxQueueSize = maxQueueSize;
|
|
11
11
|
this.flushCallback = flushCallback;
|
|
12
12
|
}
|
|
13
13
|
aggregate(logData, formatter) {
|
|
14
|
+
if (this.logs.length >= this.maxQueueSize) {
|
|
15
|
+
this.logs.shift();
|
|
16
|
+
}
|
|
14
17
|
this.logs.push({ logData, formatter });
|
|
15
|
-
if (this.logs.length >= this.maxSize) {
|
|
18
|
+
if (this.logs.length >= this.maxSize && !this.pendingFlush) {
|
|
16
19
|
const result = this.flush();
|
|
17
|
-
// Handle the case where flush returns a Promise (async flushCallback)
|
|
18
20
|
if (result instanceof Promise) {
|
|
19
|
-
result.
|
|
20
|
-
|
|
21
|
+
this.pendingFlush = result.finally(() => {
|
|
22
|
+
this.pendingFlush = null;
|
|
21
23
|
});
|
|
22
24
|
}
|
|
23
25
|
}
|
|
24
26
|
}
|
|
25
27
|
flush() {
|
|
26
|
-
if (this.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
if (this.pendingFlush) {
|
|
29
|
+
return this.pendingFlush;
|
|
30
|
+
}
|
|
31
|
+
if (this.logs.length === 0) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const logsToFlush = [...this.logs];
|
|
35
|
+
const originalLogs = [...this.logs];
|
|
36
|
+
this.logs = [];
|
|
37
|
+
try {
|
|
38
|
+
const callbackResult = this.flushCallback(logsToFlush);
|
|
39
|
+
if (callbackResult instanceof Promise) {
|
|
40
|
+
return callbackResult.catch((error) => {
|
|
41
|
+
this.logs = originalLogs;
|
|
42
|
+
throw error;
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
this.logs = originalLogs;
|
|
48
|
+
throw error;
|
|
30
49
|
}
|
|
31
50
|
}
|
|
32
51
|
}
|
|
33
52
|
exports.BatchAggregator = BatchAggregator;
|
|
34
|
-
|
|
35
|
-
* Aggregates logs based on a time interval
|
|
36
|
-
*/
|
|
53
|
+
//Aggregates logs based on a time interval
|
|
37
54
|
class TimeBasedAggregator {
|
|
38
|
-
constructor(flushInterval,
|
|
39
|
-
flushCallback) {
|
|
55
|
+
constructor(flushInterval, flushCallback, maxQueueSize = 10000) {
|
|
40
56
|
this.logs = [];
|
|
41
57
|
this.timer = null;
|
|
42
58
|
this.flushInterval = flushInterval;
|
|
59
|
+
this.maxQueueSize = maxQueueSize;
|
|
43
60
|
this.flushCallback = flushCallback;
|
|
44
61
|
}
|
|
45
62
|
aggregate(logData, formatter) {
|
|
63
|
+
if (this.logs.length >= this.maxQueueSize) {
|
|
64
|
+
this.logs.shift();
|
|
65
|
+
}
|
|
46
66
|
this.logs.push({ logData, formatter });
|
|
47
|
-
// Start
|
|
67
|
+
// Start timer if it's not already running
|
|
48
68
|
if (!this.timer) {
|
|
49
69
|
this.timer = setTimeout(() => {
|
|
50
70
|
const result = this.flush();
|
|
51
|
-
// Handle
|
|
71
|
+
// Handle case where flush returns a Promise (async flushCallback)
|
|
52
72
|
if (result instanceof Promise) {
|
|
53
|
-
result.catch(error => {
|
|
54
|
-
console.error(
|
|
73
|
+
result.catch((error) => {
|
|
74
|
+
console.error("Error in TimeBasedAggregator flush callback:", error);
|
|
55
75
|
});
|
|
56
76
|
}
|
|
57
77
|
}, this.flushInterval);
|
|
@@ -59,19 +79,30 @@ class TimeBasedAggregator {
|
|
|
59
79
|
}
|
|
60
80
|
flush() {
|
|
61
81
|
if (this.logs.length > 0) {
|
|
62
|
-
// Clear
|
|
82
|
+
// Clear timer if it exists
|
|
63
83
|
if (this.timer) {
|
|
64
84
|
clearTimeout(this.timer);
|
|
65
85
|
this.timer = null;
|
|
66
86
|
}
|
|
67
87
|
const logsToFlush = [...this.logs];
|
|
88
|
+
const originalLogs = [...this.logs];
|
|
68
89
|
this.logs = [];
|
|
69
|
-
|
|
90
|
+
try {
|
|
91
|
+
const callbackResult = this.flushCallback(logsToFlush);
|
|
92
|
+
if (callbackResult instanceof Promise) {
|
|
93
|
+
return callbackResult.catch((error) => {
|
|
94
|
+
this.logs = originalLogs;
|
|
95
|
+
throw error;
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
this.logs = originalLogs;
|
|
101
|
+
throw error;
|
|
102
|
+
}
|
|
70
103
|
}
|
|
71
104
|
}
|
|
72
|
-
|
|
73
|
-
* Stop the aggregator and cancel any pending timer without flushing
|
|
74
|
-
*/
|
|
105
|
+
//Stop aggregator and cancel any pending timer without flushing
|
|
75
106
|
stop() {
|
|
76
107
|
if (this.timer) {
|
|
77
108
|
clearTimeout(this.timer);
|
|
@@ -80,9 +111,7 @@ class TimeBasedAggregator {
|
|
|
80
111
|
}
|
|
81
112
|
}
|
|
82
113
|
exports.TimeBasedAggregator = TimeBasedAggregator;
|
|
83
|
-
|
|
84
|
-
* Combines multiple aggregators
|
|
85
|
-
*/
|
|
114
|
+
//Combines multiple aggregators
|
|
86
115
|
class CompositeAggregator {
|
|
87
116
|
constructor(aggregators) {
|
|
88
117
|
this.aggregators = aggregators;
|
|
@@ -101,8 +130,8 @@ class CompositeAggregator {
|
|
|
101
130
|
}
|
|
102
131
|
}
|
|
103
132
|
// If any aggregator returns a promise, wait for all of them
|
|
104
|
-
if (results.some(r => r instanceof Promise)) {
|
|
105
|
-
const promiseResults = results.filter(r => r instanceof Promise);
|
|
133
|
+
if (results.some((r) => r instanceof Promise)) {
|
|
134
|
+
const promiseResults = results.filter((r) => r instanceof Promise);
|
|
106
135
|
return Promise.all(promiseResults).then(() => { });
|
|
107
136
|
}
|
|
108
137
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Formatter = void 0;
|
|
4
|
-
const
|
|
5
|
-
const ColorUtil_js_1 = require("../utils/ColorUtil.js");
|
|
4
|
+
const index_js_1 = require("../utils/index.js");
|
|
6
5
|
class Formatter {
|
|
7
6
|
constructor(options = {}) {
|
|
8
7
|
const { colorize = true, json = false, timestampFormat = "YYYY-MM-DD HH:mm:ss", timestamp = false, customColors = {}, } = options;
|
|
@@ -37,7 +36,7 @@ class Formatter {
|
|
|
37
36
|
formatAsText(data) {
|
|
38
37
|
let output = "";
|
|
39
38
|
if (this.timestamp) {
|
|
40
|
-
output += `[${
|
|
39
|
+
output += `[${index_js_1.TimeUtil.format(data.timestamp, this.timestampFormat)}] `;
|
|
41
40
|
}
|
|
42
41
|
if (data.prefix) {
|
|
43
42
|
output += `${data.prefix} `;
|
|
@@ -45,7 +44,7 @@ class Formatter {
|
|
|
45
44
|
let level = data.level.toUpperCase();
|
|
46
45
|
if (this.colorize) {
|
|
47
46
|
const color = this.customColors[data.level] || data.level;
|
|
48
|
-
level =
|
|
47
|
+
level = index_js_1.ColorUtil.colorize(level, color);
|
|
49
48
|
}
|
|
50
49
|
output += `[${level}] ${data.message}`;
|
|
51
50
|
if (data.metadata) {
|