logixia 1.2.1 → 1.3.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/dist/{index-BDRSTjUt.d.ts → index-CHIsdA9n.d.ts} +53 -2
- package/dist/index-CHIsdA9n.d.ts.map +1 -0
- package/dist/{index-Drrzn-Yg.d.mts → index-iDTW2-eY.d.mts} +53 -2
- package/dist/index-iDTW2-eY.d.mts.map +1 -0
- package/dist/index.d.mts +89 -3
- package/dist/index.d.mts.map +1 -1
- package/dist/index.d.ts +89 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3 -3
- package/dist/index.mjs.map +1 -1
- package/dist/{logitron-logger.module-iO8DPE7_.mjs → logitron-logger.module-2AzkadqZ.mjs} +226 -8
- package/dist/logitron-logger.module-2AzkadqZ.mjs.map +1 -0
- package/dist/{logitron-logger.module-X6nGDVGC.js → logitron-logger.module-BqNKp0Fs.js} +240 -4
- package/dist/logitron-logger.module-BqNKp0Fs.js.map +1 -0
- package/dist/{logitron-logger.module-CY3t8yK6.d.mts → logitron-logger.module-C0G8JGVf.d.ts} +6 -4
- package/dist/logitron-logger.module-C0G8JGVf.d.ts.map +1 -0
- package/dist/{logitron-logger.module-DgEldK9V.d.ts → logitron-logger.module-DQKaZTJL.d.mts} +6 -4
- package/dist/logitron-logger.module-DQKaZTJL.d.mts.map +1 -0
- package/dist/middleware.d.mts +83 -0
- package/dist/middleware.d.mts.map +1 -0
- package/dist/middleware.d.ts +83 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/middleware.js +132 -0
- package/dist/middleware.js.map +1 -0
- package/dist/middleware.mjs +130 -0
- package/dist/middleware.mjs.map +1 -0
- package/dist/nest.d.mts +2 -2
- package/dist/nest.d.ts +2 -2
- package/dist/nest.js +2 -2
- package/dist/nest.mjs +2 -2
- package/dist/testing.d.mts +67 -0
- package/dist/testing.d.mts.map +1 -0
- package/dist/testing.d.ts +67 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +164 -0
- package/dist/testing.js.map +1 -0
- package/dist/testing.mjs +163 -0
- package/dist/testing.mjs.map +1 -0
- package/dist/{transport.manager-Vi__pagn.mjs → transport.manager-5VVdqS3o.mjs} +51 -2
- package/dist/transport.manager-5VVdqS3o.mjs.map +1 -0
- package/dist/{transport.manager-C3Xr7Tvi.js → transport.manager-DCOm4uIQ.js} +51 -2
- package/dist/transport.manager-DCOm4uIQ.js.map +1 -0
- package/dist/transports.d.mts +38 -1
- package/dist/transports.d.mts.map +1 -1
- package/dist/transports.d.ts +38 -1
- package/dist/transports.d.ts.map +1 -1
- package/dist/transports.js +1 -1
- package/dist/transports.mjs +1 -1
- package/package.json +21 -1
- package/dist/index-BDRSTjUt.d.ts.map +0 -1
- package/dist/index-Drrzn-Yg.d.mts.map +0 -1
- package/dist/logitron-logger.module-CY3t8yK6.d.mts.map +0 -1
- package/dist/logitron-logger.module-DgEldK9V.d.ts.map +0 -1
- package/dist/logitron-logger.module-X6nGDVGC.js.map +0 -1
- package/dist/logitron-logger.module-iO8DPE7_.mjs.map +0 -1
- package/dist/transport.manager-C3Xr7Tvi.js.map +0 -1
- package/dist/transport.manager-Vi__pagn.mjs.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const require_chunk = require('./chunk-BTgCAUrQ.js');
|
|
2
|
-
const require_transport_manager = require('./transport.manager-
|
|
2
|
+
const require_transport_manager = require('./transport.manager-DCOm4uIQ.js');
|
|
3
3
|
let fast_json_stringify = require("fast-json-stringify");
|
|
4
4
|
fast_json_stringify = require_chunk.__toESM(fast_json_stringify);
|
|
5
5
|
let node_async_hooks = require("node:async_hooks");
|
|
@@ -9,6 +9,75 @@ crypto = require_chunk.__toESM(crypto);
|
|
|
9
9
|
let __nestjs_common = require("@nestjs/common");
|
|
10
10
|
__nestjs_common = require_chunk.__toESM(__nestjs_common);
|
|
11
11
|
|
|
12
|
+
//#region src/context/async-context.ts
|
|
13
|
+
const _storage = new node_async_hooks.AsyncLocalStorage();
|
|
14
|
+
const LogixiaContext = {
|
|
15
|
+
run(store, callback) {
|
|
16
|
+
const parent = _storage.getStore() ?? {};
|
|
17
|
+
return _storage.run({
|
|
18
|
+
...parent,
|
|
19
|
+
...store
|
|
20
|
+
}, callback);
|
|
21
|
+
},
|
|
22
|
+
get() {
|
|
23
|
+
return _storage.getStore();
|
|
24
|
+
},
|
|
25
|
+
set(fields) {
|
|
26
|
+
const store = _storage.getStore();
|
|
27
|
+
if (!store) return;
|
|
28
|
+
Object.assign(store, fields);
|
|
29
|
+
},
|
|
30
|
+
getStorage() {
|
|
31
|
+
return _storage;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Create an Express/Connect-compatible middleware that wraps each request in
|
|
36
|
+
* a `LogixiaContext.run()` scope populated with common request fields.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* import { createExpressContextMiddleware } from 'logixia';
|
|
41
|
+
* app.use(createExpressContextMiddleware());
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
function createExpressContextMiddleware(options = {}) {
|
|
45
|
+
const { enrich, requestIdHeader = "x-request-id", traceIdHeader = "x-trace-id" } = options;
|
|
46
|
+
return function logixiaContextMiddleware(req, _res, next) {
|
|
47
|
+
const headers = req["headers"] ?? {};
|
|
48
|
+
const traceId = headers[traceIdHeader];
|
|
49
|
+
const base = {
|
|
50
|
+
requestId: headers[requestIdHeader] ?? crypto.randomUUID().slice(0, 8),
|
|
51
|
+
...traceId !== void 0 ? { traceId } : {}
|
|
52
|
+
};
|
|
53
|
+
LogixiaContext.run({
|
|
54
|
+
...base,
|
|
55
|
+
...enrich ? enrich(req) : {}
|
|
56
|
+
}, next);
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Create a Fastify lifecycle hook that wraps each request in a context scope.
|
|
61
|
+
*
|
|
62
|
+
* Register with `fastify.addHook('onRequest', createFastifyContextHook())`.
|
|
63
|
+
*/
|
|
64
|
+
function createFastifyContextHook(options = {}) {
|
|
65
|
+
const { enrich, requestIdHeader = "x-request-id", traceIdHeader = "x-trace-id" } = options;
|
|
66
|
+
return function logixiaFastifyHook(request, _reply, done) {
|
|
67
|
+
const headers = request["headers"] ?? {};
|
|
68
|
+
const traceId = headers[traceIdHeader];
|
|
69
|
+
const base = {
|
|
70
|
+
requestId: headers[requestIdHeader] ?? request["id"] ?? crypto.randomUUID().slice(0, 8),
|
|
71
|
+
...traceId !== void 0 ? { traceId } : {}
|
|
72
|
+
};
|
|
73
|
+
LogixiaContext.run({
|
|
74
|
+
...base,
|
|
75
|
+
...enrich ? enrich(request) : {}
|
|
76
|
+
}, done);
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
//#endregion
|
|
12
81
|
//#region src/types/index.ts
|
|
13
82
|
const LogLevel = {
|
|
14
83
|
ERROR: "error",
|
|
@@ -227,6 +296,137 @@ function isPlainObject(value) {
|
|
|
227
296
|
return value !== null && typeof value === "object" && !Array.isArray(value) && !(value instanceof Date) && !(value instanceof Error) && !(value instanceof RegExp);
|
|
228
297
|
}
|
|
229
298
|
|
|
299
|
+
//#endregion
|
|
300
|
+
//#region src/utils/sampling.utils.ts
|
|
301
|
+
const ALWAYS_EMIT_LEVELS = new Set(["error", "fatal"]);
|
|
302
|
+
var Sampler = class {
|
|
303
|
+
constructor(config, onStats) {
|
|
304
|
+
this.sampledTraces = /* @__PURE__ */ new Set();
|
|
305
|
+
this.droppedTraces = /* @__PURE__ */ new Set();
|
|
306
|
+
this._tokenBucket = 0;
|
|
307
|
+
this._lastRefillMs = Date.now();
|
|
308
|
+
this._stats = {
|
|
309
|
+
evaluated: 0,
|
|
310
|
+
emitted: 0,
|
|
311
|
+
dropped: 0,
|
|
312
|
+
byLevel: {},
|
|
313
|
+
windowStart: Date.now()
|
|
314
|
+
};
|
|
315
|
+
this.config = config;
|
|
316
|
+
if (config.maxLogsPerSecond && config.maxLogsPerSecond > 0) this._tokenBucket = config.maxLogsPerSecond;
|
|
317
|
+
const interval$1 = config.statsIntervalMs ?? 6e4;
|
|
318
|
+
if (interval$1 > 0 && onStats) {
|
|
319
|
+
this._statsTimer = setInterval(() => {
|
|
320
|
+
onStats(this.getStats());
|
|
321
|
+
this.resetStats();
|
|
322
|
+
}, interval$1);
|
|
323
|
+
if (this._statsTimer.unref) this._statsTimer.unref();
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Decide whether a given log entry should be emitted.
|
|
328
|
+
*
|
|
329
|
+
* @param level Log level string (lowercase)
|
|
330
|
+
* @param traceId Active trace ID, if any
|
|
331
|
+
* @returns true → emit, false → drop
|
|
332
|
+
*/
|
|
333
|
+
shouldEmit(level, traceId) {
|
|
334
|
+
var _this$config$perLevel;
|
|
335
|
+
const lvl = level.toLowerCase();
|
|
336
|
+
this._trackEvaluated(lvl);
|
|
337
|
+
if (ALWAYS_EMIT_LEVELS.has(lvl) && ((_this$config$perLevel = this.config.perLevel) === null || _this$config$perLevel === void 0 ? void 0 : _this$config$perLevel[lvl]) === void 0) {
|
|
338
|
+
this._trackEmitted(lvl);
|
|
339
|
+
return true;
|
|
340
|
+
}
|
|
341
|
+
if (this.config.traceConsistent && traceId) {
|
|
342
|
+
if (this.sampledTraces.has(traceId)) {
|
|
343
|
+
this._trackEmitted(lvl);
|
|
344
|
+
return true;
|
|
345
|
+
}
|
|
346
|
+
if (this.droppedTraces.has(traceId)) {
|
|
347
|
+
this._trackDropped(lvl);
|
|
348
|
+
return false;
|
|
349
|
+
}
|
|
350
|
+
const emit = this._sampleByRate(lvl);
|
|
351
|
+
if (emit) this.sampledTraces.add(traceId);
|
|
352
|
+
else this.droppedTraces.add(traceId);
|
|
353
|
+
if (emit) this._trackEmitted(lvl);
|
|
354
|
+
else this._trackDropped(lvl);
|
|
355
|
+
return emit;
|
|
356
|
+
}
|
|
357
|
+
if (!this._sampleByRate(lvl)) {
|
|
358
|
+
this._trackDropped(lvl);
|
|
359
|
+
return false;
|
|
360
|
+
}
|
|
361
|
+
if (this.config.maxLogsPerSecond && this.config.maxLogsPerSecond > 0) {
|
|
362
|
+
if (!this._consumeToken()) {
|
|
363
|
+
this._trackDropped(lvl);
|
|
364
|
+
return false;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
this._trackEmitted(lvl);
|
|
368
|
+
return true;
|
|
369
|
+
}
|
|
370
|
+
getStats() {
|
|
371
|
+
return {
|
|
372
|
+
...this._stats,
|
|
373
|
+
byLevel: { ...this._stats.byLevel }
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
resetStats() {
|
|
377
|
+
this._stats = {
|
|
378
|
+
evaluated: 0,
|
|
379
|
+
emitted: 0,
|
|
380
|
+
dropped: 0,
|
|
381
|
+
byLevel: {},
|
|
382
|
+
windowStart: Date.now()
|
|
383
|
+
};
|
|
384
|
+
this.sampledTraces.clear();
|
|
385
|
+
this.droppedTraces.clear();
|
|
386
|
+
}
|
|
387
|
+
destroy() {
|
|
388
|
+
if (this._statsTimer) clearInterval(this._statsTimer);
|
|
389
|
+
}
|
|
390
|
+
_sampleByRate(level) {
|
|
391
|
+
var _this$config$perLevel2, _this$config$perLevel3;
|
|
392
|
+
const rate = ((_this$config$perLevel2 = this.config.perLevel) === null || _this$config$perLevel2 === void 0 ? void 0 : _this$config$perLevel2[level]) ?? ((_this$config$perLevel3 = this.config.perLevel) === null || _this$config$perLevel3 === void 0 ? void 0 : _this$config$perLevel3["*"]) ?? this.config.rate ?? 1;
|
|
393
|
+
if (rate >= 1) return true;
|
|
394
|
+
if (rate <= 0) return false;
|
|
395
|
+
return Math.random() < rate;
|
|
396
|
+
}
|
|
397
|
+
_consumeToken() {
|
|
398
|
+
const now = Date.now();
|
|
399
|
+
const elapsed = (now - this._lastRefillMs) / 1e3;
|
|
400
|
+
const max$1 = this.config.maxLogsPerSecond;
|
|
401
|
+
this._tokenBucket = Math.min(max$1, this._tokenBucket + elapsed * max$1);
|
|
402
|
+
this._lastRefillMs = now;
|
|
403
|
+
if (this._tokenBucket >= 1) {
|
|
404
|
+
this._tokenBucket -= 1;
|
|
405
|
+
return true;
|
|
406
|
+
}
|
|
407
|
+
return false;
|
|
408
|
+
}
|
|
409
|
+
_ensure(level) {
|
|
410
|
+
if (!this._stats.byLevel[level]) this._stats.byLevel[level] = {
|
|
411
|
+
evaluated: 0,
|
|
412
|
+
emitted: 0
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
_trackEvaluated(level) {
|
|
416
|
+
this._stats.evaluated++;
|
|
417
|
+
this._ensure(level);
|
|
418
|
+
this._stats.byLevel[level].evaluated++;
|
|
419
|
+
}
|
|
420
|
+
_trackEmitted(level) {
|
|
421
|
+
this._stats.emitted++;
|
|
422
|
+
this._ensure(level);
|
|
423
|
+
this._stats.byLevel[level].emitted++;
|
|
424
|
+
}
|
|
425
|
+
_trackDropped(_level) {
|
|
426
|
+
this._stats.dropped++;
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
|
|
230
430
|
//#endregion
|
|
231
431
|
//#region src/utils/shutdown.utils.ts
|
|
232
432
|
/** Module-level registry of all logger instances that have opted into graceful shutdown */
|
|
@@ -548,6 +748,13 @@ var LogixiaLogger = class LogixiaLogger {
|
|
|
548
748
|
};
|
|
549
749
|
this.context = context$1 ?? "";
|
|
550
750
|
if (this.config.transports) this.transportManager = new require_transport_manager.TransportManager(this.config.transports);
|
|
751
|
+
if (this.config.sampling) this._sampler = new Sampler(this.config.sampling, (stats) => {
|
|
752
|
+
process.stdout.write(JSON.stringify({
|
|
753
|
+
level: "info",
|
|
754
|
+
message: "[logixia/sampling] stats",
|
|
755
|
+
...stats
|
|
756
|
+
}) + "\n");
|
|
757
|
+
});
|
|
551
758
|
this.setupGracefulShutdown();
|
|
552
759
|
this.createCustomLevelMethods();
|
|
553
760
|
this._buildPerfCaches();
|
|
@@ -787,6 +994,7 @@ var LogixiaLogger = class LogixiaLogger {
|
|
|
787
994
|
return this.transportManager.healthCheck();
|
|
788
995
|
}
|
|
789
996
|
async close() {
|
|
997
|
+
var _this$_sampler;
|
|
790
998
|
for (const [label, timer$1] of this.timers) await this.warn(`Timer '${label}' was not ended properly`, {
|
|
791
999
|
startTime: new Date(timer$1.startTime).toISOString(),
|
|
792
1000
|
duration: `${Date.now() - timer$1.startTime}ms (incomplete)`
|
|
@@ -796,15 +1004,25 @@ var LogixiaLogger = class LogixiaLogger {
|
|
|
796
1004
|
await this.transportManager.flush();
|
|
797
1005
|
await this.transportManager.close();
|
|
798
1006
|
}
|
|
1007
|
+
(_this$_sampler = this._sampler) === null || _this$_sampler === void 0 || _this$_sampler.destroy();
|
|
799
1008
|
deregisterFromShutdown(this);
|
|
800
1009
|
}
|
|
801
1010
|
async log(level, message, data) {
|
|
802
1011
|
if (this.config.silent) return;
|
|
803
1012
|
if (!this.shouldLog(level)) return;
|
|
804
|
-
|
|
805
|
-
|
|
1013
|
+
if (this._sampler) {
|
|
1014
|
+
const traceId$1 = this.config.traceId ? getCurrentTraceId() ?? this.fallbackTraceId : void 0;
|
|
1015
|
+
if (!this._sampler.shouldEmit(level, traceId$1)) return;
|
|
1016
|
+
}
|
|
1017
|
+
const alsContext = LogixiaContext.get();
|
|
1018
|
+
const mergedData = alsContext && Object.keys(alsContext).length > 0 ? {
|
|
1019
|
+
...alsContext,
|
|
806
1020
|
...data
|
|
807
1021
|
} : data;
|
|
1022
|
+
const rawPayload = this._hasContextData ? {
|
|
1023
|
+
...this.contextData,
|
|
1024
|
+
...mergedData
|
|
1025
|
+
} : mergedData;
|
|
808
1026
|
let payload;
|
|
809
1027
|
if (rawPayload !== void 0 && rawPayload !== null) payload = this._hasRedact ? applyRedaction(rawPayload, this.config.redact) ?? rawPayload : rawPayload;
|
|
810
1028
|
const traceId = this.config.traceId ? getCurrentTraceId() ?? this.fallbackTraceId : void 0;
|
|
@@ -10349,6 +10567,12 @@ Object.defineProperty(exports, 'LogLevel', {
|
|
|
10349
10567
|
return LogLevel;
|
|
10350
10568
|
}
|
|
10351
10569
|
});
|
|
10570
|
+
Object.defineProperty(exports, 'LogixiaContext', {
|
|
10571
|
+
enumerable: true,
|
|
10572
|
+
get: function () {
|
|
10573
|
+
return LogixiaContext;
|
|
10574
|
+
}
|
|
10575
|
+
});
|
|
10352
10576
|
Object.defineProperty(exports, 'LogixiaLogger', {
|
|
10353
10577
|
enumerable: true,
|
|
10354
10578
|
get: function () {
|
|
@@ -10385,6 +10609,18 @@ Object.defineProperty(exports, 'applyRedaction', {
|
|
|
10385
10609
|
return applyRedaction;
|
|
10386
10610
|
}
|
|
10387
10611
|
});
|
|
10612
|
+
Object.defineProperty(exports, 'createExpressContextMiddleware', {
|
|
10613
|
+
enumerable: true,
|
|
10614
|
+
get: function () {
|
|
10615
|
+
return createExpressContextMiddleware;
|
|
10616
|
+
}
|
|
10617
|
+
});
|
|
10618
|
+
Object.defineProperty(exports, 'createFastifyContextHook', {
|
|
10619
|
+
enumerable: true,
|
|
10620
|
+
get: function () {
|
|
10621
|
+
return createFastifyContextHook;
|
|
10622
|
+
}
|
|
10623
|
+
});
|
|
10388
10624
|
Object.defineProperty(exports, 'createLogger', {
|
|
10389
10625
|
enumerable: true,
|
|
10390
10626
|
get: function () {
|
|
@@ -10481,4 +10717,4 @@ Object.defineProperty(exports, 'traceStorage', {
|
|
|
10481
10717
|
return traceStorage;
|
|
10482
10718
|
}
|
|
10483
10719
|
});
|
|
10484
|
-
//# sourceMappingURL=logitron-logger.module-
|
|
10720
|
+
//# sourceMappingURL=logitron-logger.module-BqNKp0Fs.js.map
|