@morojs/moro 1.5.17 → 1.6.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 +48 -65
- package/dist/core/auth/morojs-adapter.js +12 -16
- package/dist/core/auth/morojs-adapter.js.map +1 -1
- package/dist/core/config/file-loader.d.ts +5 -0
- package/dist/core/config/file-loader.js +171 -0
- package/dist/core/config/file-loader.js.map +1 -1
- package/dist/core/config/index.d.ts +10 -39
- package/dist/core/config/index.js +29 -66
- package/dist/core/config/index.js.map +1 -1
- package/dist/core/config/loader.d.ts +7 -0
- package/dist/core/config/loader.js +269 -0
- package/dist/core/config/loader.js.map +1 -0
- package/dist/core/config/schema.js +31 -41
- package/dist/core/config/schema.js.map +1 -1
- package/dist/core/config/utils.d.ts +2 -9
- package/dist/core/config/utils.js +32 -19
- package/dist/core/config/utils.js.map +1 -1
- package/dist/core/config/validation.d.ts +17 -0
- package/dist/core/config/validation.js +131 -0
- package/dist/core/config/validation.js.map +1 -0
- package/dist/core/database/adapters/mongodb.d.ts +0 -10
- package/dist/core/database/adapters/mongodb.js +2 -23
- package/dist/core/database/adapters/mongodb.js.map +1 -1
- package/dist/core/database/adapters/mysql.d.ts +0 -11
- package/dist/core/database/adapters/mysql.js +0 -1
- package/dist/core/database/adapters/mysql.js.map +1 -1
- package/dist/core/database/adapters/postgresql.d.ts +1 -9
- package/dist/core/database/adapters/postgresql.js +1 -1
- package/dist/core/database/adapters/postgresql.js.map +1 -1
- package/dist/core/database/adapters/redis.d.ts +0 -9
- package/dist/core/database/adapters/redis.js +4 -14
- package/dist/core/database/adapters/redis.js.map +1 -1
- package/dist/core/framework.d.ts +7 -6
- package/dist/core/framework.js +16 -131
- package/dist/core/framework.js.map +1 -1
- package/dist/core/http/http-server.d.ts +0 -12
- package/dist/core/http/http-server.js +23 -151
- package/dist/core/http/http-server.js.map +1 -1
- package/dist/core/http/router.d.ts +0 -12
- package/dist/core/http/router.js +36 -114
- package/dist/core/http/router.js.map +1 -1
- package/dist/core/logger/filters.js +4 -12
- package/dist/core/logger/filters.js.map +1 -1
- package/dist/core/logger/index.d.ts +1 -1
- package/dist/core/logger/index.js +1 -2
- package/dist/core/logger/index.js.map +1 -1
- package/dist/core/logger/logger.d.ts +13 -29
- package/dist/core/logger/logger.js +203 -380
- package/dist/core/logger/logger.js.map +1 -1
- package/dist/core/logger/outputs.js +2 -0
- package/dist/core/logger/outputs.js.map +1 -1
- package/dist/core/middleware/built-in/auth.js +17 -88
- package/dist/core/middleware/built-in/auth.js.map +1 -1
- package/dist/core/middleware/built-in/cache.js +1 -3
- package/dist/core/middleware/built-in/cache.js.map +1 -1
- package/dist/core/middleware/built-in/index.d.ts +0 -1
- package/dist/core/middleware/built-in/index.js +1 -6
- package/dist/core/middleware/built-in/index.js.map +1 -1
- package/dist/core/middleware/built-in/request-logger.js +2 -3
- package/dist/core/middleware/built-in/request-logger.js.map +1 -1
- package/dist/core/middleware/built-in/sse.js +7 -9
- package/dist/core/middleware/built-in/sse.js.map +1 -1
- package/dist/core/modules/auto-discovery.d.ts +0 -17
- package/dist/core/modules/auto-discovery.js +12 -367
- package/dist/core/modules/auto-discovery.js.map +1 -1
- package/dist/core/modules/modules.js +2 -12
- package/dist/core/modules/modules.js.map +1 -1
- package/dist/core/networking/adapters/ws-adapter.d.ts +1 -1
- package/dist/core/networking/adapters/ws-adapter.js +2 -2
- package/dist/core/networking/adapters/ws-adapter.js.map +1 -1
- package/dist/core/networking/service-discovery.js +7 -7
- package/dist/core/networking/service-discovery.js.map +1 -1
- package/dist/core/routing/index.d.ts +0 -20
- package/dist/core/routing/index.js +13 -178
- package/dist/core/routing/index.js.map +1 -1
- package/dist/core/runtime/node-adapter.js +6 -12
- package/dist/core/runtime/node-adapter.js.map +1 -1
- package/dist/moro.d.ts +0 -48
- package/dist/moro.js +148 -456
- package/dist/moro.js.map +1 -1
- package/dist/types/config.d.ts +2 -58
- package/dist/types/core.d.ts +40 -34
- package/dist/types/http.d.ts +1 -16
- package/dist/types/logger.d.ts +0 -7
- package/dist/types/module.d.ts +0 -11
- package/package.json +2 -2
- package/src/core/auth/morojs-adapter.ts +13 -18
- package/src/core/config/file-loader.ts +233 -0
- package/src/core/config/index.ts +32 -77
- package/src/core/config/loader.ts +633 -0
- package/src/core/config/schema.ts +31 -41
- package/src/core/config/utils.ts +29 -22
- package/src/core/config/validation.ts +140 -0
- package/src/core/database/README.md +16 -26
- package/src/core/database/adapters/mongodb.ts +2 -30
- package/src/core/database/adapters/mysql.ts +0 -14
- package/src/core/database/adapters/postgresql.ts +2 -12
- package/src/core/database/adapters/redis.ts +4 -27
- package/src/core/framework.ts +23 -163
- package/src/core/http/http-server.ts +36 -176
- package/src/core/http/router.ts +38 -127
- package/src/core/logger/filters.ts +4 -12
- package/src/core/logger/index.ts +0 -1
- package/src/core/logger/logger.ts +216 -427
- package/src/core/logger/outputs.ts +2 -0
- package/src/core/middleware/built-in/auth.ts +17 -98
- package/src/core/middleware/built-in/cache.ts +1 -3
- package/src/core/middleware/built-in/index.ts +0 -8
- package/src/core/middleware/built-in/request-logger.ts +1 -3
- package/src/core/middleware/built-in/sse.ts +7 -9
- package/src/core/modules/auto-discovery.ts +13 -476
- package/src/core/modules/modules.ts +9 -20
- package/src/core/networking/adapters/ws-adapter.ts +5 -2
- package/src/core/networking/service-discovery.ts +7 -6
- package/src/core/routing/index.ts +14 -198
- package/src/core/runtime/node-adapter.ts +6 -12
- package/src/moro.ts +166 -554
- package/src/types/config.ts +2 -59
- package/src/types/core.ts +45 -47
- package/src/types/http.ts +1 -23
- package/src/types/logger.ts +0 -9
- package/src/types/module.ts +0 -12
- package/dist/core/config/config-manager.d.ts +0 -44
- package/dist/core/config/config-manager.js +0 -114
- package/dist/core/config/config-manager.js.map +0 -1
- package/dist/core/config/config-sources.d.ts +0 -21
- package/dist/core/config/config-sources.js +0 -502
- package/dist/core/config/config-sources.js.map +0 -1
- package/dist/core/config/config-validator.d.ts +0 -21
- package/dist/core/config/config-validator.js +0 -765
- package/dist/core/config/config-validator.js.map +0 -1
- package/dist/core/middleware/built-in/jwt-helpers.d.ts +0 -118
- package/dist/core/middleware/built-in/jwt-helpers.js +0 -221
- package/dist/core/middleware/built-in/jwt-helpers.js.map +0 -1
- package/src/core/config/config-manager.ts +0 -133
- package/src/core/config/config-sources.ts +0 -596
- package/src/core/config/config-validator.ts +0 -1078
- package/src/core/middleware/built-in/jwt-helpers.ts +0 -240
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createFrameworkLogger = exports.logger = exports.MoroLogger = void 0;
|
|
4
4
|
exports.configureGlobalLogger = configureGlobalLogger;
|
|
5
|
-
exports.destroyGlobalLogger = destroyGlobalLogger;
|
|
6
5
|
exports.applyLoggingConfiguration = applyLoggingConfiguration;
|
|
7
6
|
// Moro Logger - Beautiful, Fast, Feature-Rich
|
|
8
7
|
const perf_hooks_1 = require("perf_hooks");
|
|
@@ -33,23 +32,12 @@ class MoroLogger {
|
|
|
33
32
|
cachedTimestamp = '';
|
|
34
33
|
lastTimestamp = 0;
|
|
35
34
|
timestampCacheInterval = 100; // 100ms for better precision
|
|
36
|
-
//
|
|
37
|
-
static ENTRY_POOL = [];
|
|
38
|
-
static MAX_POOL_SIZE = 100;
|
|
39
|
-
static poolIndex = 0;
|
|
40
|
-
// String builder for efficient concatenation
|
|
41
|
-
static stringBuilder = [];
|
|
42
|
-
static stringBuilderIndex = 0;
|
|
43
|
-
// Buffered output for performance
|
|
35
|
+
// Buffered output for micro-batching
|
|
44
36
|
outputBuffer = [];
|
|
45
37
|
bufferSize = 0;
|
|
46
|
-
maxBufferSize =
|
|
38
|
+
maxBufferSize = 1024; // 1KB buffer
|
|
47
39
|
flushTimeout = null;
|
|
48
40
|
flushInterval = 1; // 1ms micro-batching
|
|
49
|
-
// Buffer overflow protection
|
|
50
|
-
bufferOverflowThreshold;
|
|
51
|
-
emergencyFlushInProgress = false;
|
|
52
|
-
isDestroyed = false;
|
|
53
41
|
// High-performance output methods
|
|
54
42
|
static LEVELS = {
|
|
55
43
|
debug: 0,
|
|
@@ -58,6 +46,76 @@ class MoroLogger {
|
|
|
58
46
|
error: 3,
|
|
59
47
|
fatal: 4,
|
|
60
48
|
};
|
|
49
|
+
// Static pre-allocated strings for maximum performance
|
|
50
|
+
static LEVEL_STRINGS = {
|
|
51
|
+
debug: 'DEBUG',
|
|
52
|
+
info: 'INFO',
|
|
53
|
+
warn: 'WARN',
|
|
54
|
+
error: 'ERROR',
|
|
55
|
+
fatal: 'FATAL',
|
|
56
|
+
};
|
|
57
|
+
// Pre-allocated ANSI color codes
|
|
58
|
+
static ANSI_COLORS = {
|
|
59
|
+
reset: '\x1b[0m',
|
|
60
|
+
bold: '\x1b[1m',
|
|
61
|
+
dim: '\x1b[2m',
|
|
62
|
+
red: '\x1b[31m',
|
|
63
|
+
green: '\x1b[32m',
|
|
64
|
+
yellow: '\x1b[33m',
|
|
65
|
+
blue: '\x1b[34m',
|
|
66
|
+
magenta: '\x1b[35m',
|
|
67
|
+
cyan: '\x1b[36m',
|
|
68
|
+
white: '\x1b[37m',
|
|
69
|
+
gray: '\x1b[90m',
|
|
70
|
+
};
|
|
71
|
+
// Object pool for LogEntry reuse
|
|
72
|
+
static ENTRY_POOL = [];
|
|
73
|
+
static MAX_POOL_SIZE = 100;
|
|
74
|
+
static poolIndex = 0;
|
|
75
|
+
// Object pool management
|
|
76
|
+
static getPooledEntry() {
|
|
77
|
+
if (MoroLogger.poolIndex > 0) {
|
|
78
|
+
return MoroLogger.ENTRY_POOL[--MoroLogger.poolIndex];
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
timestamp: new Date(),
|
|
82
|
+
level: 'info',
|
|
83
|
+
message: '',
|
|
84
|
+
context: undefined,
|
|
85
|
+
metadata: undefined,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
static returnPooledEntry(entry) {
|
|
89
|
+
if (MoroLogger.poolIndex < MoroLogger.MAX_POOL_SIZE) {
|
|
90
|
+
// Reset the entry
|
|
91
|
+
entry.timestamp = new Date();
|
|
92
|
+
entry.level = 'info';
|
|
93
|
+
entry.message = '';
|
|
94
|
+
entry.context = undefined;
|
|
95
|
+
entry.metadata = undefined;
|
|
96
|
+
MoroLogger.ENTRY_POOL[MoroLogger.poolIndex++] = entry;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// String builder for efficient concatenation
|
|
100
|
+
static stringBuilder = [];
|
|
101
|
+
static stringBuilderIndex = 0;
|
|
102
|
+
static resetStringBuilder() {
|
|
103
|
+
MoroLogger.stringBuilderIndex = 0;
|
|
104
|
+
}
|
|
105
|
+
static appendToBuilder(str) {
|
|
106
|
+
if (MoroLogger.stringBuilderIndex < MoroLogger.stringBuilder.length) {
|
|
107
|
+
MoroLogger.stringBuilder[MoroLogger.stringBuilderIndex++] = str;
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
MoroLogger.stringBuilder.push(str);
|
|
111
|
+
MoroLogger.stringBuilderIndex++;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
static buildString() {
|
|
115
|
+
const result = MoroLogger.stringBuilder.slice(0, MoroLogger.stringBuilderIndex).join('');
|
|
116
|
+
MoroLogger.resetStringBuilder();
|
|
117
|
+
return result;
|
|
118
|
+
}
|
|
61
119
|
static COLORS = {
|
|
62
120
|
debug: '\x1b[36m', // Cyan
|
|
63
121
|
info: '\x1b[32m', // Green
|
|
@@ -68,20 +126,11 @@ class MoroLogger {
|
|
|
68
126
|
context: '\x1b[34m', // Blue
|
|
69
127
|
metadata: '\x1b[37m', // White
|
|
70
128
|
performance: '\x1b[36m', // Cyan
|
|
71
|
-
reset: '\x1b[0m', // Reset
|
|
72
129
|
};
|
|
73
130
|
static RESET = '\x1b[0m';
|
|
74
131
|
static BOLD = '\x1b[1m';
|
|
75
|
-
// Static pre-allocated strings for performance
|
|
76
|
-
static LEVEL_STRINGS = {
|
|
77
|
-
debug: 'DEBUG',
|
|
78
|
-
info: 'INFO ',
|
|
79
|
-
warn: 'WARN ',
|
|
80
|
-
error: 'ERROR',
|
|
81
|
-
fatal: 'FATAL',
|
|
82
|
-
};
|
|
83
132
|
constructor(options = {}) {
|
|
84
|
-
this.options =
|
|
133
|
+
this.options = {
|
|
85
134
|
level: 'info',
|
|
86
135
|
enableColors: true,
|
|
87
136
|
enableTimestamp: true,
|
|
@@ -92,14 +141,9 @@ class MoroLogger {
|
|
|
92
141
|
outputs: [],
|
|
93
142
|
filters: [],
|
|
94
143
|
maxEntries: 1000,
|
|
95
|
-
maxBufferSize: 1000,
|
|
96
144
|
...options,
|
|
97
|
-
}
|
|
145
|
+
};
|
|
98
146
|
this.level = this.options.level || 'info';
|
|
99
|
-
// Initialize buffer size from options
|
|
100
|
-
this.maxBufferSize = this.options.maxBufferSize || 1000;
|
|
101
|
-
// Initialize buffer overflow protection
|
|
102
|
-
this.bufferOverflowThreshold = this.maxBufferSize * 2;
|
|
103
147
|
// Add default console output
|
|
104
148
|
this.addOutput({
|
|
105
149
|
name: 'console',
|
|
@@ -110,52 +154,6 @@ class MoroLogger {
|
|
|
110
154
|
this.options.outputs?.forEach(output => this.addOutput(output));
|
|
111
155
|
this.options.filters?.forEach(filter => this.addFilter(filter));
|
|
112
156
|
}
|
|
113
|
-
// Object pooling methods
|
|
114
|
-
static getPooledEntry() {
|
|
115
|
-
if (MoroLogger.ENTRY_POOL.length > 0) {
|
|
116
|
-
const entry = MoroLogger.ENTRY_POOL.pop();
|
|
117
|
-
// Properly reset ALL properties to prevent memory leaks
|
|
118
|
-
entry.timestamp = new Date();
|
|
119
|
-
entry.level = 'info';
|
|
120
|
-
entry.message = '';
|
|
121
|
-
entry.context = undefined;
|
|
122
|
-
entry.metadata = undefined;
|
|
123
|
-
entry.performance = undefined;
|
|
124
|
-
entry.moduleId = undefined;
|
|
125
|
-
return entry;
|
|
126
|
-
}
|
|
127
|
-
return MoroLogger.createFreshEntry();
|
|
128
|
-
}
|
|
129
|
-
// ADD this new method:
|
|
130
|
-
static createFreshEntry() {
|
|
131
|
-
return {
|
|
132
|
-
timestamp: new Date(),
|
|
133
|
-
level: 'info',
|
|
134
|
-
message: '',
|
|
135
|
-
context: undefined,
|
|
136
|
-
metadata: undefined,
|
|
137
|
-
performance: undefined,
|
|
138
|
-
moduleId: undefined,
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
static returnPooledEntry(entry) {
|
|
142
|
-
if (MoroLogger.ENTRY_POOL.length < MoroLogger.MAX_POOL_SIZE) {
|
|
143
|
-
MoroLogger.ENTRY_POOL.push(entry);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
// String builder methods
|
|
147
|
-
static resetStringBuilder() {
|
|
148
|
-
MoroLogger.stringBuilder.length = 0;
|
|
149
|
-
MoroLogger.stringBuilderIndex = 0;
|
|
150
|
-
}
|
|
151
|
-
static appendToBuilder(str) {
|
|
152
|
-
MoroLogger.stringBuilder[MoroLogger.stringBuilderIndex++] = str;
|
|
153
|
-
}
|
|
154
|
-
static buildString() {
|
|
155
|
-
const result = MoroLogger.stringBuilder.join('');
|
|
156
|
-
MoroLogger.resetStringBuilder();
|
|
157
|
-
return result;
|
|
158
|
-
}
|
|
159
157
|
debug(message, context, metadata) {
|
|
160
158
|
this.log('debug', message, context, metadata);
|
|
161
159
|
}
|
|
@@ -190,9 +188,7 @@ class MoroLogger {
|
|
|
190
188
|
}
|
|
191
189
|
}
|
|
192
190
|
child(context, metadata) {
|
|
193
|
-
|
|
194
|
-
const childOptions = { ...this.options, level: this.level };
|
|
195
|
-
const childLogger = new MoroLogger(childOptions);
|
|
191
|
+
const childLogger = new MoroLogger(this.options);
|
|
196
192
|
childLogger.contextPrefix = this.contextPrefix ? `${this.contextPrefix}:${context}` : context;
|
|
197
193
|
childLogger.contextMetadata = { ...this.contextMetadata, ...metadata };
|
|
198
194
|
childLogger.outputs = this.outputs;
|
|
@@ -204,9 +200,6 @@ class MoroLogger {
|
|
|
204
200
|
setLevel(level) {
|
|
205
201
|
this.level = level;
|
|
206
202
|
}
|
|
207
|
-
getLevel() {
|
|
208
|
-
return this.level;
|
|
209
|
-
}
|
|
210
203
|
addOutput(output) {
|
|
211
204
|
this.outputs.set(output.name, output);
|
|
212
205
|
}
|
|
@@ -249,16 +242,6 @@ class MoroLogger {
|
|
|
249
242
|
}
|
|
250
243
|
return this.cachedTimestamp;
|
|
251
244
|
}
|
|
252
|
-
// Cached timestamp generation (updates once per second)
|
|
253
|
-
getFastCachedTimestamp() {
|
|
254
|
-
const now = Date.now();
|
|
255
|
-
if (now - this.lastTimestamp > 1000) {
|
|
256
|
-
// Update every second
|
|
257
|
-
this.lastTimestamp = now;
|
|
258
|
-
this.cachedTimestamp = new Date(now).toISOString().slice(0, 19).replace('T', ' ');
|
|
259
|
-
}
|
|
260
|
-
return this.cachedTimestamp;
|
|
261
|
-
}
|
|
262
245
|
getMetrics() {
|
|
263
246
|
const now = Date.now();
|
|
264
247
|
const uptime = (now - this.startTime) / 1000; // seconds
|
|
@@ -283,34 +266,47 @@ class MoroLogger {
|
|
|
283
266
|
memoryUsage: 0,
|
|
284
267
|
};
|
|
285
268
|
}
|
|
286
|
-
// Optimized logging method
|
|
269
|
+
// Optimized logging method with aggressive level checking
|
|
287
270
|
log(level, message, context, metadata) {
|
|
288
|
-
//
|
|
289
|
-
const
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
271
|
+
// AGGRESSIVE LEVEL CHECK - numeric comparison for maximum speed
|
|
272
|
+
const levelNum = MoroLogger.LEVELS[level];
|
|
273
|
+
const effectiveLevelNum = this.parent
|
|
274
|
+
? MoroLogger.LEVELS[this.parent.level]
|
|
275
|
+
: MoroLogger.LEVELS[this.level];
|
|
276
|
+
if (levelNum < effectiveLevelNum) {
|
|
277
|
+
return; // Exit immediately if level is too low
|
|
278
|
+
}
|
|
279
|
+
// ULTRA-FAST PATH: Just message, no context, no metadata
|
|
294
280
|
if (!metadata && !context && !this.contextPrefix && !this.contextMetadata) {
|
|
295
|
-
|
|
281
|
+
const levelStr = MoroLogger.LEVEL_STRINGS[level];
|
|
282
|
+
this.output(`${levelStr} ${message}\n`, level);
|
|
296
283
|
return;
|
|
297
284
|
}
|
|
298
|
-
//
|
|
285
|
+
// FAST PATH: Message + context, no metadata
|
|
299
286
|
if (!metadata && !this.contextMetadata) {
|
|
300
|
-
|
|
287
|
+
const levelStr = MoroLogger.LEVEL_STRINGS[level];
|
|
288
|
+
if (context) {
|
|
289
|
+
this.output(`${levelStr} [${context}] ${message}\n`, level);
|
|
290
|
+
}
|
|
291
|
+
else {
|
|
292
|
+
this.output(`${levelStr} ${message}\n`, level);
|
|
293
|
+
}
|
|
301
294
|
return;
|
|
302
295
|
}
|
|
303
|
-
//
|
|
304
|
-
if (metadata && Object.keys(metadata).length
|
|
305
|
-
|
|
296
|
+
// MEDIUM PATH: Message + context + simple metadata
|
|
297
|
+
if (metadata && Object.keys(metadata).length <= 3 && !this.contextMetadata) {
|
|
298
|
+
const levelStr = MoroLogger.LEVEL_STRINGS[level];
|
|
299
|
+
const contextStr = context ? `[${context}] ` : '';
|
|
300
|
+
const metaStr = this.stringify(metadata);
|
|
301
|
+
this.output(`${levelStr} ${contextStr}${message} ${metaStr}\n`, level);
|
|
306
302
|
return;
|
|
307
303
|
}
|
|
308
|
-
//
|
|
304
|
+
// FULL PATH: All features enabled
|
|
309
305
|
this.fullLog(level, message, context, metadata);
|
|
310
306
|
}
|
|
311
|
-
// Full logging with all features
|
|
307
|
+
// Full logging with all features using object pooling
|
|
312
308
|
fullLog(level, message, context, metadata) {
|
|
313
|
-
//
|
|
309
|
+
// Get pooled entry to avoid allocation
|
|
314
310
|
const entry = MoroLogger.getPooledEntry();
|
|
315
311
|
const now = Date.now();
|
|
316
312
|
entry.timestamp = new Date(now);
|
|
@@ -327,7 +323,6 @@ class MoroLogger {
|
|
|
327
323
|
if (this.filters.size > 0) {
|
|
328
324
|
for (const filter of this.filters.values()) {
|
|
329
325
|
if (!filter.filter(entry)) {
|
|
330
|
-
MoroLogger.returnPooledEntry(entry);
|
|
331
326
|
return;
|
|
332
327
|
}
|
|
333
328
|
}
|
|
@@ -338,76 +333,8 @@ class MoroLogger {
|
|
|
338
333
|
this.addToHistory(entry);
|
|
339
334
|
// Write to outputs with batched processing
|
|
340
335
|
this.writeToOutputs(entry, level);
|
|
341
|
-
// Return entry to pool
|
|
342
|
-
MoroLogger.returnPooledEntry(entry);
|
|
343
|
-
}
|
|
344
|
-
// Absolute minimal logging - pure speed, no overhead
|
|
345
|
-
complexLog(level, message, context, metadata) {
|
|
346
|
-
// Use object pooling for LogEntry (Pino's technique)
|
|
347
|
-
const entry = MoroLogger.getPooledEntry();
|
|
348
|
-
const now = Date.now();
|
|
349
|
-
entry.timestamp = new Date(now);
|
|
350
|
-
entry.level = level;
|
|
351
|
-
entry.message = message;
|
|
352
|
-
entry.context = this.contextPrefix
|
|
353
|
-
? context
|
|
354
|
-
? `${this.contextPrefix}:${context}`
|
|
355
|
-
: this.contextPrefix
|
|
356
|
-
: context;
|
|
357
|
-
entry.metadata = this.createMetadata(metadata);
|
|
358
|
-
entry.performance = this.options.enablePerformance ? this.getPerformanceData(now) : undefined;
|
|
359
|
-
// Write to outputs with batched processing
|
|
360
|
-
this.writeToOutputs(entry, level);
|
|
361
|
-
// Return entry to pool
|
|
362
|
-
MoroLogger.returnPooledEntry(entry);
|
|
363
|
-
}
|
|
364
|
-
// Simple log writer with colors for minimal overhead cases
|
|
365
|
-
writeSimpleLog(level, message, context) {
|
|
366
|
-
const colors = this.options.enableColors !== false;
|
|
367
|
-
const levelReset = colors ? MoroLogger.RESET : '';
|
|
368
|
-
MoroLogger.resetStringBuilder();
|
|
369
|
-
// Timestamp with caching optimization
|
|
370
|
-
if (this.options.enableTimestamp !== false) {
|
|
371
|
-
const timestamp = this.getFastCachedTimestamp();
|
|
372
|
-
if (colors) {
|
|
373
|
-
MoroLogger.appendToBuilder(MoroLogger.COLORS.timestamp);
|
|
374
|
-
MoroLogger.appendToBuilder(timestamp);
|
|
375
|
-
MoroLogger.appendToBuilder(levelReset);
|
|
376
|
-
}
|
|
377
|
-
else {
|
|
378
|
-
MoroLogger.appendToBuilder(timestamp);
|
|
379
|
-
}
|
|
380
|
-
MoroLogger.appendToBuilder(' ');
|
|
381
|
-
}
|
|
382
|
-
// Level with pre-allocated strings
|
|
383
|
-
const levelStr = MoroLogger.LEVEL_STRINGS[level];
|
|
384
|
-
if (colors) {
|
|
385
|
-
MoroLogger.appendToBuilder(MoroLogger.COLORS[level]);
|
|
386
|
-
MoroLogger.appendToBuilder(MoroLogger.BOLD);
|
|
387
|
-
MoroLogger.appendToBuilder(levelStr);
|
|
388
|
-
MoroLogger.appendToBuilder(levelReset);
|
|
389
|
-
}
|
|
390
|
-
else {
|
|
391
|
-
MoroLogger.appendToBuilder(levelStr);
|
|
392
|
-
}
|
|
393
|
-
// Context
|
|
394
|
-
if (context && this.options.enableContext !== false) {
|
|
395
|
-
MoroLogger.appendToBuilder(' ');
|
|
396
|
-
if (colors) {
|
|
397
|
-
MoroLogger.appendToBuilder(MoroLogger.COLORS.context);
|
|
398
|
-
MoroLogger.appendToBuilder(`[${context}]`);
|
|
399
|
-
MoroLogger.appendToBuilder(levelReset);
|
|
400
|
-
}
|
|
401
|
-
else {
|
|
402
|
-
MoroLogger.appendToBuilder(`[${context}]`);
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
// Message
|
|
406
|
-
MoroLogger.appendToBuilder(' ');
|
|
407
|
-
MoroLogger.appendToBuilder(message);
|
|
408
|
-
// Output main log line with high-performance method
|
|
409
|
-
const finalMessage = MoroLogger.buildString();
|
|
410
|
-
this.output(`${finalMessage}\n`, level);
|
|
336
|
+
// Return entry to pool after a short delay to allow async operations
|
|
337
|
+
setTimeout(() => MoroLogger.returnPooledEntry(entry), 0);
|
|
411
338
|
}
|
|
412
339
|
updateMetrics(entry) {
|
|
413
340
|
this.metrics.totalLogs++;
|
|
@@ -455,35 +382,23 @@ class MoroLogger {
|
|
|
455
382
|
writeToOutputs(entry, level) {
|
|
456
383
|
if (this.outputs.size === 0)
|
|
457
384
|
return;
|
|
458
|
-
let successCount = 0;
|
|
459
|
-
const errors = [];
|
|
460
385
|
for (const output of this.outputs.values()) {
|
|
461
386
|
if (!output.level || MoroLogger.LEVELS[level] >= MoroLogger.LEVELS[output.level]) {
|
|
462
387
|
try {
|
|
463
388
|
output.write(entry);
|
|
464
|
-
successCount++;
|
|
465
389
|
}
|
|
466
390
|
catch (error) {
|
|
467
|
-
|
|
468
|
-
|
|
391
|
+
// Fallback to console.error for logger errors
|
|
392
|
+
// eslint-disable-next-line no-console
|
|
393
|
+
console.error('Logger output error:', error);
|
|
469
394
|
}
|
|
470
395
|
}
|
|
471
396
|
}
|
|
472
|
-
// If all outputs fail, use emergency console
|
|
473
|
-
if (successCount === 0 && this.outputs.size > 0) {
|
|
474
|
-
this.emergencyConsoleWrite(entry);
|
|
475
|
-
}
|
|
476
|
-
// Log output errors (but avoid infinite loops)
|
|
477
|
-
if (errors.length > 0 && level !== 'error') {
|
|
478
|
-
this.error(`Logger output errors: ${errors.length} failed`, 'MoroLogger', {
|
|
479
|
-
errors: errors.map(e => e.outputName),
|
|
480
|
-
});
|
|
481
|
-
}
|
|
482
397
|
}
|
|
483
398
|
writeToConsole(entry) {
|
|
484
399
|
const format = this.options.format || 'pretty';
|
|
485
400
|
if (format === 'json') {
|
|
486
|
-
this.output(
|
|
401
|
+
this.output(JSON.stringify(entry) + '\n', entry.level);
|
|
487
402
|
return;
|
|
488
403
|
}
|
|
489
404
|
if (format === 'compact') {
|
|
@@ -497,7 +412,6 @@ class MoroLogger {
|
|
|
497
412
|
}
|
|
498
413
|
writePrettyLog(entry) {
|
|
499
414
|
const colors = this.options.enableColors !== false;
|
|
500
|
-
const levelReset = colors ? MoroLogger.RESET : '';
|
|
501
415
|
MoroLogger.resetStringBuilder();
|
|
502
416
|
// Timestamp with caching optimization
|
|
503
417
|
if (this.options.enableTimestamp !== false) {
|
|
@@ -505,29 +419,35 @@ class MoroLogger {
|
|
|
505
419
|
if (colors) {
|
|
506
420
|
MoroLogger.appendToBuilder(MoroLogger.COLORS.timestamp);
|
|
507
421
|
MoroLogger.appendToBuilder(timestamp);
|
|
508
|
-
MoroLogger.appendToBuilder(
|
|
422
|
+
MoroLogger.appendToBuilder(MoroLogger.RESET);
|
|
509
423
|
}
|
|
510
424
|
else {
|
|
511
425
|
MoroLogger.appendToBuilder(timestamp);
|
|
512
426
|
}
|
|
427
|
+
}
|
|
428
|
+
// Level with color using pre-allocated strings
|
|
429
|
+
const levelColor = colors ? MoroLogger.COLORS[entry.level] : '';
|
|
430
|
+
const levelReset = colors ? MoroLogger.RESET : '';
|
|
431
|
+
const levelText = MoroLogger.LEVEL_STRINGS[entry.level];
|
|
432
|
+
// Add space after timestamp if present
|
|
433
|
+
if (this.options.enableTimestamp !== false) {
|
|
513
434
|
MoroLogger.appendToBuilder(' ');
|
|
514
435
|
}
|
|
515
|
-
// Level with pre-allocated strings
|
|
516
|
-
const levelStr = MoroLogger.LEVEL_STRINGS[entry.level];
|
|
517
436
|
if (colors) {
|
|
518
|
-
MoroLogger.appendToBuilder(
|
|
437
|
+
MoroLogger.appendToBuilder(levelColor);
|
|
519
438
|
MoroLogger.appendToBuilder(MoroLogger.BOLD);
|
|
520
|
-
MoroLogger.appendToBuilder(
|
|
439
|
+
MoroLogger.appendToBuilder(levelText);
|
|
521
440
|
MoroLogger.appendToBuilder(levelReset);
|
|
522
441
|
}
|
|
523
442
|
else {
|
|
524
|
-
MoroLogger.appendToBuilder(
|
|
443
|
+
MoroLogger.appendToBuilder(levelText);
|
|
525
444
|
}
|
|
526
445
|
// Context
|
|
527
446
|
if (entry.context && this.options.enableContext !== false) {
|
|
528
|
-
MoroLogger.
|
|
447
|
+
const contextColor = colors ? MoroLogger.COLORS.context : '';
|
|
448
|
+
MoroLogger.appendToBuilder(' '); // Space before context
|
|
529
449
|
if (colors) {
|
|
530
|
-
MoroLogger.appendToBuilder(
|
|
450
|
+
MoroLogger.appendToBuilder(contextColor);
|
|
531
451
|
MoroLogger.appendToBuilder(`[${entry.context}]`);
|
|
532
452
|
MoroLogger.appendToBuilder(levelReset);
|
|
533
453
|
}
|
|
@@ -536,7 +456,7 @@ class MoroLogger {
|
|
|
536
456
|
}
|
|
537
457
|
}
|
|
538
458
|
// Message
|
|
539
|
-
MoroLogger.appendToBuilder(' ');
|
|
459
|
+
MoroLogger.appendToBuilder(' '); // Space before message
|
|
540
460
|
MoroLogger.appendToBuilder(entry.message);
|
|
541
461
|
// Performance info
|
|
542
462
|
if (entry.performance && this.options.enablePerformance !== false) {
|
|
@@ -549,7 +469,7 @@ class MoroLogger {
|
|
|
549
469
|
perfParts.push(`${Math.round(entry.performance.memory)}MB`);
|
|
550
470
|
}
|
|
551
471
|
if (perfParts.length > 0) {
|
|
552
|
-
MoroLogger.appendToBuilder(' ');
|
|
472
|
+
MoroLogger.appendToBuilder(' '); // Space before performance info
|
|
553
473
|
if (colors) {
|
|
554
474
|
MoroLogger.appendToBuilder(perfColor);
|
|
555
475
|
MoroLogger.appendToBuilder(`(${perfParts.join(', ')})`);
|
|
@@ -567,20 +487,19 @@ class MoroLogger {
|
|
|
567
487
|
const metaColor = colors ? MoroLogger.COLORS.metadata : '';
|
|
568
488
|
const cleanMetadata = this.cleanMetadata(entry.metadata);
|
|
569
489
|
if (Object.keys(cleanMetadata).length > 0) {
|
|
570
|
-
MoroLogger.appendToBuilder(' ');
|
|
571
490
|
if (colors) {
|
|
572
491
|
MoroLogger.appendToBuilder(metaColor);
|
|
573
|
-
MoroLogger.appendToBuilder(this.
|
|
492
|
+
MoroLogger.appendToBuilder(this.stringify(cleanMetadata));
|
|
574
493
|
MoroLogger.appendToBuilder(levelReset);
|
|
575
494
|
}
|
|
576
495
|
else {
|
|
577
|
-
MoroLogger.appendToBuilder(this.
|
|
496
|
+
MoroLogger.appendToBuilder(this.stringify(cleanMetadata));
|
|
578
497
|
}
|
|
579
498
|
}
|
|
580
499
|
}
|
|
581
500
|
// Output main log line with high-performance method
|
|
582
501
|
const finalMessage = MoroLogger.buildString();
|
|
583
|
-
this.output(
|
|
502
|
+
this.output(finalMessage + '\n', entry.level);
|
|
584
503
|
// Stack trace for errors
|
|
585
504
|
if (entry.metadata?.stack && (entry.level === 'error' || entry.level === 'fatal')) {
|
|
586
505
|
const stackColor = colors ? MoroLogger.COLORS.error : '';
|
|
@@ -597,179 +516,77 @@ class MoroLogger {
|
|
|
597
516
|
}
|
|
598
517
|
return clean;
|
|
599
518
|
}
|
|
600
|
-
//
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
!this.emergencyFlushInProgress) {
|
|
605
|
-
this.emergencyFlushInProgress = true;
|
|
606
|
-
this.forceFlushBuffer();
|
|
607
|
-
this.emergencyFlushInProgress = false;
|
|
519
|
+
// Fast JSON stringify with error handling
|
|
520
|
+
stringify(obj) {
|
|
521
|
+
try {
|
|
522
|
+
return JSON.stringify(obj);
|
|
608
523
|
}
|
|
524
|
+
catch {
|
|
525
|
+
return '[Circular Reference]';
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
// High-performance output with micro-batching
|
|
529
|
+
output(message, level = 'info') {
|
|
530
|
+
// Add to buffer
|
|
609
531
|
this.outputBuffer.push(message);
|
|
610
|
-
this.bufferSize
|
|
611
|
-
//
|
|
612
|
-
if (
|
|
532
|
+
this.bufferSize += message.length;
|
|
533
|
+
// Flush immediately if buffer is full or for errors
|
|
534
|
+
if (this.bufferSize >= this.maxBufferSize || level === 'error' || level === 'fatal') {
|
|
613
535
|
this.flushBuffer();
|
|
614
536
|
}
|
|
615
537
|
else {
|
|
538
|
+
// Schedule flush with micro-batching
|
|
616
539
|
this.scheduleFlush();
|
|
617
540
|
}
|
|
618
541
|
}
|
|
619
542
|
scheduleFlush() {
|
|
620
|
-
if (this.flushTimeout
|
|
621
|
-
return; // Already scheduled
|
|
622
|
-
}
|
|
543
|
+
if (this.flushTimeout)
|
|
544
|
+
return; // Already scheduled
|
|
623
545
|
this.flushTimeout = setTimeout(() => {
|
|
624
546
|
this.flushBuffer();
|
|
547
|
+
this.flushTimeout = null;
|
|
625
548
|
}, this.flushInterval);
|
|
626
549
|
}
|
|
627
550
|
flushBuffer() {
|
|
628
|
-
if (this.outputBuffer.length === 0)
|
|
551
|
+
if (this.outputBuffer.length === 0)
|
|
629
552
|
return;
|
|
630
|
-
}
|
|
631
|
-
// Group messages by stream type
|
|
632
|
-
const stdoutMessages = [];
|
|
633
|
-
const stderrMessages = [];
|
|
634
|
-
for (const message of this.outputBuffer) {
|
|
635
|
-
// Determine stream based on message content or level
|
|
636
|
-
if (message.includes('ERROR') || message.includes('FATAL')) {
|
|
637
|
-
stderrMessages.push(message);
|
|
638
|
-
}
|
|
639
|
-
else {
|
|
640
|
-
stdoutMessages.push(message);
|
|
641
|
-
}
|
|
642
|
-
}
|
|
643
|
-
// Write to appropriate streams with error handling
|
|
644
553
|
try {
|
|
645
|
-
|
|
554
|
+
// Group by stream type for efficiency
|
|
555
|
+
const stdoutMessages = [];
|
|
556
|
+
const stderrMessages = [];
|
|
557
|
+
for (const message of this.outputBuffer) {
|
|
558
|
+
// Determine stream based on message content (simple heuristic)
|
|
559
|
+
if (message.includes('ERROR') || message.includes('FATAL')) {
|
|
560
|
+
stderrMessages.push(message);
|
|
561
|
+
}
|
|
562
|
+
else {
|
|
563
|
+
stdoutMessages.push(message);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
// Write to streams
|
|
567
|
+
if (stdoutMessages.length > 0) {
|
|
646
568
|
process.stdout.write(stdoutMessages.join(''));
|
|
647
569
|
}
|
|
648
|
-
if (stderrMessages.length > 0
|
|
570
|
+
if (stderrMessages.length > 0) {
|
|
649
571
|
process.stderr.write(stderrMessages.join(''));
|
|
650
572
|
}
|
|
651
573
|
}
|
|
652
574
|
catch {
|
|
653
|
-
// Fallback to console if
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
catch {
|
|
659
|
-
// If even console.log fails, just ignore
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
// Clear buffer
|
|
663
|
-
this.outputBuffer.length = 0;
|
|
664
|
-
this.bufferSize = 0;
|
|
665
|
-
// Clear timeout
|
|
666
|
-
if (this.flushTimeout) {
|
|
667
|
-
clearTimeout(this.flushTimeout);
|
|
668
|
-
this.flushTimeout = null;
|
|
669
|
-
}
|
|
670
|
-
}
|
|
671
|
-
// Emergency flush for buffer overflow protection
|
|
672
|
-
forceFlushBuffer() {
|
|
673
|
-
if (this.outputBuffer.length === 0)
|
|
674
|
-
return;
|
|
675
|
-
try {
|
|
676
|
-
const message = this.outputBuffer.join('');
|
|
677
|
-
process.stdout.write(message);
|
|
678
|
-
}
|
|
679
|
-
catch (error) {
|
|
680
|
-
// Emergency fallback - write individual messages
|
|
681
|
-
for (const msg of this.outputBuffer) {
|
|
682
|
-
try {
|
|
683
|
-
process.stdout.write(msg);
|
|
684
|
-
}
|
|
685
|
-
catch {
|
|
686
|
-
// If even this fails, give up on this batch
|
|
687
|
-
break;
|
|
575
|
+
// Fallback to console methods if stream write fails
|
|
576
|
+
for (const message of this.outputBuffer) {
|
|
577
|
+
if (message.includes('ERROR') || message.includes('FATAL')) {
|
|
578
|
+
// eslint-disable-next-line no-console
|
|
579
|
+
console.error(message.trim());
|
|
688
580
|
}
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
this.outputBuffer.length = 0;
|
|
693
|
-
this.bufferSize = 0;
|
|
694
|
-
}
|
|
695
|
-
}
|
|
696
|
-
// Safe stringify with circular reference detection
|
|
697
|
-
safeStringify(obj, maxDepth = 3) {
|
|
698
|
-
const seen = new WeakSet();
|
|
699
|
-
const stringify = (value, depth) => {
|
|
700
|
-
if (depth > maxDepth)
|
|
701
|
-
return '[Max Depth Reached]';
|
|
702
|
-
if (value === null || typeof value !== 'object')
|
|
703
|
-
return value;
|
|
704
|
-
if (seen.has(value))
|
|
705
|
-
return '[Circular Reference]';
|
|
706
|
-
seen.add(value);
|
|
707
|
-
if (Array.isArray(value)) {
|
|
708
|
-
return value.map(item => stringify(item, depth + 1));
|
|
709
|
-
}
|
|
710
|
-
const result = {};
|
|
711
|
-
for (const [key, val] of Object.entries(value)) {
|
|
712
|
-
if (typeof val !== 'function') {
|
|
713
|
-
// Skip functions
|
|
714
|
-
result[key] = stringify(val, depth + 1);
|
|
581
|
+
else {
|
|
582
|
+
// eslint-disable-next-line no-console
|
|
583
|
+
console.log(message.trim());
|
|
715
584
|
}
|
|
716
585
|
}
|
|
717
|
-
return result;
|
|
718
|
-
};
|
|
719
|
-
try {
|
|
720
|
-
return JSON.stringify(stringify(obj, 0));
|
|
721
|
-
}
|
|
722
|
-
catch (error) {
|
|
723
|
-
return '[Stringify Error]';
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
// Configuration validation
|
|
727
|
-
validateOptions(options) {
|
|
728
|
-
const validated = { ...options };
|
|
729
|
-
// Validate log level
|
|
730
|
-
const validLevels = ['debug', 'info', 'warn', 'error', 'fatal'];
|
|
731
|
-
if (validated.level && !validLevels.includes(validated.level)) {
|
|
732
|
-
console.warn(`[MoroLogger] Invalid log level: ${validated.level}, defaulting to 'info'`);
|
|
733
|
-
validated.level = 'info';
|
|
734
|
-
}
|
|
735
|
-
// Validate max entries
|
|
736
|
-
if (validated.maxEntries !== undefined) {
|
|
737
|
-
if (validated.maxEntries < 1 || validated.maxEntries > 100000) {
|
|
738
|
-
console.warn(`[MoroLogger] Invalid maxEntries: ${validated.maxEntries}, defaulting to 1000`);
|
|
739
|
-
validated.maxEntries = 1000;
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
// Validate buffer size
|
|
743
|
-
if (validated.maxBufferSize !== undefined) {
|
|
744
|
-
if (validated.maxBufferSize < 10 || validated.maxBufferSize > 10000) {
|
|
745
|
-
console.warn(`[MoroLogger] Invalid maxBufferSize: ${validated.maxBufferSize}, defaulting to 1000`);
|
|
746
|
-
validated.maxBufferSize = 1000;
|
|
747
|
-
}
|
|
748
|
-
}
|
|
749
|
-
return validated;
|
|
750
|
-
}
|
|
751
|
-
// Error handling methods
|
|
752
|
-
handleOutputError(outputName, error) {
|
|
753
|
-
// Could implement output retry logic, circuit breaker, etc.
|
|
754
|
-
// For now, just track the error
|
|
755
|
-
if (!this.metrics.outputErrors) {
|
|
756
|
-
this.metrics.outputErrors = {};
|
|
757
|
-
}
|
|
758
|
-
this.metrics.outputErrors[outputName] = (this.metrics.outputErrors[outputName] || 0) + 1;
|
|
759
|
-
}
|
|
760
|
-
emergencyConsoleWrite(entry) {
|
|
761
|
-
const message = `${entry.timestamp.toISOString()} ${entry.level.toUpperCase()} ${entry.message}`;
|
|
762
|
-
try {
|
|
763
|
-
if (entry.level === 'error' || entry.level === 'fatal') {
|
|
764
|
-
process.stderr.write(`[EMERGENCY] ${message}\n`);
|
|
765
|
-
}
|
|
766
|
-
else {
|
|
767
|
-
process.stdout.write(`[EMERGENCY] ${message}\n`);
|
|
768
|
-
}
|
|
769
|
-
}
|
|
770
|
-
catch {
|
|
771
|
-
// If even emergency write fails, there's nothing more we can do
|
|
772
586
|
}
|
|
587
|
+
// Reset buffer
|
|
588
|
+
this.outputBuffer.length = 0;
|
|
589
|
+
this.bufferSize = 0;
|
|
773
590
|
}
|
|
774
591
|
// Force flush streams (useful for shutdown)
|
|
775
592
|
flush() {
|
|
@@ -781,36 +598,27 @@ class MoroLogger {
|
|
|
781
598
|
// Flush any remaining buffer
|
|
782
599
|
this.flushBuffer();
|
|
783
600
|
try {
|
|
784
|
-
// Force flush streams
|
|
601
|
+
// Force flush streams
|
|
785
602
|
if (process.stdout.writable) {
|
|
786
|
-
process.stdout.
|
|
603
|
+
process.stdout.end();
|
|
787
604
|
}
|
|
788
605
|
if (process.stderr.writable) {
|
|
789
|
-
process.stderr.
|
|
606
|
+
process.stderr.end();
|
|
790
607
|
}
|
|
791
608
|
}
|
|
792
609
|
catch {
|
|
793
610
|
// Ignore flush errors
|
|
794
611
|
}
|
|
795
612
|
}
|
|
796
|
-
//
|
|
797
|
-
|
|
798
|
-
//
|
|
799
|
-
this.isDestroyed = true;
|
|
800
|
-
// Clear any remaining timeouts
|
|
613
|
+
// Cleanup method to clear all timeouts and handles
|
|
614
|
+
cleanup() {
|
|
615
|
+
// Clear any pending flush timeout
|
|
801
616
|
if (this.flushTimeout) {
|
|
802
617
|
clearTimeout(this.flushTimeout);
|
|
803
618
|
this.flushTimeout = null;
|
|
804
619
|
}
|
|
805
|
-
// Flush any remaining
|
|
620
|
+
// Flush any remaining output
|
|
806
621
|
this.flushBuffer();
|
|
807
|
-
// Clear outputs and filters
|
|
808
|
-
this.outputs.clear();
|
|
809
|
-
this.filters.clear();
|
|
810
|
-
// Clear history
|
|
811
|
-
this.history.length = 0;
|
|
812
|
-
this.historyIndex = 0;
|
|
813
|
-
this.historySize = 0;
|
|
814
622
|
}
|
|
815
623
|
}
|
|
816
624
|
exports.MoroLogger = MoroLogger;
|
|
@@ -823,6 +631,28 @@ exports.logger = new MoroLogger({
|
|
|
823
631
|
enableColors: !process.env.NO_COLOR,
|
|
824
632
|
format: process.env.LOG_FORMAT || 'pretty',
|
|
825
633
|
});
|
|
634
|
+
// Add cleanup handlers for Jest and other test runners
|
|
635
|
+
if (typeof process !== 'undefined') {
|
|
636
|
+
// Cleanup on process exit
|
|
637
|
+
process.on('beforeExit', () => {
|
|
638
|
+
exports.logger.cleanup();
|
|
639
|
+
});
|
|
640
|
+
process.on('SIGINT', () => {
|
|
641
|
+
exports.logger.cleanup();
|
|
642
|
+
process.exit(0);
|
|
643
|
+
});
|
|
644
|
+
process.on('SIGTERM', () => {
|
|
645
|
+
exports.logger.cleanup();
|
|
646
|
+
process.exit(0);
|
|
647
|
+
});
|
|
648
|
+
// For Jest and other test runners - cleanup on uncaught exceptions
|
|
649
|
+
process.on('uncaughtException', () => {
|
|
650
|
+
exports.logger.cleanup();
|
|
651
|
+
});
|
|
652
|
+
process.on('unhandledRejection', () => {
|
|
653
|
+
exports.logger.cleanup();
|
|
654
|
+
});
|
|
655
|
+
}
|
|
826
656
|
/**
|
|
827
657
|
* Configure the global logger with new settings
|
|
828
658
|
* This allows runtime configuration of the logger
|
|
@@ -834,13 +664,6 @@ function configureGlobalLogger(options) {
|
|
|
834
664
|
// Additional configuration options can be added here as needed
|
|
835
665
|
// For now, focusing on level which is the most critical
|
|
836
666
|
}
|
|
837
|
-
/**
|
|
838
|
-
* Destroy the global logger and clean up resources (for testing)
|
|
839
|
-
* @internal
|
|
840
|
-
*/
|
|
841
|
-
function destroyGlobalLogger() {
|
|
842
|
-
exports.logger.destroy();
|
|
843
|
-
}
|
|
844
667
|
/**
|
|
845
668
|
* Apply logging configuration from the config system and/or createApp options
|
|
846
669
|
*/
|