zario 0.3.5 → 0.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/cjs/aggregation/LogAggregator.js +48 -27
- package/dist/cjs/core/Formatter.js +3 -4
- package/dist/cjs/core/Logger.js +5 -13
- package/dist/cjs/filters/Filter.js +52 -18
- package/dist/cjs/filters/index.js +0 -1
- package/dist/cjs/index.js +3 -1
- package/dist/cjs/utils/index.js +78 -0
- package/dist/esm/aggregation/LogAggregator.d.ts +4 -27
- package/dist/esm/aggregation/LogAggregator.js +48 -27
- package/dist/esm/core/Formatter.js +1 -2
- package/dist/esm/core/Logger.d.ts +2 -1
- package/dist/esm/core/Logger.js +4 -12
- 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 +2 -1
- package/dist/esm/index.js +4 -1
- package/dist/esm/utils/index.d.ts +15 -0
- package/dist/esm/utils/index.js +72 -0
- package/package.json +4 -3
- 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
|
@@ -267,10 +267,10 @@ aggregatedLogger.flushAggregators();
|
|
|
267
267
|
|
|
268
268
|
### Methods
|
|
269
269
|
|
|
270
|
-
- `logger.debug(message, metadata?)` - Debug
|
|
271
|
-
- `logger.info(message, metadata?)` - Info
|
|
272
|
-
- `logger.warn(message, metadata?)` - Warning
|
|
273
|
-
- `logger.error(message, metadata?)` - Error
|
|
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
274
|
- `logger.logWithLevel(level, message, metadata?)` - Log a message at an arbitrary/custom level
|
|
275
275
|
- `logger.createChild(options)` - Creates a child logger with inherited settings
|
|
276
276
|
- `logger.setLevel(level)` - Change the logger level at runtime
|
|
@@ -1,42 +1,54 @@
|
|
|
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
6
|
constructor(maxSize = 100, flushCallback) {
|
|
9
7
|
this.logs = [];
|
|
8
|
+
this.pendingFlush = null;
|
|
10
9
|
this.maxSize = maxSize;
|
|
11
10
|
this.flushCallback = flushCallback;
|
|
12
11
|
}
|
|
13
12
|
aggregate(logData, formatter) {
|
|
14
13
|
this.logs.push({ logData, formatter });
|
|
15
|
-
if (this.logs.length >= this.maxSize) {
|
|
14
|
+
if (this.logs.length >= this.maxSize && !this.pendingFlush) {
|
|
16
15
|
const result = this.flush();
|
|
17
|
-
// Handle the case where flush returns a Promise (async flushCallback)
|
|
18
16
|
if (result instanceof Promise) {
|
|
19
|
-
result.
|
|
20
|
-
|
|
17
|
+
this.pendingFlush = result.finally(() => {
|
|
18
|
+
this.pendingFlush = null;
|
|
21
19
|
});
|
|
22
20
|
}
|
|
23
21
|
}
|
|
24
22
|
}
|
|
25
23
|
flush() {
|
|
26
|
-
if (this.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
if (this.pendingFlush) {
|
|
25
|
+
return this.pendingFlush;
|
|
26
|
+
}
|
|
27
|
+
if (this.logs.length === 0) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const logsToFlush = [...this.logs];
|
|
31
|
+
const originalLogs = [...this.logs];
|
|
32
|
+
this.logs = [];
|
|
33
|
+
try {
|
|
34
|
+
const callbackResult = this.flushCallback(logsToFlush);
|
|
35
|
+
if (callbackResult instanceof Promise) {
|
|
36
|
+
return callbackResult.catch((error) => {
|
|
37
|
+
this.logs = originalLogs;
|
|
38
|
+
throw error;
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
this.logs = originalLogs;
|
|
44
|
+
throw error;
|
|
30
45
|
}
|
|
31
46
|
}
|
|
32
47
|
}
|
|
33
48
|
exports.BatchAggregator = BatchAggregator;
|
|
34
|
-
|
|
35
|
-
* Aggregates logs based on a time interval
|
|
36
|
-
*/
|
|
49
|
+
//Aggregates logs based on a time interval
|
|
37
50
|
class TimeBasedAggregator {
|
|
38
|
-
constructor(flushInterval,
|
|
39
|
-
flushCallback) {
|
|
51
|
+
constructor(flushInterval, flushCallback) {
|
|
40
52
|
this.logs = [];
|
|
41
53
|
this.timer = null;
|
|
42
54
|
this.flushInterval = flushInterval;
|
|
@@ -50,8 +62,8 @@ class TimeBasedAggregator {
|
|
|
50
62
|
const result = this.flush();
|
|
51
63
|
// Handle the case where flush returns a Promise (async flushCallback)
|
|
52
64
|
if (result instanceof Promise) {
|
|
53
|
-
result.catch(error => {
|
|
54
|
-
console.error(
|
|
65
|
+
result.catch((error) => {
|
|
66
|
+
console.error("Error in TimeBasedAggregator flush callback:", error);
|
|
55
67
|
});
|
|
56
68
|
}
|
|
57
69
|
}, this.flushInterval);
|
|
@@ -65,13 +77,24 @@ class TimeBasedAggregator {
|
|
|
65
77
|
this.timer = null;
|
|
66
78
|
}
|
|
67
79
|
const logsToFlush = [...this.logs];
|
|
80
|
+
const originalLogs = [...this.logs];
|
|
68
81
|
this.logs = [];
|
|
69
|
-
|
|
82
|
+
try {
|
|
83
|
+
const callbackResult = this.flushCallback(logsToFlush);
|
|
84
|
+
if (callbackResult instanceof Promise) {
|
|
85
|
+
return callbackResult.catch((error) => {
|
|
86
|
+
this.logs = originalLogs;
|
|
87
|
+
throw error;
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
this.logs = originalLogs;
|
|
93
|
+
throw error;
|
|
94
|
+
}
|
|
70
95
|
}
|
|
71
96
|
}
|
|
72
|
-
|
|
73
|
-
* Stop the aggregator and cancel any pending timer without flushing
|
|
74
|
-
*/
|
|
97
|
+
//Stop the aggregator and cancel any pending timer without flushing
|
|
75
98
|
stop() {
|
|
76
99
|
if (this.timer) {
|
|
77
100
|
clearTimeout(this.timer);
|
|
@@ -80,9 +103,7 @@ class TimeBasedAggregator {
|
|
|
80
103
|
}
|
|
81
104
|
}
|
|
82
105
|
exports.TimeBasedAggregator = TimeBasedAggregator;
|
|
83
|
-
|
|
84
|
-
* Combines multiple aggregators
|
|
85
|
-
*/
|
|
106
|
+
//Combines multiple aggregators
|
|
86
107
|
class CompositeAggregator {
|
|
87
108
|
constructor(aggregators) {
|
|
88
109
|
this.aggregators = aggregators;
|
|
@@ -101,8 +122,8 @@ class CompositeAggregator {
|
|
|
101
122
|
}
|
|
102
123
|
}
|
|
103
124
|
// 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);
|
|
125
|
+
if (results.some((r) => r instanceof Promise)) {
|
|
126
|
+
const promiseResults = results.filter((r) => r instanceof Promise);
|
|
106
127
|
return Promise.all(promiseResults).then(() => { });
|
|
107
128
|
}
|
|
108
129
|
}
|
|
@@ -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) {
|
package/dist/cjs/core/Logger.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.Logger = void 0;
|
|
|
4
4
|
const Formatter_js_1 = require("./Formatter.js");
|
|
5
5
|
const ConsoleTransport_js_1 = require("../transports/ConsoleTransport.js");
|
|
6
6
|
const StructuredExtensions_js_1 = require("../structured/StructuredExtensions.js");
|
|
7
|
+
const index_js_1 = require("../utils/index.js");
|
|
7
8
|
class Logger {
|
|
8
9
|
constructor(options = {}) {
|
|
9
10
|
this.transports = [];
|
|
@@ -261,8 +262,7 @@ class Logger {
|
|
|
261
262
|
return new Logger({ ...options, parent: this });
|
|
262
263
|
}
|
|
263
264
|
startTimer(name) {
|
|
264
|
-
|
|
265
|
-
return new Timer(name, (message) => this.info(message));
|
|
265
|
+
return new index_js_1.Timer(name, (message) => this.info(message));
|
|
266
266
|
}
|
|
267
267
|
/**
|
|
268
268
|
* Add a filter to the logger
|
|
@@ -310,17 +310,9 @@ class Logger {
|
|
|
310
310
|
async flushAggregators() {
|
|
311
311
|
const flushPromises = [];
|
|
312
312
|
for (const aggregator of this.aggregators) {
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
// Wrap the promise to catch and log rejections, so one failure doesn't stop others
|
|
317
|
-
flushPromises.push(result.catch(error => {
|
|
318
|
-
console.error('Error flushing aggregator:', error);
|
|
319
|
-
}));
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
catch (error) {
|
|
323
|
-
console.error('Error flushing aggregator:', error);
|
|
313
|
+
const result = aggregator.flush();
|
|
314
|
+
if (result instanceof Promise) {
|
|
315
|
+
flushPromises.push(result);
|
|
324
316
|
}
|
|
325
317
|
}
|
|
326
318
|
await Promise.all(flushPromises);
|
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.PredicateFilter = exports.NotFilter = exports.OrFilter = exports.CompositeFilter = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* A filter that combines multiple filters with AND logic
|
|
6
|
-
* Note: With an empty array of filters, this returns true (allows all logs).
|
|
7
|
-
* This follows the mathematical concept of vacuous truth - "all" conditions
|
|
8
|
-
* are satisfied when there are no conditions to check.
|
|
9
|
-
*/
|
|
3
|
+
exports.FieldFilter = exports.MetadataFilter = exports.PrefixFilter = exports.LevelFilter = exports.PredicateFilter = exports.NotFilter = exports.OrFilter = exports.CompositeFilter = void 0;
|
|
10
4
|
class CompositeFilter {
|
|
11
5
|
constructor(filters) {
|
|
12
6
|
this.filters = filters;
|
|
@@ -16,11 +10,6 @@ class CompositeFilter {
|
|
|
16
10
|
}
|
|
17
11
|
}
|
|
18
12
|
exports.CompositeFilter = CompositeFilter;
|
|
19
|
-
/**
|
|
20
|
-
* A filter that combines multiple filters with OR logic
|
|
21
|
-
* Note: With an empty array of filters, this returns false (blocks all logs).
|
|
22
|
-
* This is because there are no matching conditions when the filter array is empty.
|
|
23
|
-
*/
|
|
24
13
|
class OrFilter {
|
|
25
14
|
constructor(filters) {
|
|
26
15
|
this.filters = filters;
|
|
@@ -30,9 +19,6 @@ class OrFilter {
|
|
|
30
19
|
}
|
|
31
20
|
}
|
|
32
21
|
exports.OrFilter = OrFilter;
|
|
33
|
-
/**
|
|
34
|
-
* A filter that negates another filter
|
|
35
|
-
*/
|
|
36
22
|
class NotFilter {
|
|
37
23
|
constructor(filter) {
|
|
38
24
|
this.filter = filter;
|
|
@@ -42,9 +28,6 @@ class NotFilter {
|
|
|
42
28
|
}
|
|
43
29
|
}
|
|
44
30
|
exports.NotFilter = NotFilter;
|
|
45
|
-
/**
|
|
46
|
-
* A filter based on a predicate function
|
|
47
|
-
*/
|
|
48
31
|
class PredicateFilter {
|
|
49
32
|
constructor(predicate) {
|
|
50
33
|
this.predicate = predicate;
|
|
@@ -54,3 +37,54 @@ class PredicateFilter {
|
|
|
54
37
|
}
|
|
55
38
|
}
|
|
56
39
|
exports.PredicateFilter = PredicateFilter;
|
|
40
|
+
class LevelFilter {
|
|
41
|
+
constructor(allowedLevels) {
|
|
42
|
+
this.allowedLevels = new Set(allowedLevels);
|
|
43
|
+
}
|
|
44
|
+
shouldEmit(logData) {
|
|
45
|
+
return this.allowedLevels.has(logData.level);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
exports.LevelFilter = LevelFilter;
|
|
49
|
+
class PrefixFilter {
|
|
50
|
+
constructor(allowedPrefixes) {
|
|
51
|
+
this.allowedPrefixes = new Set(allowedPrefixes);
|
|
52
|
+
}
|
|
53
|
+
shouldEmit(logData) {
|
|
54
|
+
if (!logData.prefix) {
|
|
55
|
+
return this.allowedPrefixes.has('');
|
|
56
|
+
}
|
|
57
|
+
return this.allowedPrefixes.has(logData.prefix);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
exports.PrefixFilter = PrefixFilter;
|
|
61
|
+
class MetadataFilter {
|
|
62
|
+
constructor(requiredMetadata) {
|
|
63
|
+
this.requiredMetadata = requiredMetadata;
|
|
64
|
+
}
|
|
65
|
+
shouldEmit(logData) {
|
|
66
|
+
if (!logData.metadata) {
|
|
67
|
+
return Object.keys(this.requiredMetadata).length === 0;
|
|
68
|
+
}
|
|
69
|
+
for (const [key, value] of Object.entries(this.requiredMetadata)) {
|
|
70
|
+
if (logData.metadata[key] !== value) {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
exports.MetadataFilter = MetadataFilter;
|
|
78
|
+
class FieldFilter {
|
|
79
|
+
constructor(fieldName, expectedValue) {
|
|
80
|
+
this.fieldName = fieldName;
|
|
81
|
+
this.expectedValue = expectedValue;
|
|
82
|
+
}
|
|
83
|
+
shouldEmit(logData) {
|
|
84
|
+
if (!logData.metadata) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
return logData.metadata[this.fieldName] === this.expectedValue;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
exports.FieldFilter = FieldFilter;
|
package/dist/cjs/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.LogEnrichmentPipeline = exports.MetadataEnricher = exports.CompositeAggregator = exports.TimeBasedAggregator = exports.BatchAggregator = exports.FieldFilter = exports.MetadataFilter = exports.PrefixFilter = exports.LevelFilter = exports.PredicateFilter = exports.NotFilter = exports.OrFilter = exports.CompositeFilter = exports.FilterableTransport = exports.HttpTransport = exports.FileTransport = exports.ConsoleTransport = exports.Logger = void 0;
|
|
3
|
+
exports.Timer = exports.LogEnrichmentPipeline = exports.MetadataEnricher = exports.CompositeAggregator = exports.TimeBasedAggregator = exports.BatchAggregator = exports.FieldFilter = exports.MetadataFilter = exports.PrefixFilter = exports.LevelFilter = exports.PredicateFilter = exports.NotFilter = exports.OrFilter = exports.CompositeFilter = exports.FilterableTransport = exports.HttpTransport = exports.FileTransport = exports.ConsoleTransport = exports.Logger = void 0;
|
|
4
4
|
const Logger_js_1 = require("./core/Logger.js");
|
|
5
5
|
Object.defineProperty(exports, "Logger", { enumerable: true, get: function () { return Logger_js_1.Logger; } });
|
|
6
6
|
const index_js_1 = require("./transports/index.js");
|
|
@@ -24,6 +24,8 @@ Object.defineProperty(exports, "CompositeAggregator", { enumerable: true, get: f
|
|
|
24
24
|
const index_js_4 = require("./structured/index.js");
|
|
25
25
|
Object.defineProperty(exports, "MetadataEnricher", { enumerable: true, get: function () { return index_js_4.MetadataEnricher; } });
|
|
26
26
|
Object.defineProperty(exports, "LogEnrichmentPipeline", { enumerable: true, get: function () { return index_js_4.LogEnrichmentPipeline; } });
|
|
27
|
+
const index_js_5 = require("./utils/index.js");
|
|
28
|
+
Object.defineProperty(exports, "Timer", { enumerable: true, get: function () { return index_js_5.Timer; } });
|
|
27
29
|
// Configure default transports to maintain backward compatibility
|
|
28
30
|
Logger_js_1.Logger.defaultTransportsFactory = (isProd) => {
|
|
29
31
|
if (isProd) {
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Timer = exports.TimeUtil = exports.ColorUtil = void 0;
|
|
4
|
+
class ColorUtil {
|
|
5
|
+
static colorize(text, color) {
|
|
6
|
+
const supportsColor = process.env.FORCE_COLOR !== "0" &&
|
|
7
|
+
(process.stdout.isTTY || process.env.FORCE_COLOR === "1");
|
|
8
|
+
if (!supportsColor) {
|
|
9
|
+
return text;
|
|
10
|
+
}
|
|
11
|
+
const colorCode = ColorUtil.ANSI_COLORS[color] || ColorUtil.ANSI_COLORS.reset;
|
|
12
|
+
return `${colorCode}${text}${ColorUtil.ANSI_COLORS.reset}`;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
exports.ColorUtil = ColorUtil;
|
|
16
|
+
ColorUtil.ANSI_COLORS = {
|
|
17
|
+
black: "\x1b[30m",
|
|
18
|
+
red: "\x1b[31m",
|
|
19
|
+
green: "\x1b[32m",
|
|
20
|
+
yellow: "\x1b[33m",
|
|
21
|
+
blue: "\x1b[34m",
|
|
22
|
+
magenta: "\x1b[35m",
|
|
23
|
+
cyan: "\x1b[36m",
|
|
24
|
+
white: "\x1b[37m",
|
|
25
|
+
brightRed: "\x1b[91m",
|
|
26
|
+
brightGreen: "\x1b[92m",
|
|
27
|
+
brightYellow: "\x1b[93m",
|
|
28
|
+
brightBlue: "\x1b[94m",
|
|
29
|
+
brightMagenta: "\x1b[95m",
|
|
30
|
+
brightCyan: "\x1b[96m",
|
|
31
|
+
brightWhite: "\x1b[97m",
|
|
32
|
+
info: "\x1b[32m",
|
|
33
|
+
warn: "\x1b[33m",
|
|
34
|
+
error: "\x1b[31m",
|
|
35
|
+
debug: "\x1b[36m",
|
|
36
|
+
boring: "\x1b[37m",
|
|
37
|
+
reset: "\x1b[0m",
|
|
38
|
+
};
|
|
39
|
+
class TimeUtil {
|
|
40
|
+
static format(date, format) {
|
|
41
|
+
if (format === "ISO")
|
|
42
|
+
return date.toISOString();
|
|
43
|
+
if (format === "UTC")
|
|
44
|
+
return date.toUTCString();
|
|
45
|
+
if (format === "LOCAL")
|
|
46
|
+
return date.toLocaleString();
|
|
47
|
+
const pad = (n, width = 2) => n.toString().padStart(width, "0");
|
|
48
|
+
const tokens = {
|
|
49
|
+
YYYY: pad(date.getFullYear(), 4),
|
|
50
|
+
MM: pad(date.getMonth() + 1),
|
|
51
|
+
DD: pad(date.getDate()),
|
|
52
|
+
HH: pad(date.getHours()),
|
|
53
|
+
mm: pad(date.getMinutes()),
|
|
54
|
+
ss: pad(date.getSeconds()),
|
|
55
|
+
SSS: pad(date.getMilliseconds(), 3),
|
|
56
|
+
};
|
|
57
|
+
return format.replace(/YYYY|MM|DD|HH|mm|ss|SSS/g, (match) => tokens[match] || match);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
exports.TimeUtil = TimeUtil;
|
|
61
|
+
class Timer {
|
|
62
|
+
constructor(name, logFn) {
|
|
63
|
+
this.hasEnded = false;
|
|
64
|
+
this.name = name;
|
|
65
|
+
this.logFn = logFn;
|
|
66
|
+
this.startTime = Date.now();
|
|
67
|
+
}
|
|
68
|
+
end() {
|
|
69
|
+
if (this.hasEnded) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const endTime = Date.now();
|
|
73
|
+
const duration = endTime - this.startTime;
|
|
74
|
+
this.logFn(`${this.name} took ${duration}ms`);
|
|
75
|
+
this.hasEnded = true;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
exports.Timer = Timer;
|
|
@@ -1,27 +1,14 @@
|
|
|
1
|
-
import { LogData } from
|
|
2
|
-
import { Formatter } from
|
|
3
|
-
/**
|
|
4
|
-
* Interface for log aggregation targets
|
|
5
|
-
*/
|
|
1
|
+
import { LogData } from "../types/index.js";
|
|
2
|
+
import { Formatter } from "../core/Formatter.js";
|
|
6
3
|
export interface LogAggregator {
|
|
7
|
-
/**
|
|
8
|
-
* Process a log record for aggregation
|
|
9
|
-
* @param logData The structured log record
|
|
10
|
-
* @param formatter The formatter used for the log
|
|
11
|
-
*/
|
|
12
4
|
aggregate(logData: LogData, formatter: Formatter): void;
|
|
13
|
-
/**
|
|
14
|
-
* Flush any pending aggregated logs
|
|
15
|
-
*/
|
|
16
5
|
flush(): Promise<void> | void;
|
|
17
6
|
}
|
|
18
|
-
/**
|
|
19
|
-
* Aggregates logs in memory and flushes them in batches
|
|
20
|
-
*/
|
|
21
7
|
export declare class BatchAggregator implements LogAggregator {
|
|
22
8
|
private logs;
|
|
23
9
|
private maxSize;
|
|
24
10
|
private flushCallback;
|
|
11
|
+
private pendingFlush;
|
|
25
12
|
constructor(maxSize: number | undefined, flushCallback: (logs: {
|
|
26
13
|
logData: LogData;
|
|
27
14
|
formatter: Formatter;
|
|
@@ -29,29 +16,19 @@ export declare class BatchAggregator implements LogAggregator {
|
|
|
29
16
|
aggregate(logData: LogData, formatter: Formatter): void;
|
|
30
17
|
flush(): Promise<void> | void;
|
|
31
18
|
}
|
|
32
|
-
/**
|
|
33
|
-
* Aggregates logs based on a time interval
|
|
34
|
-
*/
|
|
35
19
|
export declare class TimeBasedAggregator implements LogAggregator {
|
|
36
20
|
private logs;
|
|
37
21
|
private flushInterval;
|
|
38
22
|
private flushCallback;
|
|
39
23
|
private timer;
|
|
40
|
-
constructor(flushInterval: number,
|
|
41
|
-
flushCallback: (logs: {
|
|
24
|
+
constructor(flushInterval: number, flushCallback: (logs: {
|
|
42
25
|
logData: LogData;
|
|
43
26
|
formatter: Formatter;
|
|
44
27
|
}[]) => Promise<void> | void);
|
|
45
28
|
aggregate(logData: LogData, formatter: Formatter): void;
|
|
46
29
|
flush(): Promise<void> | void;
|
|
47
|
-
/**
|
|
48
|
-
* Stop the aggregator and cancel any pending timer without flushing
|
|
49
|
-
*/
|
|
50
30
|
stop(): void;
|
|
51
31
|
}
|
|
52
|
-
/**
|
|
53
|
-
* Combines multiple aggregators
|
|
54
|
-
*/
|
|
55
32
|
export declare class CompositeAggregator implements LogAggregator {
|
|
56
33
|
private aggregators;
|
|
57
34
|
constructor(aggregators: LogAggregator[]);
|
|
@@ -1,38 +1,50 @@
|
|
|
1
|
-
|
|
2
|
-
* Aggregates logs in memory and flushes them in batches
|
|
3
|
-
*/
|
|
1
|
+
//Aggregates logs in memory and flushes them in batches
|
|
4
2
|
export class BatchAggregator {
|
|
5
3
|
constructor(maxSize = 100, flushCallback) {
|
|
6
4
|
this.logs = [];
|
|
5
|
+
this.pendingFlush = null;
|
|
7
6
|
this.maxSize = maxSize;
|
|
8
7
|
this.flushCallback = flushCallback;
|
|
9
8
|
}
|
|
10
9
|
aggregate(logData, formatter) {
|
|
11
10
|
this.logs.push({ logData, formatter });
|
|
12
|
-
if (this.logs.length >= this.maxSize) {
|
|
11
|
+
if (this.logs.length >= this.maxSize && !this.pendingFlush) {
|
|
13
12
|
const result = this.flush();
|
|
14
|
-
// Handle the case where flush returns a Promise (async flushCallback)
|
|
15
13
|
if (result instanceof Promise) {
|
|
16
|
-
result.
|
|
17
|
-
|
|
14
|
+
this.pendingFlush = result.finally(() => {
|
|
15
|
+
this.pendingFlush = null;
|
|
18
16
|
});
|
|
19
17
|
}
|
|
20
18
|
}
|
|
21
19
|
}
|
|
22
20
|
flush() {
|
|
23
|
-
if (this.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
if (this.pendingFlush) {
|
|
22
|
+
return this.pendingFlush;
|
|
23
|
+
}
|
|
24
|
+
if (this.logs.length === 0) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const logsToFlush = [...this.logs];
|
|
28
|
+
const originalLogs = [...this.logs];
|
|
29
|
+
this.logs = [];
|
|
30
|
+
try {
|
|
31
|
+
const callbackResult = this.flushCallback(logsToFlush);
|
|
32
|
+
if (callbackResult instanceof Promise) {
|
|
33
|
+
return callbackResult.catch((error) => {
|
|
34
|
+
this.logs = originalLogs;
|
|
35
|
+
throw error;
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
this.logs = originalLogs;
|
|
41
|
+
throw error;
|
|
27
42
|
}
|
|
28
43
|
}
|
|
29
44
|
}
|
|
30
|
-
|
|
31
|
-
* Aggregates logs based on a time interval
|
|
32
|
-
*/
|
|
45
|
+
//Aggregates logs based on a time interval
|
|
33
46
|
export class TimeBasedAggregator {
|
|
34
|
-
constructor(flushInterval,
|
|
35
|
-
flushCallback) {
|
|
47
|
+
constructor(flushInterval, flushCallback) {
|
|
36
48
|
this.logs = [];
|
|
37
49
|
this.timer = null;
|
|
38
50
|
this.flushInterval = flushInterval;
|
|
@@ -46,8 +58,8 @@ export class TimeBasedAggregator {
|
|
|
46
58
|
const result = this.flush();
|
|
47
59
|
// Handle the case where flush returns a Promise (async flushCallback)
|
|
48
60
|
if (result instanceof Promise) {
|
|
49
|
-
result.catch(error => {
|
|
50
|
-
console.error(
|
|
61
|
+
result.catch((error) => {
|
|
62
|
+
console.error("Error in TimeBasedAggregator flush callback:", error);
|
|
51
63
|
});
|
|
52
64
|
}
|
|
53
65
|
}, this.flushInterval);
|
|
@@ -61,13 +73,24 @@ export class TimeBasedAggregator {
|
|
|
61
73
|
this.timer = null;
|
|
62
74
|
}
|
|
63
75
|
const logsToFlush = [...this.logs];
|
|
76
|
+
const originalLogs = [...this.logs];
|
|
64
77
|
this.logs = [];
|
|
65
|
-
|
|
78
|
+
try {
|
|
79
|
+
const callbackResult = this.flushCallback(logsToFlush);
|
|
80
|
+
if (callbackResult instanceof Promise) {
|
|
81
|
+
return callbackResult.catch((error) => {
|
|
82
|
+
this.logs = originalLogs;
|
|
83
|
+
throw error;
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
this.logs = originalLogs;
|
|
89
|
+
throw error;
|
|
90
|
+
}
|
|
66
91
|
}
|
|
67
92
|
}
|
|
68
|
-
|
|
69
|
-
* Stop the aggregator and cancel any pending timer without flushing
|
|
70
|
-
*/
|
|
93
|
+
//Stop the aggregator and cancel any pending timer without flushing
|
|
71
94
|
stop() {
|
|
72
95
|
if (this.timer) {
|
|
73
96
|
clearTimeout(this.timer);
|
|
@@ -75,9 +98,7 @@ export class TimeBasedAggregator {
|
|
|
75
98
|
}
|
|
76
99
|
}
|
|
77
100
|
}
|
|
78
|
-
|
|
79
|
-
* Combines multiple aggregators
|
|
80
|
-
*/
|
|
101
|
+
//Combines multiple aggregators
|
|
81
102
|
export class CompositeAggregator {
|
|
82
103
|
constructor(aggregators) {
|
|
83
104
|
this.aggregators = aggregators;
|
|
@@ -96,8 +117,8 @@ export class CompositeAggregator {
|
|
|
96
117
|
}
|
|
97
118
|
}
|
|
98
119
|
// If any aggregator returns a promise, wait for all of them
|
|
99
|
-
if (results.some(r => r instanceof Promise)) {
|
|
100
|
-
const promiseResults = results.filter(r => r instanceof Promise);
|
|
120
|
+
if (results.some((r) => r instanceof Promise)) {
|
|
121
|
+
const promiseResults = results.filter((r) => r instanceof Promise);
|
|
101
122
|
return Promise.all(promiseResults).then(() => { });
|
|
102
123
|
}
|
|
103
124
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { TimeUtil } from "../utils/
|
|
2
|
-
import { ColorUtil } from "../utils/ColorUtil.js";
|
|
1
|
+
import { TimeUtil, ColorUtil } from "../utils/index.js";
|
|
3
2
|
export class Formatter {
|
|
4
3
|
constructor(options = {}) {
|
|
5
4
|
const { colorize = true, json = false, timestampFormat = "YYYY-MM-DD HH:mm:ss", timestamp = false, customColors = {}, } = options;
|
|
@@ -4,6 +4,7 @@ import { TransportConfig } from "../types/index.js";
|
|
|
4
4
|
import { Filter } from "../filters/Filter.js";
|
|
5
5
|
import { LogAggregator } from "../aggregation/LogAggregator.js";
|
|
6
6
|
import { LogEnricher, LogEnrichmentPipeline } from "../structured/StructuredExtensions.js";
|
|
7
|
+
import { Timer } from "../utils/index.js";
|
|
7
8
|
export interface LoggerOptions {
|
|
8
9
|
level?: LogLevel;
|
|
9
10
|
colorize?: boolean;
|
|
@@ -71,7 +72,7 @@ export declare class Logger {
|
|
|
71
72
|
getTimestampSetting(): boolean;
|
|
72
73
|
static get global(): Logger;
|
|
73
74
|
createChild(options?: LoggerOptions): Logger;
|
|
74
|
-
startTimer(name: string):
|
|
75
|
+
startTimer(name: string): Timer;
|
|
75
76
|
/**
|
|
76
77
|
* Add a filter to the logger
|
|
77
78
|
*/
|
package/dist/esm/core/Logger.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Formatter } from "./Formatter.js";
|
|
2
2
|
import { ConsoleTransport } from "../transports/ConsoleTransport.js";
|
|
3
3
|
import { LogEnrichmentPipeline } from "../structured/StructuredExtensions.js";
|
|
4
|
+
import { Timer } from "../utils/index.js";
|
|
4
5
|
export class Logger {
|
|
5
6
|
constructor(options = {}) {
|
|
6
7
|
this.transports = [];
|
|
@@ -258,7 +259,6 @@ export class Logger {
|
|
|
258
259
|
return new Logger({ ...options, parent: this });
|
|
259
260
|
}
|
|
260
261
|
startTimer(name) {
|
|
261
|
-
const { Timer } = require("../utils/Timerutil");
|
|
262
262
|
return new Timer(name, (message) => this.info(message));
|
|
263
263
|
}
|
|
264
264
|
/**
|
|
@@ -307,17 +307,9 @@ export class Logger {
|
|
|
307
307
|
async flushAggregators() {
|
|
308
308
|
const flushPromises = [];
|
|
309
309
|
for (const aggregator of this.aggregators) {
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
// Wrap the promise to catch and log rejections, so one failure doesn't stop others
|
|
314
|
-
flushPromises.push(result.catch(error => {
|
|
315
|
-
console.error('Error flushing aggregator:', error);
|
|
316
|
-
}));
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
catch (error) {
|
|
320
|
-
console.error('Error flushing aggregator:', error);
|
|
310
|
+
const result = aggregator.flush();
|
|
311
|
+
if (result instanceof Promise) {
|
|
312
|
+
flushPromises.push(result);
|
|
321
313
|
}
|
|
322
314
|
}
|
|
323
315
|
await Promise.all(flushPromises);
|