logixia 1.12.4 → 1.12.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.
Files changed (166) hide show
  1. package/README.md +80 -27
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/async-context-CSHWoHMB.js +88 -0
  4. package/dist/async-context-CSHWoHMB.js.map +1 -0
  5. package/dist/async-context-CwBNMm2E.mjs +68 -0
  6. package/dist/async-context-CwBNMm2E.mjs.map +1 -0
  7. package/dist/azure-monitor.transport-CG7ClkYj.d.ts +62 -0
  8. package/dist/azure-monitor.transport-CG7ClkYj.d.ts.map +1 -0
  9. package/dist/azure-monitor.transport-CHnjVRF-.mjs +152 -0
  10. package/dist/azure-monitor.transport-CHnjVRF-.mjs.map +1 -0
  11. package/dist/azure-monitor.transport-Cm74kXZS.d.mts +62 -0
  12. package/dist/azure-monitor.transport-Cm74kXZS.d.mts.map +1 -0
  13. package/dist/azure-monitor.transport-CrvfHd9C.js +157 -0
  14. package/dist/azure-monitor.transport-CrvfHd9C.js.map +1 -0
  15. package/dist/azure.d.mts +3 -0
  16. package/dist/azure.d.ts +3 -0
  17. package/dist/azure.js +6 -0
  18. package/dist/azure.mjs +6 -0
  19. package/dist/batch-buffer-BY-mRWIK.js +170 -0
  20. package/dist/batch-buffer-BY-mRWIK.js.map +1 -0
  21. package/dist/batch-buffer-PGvSgbmd.mjs +132 -0
  22. package/dist/batch-buffer-PGvSgbmd.mjs.map +1 -0
  23. package/dist/browser.d.mts +427 -0
  24. package/dist/browser.d.mts.map +1 -0
  25. package/dist/browser.d.ts +427 -0
  26. package/dist/browser.d.ts.map +1 -0
  27. package/dist/browser.js +590 -0
  28. package/dist/browser.js.map +1 -0
  29. package/dist/browser.mjs +586 -0
  30. package/dist/browser.mjs.map +1 -0
  31. package/dist/chunk-DLSkYcPk.mjs +7 -0
  32. package/dist/chunk-nOFOJqeH.js +30 -0
  33. package/dist/cloudwatch.d.mts +3 -0
  34. package/dist/cloudwatch.d.ts +3 -0
  35. package/dist/cloudwatch.js +6 -0
  36. package/dist/cloudwatch.mjs +6 -0
  37. package/dist/cloudwatch.transport-CGHY4buE.d.mts +81 -0
  38. package/dist/cloudwatch.transport-CGHY4buE.d.mts.map +1 -0
  39. package/dist/cloudwatch.transport-DK_8cKd3.d.ts +81 -0
  40. package/dist/cloudwatch.transport-DK_8cKd3.d.ts.map +1 -0
  41. package/dist/cloudwatch.transport-pNBNWJLt.js +370 -0
  42. package/dist/cloudwatch.transport-pNBNWJLt.js.map +1 -0
  43. package/dist/cloudwatch.transport-yBwm4OeO.mjs +360 -0
  44. package/dist/cloudwatch.transport-yBwm4OeO.mjs.map +1 -0
  45. package/dist/coerce.utils-BN980Y9V.js +44 -0
  46. package/dist/coerce.utils-BN980Y9V.js.map +1 -0
  47. package/dist/coerce.utils-Dxv4_ikC.mjs +38 -0
  48. package/dist/coerce.utils-Dxv4_ikC.mjs.map +1 -0
  49. package/dist/correlation.d.mts +238 -0
  50. package/dist/correlation.d.mts.map +1 -0
  51. package/dist/correlation.d.ts +238 -0
  52. package/dist/correlation.d.ts.map +1 -0
  53. package/dist/correlation.js +272 -0
  54. package/dist/correlation.js.map +1 -0
  55. package/dist/correlation.mjs +261 -0
  56. package/dist/correlation.mjs.map +1 -0
  57. package/dist/gcp.d.mts +3 -0
  58. package/dist/gcp.d.ts +3 -0
  59. package/dist/gcp.js +6 -0
  60. package/dist/gcp.mjs +6 -0
  61. package/dist/gcp.transport-BJuNRFe_.mjs +192 -0
  62. package/dist/gcp.transport-BJuNRFe_.mjs.map +1 -0
  63. package/dist/gcp.transport-BOhkVKlI.d.ts +71 -0
  64. package/dist/gcp.transport-BOhkVKlI.d.ts.map +1 -0
  65. package/dist/gcp.transport-Bi6CUqZR.d.mts +71 -0
  66. package/dist/gcp.transport-Bi6CUqZR.d.mts.map +1 -0
  67. package/dist/gcp.transport-SHdtc1n0.js +198 -0
  68. package/dist/gcp.transport-SHdtc1n0.js.map +1 -0
  69. package/dist/{index-CwFww7VC.d.ts → index-BPKwwERo.d.mts} +18 -174
  70. package/dist/index-BPKwwERo.d.mts.map +1 -0
  71. package/dist/{index-DnyeaoZU.d.mts → index-C1X-TE5I.d.ts} +18 -174
  72. package/dist/index-C1X-TE5I.d.ts.map +1 -0
  73. package/dist/index.d.mts +41 -11
  74. package/dist/index.d.mts.map +1 -1
  75. package/dist/index.d.ts +40 -10
  76. package/dist/index.d.ts.map +1 -1
  77. package/dist/index.js +87 -147
  78. package/dist/index.js.map +1 -1
  79. package/dist/index.mjs +62 -132
  80. package/dist/index.mjs.map +1 -1
  81. package/dist/internal-log-BUJYMZbE.js +70 -0
  82. package/dist/internal-log-BUJYMZbE.js.map +1 -0
  83. package/dist/internal-log-Cm8SOWSV.mjs +52 -0
  84. package/dist/internal-log-Cm8SOWSV.mjs.map +1 -0
  85. package/dist/{logitron-logger.module-BIGTm2V6.mjs → logitron-logger.module-Bs3XYZgF.mjs} +266 -166
  86. package/dist/logitron-logger.module-Bs3XYZgF.mjs.map +1 -0
  87. package/dist/{logitron-logger.module-BTxDpK6u.js → logitron-logger.module-BsDZR5BH.js} +297 -203
  88. package/dist/logitron-logger.module-BsDZR5BH.js.map +1 -0
  89. package/dist/{logitron-logger.module-BmT-ewin.d.ts → logitron-logger.module-CxT1F6Cm.d.ts} +23 -10
  90. package/dist/logitron-logger.module-CxT1F6Cm.d.ts.map +1 -0
  91. package/dist/{logitron-logger.module-BCq3sF27.d.mts → logitron-logger.module-zDKVd_o0.d.mts} +23 -10
  92. package/dist/logitron-logger.module-zDKVd_o0.d.mts.map +1 -0
  93. package/dist/middleware.d.mts +5 -2
  94. package/dist/middleware.d.mts.map +1 -1
  95. package/dist/middleware.d.ts +5 -2
  96. package/dist/middleware.d.ts.map +1 -1
  97. package/dist/middleware.js +13 -4
  98. package/dist/middleware.js.map +1 -1
  99. package/dist/middleware.mjs +14 -4
  100. package/dist/middleware.mjs.map +1 -1
  101. package/dist/nest.d.mts +3 -2
  102. package/dist/nest.d.mts.map +1 -1
  103. package/dist/nest.d.ts +3 -2
  104. package/dist/nest.d.ts.map +1 -1
  105. package/dist/nest.js +6 -2
  106. package/dist/nest.mjs +6 -2
  107. package/dist/safe-stringify-DJ66tW5I.mjs +118 -0
  108. package/dist/safe-stringify-DJ66tW5I.mjs.map +1 -0
  109. package/dist/safe-stringify-DWo3aZp_.js +142 -0
  110. package/dist/safe-stringify-DWo3aZp_.js.map +1 -0
  111. package/dist/search-CFQRISUv.mjs +1596 -0
  112. package/dist/search-CFQRISUv.mjs.map +1 -0
  113. package/dist/search-CQOo-Iq6.d.mts +816 -0
  114. package/dist/search-CQOo-Iq6.d.mts.map +1 -0
  115. package/dist/search-DujhR94O.d.ts +816 -0
  116. package/dist/search-DujhR94O.d.ts.map +1 -0
  117. package/dist/search-njTI2hdo.js +1631 -0
  118. package/dist/search-njTI2hdo.js.map +1 -0
  119. package/dist/search.d.mts +4 -1
  120. package/dist/search.d.ts +4 -1
  121. package/dist/search.js +9 -1
  122. package/dist/search.mjs +3 -2
  123. package/dist/testing.d.mts +2 -1
  124. package/dist/testing.d.mts.map +1 -1
  125. package/dist/testing.d.ts +2 -1
  126. package/dist/testing.d.ts.map +1 -1
  127. package/dist/{transport.manager-ciG4r5uz.js → transport.manager-BivyUTtU.js} +497 -437
  128. package/dist/transport.manager-BivyUTtU.js.map +1 -0
  129. package/dist/{transport.manager-DETpXuaY.mjs → transport.manager-D6KL3t9V.mjs} +473 -364
  130. package/dist/transport.manager-D6KL3t9V.mjs.map +1 -0
  131. package/dist/transport.types-B5vcyv2k.d.mts +187 -0
  132. package/dist/transport.types-B5vcyv2k.d.mts.map +1 -0
  133. package/dist/transport.types-BuY84TwO.d.ts +187 -0
  134. package/dist/transport.types-BuY84TwO.d.ts.map +1 -0
  135. package/dist/transports.d.mts +90 -29
  136. package/dist/transports.d.mts.map +1 -1
  137. package/dist/transports.d.ts +90 -29
  138. package/dist/transports.d.ts.map +1 -1
  139. package/dist/transports.js +14 -2
  140. package/dist/transports.mjs +10 -2
  141. package/dist/worker-entry.js +1241 -0
  142. package/dist/worker.d.mts +3 -0
  143. package/dist/worker.d.ts +3 -0
  144. package/dist/worker.js +4 -0
  145. package/dist/worker.mjs +4 -0
  146. package/dist/worker.transport-BP8Q28Z2.d.mts +76 -0
  147. package/dist/worker.transport-BP8Q28Z2.d.mts.map +1 -0
  148. package/dist/worker.transport-BhMyvqQ2.mjs +167 -0
  149. package/dist/worker.transport-BhMyvqQ2.mjs.map +1 -0
  150. package/dist/worker.transport-CfH6z37Z.js +168 -0
  151. package/dist/worker.transport-CfH6z37Z.js.map +1 -0
  152. package/dist/worker.transport-mKXgNK0L.d.ts +76 -0
  153. package/dist/worker.transport-mKXgNK0L.d.ts.map +1 -0
  154. package/package.json +23 -18
  155. package/dist/index-CwFww7VC.d.ts.map +0 -1
  156. package/dist/index-DnyeaoZU.d.mts.map +0 -1
  157. package/dist/logitron-logger.module-BCq3sF27.d.mts.map +0 -1
  158. package/dist/logitron-logger.module-BIGTm2V6.mjs.map +0 -1
  159. package/dist/logitron-logger.module-BTxDpK6u.js.map +0 -1
  160. package/dist/logitron-logger.module-BmT-ewin.d.ts.map +0 -1
  161. package/dist/search-Cg_OasF-.d.ts +0 -1
  162. package/dist/search-DN676Dnz.d.mts +0 -1
  163. package/dist/search-DOvSI-mb.mjs +0 -1
  164. package/dist/search-DoZF3RZj.js +0 -0
  165. package/dist/transport.manager-DETpXuaY.mjs.map +0 -1
  166. package/dist/transport.manager-ciG4r5uz.js.map +0 -1
@@ -1,74 +1,16 @@
1
- import { d as internalError, f as internalLog, m as __require, p as internalWarn, t as TransportManager, u as safeToString } from "./transport.manager-DETpXuaY.mjs";
2
- import buildFastStringify from "fast-json-stringify";
1
+ import { t as __require } from "./chunk-DLSkYcPk.mjs";
2
+ import { n as internalLog, r as internalWarn, t as internalError } from "./internal-log-Cm8SOWSV.mjs";
3
+ import { i as stringifyForLog } from "./safe-stringify-DJ66tW5I.mjs";
4
+ import { t as LogixiaContext } from "./async-context-CwBNMm2E.mjs";
5
+ import { t as safeToString } from "./coerce.utils-Dxv4_ikC.mjs";
6
+ import { t as TransportManager } from "./transport.manager-D6KL3t9V.mjs";
7
+ import { constants } from "node:os";
3
8
  import { AsyncLocalStorage } from "node:async_hooks";
4
- import { randomUUID } from "node:crypto";
9
+ import buildFastStringify from "fast-json-stringify";
5
10
  import crypto from "crypto";
6
11
  import { Injectable, Module, Optional, RequestMethod, Scope } from "@nestjs/common";
7
12
  import { EMPTY, Observable } from "rxjs";
8
13
 
9
- //#region src/context/async-context.ts
10
- /** Generates an 8-character random ID using Node's crypto module. */
11
- function randomShortId() {
12
- return randomUUID().slice(0, 8);
13
- }
14
- const _storage = new AsyncLocalStorage();
15
- const LogixiaContext = {
16
- run(store, callback) {
17
- const parent = _storage.getStore() ?? {};
18
- return _storage.run({
19
- ...parent,
20
- ...store
21
- }, callback);
22
- },
23
- get() {
24
- return _storage.getStore();
25
- },
26
- set(fields) {
27
- const store = _storage.getStore();
28
- if (!store) return;
29
- Object.assign(store, fields);
30
- },
31
- getStorage() {
32
- return _storage;
33
- }
34
- };
35
- /**
36
- * Create an Express/Connect-compatible middleware that wraps each request in
37
- * a `LogixiaContext.run()` scope populated with common request fields.
38
- *
39
- * @example
40
- * ```ts
41
- * import { createExpressContextMiddleware } from 'logixia';
42
- * app.use(createExpressContextMiddleware());
43
- * ```
44
- */
45
- function createExpressContextMiddleware(options = {}) {
46
- const { enrich, traceIdHeader = "x-trace-id" } = options;
47
- return function logixiaContextMiddleware(req, _res, next) {
48
- const base = { traceId: (req["headers"] ?? {})[traceIdHeader] ?? randomShortId() };
49
- LogixiaContext.run({
50
- ...base,
51
- ...enrich ? enrich(req) : {}
52
- }, next);
53
- };
54
- }
55
- /**
56
- * Create a Fastify lifecycle hook that wraps each request in a context scope.
57
- *
58
- * Register with `fastify.addHook('onRequest', createFastifyContextHook())`.
59
- */
60
- function createFastifyContextHook(options = {}) {
61
- const { enrich, traceIdHeader = "x-trace-id" } = options;
62
- return function logixiaFastifyHook(request, _reply, done) {
63
- const base = { traceId: (request["headers"] ?? {})[traceIdHeader] ?? request["id"] ?? randomShortId() };
64
- LogixiaContext.run({
65
- ...base,
66
- ...enrich ? enrich(request) : {}
67
- }, done);
68
- };
69
- }
70
-
71
- //#endregion
72
14
  //#region src/plugin.ts
73
15
  /**
74
16
  * Holds an ordered list of `LogixiaPlugin` instances and dispatches lifecycle
@@ -566,7 +508,7 @@ function pathToRegExp(pattern) {
566
508
  }
567
509
  regexStr += segment === "*" ? "[^.]+" : segment.replace(/[$()*+.?[\\\]^{|}]/g, "\\$&");
568
510
  }
569
- return /* @__PURE__ */ new RegExp(`^${regexStr}$`);
511
+ return new RegExp(`^${regexStr}$`, "i");
570
512
  }
571
513
  /** Pre-compiled path matchers keyed by pattern string for perf */
572
514
  const patternCache = /* @__PURE__ */ new Map();
@@ -583,34 +525,66 @@ function applyPatterns(value, patterns, censor) {
583
525
  for (const pattern of patterns) redacted = redacted.replace(pattern, censor);
584
526
  return redacted;
585
527
  }
586
- function redactArrayItem(item, config, fullPath, skipPatternScan) {
587
- if (isPlainObject(item)) return redactObject(item, config, fullPath);
588
- const { patterns = [], censor = DEFAULT_CENSOR } = config;
589
- if (!skipPatternScan && typeof item === "string" && patterns.length > 0) return applyPatterns(item, patterns, censor);
590
- return item;
528
+ const CIRCULAR = "[Circular]";
529
+ function joinPath(parent, key) {
530
+ return parent ? `${parent}.${key}` : key;
591
531
  }
592
- function redactField(value, config, fullPath) {
593
- const { paths = [], excludePaths = [], patterns = [], censor = DEFAULT_CENSOR } = config;
594
- if (paths.some((p) => matchesPath(fullPath, p))) return censor;
595
- if (isPlainObject(value)) return redactObject(value, config, fullPath);
596
- const skipPatternScan = excludePaths.some((p) => matchesPath(fullPath, p));
597
- if (!skipPatternScan && typeof value === "string" && patterns.length > 0) return applyPatterns(value, patterns, censor);
598
- if (Array.isArray(value)) return value.map((item) => redactArrayItem(item, config, fullPath, skipPatternScan));
532
+ function walkValue(value, state, fullPath, bare) {
533
+ const { paths = [], excludePaths = [], patterns = [], censor = DEFAULT_CENSOR } = state.config;
534
+ if (paths.some((p) => matchesPath(fullPath, p) || matchesPath(bare, p))) return censor;
535
+ if (typeof value === "string") {
536
+ if (patterns.length === 0) return value;
537
+ if (excludePaths.some((p) => matchesPath(fullPath, p) || matchesPath(bare, p))) return value;
538
+ return applyPatterns(value, patterns, censor);
539
+ }
540
+ if (Array.isArray(value)) return walkContainer(value, state, fullPath, bare, walkArray);
541
+ if (isPlainObject(value)) return walkContainer(value, state, fullPath, bare, walkRecord);
599
542
  return value;
600
543
  }
544
+ function walkContainer(value, state, fullPath, bare, walk) {
545
+ if (state.ancestors.has(value)) return CIRCULAR;
546
+ state.ancestors.add(value);
547
+ try {
548
+ return walk(value, state, fullPath, bare);
549
+ } finally {
550
+ state.ancestors.delete(value);
551
+ }
552
+ }
601
553
  /**
602
- * Deep-clone and redact an object according to the given RedactConfig.
603
- * Non-objects are returned as-is (with pattern replacement on strings).
604
- *
605
- * The function is intentionally non-mutating — it returns a new object.
554
+ * Array elements are matched by their indexed path (`users.0.password`) and by
555
+ * the index-free path (`users.password`) that earlier versions used.
556
+ */
557
+ function walkArray(arr, state, fullPath, bare) {
558
+ let result;
559
+ for (const [i, item] of arr.entries()) {
560
+ const next = walkValue(item, state, joinPath(fullPath, String(i)), bare);
561
+ if (next !== item && !result) result = arr.slice(0, i);
562
+ if (result) result.push(next);
563
+ }
564
+ return result ?? arr;
565
+ }
566
+ function walkRecord(obj, state, fullPath, bare) {
567
+ let result;
568
+ const entries = Object.entries(obj);
569
+ for (const [index, [key, value]] of entries.entries()) {
570
+ const forbidden = key === "__proto__" || key === "constructor" || key === "prototype";
571
+ const next = forbidden ? void 0 : walkValue(value, state, joinPath(fullPath, key), joinPath(bare, key));
572
+ if ((forbidden || next !== value) && !result) result = Object.fromEntries(entries.slice(0, index));
573
+ if (result && !forbidden) result[key] = next;
574
+ }
575
+ return result ?? obj;
576
+ }
577
+ /**
578
+ * Redact an object according to the given RedactConfig and return a new
579
+ * top-level object. Subtrees with nothing to redact are shared with the input,
580
+ * never mutated. Circular references become `[Circular]`.
606
581
  */
607
582
  function redactObject(obj, config, _currentPath = "") {
608
- const result = {};
609
- for (const [key, value] of Object.entries(obj)) {
610
- if (key === "__proto__" || key === "constructor" || key === "prototype") continue;
611
- result[key] = redactField(value, config, _currentPath ? `${_currentPath}.${key}` : key);
612
- }
613
- return result;
583
+ const result = walkRecord(obj, {
584
+ config,
585
+ ancestors: new Set([obj])
586
+ }, _currentPath, _currentPath);
587
+ return result === obj ? { ...obj } : result;
614
588
  }
615
589
  /**
616
590
  * Apply pattern-based redaction to a single string (e.g. the log message).
@@ -637,8 +611,25 @@ function applyRedaction(payload, config) {
637
611
  if ((!resolved.paths || resolved.paths.length === 0) && (!resolved.patterns || resolved.patterns.length === 0)) return payload;
638
612
  return redactObject(payload, resolved);
639
613
  }
614
+ const OPAQUE_BUILTINS = [
615
+ Date,
616
+ Error,
617
+ RegExp,
618
+ URL,
619
+ URLSearchParams,
620
+ ArrayBuffer,
621
+ DataView,
622
+ Map,
623
+ Set,
624
+ WeakMap,
625
+ WeakSet,
626
+ Promise
627
+ ];
628
+ /** Plain objects and class instances are walked; built-ins are left alone. */
640
629
  function isPlainObject(value) {
641
- return value !== null && typeof value === "object" && !Array.isArray(value) && !(value instanceof Date) && !(value instanceof Error) && !(value instanceof RegExp);
630
+ if (value === null || typeof value !== "object") return false;
631
+ if (ArrayBuffer.isView(value)) return false;
632
+ return !OPAQUE_BUILTINS.some((ctor) => value instanceof ctor);
642
633
  }
643
634
 
644
635
  //#endregion
@@ -650,12 +641,14 @@ const ALWAYS_EMIT_LEVELS = new Set([
650
641
  ]);
651
642
  var Sampler = class {
652
643
  constructor(config, onStats) {
653
- this.sampledTraces = /* @__PURE__ */ new Set();
654
- this.droppedTraces = /* @__PURE__ */ new Set();
644
+ this.traceDecisions = /* @__PURE__ */ new Map();
655
645
  this.maxTrackedTraces = 1e5;
646
+ this.traceTtlMs = 5 * 6e4;
656
647
  this._tokenBucket = 0;
657
648
  this._lastRefillMs = Date.now();
658
649
  this._adaptiveWindow = [];
650
+ this._adaptiveHead = 0;
651
+ this._adaptiveErrors = 0;
659
652
  this._stats = {
660
653
  evaluated: 0,
661
654
  emitted: 0,
@@ -690,23 +683,7 @@ var Sampler = class {
690
683
  this._trackEmitted(lvl);
691
684
  return true;
692
685
  }
693
- if (this.config.traceConsistent && traceId) {
694
- if (this.sampledTraces.has(traceId)) {
695
- this._trackEmitted(lvl);
696
- return true;
697
- }
698
- if (this.droppedTraces.has(traceId)) {
699
- this._trackDropped(lvl);
700
- return false;
701
- }
702
- const emit = this._sampleByRate(lvl);
703
- if (emit) this._rememberTrace(this.sampledTraces, traceId);
704
- else this._rememberTrace(this.droppedTraces, traceId);
705
- if (emit) this._trackEmitted(lvl);
706
- else this._trackDropped(lvl);
707
- return emit;
708
- }
709
- if (!this._sampleByRate(lvl)) {
686
+ if (!(this.config.traceConsistent && traceId ? this._decideForTrace(traceId, lvl) : this._sampleByRate(lvl))) {
710
687
  this._trackDropped(lvl);
711
688
  return false;
712
689
  }
@@ -733,8 +710,6 @@ var Sampler = class {
733
710
  byLevel: {},
734
711
  windowStart: Date.now()
735
712
  };
736
- this.sampledTraces.clear();
737
- this.droppedTraces.clear();
738
713
  }
739
714
  destroy() {
740
715
  if (this._statsTimer) clearInterval(this._statsTimer);
@@ -747,20 +722,27 @@ var Sampler = class {
747
722
  if (rate <= 0) return false;
748
723
  return Math.random() < rate;
749
724
  }
750
- /**
751
- * Record one evaluated sample into the adaptive sliding window and evict
752
- * entries older than the window. Cheap O(evicted) amortized.
753
- */
725
+ /** Record one evaluated sample and evict entries older than the window. O(1) amortized. */
754
726
  _recordAdaptiveSample(level) {
755
727
  var _this$config$adaptive;
756
728
  const now = Date.now();
757
729
  const windowMs = ((_this$config$adaptive = this.config.adaptive) === null || _this$config$adaptive === void 0 ? void 0 : _this$config$adaptive.windowMs) ?? 1e4;
730
+ const err = level === "error" || level === "fatal";
758
731
  this._adaptiveWindow.push({
759
732
  t: now,
760
- err: level === "error" || level === "fatal"
733
+ err
761
734
  });
735
+ if (err) this._adaptiveErrors += 1;
762
736
  const cutoff = now - windowMs;
763
- while (this._adaptiveWindow.length > 0 && this._adaptiveWindow[0].t < cutoff) this._adaptiveWindow.shift();
737
+ const win = this._adaptiveWindow;
738
+ while (this._adaptiveHead < win.length && win[this._adaptiveHead].t < cutoff) {
739
+ if (win[this._adaptiveHead].err) this._adaptiveErrors -= 1;
740
+ this._adaptiveHead += 1;
741
+ }
742
+ if (this._adaptiveHead >= 1024 && this._adaptiveHead * 2 >= win.length) {
743
+ this._adaptiveWindow = win.slice(this._adaptiveHead);
744
+ this._adaptiveHead = 0;
745
+ }
764
746
  }
765
747
  /**
766
748
  * Effective boost rate (0 = no boost). Returns the configured boostRate when
@@ -771,25 +753,39 @@ var Sampler = class {
771
753
  const cfg = this.config.adaptive;
772
754
  if (!cfg) return 0;
773
755
  const minSamples = cfg.minSamples ?? 20;
774
- const total = this._adaptiveWindow.length;
756
+ const total = this._adaptiveWindow.length - this._adaptiveHead;
775
757
  if (total < minSamples) return 0;
776
- let errors = 0;
777
- for (const s of this._adaptiveWindow) if (s.err) errors += 1;
778
- return errors / total >= (cfg.errorRateThreshold ?? .05) ? cfg.boostRate ?? 1 : 0;
758
+ return this._adaptiveErrors / total >= (cfg.errorRateThreshold ?? .05) ? cfg.boostRate ?? 1 : 0;
779
759
  }
780
760
  /** @internal Expose the current adaptive boost decision (tests / observability). */
781
761
  isBoosting() {
782
762
  return this._adaptiveBoostRate() > 0;
783
763
  }
784
764
  /**
785
- * Record a trace decision, bounding the Set so it can't grow without limit.
786
- * If the Set has reached the cap, clear it before inserting — stale decisions
787
- * are simply re-made on next sight, which keeps memory bounded at the cost of
788
- * occasional re-sampling for very high-cardinality trace workloads.
765
+ * Return the cached decision for a trace, or make and cache a new one. Entries
766
+ * idle past the TTL are re-decided; the least recently used entry is evicted
767
+ * once the cap is reached.
789
768
  */
790
- _rememberTrace(set, traceId) {
791
- if (set.size >= this.maxTrackedTraces) set.clear();
792
- set.add(traceId);
769
+ _decideForTrace(traceId, level) {
770
+ const now = Date.now();
771
+ const known = this.traceDecisions.get(traceId);
772
+ if (known && now - known.seenAt <= this.traceTtlMs) {
773
+ this.traceDecisions.delete(traceId);
774
+ known.seenAt = now;
775
+ this.traceDecisions.set(traceId, known);
776
+ return known.emit;
777
+ }
778
+ const emit = this._sampleByRate(level);
779
+ this.traceDecisions.delete(traceId);
780
+ this.traceDecisions.set(traceId, {
781
+ emit,
782
+ seenAt: now
783
+ });
784
+ if (this.traceDecisions.size > this.maxTrackedTraces) {
785
+ const oldest = this.traceDecisions.keys().next().value;
786
+ if (oldest !== void 0) this.traceDecisions.delete(oldest);
787
+ }
788
+ return emit;
793
789
  }
794
790
  _consumeToken() {
795
791
  const now = Date.now();
@@ -826,6 +822,7 @@ var Sampler = class {
826
822
 
827
823
  //#endregion
828
824
  //#region src/utils/shutdown.utils.ts
825
+ const MAX_BEFORE_EXIT_FLUSHES = 5;
829
826
  /** Module-level registry of all logger instances that have opted into graceful shutdown */
830
827
  const registry = /* @__PURE__ */ new Set();
831
828
  let shutdownHandlerRegistered = false;
@@ -836,10 +833,16 @@ let shutdownInProgress = false;
836
833
  /** Our own handler + the signals we attached it to, so reset() can detach exactly it. */
837
834
  let activeHandler;
838
835
  let activeSignals = [];
836
+ let activeOptions;
837
+ let beforeExitHandler;
839
838
  /**
840
839
  * Register a logger instance so it is included in the graceful shutdown flush.
841
840
  * Called automatically when `gracefulShutdown: true` is set in logger config.
842
841
  */
842
+ /** Test helper: number of loggers currently registered for graceful shutdown. */
843
+ function _shutdownRegistrySize() {
844
+ return registry.size;
845
+ }
843
846
  function registerForShutdown(logger) {
844
847
  registry.add(logger);
845
848
  }
@@ -851,7 +854,11 @@ function deregisterFromShutdown(logger) {
851
854
  }
852
855
  /**
853
856
  * Register SIGTERM / SIGINT handlers that flush all registered loggers before
854
- * the process exits. Idempotent — calling multiple times is safe.
857
+ * the process exits. Idempotent — the first call wins and later calls with
858
+ * conflicting options print a warning. The process is ended with 128 + signal
859
+ * number only when logixia's handler is the sole listener for that signal (see
860
+ * `exit`); otherwise it just flushes and leaves shutdown to the application.
861
+ * Loggers are also flushed (not closed) on `beforeExit`.
855
862
  *
856
863
  * @example
857
864
  * ```ts
@@ -860,28 +867,64 @@ function deregisterFromShutdown(logger) {
860
867
  * ```
861
868
  */
862
869
  function flushOnExit(options = {}) {
863
- if (shutdownHandlerRegistered) return;
870
+ if (shutdownHandlerRegistered) {
871
+ warnOnConflict(activeOptions, options);
872
+ return;
873
+ }
864
874
  shutdownHandlerRegistered = true;
865
- const { timeout = 5e3, signals = ["SIGTERM", "SIGINT"], beforeFlush, afterFlush } = options;
875
+ activeOptions = options;
876
+ const { timeout = 5e3, signals = ["SIGTERM", "SIGINT"], beforeFlush, afterFlush, exit = "auto" } = options;
877
+ const shouldExit = (signal) => exit === "always" || exit === "auto" && process.listenerCount(signal) <= 1;
866
878
  const handler = async (signal) => {
867
879
  if (shutdownInProgress) return;
868
880
  shutdownInProgress = true;
869
- const forceExitTimer = setTimeout(() => {
881
+ const forceExitTimer = shouldExit(signal) ? setTimeout(() => {
870
882
  process.stderr.write(`[logixia] Graceful shutdown timed out after ${timeout}ms on ${signal}. Force-exiting.\n`);
871
883
  process.exit(1);
872
- }, timeout).unref();
884
+ }, timeout).unref() : void 0;
873
885
  try {
874
886
  if (beforeFlush) await beforeFlush();
875
887
  await Promise.allSettled([...registry].map((logger) => logger.close()));
876
888
  if (afterFlush) await afterFlush();
889
+ } catch (err) {
890
+ process.stderr.write(`[logixia] Shutdown hook failed: ${String(err)}\n`);
877
891
  } finally {
878
892
  clearTimeout(forceExitTimer);
879
- process.exit(0);
893
+ if (shouldExit(signal)) process.exit(128 + (constants.signals[signal] ?? 0));
894
+ shutdownInProgress = false;
880
895
  }
881
896
  };
882
897
  activeHandler = handler;
883
898
  activeSignals = signals;
884
899
  for (const signal of signals) process.on(signal, activeHandler);
900
+ let beforeExitFlushes = 0;
901
+ let beforeExitFlushing = false;
902
+ beforeExitHandler = () => {
903
+ if (beforeExitFlushing || shutdownInProgress || beforeExitFlushes >= MAX_BEFORE_EXIT_FLUSHES) return;
904
+ beforeExitFlushing = true;
905
+ beforeExitFlushes += 1;
906
+ Promise.allSettled([...registry].map((logger) => {
907
+ var _logger$flush;
908
+ return (_logger$flush = logger.flush) === null || _logger$flush === void 0 ? void 0 : _logger$flush.call(logger);
909
+ })).finally(() => {
910
+ beforeExitFlushing = false;
911
+ });
912
+ };
913
+ process.on("beforeExit", beforeExitHandler);
914
+ }
915
+ function warnOnConflict(active, next) {
916
+ if (!active) return;
917
+ const conflicts = [];
918
+ if (next.timeout !== void 0 && next.timeout !== (active.timeout ?? 5e3)) conflicts.push("timeout");
919
+ if (next.exit !== void 0 && next.exit !== (active.exit ?? "auto")) conflicts.push("exit");
920
+ if (next.signals !== void 0) {
921
+ const current = new Set(active.signals ?? ["SIGTERM", "SIGINT"]);
922
+ if (next.signals.length !== current.size || next.signals.some((sig) => !current.has(sig))) conflicts.push("signals");
923
+ }
924
+ if (next.beforeFlush && next.beforeFlush !== active.beforeFlush) conflicts.push("beforeFlush");
925
+ if (next.afterFlush && next.afterFlush !== active.afterFlush) conflicts.push("afterFlush");
926
+ if (conflicts.length === 0) return;
927
+ process.stderr.write(`[logixia] flushOnExit was already configured; ignoring conflicting options: ${conflicts.join(", ")}.\n`);
885
928
  }
886
929
  /**
887
930
  * Remove all graceful shutdown handlers and clear the registry.
@@ -890,8 +933,11 @@ function flushOnExit(options = {}) {
890
933
  function resetShutdownHandlers() {
891
934
  registry.clear();
892
935
  if (activeHandler) for (const signal of activeSignals) process.removeListener(signal, activeHandler);
936
+ if (beforeExitHandler) process.removeListener("beforeExit", beforeExitHandler);
937
+ beforeExitHandler = void 0;
893
938
  activeHandler = void 0;
894
939
  activeSignals = [];
940
+ activeOptions = void 0;
895
941
  shutdownHandlerRegistered = false;
896
942
  shutdownInProgress = false;
897
943
  }
@@ -1261,18 +1307,29 @@ function matchesNamespacePattern(ns, pattern) {
1261
1307
  _nsCacheEvictionCount++;
1262
1308
  if (!_nsCacheEvictionWarned) {
1263
1309
  _nsCacheEvictionWarned = true;
1264
- process.stderr.write(`[logixia] namespace pattern cache hit ${_NS_CACHE_MAX} entries — evicting. This usually means dynamic/unique patterns are being registered at runtime; review your levelOptions.namespaces configuration.\n`);
1310
+ internalWarn(`namespace pattern cache hit ${_NS_CACHE_MAX} entries — evicting. This usually means dynamic/unique patterns are being registered at runtime; review your levelOptions.namespaces configuration.`);
1265
1311
  }
1266
1312
  }
1267
1313
  _nsPatternCache.set(pattern, re);
1268
1314
  }
1269
1315
  return re.test(ns);
1270
1316
  }
1317
+ /**
1318
+ * Map a level name onto a known level key: exact match first (so custom levels
1319
+ * keep their declared casing), then lower case (so `DEBUG` → `debug`).
1320
+ */
1321
+ function canonicalLevel(level, known) {
1322
+ if (typeof level !== "string") return void 0;
1323
+ if (known.has(level)) return level;
1324
+ const lower = level.toLowerCase();
1325
+ return known.has(lower) ? lower : void 0;
1326
+ }
1271
1327
  function resolveInitialLevel(config) {
1272
- var _config$levelOptions;
1328
+ var _config$levelOptions, _config$levelOptions2;
1273
1329
  const envLevel = process.env["LOGIXIA_LEVEL"];
1274
- if (envLevel) return envLevel;
1275
- if ((_config$levelOptions = config.levelOptions) === null || _config$levelOptions === void 0 ? void 0 : _config$levelOptions.level) return config.levelOptions.level;
1330
+ const knownLevels = new Set([...Object.values(LogLevel), ...Object.keys(((_config$levelOptions = config.levelOptions) === null || _config$levelOptions === void 0 ? void 0 : _config$levelOptions.levels) ?? {})]);
1331
+ if (envLevel && canonicalLevel(envLevel, knownLevels)) return envLevel;
1332
+ if ((_config$levelOptions2 = config.levelOptions) === null || _config$levelOptions2 === void 0 ? void 0 : _config$levelOptions2.level) return config.levelOptions.level;
1276
1333
  const nodeEnv = process.env["NODE_ENV"];
1277
1334
  if (nodeEnv === "development") return LogLevel.DEBUG;
1278
1335
  if (nodeEnv === "test") return LogLevel.WARN;
@@ -1281,20 +1338,22 @@ function resolveInitialLevel(config) {
1281
1338
  return LogLevel.INFO;
1282
1339
  }
1283
1340
  var LogixiaLogger = class LogixiaLogger {
1284
- constructor(config, context) {
1341
+ constructor(config, context, parent) {
1285
1342
  this.timers = /* @__PURE__ */ new Map();
1286
1343
  this.contextData = {};
1287
1344
  this.fieldState = /* @__PURE__ */ new Map();
1288
1345
  this.fallbackTraceId = TraceContext.instance.generate();
1289
1346
  this._levelValues = /* @__PURE__ */ new Map();
1290
1347
  this._minLevelValue = 2;
1348
+ this._warnedInvalidLevels = /* @__PURE__ */ new Set();
1291
1349
  this._colorMap = /* @__PURE__ */ new Map();
1292
1350
  this._fieldCache = /* @__PURE__ */ new Map();
1293
1351
  this._hasContextData = false;
1294
1352
  this._formattedLevels = /* @__PURE__ */ new Map();
1295
1353
  this._formattedAppName = "";
1296
1354
  this._hasRedact = false;
1297
- this._pluginRegistry = new PluginRegistry();
1355
+ this._parent = parent;
1356
+ this._pluginRegistry = parent ? parent._pluginRegistry : new PluginRegistry();
1298
1357
  this.config = {
1299
1358
  appName: "App",
1300
1359
  environment: "development",
@@ -1341,7 +1400,10 @@ var LogixiaLogger = class LogixiaLogger {
1341
1400
  timeTaken: "[time_taken_MS]"
1342
1401
  };
1343
1402
  this.context = context ?? "";
1344
- if (this.config.transports) {
1403
+ if (parent) {
1404
+ this.transportManager = parent.transportManager;
1405
+ this._sampler = parent._sampler;
1406
+ } else if (this.config.transports) {
1345
1407
  var _this$config$levelOpt;
1346
1408
  const transportsWithColors = { ...this.config.transports };
1347
1409
  const userColors = (_this$config$levelOpt = this.config.levelOptions) === null || _this$config$levelOpt === void 0 ? void 0 : _this$config$levelOpt.colors;
@@ -1351,16 +1413,16 @@ var LogixiaLogger = class LogixiaLogger {
1351
1413
  };
1352
1414
  this.transportManager = new TransportManager(transportsWithColors);
1353
1415
  }
1354
- if (this.config.sampling) this._sampler = new Sampler(this.config.sampling, (stats) => {
1416
+ if (!parent && this.config.sampling) this._sampler = new Sampler(this.config.sampling, (stats) => {
1355
1417
  process.stdout.write(JSON.stringify({
1356
1418
  level: "info",
1357
1419
  message: "[logixia/sampling] stats",
1358
1420
  ...stats
1359
1421
  }) + "\n");
1360
1422
  });
1361
- this.setupGracefulShutdown();
1423
+ if (!parent) this.setupGracefulShutdown();
1362
1424
  this.createCustomLevelMethods();
1363
- for (const p of globalPluginRegistry._plugins) this._pluginRegistry.register(p);
1425
+ if (!parent) for (const p of globalPluginRegistry._plugins) this._pluginRegistry.register(p);
1364
1426
  this._buildPerfCaches();
1365
1427
  }
1366
1428
  setupGracefulShutdown() {
@@ -1371,7 +1433,8 @@ var LogixiaLogger = class LogixiaLogger {
1371
1433
  registerForShutdown(this);
1372
1434
  flushOnExit({
1373
1435
  timeout: normalized.timeout ?? 5e3,
1374
- signals: normalized.signals ?? ["SIGTERM", "SIGINT"]
1436
+ signals: normalized.signals ?? ["SIGTERM", "SIGINT"],
1437
+ ...normalized.exit ? { exit: normalized.exit } : {}
1375
1438
  });
1376
1439
  }
1377
1440
  createCustomLevelMethods() {
@@ -1398,6 +1461,8 @@ var LogixiaLogger = class LogixiaLogger {
1398
1461
  [LogLevel.VERBOSE, 5],
1399
1462
  ...customLevelEntries
1400
1463
  ]);
1464
+ this.config.levelOptions = this.config.levelOptions ?? {};
1465
+ this.config.levelOptions.level = this._validLevel(this.config.levelOptions.level, "levelOptions.level") ?? LogLevel.INFO;
1401
1466
  const effectiveLevel = this.resolveEffectiveLevel();
1402
1467
  this._minLevelValue = this._levelValues.get(effectiveLevel) ?? 2;
1403
1468
  this._colorMap = new Map([
@@ -1533,15 +1598,39 @@ var LogixiaLogger = class LogixiaLogger {
1533
1598
  }
1534
1599
  }
1535
1600
  setLevel(level) {
1601
+ const canonical = canonicalLevel(level, this._levelValues);
1602
+ if (canonical === void 0) {
1603
+ internalWarn(`setLevel: unknown log level '${String(level)}' ignored; valid levels: ${this._validLevelList()}. Keeping '${this.getLevel()}'.`);
1604
+ return;
1605
+ }
1536
1606
  this.config.levelOptions = this.config.levelOptions ?? {};
1537
- this.config.levelOptions.level = level;
1538
- this._minLevelValue = this._levelValues.get(level) ?? this._minLevelValue;
1607
+ this.config.levelOptions.level = canonical;
1608
+ this._minLevelValue = this._levelValues.get(canonical) ?? this._minLevelValue;
1539
1609
  this._buildPerfCaches();
1540
1610
  }
1541
1611
  getLevel() {
1542
1612
  var _this$config$levelOpt5;
1543
1613
  return ((_this$config$levelOpt5 = this.config.levelOptions) === null || _this$config$levelOpt5 === void 0 ? void 0 : _this$config$levelOpt5.level) ?? LogLevel.INFO;
1544
1614
  }
1615
+ _validLevelList() {
1616
+ return [...this._levelValues.keys()].join(", ");
1617
+ }
1618
+ /**
1619
+ * Canonicalise a level from config/ENV. Unknown values return undefined so the
1620
+ * caller falls through to the next source, and warn once per logger per source.
1621
+ */
1622
+ _validLevel(level, source) {
1623
+ if (level === void 0 || level === "") return void 0;
1624
+ const canonical = canonicalLevel(level, this._levelValues);
1625
+ if (canonical === void 0) {
1626
+ const key = `${source}=${String(level)}`;
1627
+ if (!this._warnedInvalidLevels.has(key)) {
1628
+ this._warnedInvalidLevels.add(key);
1629
+ internalWarn(`Unknown log level '${String(level)}' from ${source}; valid levels: ${this._validLevelList()}. Falling back to the next level source (default '${LogLevel.INFO}').`);
1630
+ }
1631
+ }
1632
+ return canonical;
1633
+ }
1545
1634
  /**
1546
1635
  * Replace the per-namespace level map at runtime — no restart needed.
1547
1636
  *
@@ -1616,10 +1705,12 @@ var LogixiaLogger = class LogixiaLogger {
1616
1705
  this.fieldState.clear();
1617
1706
  internalLog("Field state reset to configuration defaults");
1618
1707
  }
1708
+ /** @deprecated No-op. Library code never prompts on stdin; use setTransportLevels(). */
1619
1709
  enableTransportLevelPrompting() {
1620
1710
  if (this.transportManager) this.transportManager.enableLevelPrompting();
1621
1711
  else internalWarn("Transport manager not initialized");
1622
1712
  }
1713
+ /** @deprecated No-op. */
1623
1714
  disableTransportLevelPrompting() {
1624
1715
  if (this.transportManager) this.transportManager.disableLevelPrompting();
1625
1716
  else internalWarn("Transport manager not initialized");
@@ -1641,7 +1732,7 @@ var LogixiaLogger = class LogixiaLogger {
1641
1732
  return ((_this$transportManage = this.transportManager) === null || _this$transportManage === void 0 ? void 0 : _this$transportManage.getTransports()) ?? [];
1642
1733
  }
1643
1734
  child(context, data) {
1644
- const childLogger = new LogixiaLogger(this.config, context);
1735
+ const childLogger = new LogixiaLogger(this.config, context, this);
1645
1736
  const mergedContextData = {
1646
1737
  ...this.contextData,
1647
1738
  ...data
@@ -1692,6 +1783,7 @@ var LogixiaLogger = class LogixiaLogger {
1692
1783
  duration: `${Date.now() - timer.startTime}ms (incomplete)`
1693
1784
  });
1694
1785
  this.timers.clear();
1786
+ if (this._parent) return;
1695
1787
  if (this.transportManager) await this.transportManager.close();
1696
1788
  (_this$_sampler = this._sampler) === null || _this$_sampler === void 0 || _this$_sampler.destroy();
1697
1789
  await this._pluginRegistry.runOnShutdown();
@@ -1701,7 +1793,7 @@ var LogixiaLogger = class LogixiaLogger {
1701
1793
  if (this.config.silent) return;
1702
1794
  if (!this.shouldLog(level)) return;
1703
1795
  if (this._sampler) {
1704
- const traceId$1 = this.config.traceId ? TraceContext.instance.getCurrentTraceId() ?? this.fallbackTraceId : void 0;
1796
+ const traceId$1 = this.config.traceId ? TraceContext.instance.getCurrentTraceId() : void 0;
1705
1797
  if (!this._sampler.shouldEmit(level, traceId$1)) return;
1706
1798
  }
1707
1799
  const alsContext = LogixiaContext.get();
@@ -1766,21 +1858,28 @@ var LogixiaLogger = class LogixiaLogger {
1766
1858
  const ns = this.context;
1767
1859
  if (ns) {
1768
1860
  const nsKey = ns.split(".")[0].toUpperCase();
1769
- const envNsLevel = process.env[`LOGIXIA_LEVEL_${nsKey}`];
1861
+ const envNsLevel = this._validLevel(process.env[`LOGIXIA_LEVEL_${nsKey}`], `LOGIXIA_LEVEL_${nsKey}`);
1770
1862
  if (envNsLevel) return envNsLevel;
1771
1863
  const namespaceLevels = this.config.namespaceLevels;
1772
1864
  if (namespaceLevels) {
1773
1865
  const sortedPatterns = Object.keys(namespaceLevels).sort((a, b) => b.length - a.length);
1774
- for (const pattern of sortedPatterns) if (matchesNamespacePattern(ns, pattern)) return namespaceLevels[pattern];
1866
+ for (const pattern of sortedPatterns) if (matchesNamespacePattern(ns, pattern)) {
1867
+ const nsLevel = this._validLevel(namespaceLevels[pattern], `namespaceLevels['${pattern}']`);
1868
+ if (nsLevel) return nsLevel;
1869
+ }
1775
1870
  }
1776
1871
  }
1777
- const globalEnv = process.env["LOGIXIA_LEVEL"];
1872
+ const globalEnv = this._validLevel(process.env["LOGIXIA_LEVEL"], "LOGIXIA_LEVEL");
1778
1873
  if (globalEnv) return globalEnv;
1779
1874
  return this.getLevel();
1780
1875
  }
1781
1876
  formatLog(entry) {
1782
1877
  var _this$config$format2, _this$config$format3, _this$config$format4;
1783
- if ((_this$config$format2 = this.config.format) === null || _this$config$format2 === void 0 ? void 0 : _this$config$format2.json) return _fastStringifyEntry(entry);
1878
+ if ((_this$config$format2 = this.config.format) === null || _this$config$format2 === void 0 ? void 0 : _this$config$format2.json) try {
1879
+ return _fastStringifyEntry(entry);
1880
+ } catch {
1881
+ return stringifyForLog(entry);
1882
+ }
1784
1883
  let formatted = "";
1785
1884
  const doColorize = ((_this$config$format3 = this.config.format) === null || _this$config$format3 === void 0 ? void 0 : _this$config$format3.colorize) ?? true;
1786
1885
  const gray = doColorize ? this._colorMap.get("gray") : "";
@@ -1793,7 +1892,7 @@ var LogixiaLogger = class LogixiaLogger {
1793
1892
  if (entry.traceId && this._fieldCache.get("traceId") !== false) formatted += `${cyan}[${entry.traceId}]${reset} `;
1794
1893
  if (entry.context && this._fieldCache.get("context") !== false) formatted += `${yellow}[${entry.context}]${reset} `;
1795
1894
  if (this._fieldCache.get("message") !== false) formatted += entry.message;
1796
- if (entry.payload !== void 0 && this._fieldCache.get("payload") !== false) formatted += ` ${JSON.stringify(entry.payload)}`;
1895
+ if (entry.payload !== void 0 && this._fieldCache.get("payload") !== false) formatted += ` ${stringifyForLog(entry.payload)}`;
1797
1896
  return formatted;
1798
1897
  }
1799
1898
  colorize(text, color) {
@@ -1830,10 +1929,10 @@ var LogixiaLogger = class LogixiaLogger {
1830
1929
  }
1831
1930
  };
1832
1931
  function createLogger(config, context) {
1833
- var _config$levelOptions2;
1932
+ var _config$levelOptions3;
1834
1933
  const logger = new LogixiaLogger(config, context);
1835
1934
  const mutableLogger = logger;
1836
- if ((_config$levelOptions2 = config.levelOptions) === null || _config$levelOptions2 === void 0 ? void 0 : _config$levelOptions2.levels) {
1935
+ if ((_config$levelOptions3 = config.levelOptions) === null || _config$levelOptions3 === void 0 ? void 0 : _config$levelOptions3.levels) {
1837
1936
  for (const levelName of Object.keys(config.levelOptions.levels)) if (!mutableLogger[levelName]) mutableLogger[levelName] = async (message, data) => {
1838
1937
  await logger.logLevel(levelName, message, data);
1839
1938
  };
@@ -2178,7 +2277,7 @@ let TraceMiddleware = class TraceMiddleware$1 {
2178
2277
  if (!traceId && this.config.generator) {
2179
2278
  const candidate = this.config.generator();
2180
2279
  if (typeof candidate === "string" && candidate.trim().length > 0) traceId = candidate;
2181
- else process.stderr.write("[logixia] TraceIdConfig.generator returned a non-string/empty value — using built-in generator.\n");
2280
+ else internalWarn("TraceIdConfig.generator returned a non-string/empty value — using built-in generator.");
2182
2281
  }
2183
2282
  if (!traceId) traceId = this.ctx.generate();
2184
2283
  req.traceId = traceId;
@@ -2267,6 +2366,7 @@ const DEFAULT_ROUTES = [{
2267
2366
  method: RequestMethod.ALL
2268
2367
  }];
2269
2368
  const LOGIXIA_LOGGER_CONFIG = "LOGIXIA_LOGGER_CONFIG";
2369
+ const LOGIXIA_TRACE_CONFIG = "TRACE_CONFIG";
2270
2370
  const LOGIXIA_LOGGER_PREFIX = "LOGIXIA_LOGGER_";
2271
2371
  let LogixiaLoggerModule = class LogixiaLoggerModule$1 {
2272
2372
  static {
@@ -2291,7 +2391,7 @@ let LogixiaLoggerModule = class LogixiaLoggerModule$1 {
2291
2391
  */
2292
2392
  static _setGlobalLogger(service) {
2293
2393
  if (_LogixiaLoggerModule._globalLogger !== null) {
2294
- process.stderr.write("[logixia] LogixiaLoggerModule.forRoot() was called more than once — ignoring the second init. If this is intentional (e.g. in tests), call LogixiaLoggerModule._resetGlobalLogger() first.\n");
2394
+ internalWarn("LogixiaLoggerModule.forRoot() was called more than once — ignoring the second init. If this is intentional (e.g. in tests), call LogixiaLoggerModule._resetGlobalLogger() first.");
2295
2395
  return;
2296
2396
  }
2297
2397
  _LogixiaLoggerModule._globalLogger = service;
@@ -2349,7 +2449,7 @@ let LogixiaLoggerModule = class LogixiaLoggerModule$1 {
2349
2449
  useValue: config || {}
2350
2450
  },
2351
2451
  {
2352
- provide: "TRACE_CONFIG",
2452
+ provide: LOGIXIA_TRACE_CONFIG,
2353
2453
  useValue: traceConfig
2354
2454
  },
2355
2455
  {
@@ -2389,12 +2489,12 @@ let LogixiaLoggerModule = class LogixiaLoggerModule$1 {
2389
2489
  {
2390
2490
  provide: KafkaTraceInterceptor,
2391
2491
  useFactory: (traceConfig$1) => new KafkaTraceInterceptor(traceConfig$1),
2392
- inject: ["TRACE_CONFIG"]
2492
+ inject: [LOGIXIA_TRACE_CONFIG]
2393
2493
  },
2394
2494
  {
2395
2495
  provide: WebSocketTraceInterceptor,
2396
2496
  useFactory: (traceConfig$1) => new WebSocketTraceInterceptor(traceConfig$1),
2397
- inject: ["TRACE_CONFIG"]
2497
+ inject: [LOGIXIA_TRACE_CONFIG]
2398
2498
  }
2399
2499
  ],
2400
2500
  exports: [
@@ -2416,7 +2516,7 @@ let LogixiaLoggerModule = class LogixiaLoggerModule$1 {
2416
2516
  providers: [
2417
2517
  ...this.createAsyncProviders(options),
2418
2518
  {
2419
- provide: "TRACE_CONFIG",
2519
+ provide: LOGIXIA_TRACE_CONFIG,
2420
2520
  useFactory: (loggerConfig) => {
2421
2521
  return typeof (loggerConfig === null || loggerConfig === void 0 ? void 0 : loggerConfig.traceId) === "object" ? loggerConfig.traceId : { enabled: !!(loggerConfig === null || loggerConfig === void 0 ? void 0 : loggerConfig.traceId) };
2422
2522
  },
@@ -2461,12 +2561,12 @@ let LogixiaLoggerModule = class LogixiaLoggerModule$1 {
2461
2561
  {
2462
2562
  provide: KafkaTraceInterceptor,
2463
2563
  useFactory: (traceConfig) => new KafkaTraceInterceptor(traceConfig),
2464
- inject: ["TRACE_CONFIG"]
2564
+ inject: [LOGIXIA_TRACE_CONFIG]
2465
2565
  },
2466
2566
  {
2467
2567
  provide: WebSocketTraceInterceptor,
2468
2568
  useFactory: (traceConfig) => new WebSocketTraceInterceptor(traceConfig),
2469
- inject: ["TRACE_CONFIG"]
2569
+ inject: [LOGIXIA_TRACE_CONFIG]
2470
2570
  }
2471
2571
  ],
2472
2572
  exports: [
@@ -2518,5 +2618,5 @@ let LogixiaLoggerModule = class LogixiaLoggerModule$1 {
2518
2618
  LogixiaLoggerModule = _LogixiaLoggerModule = __decorate([Module({})], LogixiaLoggerModule);
2519
2619
 
2520
2620
  //#endregion
2521
- export { redactObject as A, LogLevel as B, setTraceId as C, registerForShutdown as D, flushOnExit as E, isError as F, createExpressContextMiddleware as G, globalPluginRegistry as H, normalizeError as I, createFastifyContextHook as K, serializeError as L, getActiveOtelContext as M, getOtelMetaFields as N, resetShutdownHandlers as O, initOtelBridge as P, DEFAULT_LOG_COLORS as R, runWithTraceId as S, deregisterFromShutdown as T, usePlugin as U, PluginRegistry as V, LogixiaContext as W, _setActiveContextKey as _, TraceMiddleware as a, getCurrentTraceId as b, KafkaTraceInterceptor as c, __decorateMetadata as d, LogixiaLogger as f, TraceContext as g, TRACE_CONTEXT_KEY as h, WebSocketTraceInterceptor as i, disableOtelBridge as j, applyRedaction as k, LogixiaLoggerService as l, DEFAULT_TRACE_HEADERS as m, LOGIXIA_LOGGER_PREFIX as n, resolveResponseHeader as o, createLogger as p, LogixiaLoggerModule as r, __decorateParam as s, LOGIXIA_LOGGER_CONFIG as t, __decorate as u, createTraceMiddleware as v, traceStorage as w, getTraceContextKey as x, extractTraceId as y, DEFAULT_LOG_LEVELS as z };
2522
- //# sourceMappingURL=logitron-logger.module-BIGTm2V6.mjs.map
2621
+ export { resetShutdownHandlers as A, DEFAULT_LOG_COLORS as B, runWithTraceId as C, deregisterFromShutdown as D, _shutdownRegistrySize as E, getOtelMetaFields as F, usePlugin as G, LogLevel as H, initOtelBridge as I, isError as L, redactObject as M, disableOtelBridge as N, flushOnExit as O, getActiveOtelContext as P, normalizeError as R, getTraceContextKey as S, traceStorage as T, PluginRegistry as U, DEFAULT_LOG_LEVELS as V, globalPluginRegistry as W, TraceContext as _, WebSocketTraceInterceptor as a, extractTraceId as b, __decorateParam as c, __decorate as d, __decorateMetadata as f, TRACE_CONTEXT_KEY as g, DEFAULT_TRACE_HEADERS as h, LogixiaLoggerModule as i, applyRedaction as j, registerForShutdown as k, KafkaTraceInterceptor as l, createLogger as m, LOGIXIA_LOGGER_PREFIX as n, TraceMiddleware as o, LogixiaLogger as p, LOGIXIA_TRACE_CONFIG as r, resolveResponseHeader as s, LOGIXIA_LOGGER_CONFIG as t, LogixiaLoggerService as u, _setActiveContextKey as v, setTraceId as w, getCurrentTraceId as x, createTraceMiddleware as y, serializeError as z };
2622
+ //# sourceMappingURL=logitron-logger.module-Bs3XYZgF.mjs.map