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,80 +1,22 @@
1
- const require_transport_manager = require('./transport.manager-ciG4r5uz.js');
2
- let fast_json_stringify = require("fast-json-stringify");
3
- fast_json_stringify = require_transport_manager.__toESM(fast_json_stringify);
1
+ const require_chunk = require('./chunk-nOFOJqeH.js');
2
+ const require_internal_log = require('./internal-log-BUJYMZbE.js');
3
+ const require_safe_stringify = require('./safe-stringify-DWo3aZp_.js');
4
+ const require_async_context = require('./async-context-CSHWoHMB.js');
5
+ const require_coerce_utils = require('./coerce.utils-BN980Y9V.js');
6
+ const require_transport_manager = require('./transport.manager-BivyUTtU.js');
7
+ let node_os = require("node:os");
8
+ node_os = require_chunk.__toESM(node_os);
4
9
  let node_async_hooks = require("node:async_hooks");
5
- node_async_hooks = require_transport_manager.__toESM(node_async_hooks);
6
- let node_crypto = require("node:crypto");
7
- node_crypto = require_transport_manager.__toESM(node_crypto);
10
+ node_async_hooks = require_chunk.__toESM(node_async_hooks);
11
+ let fast_json_stringify = require("fast-json-stringify");
12
+ fast_json_stringify = require_chunk.__toESM(fast_json_stringify);
8
13
  let crypto = require("crypto");
9
- crypto = require_transport_manager.__toESM(crypto);
14
+ crypto = require_chunk.__toESM(crypto);
10
15
  let __nestjs_common = require("@nestjs/common");
11
- __nestjs_common = require_transport_manager.__toESM(__nestjs_common);
16
+ __nestjs_common = require_chunk.__toESM(__nestjs_common);
12
17
  let rxjs = require("rxjs");
13
- rxjs = require_transport_manager.__toESM(rxjs);
14
-
15
- //#region src/context/async-context.ts
16
- /** Generates an 8-character random ID using Node's crypto module. */
17
- function randomShortId() {
18
- return (0, node_crypto.randomUUID)().slice(0, 8);
19
- }
20
- const _storage = new node_async_hooks.AsyncLocalStorage();
21
- const LogixiaContext = {
22
- run(store, callback) {
23
- const parent = _storage.getStore() ?? {};
24
- return _storage.run({
25
- ...parent,
26
- ...store
27
- }, callback);
28
- },
29
- get() {
30
- return _storage.getStore();
31
- },
32
- set(fields) {
33
- const store = _storage.getStore();
34
- if (!store) return;
35
- Object.assign(store, fields);
36
- },
37
- getStorage() {
38
- return _storage;
39
- }
40
- };
41
- /**
42
- * Create an Express/Connect-compatible middleware that wraps each request in
43
- * a `LogixiaContext.run()` scope populated with common request fields.
44
- *
45
- * @example
46
- * ```ts
47
- * import { createExpressContextMiddleware } from 'logixia';
48
- * app.use(createExpressContextMiddleware());
49
- * ```
50
- */
51
- function createExpressContextMiddleware(options = {}) {
52
- const { enrich, traceIdHeader = "x-trace-id" } = options;
53
- return function logixiaContextMiddleware(req, _res, next) {
54
- const base = { traceId: (req["headers"] ?? {})[traceIdHeader] ?? randomShortId() };
55
- LogixiaContext.run({
56
- ...base,
57
- ...enrich ? enrich(req) : {}
58
- }, next);
59
- };
60
- }
61
- /**
62
- * Create a Fastify lifecycle hook that wraps each request in a context scope.
63
- *
64
- * Register with `fastify.addHook('onRequest', createFastifyContextHook())`.
65
- */
66
- function createFastifyContextHook(options = {}) {
67
- const { enrich, traceIdHeader = "x-trace-id" } = options;
68
- return function logixiaFastifyHook(request, _reply, done) {
69
- const base = { traceId: (request["headers"] ?? {})[traceIdHeader] ?? request["id"] ?? randomShortId() };
70
- LogixiaContext.run({
71
- ...base,
72
- ...enrich ? enrich(request) : {}
73
- }, done);
74
- };
75
- }
18
+ rxjs = require_chunk.__toESM(rxjs);
76
19
 
77
- //#endregion
78
20
  //#region src/plugin.ts
79
21
  /**
80
22
  * Holds an ordered list of `LogixiaPlugin` instances and dispatches lifecycle
@@ -572,7 +514,7 @@ function pathToRegExp(pattern) {
572
514
  }
573
515
  regexStr += segment === "*" ? "[^.]+" : segment.replace(/[$()*+.?[\\\]^{|}]/g, "\\$&");
574
516
  }
575
- return /* @__PURE__ */ new RegExp(`^${regexStr}$`);
517
+ return new RegExp(`^${regexStr}$`, "i");
576
518
  }
577
519
  /** Pre-compiled path matchers keyed by pattern string for perf */
578
520
  const patternCache = /* @__PURE__ */ new Map();
@@ -589,34 +531,66 @@ function applyPatterns(value, patterns, censor) {
589
531
  for (const pattern of patterns) redacted = redacted.replace(pattern, censor);
590
532
  return redacted;
591
533
  }
592
- function redactArrayItem(item, config, fullPath, skipPatternScan) {
593
- if (isPlainObject(item)) return redactObject(item, config, fullPath);
594
- const { patterns = [], censor = DEFAULT_CENSOR } = config;
595
- if (!skipPatternScan && typeof item === "string" && patterns.length > 0) return applyPatterns(item, patterns, censor);
596
- return item;
534
+ const CIRCULAR = "[Circular]";
535
+ function joinPath(parent, key) {
536
+ return parent ? `${parent}.${key}` : key;
597
537
  }
598
- function redactField(value, config, fullPath) {
599
- const { paths = [], excludePaths = [], patterns = [], censor = DEFAULT_CENSOR } = config;
600
- if (paths.some((p) => matchesPath(fullPath, p))) return censor;
601
- if (isPlainObject(value)) return redactObject(value, config, fullPath);
602
- const skipPatternScan = excludePaths.some((p) => matchesPath(fullPath, p));
603
- if (!skipPatternScan && typeof value === "string" && patterns.length > 0) return applyPatterns(value, patterns, censor);
604
- if (Array.isArray(value)) return value.map((item) => redactArrayItem(item, config, fullPath, skipPatternScan));
538
+ function walkValue(value, state, fullPath, bare) {
539
+ const { paths = [], excludePaths = [], patterns = [], censor = DEFAULT_CENSOR } = state.config;
540
+ if (paths.some((p) => matchesPath(fullPath, p) || matchesPath(bare, p))) return censor;
541
+ if (typeof value === "string") {
542
+ if (patterns.length === 0) return value;
543
+ if (excludePaths.some((p) => matchesPath(fullPath, p) || matchesPath(bare, p))) return value;
544
+ return applyPatterns(value, patterns, censor);
545
+ }
546
+ if (Array.isArray(value)) return walkContainer(value, state, fullPath, bare, walkArray);
547
+ if (isPlainObject(value)) return walkContainer(value, state, fullPath, bare, walkRecord);
605
548
  return value;
606
549
  }
550
+ function walkContainer(value, state, fullPath, bare, walk) {
551
+ if (state.ancestors.has(value)) return CIRCULAR;
552
+ state.ancestors.add(value);
553
+ try {
554
+ return walk(value, state, fullPath, bare);
555
+ } finally {
556
+ state.ancestors.delete(value);
557
+ }
558
+ }
607
559
  /**
608
- * Deep-clone and redact an object according to the given RedactConfig.
609
- * Non-objects are returned as-is (with pattern replacement on strings).
610
- *
611
- * The function is intentionally non-mutating — it returns a new object.
560
+ * Array elements are matched by their indexed path (`users.0.password`) and by
561
+ * the index-free path (`users.password`) that earlier versions used.
562
+ */
563
+ function walkArray(arr, state, fullPath, bare) {
564
+ let result;
565
+ for (const [i, item] of arr.entries()) {
566
+ const next = walkValue(item, state, joinPath(fullPath, String(i)), bare);
567
+ if (next !== item && !result) result = arr.slice(0, i);
568
+ if (result) result.push(next);
569
+ }
570
+ return result ?? arr;
571
+ }
572
+ function walkRecord(obj, state, fullPath, bare) {
573
+ let result;
574
+ const entries = Object.entries(obj);
575
+ for (const [index, [key, value]] of entries.entries()) {
576
+ const forbidden = key === "__proto__" || key === "constructor" || key === "prototype";
577
+ const next = forbidden ? void 0 : walkValue(value, state, joinPath(fullPath, key), joinPath(bare, key));
578
+ if ((forbidden || next !== value) && !result) result = Object.fromEntries(entries.slice(0, index));
579
+ if (result && !forbidden) result[key] = next;
580
+ }
581
+ return result ?? obj;
582
+ }
583
+ /**
584
+ * Redact an object according to the given RedactConfig and return a new
585
+ * top-level object. Subtrees with nothing to redact are shared with the input,
586
+ * never mutated. Circular references become `[Circular]`.
612
587
  */
613
588
  function redactObject(obj, config, _currentPath = "") {
614
- const result = {};
615
- for (const [key, value] of Object.entries(obj)) {
616
- if (key === "__proto__" || key === "constructor" || key === "prototype") continue;
617
- result[key] = redactField(value, config, _currentPath ? `${_currentPath}.${key}` : key);
618
- }
619
- return result;
589
+ const result = walkRecord(obj, {
590
+ config,
591
+ ancestors: new Set([obj])
592
+ }, _currentPath, _currentPath);
593
+ return result === obj ? { ...obj } : result;
620
594
  }
621
595
  /**
622
596
  * Apply pattern-based redaction to a single string (e.g. the log message).
@@ -643,8 +617,25 @@ function applyRedaction(payload, config) {
643
617
  if ((!resolved.paths || resolved.paths.length === 0) && (!resolved.patterns || resolved.patterns.length === 0)) return payload;
644
618
  return redactObject(payload, resolved);
645
619
  }
620
+ const OPAQUE_BUILTINS = [
621
+ Date,
622
+ Error,
623
+ RegExp,
624
+ URL,
625
+ URLSearchParams,
626
+ ArrayBuffer,
627
+ DataView,
628
+ Map,
629
+ Set,
630
+ WeakMap,
631
+ WeakSet,
632
+ Promise
633
+ ];
634
+ /** Plain objects and class instances are walked; built-ins are left alone. */
646
635
  function isPlainObject(value) {
647
- return value !== null && typeof value === "object" && !Array.isArray(value) && !(value instanceof Date) && !(value instanceof Error) && !(value instanceof RegExp);
636
+ if (value === null || typeof value !== "object") return false;
637
+ if (ArrayBuffer.isView(value)) return false;
638
+ return !OPAQUE_BUILTINS.some((ctor) => value instanceof ctor);
648
639
  }
649
640
 
650
641
  //#endregion
@@ -656,12 +647,14 @@ const ALWAYS_EMIT_LEVELS = new Set([
656
647
  ]);
657
648
  var Sampler = class {
658
649
  constructor(config, onStats) {
659
- this.sampledTraces = /* @__PURE__ */ new Set();
660
- this.droppedTraces = /* @__PURE__ */ new Set();
650
+ this.traceDecisions = /* @__PURE__ */ new Map();
661
651
  this.maxTrackedTraces = 1e5;
652
+ this.traceTtlMs = 5 * 6e4;
662
653
  this._tokenBucket = 0;
663
654
  this._lastRefillMs = Date.now();
664
655
  this._adaptiveWindow = [];
656
+ this._adaptiveHead = 0;
657
+ this._adaptiveErrors = 0;
665
658
  this._stats = {
666
659
  evaluated: 0,
667
660
  emitted: 0,
@@ -696,23 +689,7 @@ var Sampler = class {
696
689
  this._trackEmitted(lvl);
697
690
  return true;
698
691
  }
699
- if (this.config.traceConsistent && traceId) {
700
- if (this.sampledTraces.has(traceId)) {
701
- this._trackEmitted(lvl);
702
- return true;
703
- }
704
- if (this.droppedTraces.has(traceId)) {
705
- this._trackDropped(lvl);
706
- return false;
707
- }
708
- const emit = this._sampleByRate(lvl);
709
- if (emit) this._rememberTrace(this.sampledTraces, traceId);
710
- else this._rememberTrace(this.droppedTraces, traceId);
711
- if (emit) this._trackEmitted(lvl);
712
- else this._trackDropped(lvl);
713
- return emit;
714
- }
715
- if (!this._sampleByRate(lvl)) {
692
+ if (!(this.config.traceConsistent && traceId ? this._decideForTrace(traceId, lvl) : this._sampleByRate(lvl))) {
716
693
  this._trackDropped(lvl);
717
694
  return false;
718
695
  }
@@ -739,8 +716,6 @@ var Sampler = class {
739
716
  byLevel: {},
740
717
  windowStart: Date.now()
741
718
  };
742
- this.sampledTraces.clear();
743
- this.droppedTraces.clear();
744
719
  }
745
720
  destroy() {
746
721
  if (this._statsTimer) clearInterval(this._statsTimer);
@@ -753,20 +728,27 @@ var Sampler = class {
753
728
  if (rate <= 0) return false;
754
729
  return Math.random() < rate;
755
730
  }
756
- /**
757
- * Record one evaluated sample into the adaptive sliding window and evict
758
- * entries older than the window. Cheap O(evicted) amortized.
759
- */
731
+ /** Record one evaluated sample and evict entries older than the window. O(1) amortized. */
760
732
  _recordAdaptiveSample(level) {
761
733
  var _this$config$adaptive;
762
734
  const now = Date.now();
763
735
  const windowMs = ((_this$config$adaptive = this.config.adaptive) === null || _this$config$adaptive === void 0 ? void 0 : _this$config$adaptive.windowMs) ?? 1e4;
736
+ const err = level === "error" || level === "fatal";
764
737
  this._adaptiveWindow.push({
765
738
  t: now,
766
- err: level === "error" || level === "fatal"
739
+ err
767
740
  });
741
+ if (err) this._adaptiveErrors += 1;
768
742
  const cutoff = now - windowMs;
769
- while (this._adaptiveWindow.length > 0 && this._adaptiveWindow[0].t < cutoff) this._adaptiveWindow.shift();
743
+ const win = this._adaptiveWindow;
744
+ while (this._adaptiveHead < win.length && win[this._adaptiveHead].t < cutoff) {
745
+ if (win[this._adaptiveHead].err) this._adaptiveErrors -= 1;
746
+ this._adaptiveHead += 1;
747
+ }
748
+ if (this._adaptiveHead >= 1024 && this._adaptiveHead * 2 >= win.length) {
749
+ this._adaptiveWindow = win.slice(this._adaptiveHead);
750
+ this._adaptiveHead = 0;
751
+ }
770
752
  }
771
753
  /**
772
754
  * Effective boost rate (0 = no boost). Returns the configured boostRate when
@@ -777,25 +759,39 @@ var Sampler = class {
777
759
  const cfg = this.config.adaptive;
778
760
  if (!cfg) return 0;
779
761
  const minSamples = cfg.minSamples ?? 20;
780
- const total = this._adaptiveWindow.length;
762
+ const total = this._adaptiveWindow.length - this._adaptiveHead;
781
763
  if (total < minSamples) return 0;
782
- let errors = 0;
783
- for (const s of this._adaptiveWindow) if (s.err) errors += 1;
784
- return errors / total >= (cfg.errorRateThreshold ?? .05) ? cfg.boostRate ?? 1 : 0;
764
+ return this._adaptiveErrors / total >= (cfg.errorRateThreshold ?? .05) ? cfg.boostRate ?? 1 : 0;
785
765
  }
786
766
  /** @internal Expose the current adaptive boost decision (tests / observability). */
787
767
  isBoosting() {
788
768
  return this._adaptiveBoostRate() > 0;
789
769
  }
790
770
  /**
791
- * Record a trace decision, bounding the Set so it can't grow without limit.
792
- * If the Set has reached the cap, clear it before inserting — stale decisions
793
- * are simply re-made on next sight, which keeps memory bounded at the cost of
794
- * occasional re-sampling for very high-cardinality trace workloads.
771
+ * Return the cached decision for a trace, or make and cache a new one. Entries
772
+ * idle past the TTL are re-decided; the least recently used entry is evicted
773
+ * once the cap is reached.
795
774
  */
796
- _rememberTrace(set, traceId) {
797
- if (set.size >= this.maxTrackedTraces) set.clear();
798
- set.add(traceId);
775
+ _decideForTrace(traceId, level) {
776
+ const now = Date.now();
777
+ const known = this.traceDecisions.get(traceId);
778
+ if (known && now - known.seenAt <= this.traceTtlMs) {
779
+ this.traceDecisions.delete(traceId);
780
+ known.seenAt = now;
781
+ this.traceDecisions.set(traceId, known);
782
+ return known.emit;
783
+ }
784
+ const emit = this._sampleByRate(level);
785
+ this.traceDecisions.delete(traceId);
786
+ this.traceDecisions.set(traceId, {
787
+ emit,
788
+ seenAt: now
789
+ });
790
+ if (this.traceDecisions.size > this.maxTrackedTraces) {
791
+ const oldest = this.traceDecisions.keys().next().value;
792
+ if (oldest !== void 0) this.traceDecisions.delete(oldest);
793
+ }
794
+ return emit;
799
795
  }
800
796
  _consumeToken() {
801
797
  const now = Date.now();
@@ -832,6 +828,7 @@ var Sampler = class {
832
828
 
833
829
  //#endregion
834
830
  //#region src/utils/shutdown.utils.ts
831
+ const MAX_BEFORE_EXIT_FLUSHES = 5;
835
832
  /** Module-level registry of all logger instances that have opted into graceful shutdown */
836
833
  const registry = /* @__PURE__ */ new Set();
837
834
  let shutdownHandlerRegistered = false;
@@ -842,10 +839,16 @@ let shutdownInProgress = false;
842
839
  /** Our own handler + the signals we attached it to, so reset() can detach exactly it. */
843
840
  let activeHandler;
844
841
  let activeSignals = [];
842
+ let activeOptions;
843
+ let beforeExitHandler;
845
844
  /**
846
845
  * Register a logger instance so it is included in the graceful shutdown flush.
847
846
  * Called automatically when `gracefulShutdown: true` is set in logger config.
848
847
  */
848
+ /** Test helper: number of loggers currently registered for graceful shutdown. */
849
+ function _shutdownRegistrySize() {
850
+ return registry.size;
851
+ }
849
852
  function registerForShutdown(logger) {
850
853
  registry.add(logger);
851
854
  }
@@ -857,7 +860,11 @@ function deregisterFromShutdown(logger) {
857
860
  }
858
861
  /**
859
862
  * Register SIGTERM / SIGINT handlers that flush all registered loggers before
860
- * the process exits. Idempotent — calling multiple times is safe.
863
+ * the process exits. Idempotent — the first call wins and later calls with
864
+ * conflicting options print a warning. The process is ended with 128 + signal
865
+ * number only when logixia's handler is the sole listener for that signal (see
866
+ * `exit`); otherwise it just flushes and leaves shutdown to the application.
867
+ * Loggers are also flushed (not closed) on `beforeExit`.
861
868
  *
862
869
  * @example
863
870
  * ```ts
@@ -866,28 +873,64 @@ function deregisterFromShutdown(logger) {
866
873
  * ```
867
874
  */
868
875
  function flushOnExit(options = {}) {
869
- if (shutdownHandlerRegistered) return;
876
+ if (shutdownHandlerRegistered) {
877
+ warnOnConflict(activeOptions, options);
878
+ return;
879
+ }
870
880
  shutdownHandlerRegistered = true;
871
- const { timeout = 5e3, signals = ["SIGTERM", "SIGINT"], beforeFlush, afterFlush } = options;
881
+ activeOptions = options;
882
+ const { timeout = 5e3, signals = ["SIGTERM", "SIGINT"], beforeFlush, afterFlush, exit = "auto" } = options;
883
+ const shouldExit = (signal) => exit === "always" || exit === "auto" && process.listenerCount(signal) <= 1;
872
884
  const handler = async (signal) => {
873
885
  if (shutdownInProgress) return;
874
886
  shutdownInProgress = true;
875
- const forceExitTimer = setTimeout(() => {
887
+ const forceExitTimer = shouldExit(signal) ? setTimeout(() => {
876
888
  process.stderr.write(`[logixia] Graceful shutdown timed out after ${timeout}ms on ${signal}. Force-exiting.\n`);
877
889
  process.exit(1);
878
- }, timeout).unref();
890
+ }, timeout).unref() : void 0;
879
891
  try {
880
892
  if (beforeFlush) await beforeFlush();
881
893
  await Promise.allSettled([...registry].map((logger) => logger.close()));
882
894
  if (afterFlush) await afterFlush();
895
+ } catch (err) {
896
+ process.stderr.write(`[logixia] Shutdown hook failed: ${String(err)}\n`);
883
897
  } finally {
884
898
  clearTimeout(forceExitTimer);
885
- process.exit(0);
899
+ if (shouldExit(signal)) process.exit(128 + (node_os.constants.signals[signal] ?? 0));
900
+ shutdownInProgress = false;
886
901
  }
887
902
  };
888
903
  activeHandler = handler;
889
904
  activeSignals = signals;
890
905
  for (const signal of signals) process.on(signal, activeHandler);
906
+ let beforeExitFlushes = 0;
907
+ let beforeExitFlushing = false;
908
+ beforeExitHandler = () => {
909
+ if (beforeExitFlushing || shutdownInProgress || beforeExitFlushes >= MAX_BEFORE_EXIT_FLUSHES) return;
910
+ beforeExitFlushing = true;
911
+ beforeExitFlushes += 1;
912
+ Promise.allSettled([...registry].map((logger) => {
913
+ var _logger$flush;
914
+ return (_logger$flush = logger.flush) === null || _logger$flush === void 0 ? void 0 : _logger$flush.call(logger);
915
+ })).finally(() => {
916
+ beforeExitFlushing = false;
917
+ });
918
+ };
919
+ process.on("beforeExit", beforeExitHandler);
920
+ }
921
+ function warnOnConflict(active, next) {
922
+ if (!active) return;
923
+ const conflicts = [];
924
+ if (next.timeout !== void 0 && next.timeout !== (active.timeout ?? 5e3)) conflicts.push("timeout");
925
+ if (next.exit !== void 0 && next.exit !== (active.exit ?? "auto")) conflicts.push("exit");
926
+ if (next.signals !== void 0) {
927
+ const current = new Set(active.signals ?? ["SIGTERM", "SIGINT"]);
928
+ if (next.signals.length !== current.size || next.signals.some((sig) => !current.has(sig))) conflicts.push("signals");
929
+ }
930
+ if (next.beforeFlush && next.beforeFlush !== active.beforeFlush) conflicts.push("beforeFlush");
931
+ if (next.afterFlush && next.afterFlush !== active.afterFlush) conflicts.push("afterFlush");
932
+ if (conflicts.length === 0) return;
933
+ process.stderr.write(`[logixia] flushOnExit was already configured; ignoring conflicting options: ${conflicts.join(", ")}.\n`);
891
934
  }
892
935
  /**
893
936
  * Remove all graceful shutdown handlers and clear the registry.
@@ -896,8 +939,11 @@ function flushOnExit(options = {}) {
896
939
  function resetShutdownHandlers() {
897
940
  registry.clear();
898
941
  if (activeHandler) for (const signal of activeSignals) process.removeListener(signal, activeHandler);
942
+ if (beforeExitHandler) process.removeListener("beforeExit", beforeExitHandler);
943
+ beforeExitHandler = void 0;
899
944
  activeHandler = void 0;
900
945
  activeSignals = [];
946
+ activeOptions = void 0;
901
947
  shutdownHandlerRegistered = false;
902
948
  shutdownInProgress = false;
903
949
  }
@@ -1267,18 +1313,29 @@ function matchesNamespacePattern(ns, pattern) {
1267
1313
  _nsCacheEvictionCount++;
1268
1314
  if (!_nsCacheEvictionWarned) {
1269
1315
  _nsCacheEvictionWarned = true;
1270
- 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`);
1316
+ require_internal_log.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.`);
1271
1317
  }
1272
1318
  }
1273
1319
  _nsPatternCache.set(pattern, re);
1274
1320
  }
1275
1321
  return re.test(ns);
1276
1322
  }
1323
+ /**
1324
+ * Map a level name onto a known level key: exact match first (so custom levels
1325
+ * keep their declared casing), then lower case (so `DEBUG` → `debug`).
1326
+ */
1327
+ function canonicalLevel(level, known) {
1328
+ if (typeof level !== "string") return void 0;
1329
+ if (known.has(level)) return level;
1330
+ const lower = level.toLowerCase();
1331
+ return known.has(lower) ? lower : void 0;
1332
+ }
1277
1333
  function resolveInitialLevel(config) {
1278
- var _config$levelOptions;
1334
+ var _config$levelOptions, _config$levelOptions2;
1279
1335
  const envLevel = process.env["LOGIXIA_LEVEL"];
1280
- if (envLevel) return envLevel;
1281
- if ((_config$levelOptions = config.levelOptions) === null || _config$levelOptions === void 0 ? void 0 : _config$levelOptions.level) return config.levelOptions.level;
1336
+ const knownLevels = new Set([...Object.values(LogLevel), ...Object.keys(((_config$levelOptions = config.levelOptions) === null || _config$levelOptions === void 0 ? void 0 : _config$levelOptions.levels) ?? {})]);
1337
+ if (envLevel && canonicalLevel(envLevel, knownLevels)) return envLevel;
1338
+ if ((_config$levelOptions2 = config.levelOptions) === null || _config$levelOptions2 === void 0 ? void 0 : _config$levelOptions2.level) return config.levelOptions.level;
1282
1339
  const nodeEnv = process.env["NODE_ENV"];
1283
1340
  if (nodeEnv === "development") return LogLevel.DEBUG;
1284
1341
  if (nodeEnv === "test") return LogLevel.WARN;
@@ -1287,20 +1344,22 @@ function resolveInitialLevel(config) {
1287
1344
  return LogLevel.INFO;
1288
1345
  }
1289
1346
  var LogixiaLogger = class LogixiaLogger {
1290
- constructor(config, context) {
1347
+ constructor(config, context, parent) {
1291
1348
  this.timers = /* @__PURE__ */ new Map();
1292
1349
  this.contextData = {};
1293
1350
  this.fieldState = /* @__PURE__ */ new Map();
1294
1351
  this.fallbackTraceId = TraceContext.instance.generate();
1295
1352
  this._levelValues = /* @__PURE__ */ new Map();
1296
1353
  this._minLevelValue = 2;
1354
+ this._warnedInvalidLevels = /* @__PURE__ */ new Set();
1297
1355
  this._colorMap = /* @__PURE__ */ new Map();
1298
1356
  this._fieldCache = /* @__PURE__ */ new Map();
1299
1357
  this._hasContextData = false;
1300
1358
  this._formattedLevels = /* @__PURE__ */ new Map();
1301
1359
  this._formattedAppName = "";
1302
1360
  this._hasRedact = false;
1303
- this._pluginRegistry = new PluginRegistry();
1361
+ this._parent = parent;
1362
+ this._pluginRegistry = parent ? parent._pluginRegistry : new PluginRegistry();
1304
1363
  this.config = {
1305
1364
  appName: "App",
1306
1365
  environment: "development",
@@ -1347,7 +1406,10 @@ var LogixiaLogger = class LogixiaLogger {
1347
1406
  timeTaken: "[time_taken_MS]"
1348
1407
  };
1349
1408
  this.context = context ?? "";
1350
- if (this.config.transports) {
1409
+ if (parent) {
1410
+ this.transportManager = parent.transportManager;
1411
+ this._sampler = parent._sampler;
1412
+ } else if (this.config.transports) {
1351
1413
  var _this$config$levelOpt;
1352
1414
  const transportsWithColors = { ...this.config.transports };
1353
1415
  const userColors = (_this$config$levelOpt = this.config.levelOptions) === null || _this$config$levelOpt === void 0 ? void 0 : _this$config$levelOpt.colors;
@@ -1357,16 +1419,16 @@ var LogixiaLogger = class LogixiaLogger {
1357
1419
  };
1358
1420
  this.transportManager = new require_transport_manager.TransportManager(transportsWithColors);
1359
1421
  }
1360
- if (this.config.sampling) this._sampler = new Sampler(this.config.sampling, (stats) => {
1422
+ if (!parent && this.config.sampling) this._sampler = new Sampler(this.config.sampling, (stats) => {
1361
1423
  process.stdout.write(JSON.stringify({
1362
1424
  level: "info",
1363
1425
  message: "[logixia/sampling] stats",
1364
1426
  ...stats
1365
1427
  }) + "\n");
1366
1428
  });
1367
- this.setupGracefulShutdown();
1429
+ if (!parent) this.setupGracefulShutdown();
1368
1430
  this.createCustomLevelMethods();
1369
- for (const p of globalPluginRegistry._plugins) this._pluginRegistry.register(p);
1431
+ if (!parent) for (const p of globalPluginRegistry._plugins) this._pluginRegistry.register(p);
1370
1432
  this._buildPerfCaches();
1371
1433
  }
1372
1434
  setupGracefulShutdown() {
@@ -1377,7 +1439,8 @@ var LogixiaLogger = class LogixiaLogger {
1377
1439
  registerForShutdown(this);
1378
1440
  flushOnExit({
1379
1441
  timeout: normalized.timeout ?? 5e3,
1380
- signals: normalized.signals ?? ["SIGTERM", "SIGINT"]
1442
+ signals: normalized.signals ?? ["SIGTERM", "SIGINT"],
1443
+ ...normalized.exit ? { exit: normalized.exit } : {}
1381
1444
  });
1382
1445
  }
1383
1446
  createCustomLevelMethods() {
@@ -1404,6 +1467,8 @@ var LogixiaLogger = class LogixiaLogger {
1404
1467
  [LogLevel.VERBOSE, 5],
1405
1468
  ...customLevelEntries
1406
1469
  ]);
1470
+ this.config.levelOptions = this.config.levelOptions ?? {};
1471
+ this.config.levelOptions.level = this._validLevel(this.config.levelOptions.level, "levelOptions.level") ?? LogLevel.INFO;
1407
1472
  const effectiveLevel = this.resolveEffectiveLevel();
1408
1473
  this._minLevelValue = this._levelValues.get(effectiveLevel) ?? 2;
1409
1474
  this._colorMap = new Map([
@@ -1539,15 +1604,39 @@ var LogixiaLogger = class LogixiaLogger {
1539
1604
  }
1540
1605
  }
1541
1606
  setLevel(level) {
1607
+ const canonical = canonicalLevel(level, this._levelValues);
1608
+ if (canonical === void 0) {
1609
+ require_internal_log.internalWarn(`setLevel: unknown log level '${String(level)}' ignored; valid levels: ${this._validLevelList()}. Keeping '${this.getLevel()}'.`);
1610
+ return;
1611
+ }
1542
1612
  this.config.levelOptions = this.config.levelOptions ?? {};
1543
- this.config.levelOptions.level = level;
1544
- this._minLevelValue = this._levelValues.get(level) ?? this._minLevelValue;
1613
+ this.config.levelOptions.level = canonical;
1614
+ this._minLevelValue = this._levelValues.get(canonical) ?? this._minLevelValue;
1545
1615
  this._buildPerfCaches();
1546
1616
  }
1547
1617
  getLevel() {
1548
1618
  var _this$config$levelOpt5;
1549
1619
  return ((_this$config$levelOpt5 = this.config.levelOptions) === null || _this$config$levelOpt5 === void 0 ? void 0 : _this$config$levelOpt5.level) ?? LogLevel.INFO;
1550
1620
  }
1621
+ _validLevelList() {
1622
+ return [...this._levelValues.keys()].join(", ");
1623
+ }
1624
+ /**
1625
+ * Canonicalise a level from config/ENV. Unknown values return undefined so the
1626
+ * caller falls through to the next source, and warn once per logger per source.
1627
+ */
1628
+ _validLevel(level, source) {
1629
+ if (level === void 0 || level === "") return void 0;
1630
+ const canonical = canonicalLevel(level, this._levelValues);
1631
+ if (canonical === void 0) {
1632
+ const key = `${source}=${String(level)}`;
1633
+ if (!this._warnedInvalidLevels.has(key)) {
1634
+ this._warnedInvalidLevels.add(key);
1635
+ require_internal_log.internalWarn(`Unknown log level '${String(level)}' from ${source}; valid levels: ${this._validLevelList()}. Falling back to the next level source (default '${LogLevel.INFO}').`);
1636
+ }
1637
+ }
1638
+ return canonical;
1639
+ }
1551
1640
  /**
1552
1641
  * Replace the per-namespace level map at runtime — no restart needed.
1553
1642
  *
@@ -1579,7 +1668,7 @@ var LogixiaLogger = class LogixiaLogger {
1579
1668
  return { ...this.config.namespaceLevels };
1580
1669
  }
1581
1670
  setContext(context) {
1582
- this.context = typeof context === "string" ? context : require_transport_manager.safeToString(context);
1671
+ this.context = typeof context === "string" ? context : require_coerce_utils.safeToString(context);
1583
1672
  }
1584
1673
  getContext() {
1585
1674
  return this.context;
@@ -1588,13 +1677,13 @@ var LogixiaLogger = class LogixiaLogger {
1588
1677
  this.fieldState.set(fieldName, true);
1589
1678
  this._fieldCache.set(fieldName, true);
1590
1679
  if (fieldName === "level" || fieldName === "appName") this._buildPerfCaches();
1591
- require_transport_manager.internalLog(`Field '${fieldName}' enabled`);
1680
+ require_internal_log.internalLog(`Field '${fieldName}' enabled`);
1592
1681
  }
1593
1682
  disableField(fieldName) {
1594
1683
  this.fieldState.set(fieldName, false);
1595
1684
  this._fieldCache.set(fieldName, false);
1596
1685
  if (fieldName === "level" || fieldName === "appName") this._buildPerfCaches();
1597
- require_transport_manager.internalLog(`Field '${fieldName}' disabled`);
1686
+ require_internal_log.internalLog(`Field '${fieldName}' disabled`);
1598
1687
  }
1599
1688
  isFieldEnabled(fieldName) {
1600
1689
  var _this$config$fields2;
@@ -1620,34 +1709,36 @@ var LogixiaLogger = class LogixiaLogger {
1620
1709
  }
1621
1710
  resetFieldState() {
1622
1711
  this.fieldState.clear();
1623
- require_transport_manager.internalLog("Field state reset to configuration defaults");
1712
+ require_internal_log.internalLog("Field state reset to configuration defaults");
1624
1713
  }
1714
+ /** @deprecated No-op. Library code never prompts on stdin; use setTransportLevels(). */
1625
1715
  enableTransportLevelPrompting() {
1626
1716
  if (this.transportManager) this.transportManager.enableLevelPrompting();
1627
- else require_transport_manager.internalWarn("Transport manager not initialized");
1717
+ else require_internal_log.internalWarn("Transport manager not initialized");
1628
1718
  }
1719
+ /** @deprecated No-op. */
1629
1720
  disableTransportLevelPrompting() {
1630
1721
  if (this.transportManager) this.transportManager.disableLevelPrompting();
1631
- else require_transport_manager.internalWarn("Transport manager not initialized");
1722
+ else require_internal_log.internalWarn("Transport manager not initialized");
1632
1723
  }
1633
1724
  setTransportLevels(transportId, levels) {
1634
1725
  if (this.transportManager) this.transportManager.setTransportLevels(transportId, levels);
1635
- else require_transport_manager.internalWarn("Transport manager not initialized");
1726
+ else require_internal_log.internalWarn("Transport manager not initialized");
1636
1727
  }
1637
1728
  getTransportLevels(transportId) {
1638
1729
  if (this.transportManager) return this.transportManager.getTransportLevels(transportId);
1639
- require_transport_manager.internalWarn("Transport manager not initialized");
1730
+ require_internal_log.internalWarn("Transport manager not initialized");
1640
1731
  }
1641
1732
  clearTransportLevelPreferences() {
1642
1733
  if (this.transportManager) this.transportManager.clearTransportLevelPreferences();
1643
- else require_transport_manager.internalWarn("Transport manager not initialized");
1734
+ else require_internal_log.internalWarn("Transport manager not initialized");
1644
1735
  }
1645
1736
  getAvailableTransports() {
1646
1737
  var _this$transportManage;
1647
1738
  return ((_this$transportManage = this.transportManager) === null || _this$transportManage === void 0 ? void 0 : _this$transportManage.getTransports()) ?? [];
1648
1739
  }
1649
1740
  child(context, data) {
1650
- const childLogger = new LogixiaLogger(this.config, context);
1741
+ const childLogger = new LogixiaLogger(this.config, context, this);
1651
1742
  const mergedContextData = {
1652
1743
  ...this.contextData,
1653
1744
  ...data
@@ -1698,6 +1789,7 @@ var LogixiaLogger = class LogixiaLogger {
1698
1789
  duration: `${Date.now() - timer.startTime}ms (incomplete)`
1699
1790
  });
1700
1791
  this.timers.clear();
1792
+ if (this._parent) return;
1701
1793
  if (this.transportManager) await this.transportManager.close();
1702
1794
  (_this$_sampler = this._sampler) === null || _this$_sampler === void 0 || _this$_sampler.destroy();
1703
1795
  await this._pluginRegistry.runOnShutdown();
@@ -1707,10 +1799,10 @@ var LogixiaLogger = class LogixiaLogger {
1707
1799
  if (this.config.silent) return;
1708
1800
  if (!this.shouldLog(level)) return;
1709
1801
  if (this._sampler) {
1710
- const traceId$1 = this.config.traceId ? TraceContext.instance.getCurrentTraceId() ?? this.fallbackTraceId : void 0;
1802
+ const traceId$1 = this.config.traceId ? TraceContext.instance.getCurrentTraceId() : void 0;
1711
1803
  if (!this._sampler.shouldEmit(level, traceId$1)) return;
1712
1804
  }
1713
- const alsContext = LogixiaContext.get();
1805
+ const alsContext = require_async_context.LogixiaContext.get();
1714
1806
  const hasAls = alsContext !== void 0 && Object.keys(alsContext).length > 0;
1715
1807
  const otelFields = _isOtelBridgeEnabled() ? _getOtelPayloadIfEnabled() : void 0;
1716
1808
  const hasOtel = otelFields !== void 0 && Object.keys(otelFields).length > 0;
@@ -1772,21 +1864,28 @@ var LogixiaLogger = class LogixiaLogger {
1772
1864
  const ns = this.context;
1773
1865
  if (ns) {
1774
1866
  const nsKey = ns.split(".")[0].toUpperCase();
1775
- const envNsLevel = process.env[`LOGIXIA_LEVEL_${nsKey}`];
1867
+ const envNsLevel = this._validLevel(process.env[`LOGIXIA_LEVEL_${nsKey}`], `LOGIXIA_LEVEL_${nsKey}`);
1776
1868
  if (envNsLevel) return envNsLevel;
1777
1869
  const namespaceLevels = this.config.namespaceLevels;
1778
1870
  if (namespaceLevels) {
1779
1871
  const sortedPatterns = Object.keys(namespaceLevels).sort((a, b) => b.length - a.length);
1780
- for (const pattern of sortedPatterns) if (matchesNamespacePattern(ns, pattern)) return namespaceLevels[pattern];
1872
+ for (const pattern of sortedPatterns) if (matchesNamespacePattern(ns, pattern)) {
1873
+ const nsLevel = this._validLevel(namespaceLevels[pattern], `namespaceLevels['${pattern}']`);
1874
+ if (nsLevel) return nsLevel;
1875
+ }
1781
1876
  }
1782
1877
  }
1783
- const globalEnv = process.env["LOGIXIA_LEVEL"];
1878
+ const globalEnv = this._validLevel(process.env["LOGIXIA_LEVEL"], "LOGIXIA_LEVEL");
1784
1879
  if (globalEnv) return globalEnv;
1785
1880
  return this.getLevel();
1786
1881
  }
1787
1882
  formatLog(entry) {
1788
1883
  var _this$config$format2, _this$config$format3, _this$config$format4;
1789
- if ((_this$config$format2 = this.config.format) === null || _this$config$format2 === void 0 ? void 0 : _this$config$format2.json) return _fastStringifyEntry(entry);
1884
+ if ((_this$config$format2 = this.config.format) === null || _this$config$format2 === void 0 ? void 0 : _this$config$format2.json) try {
1885
+ return _fastStringifyEntry(entry);
1886
+ } catch {
1887
+ return require_safe_stringify.stringifyForLog(entry);
1888
+ }
1790
1889
  let formatted = "";
1791
1890
  const doColorize = ((_this$config$format3 = this.config.format) === null || _this$config$format3 === void 0 ? void 0 : _this$config$format3.colorize) ?? true;
1792
1891
  const gray = doColorize ? this._colorMap.get("gray") : "";
@@ -1799,7 +1898,7 @@ var LogixiaLogger = class LogixiaLogger {
1799
1898
  if (entry.traceId && this._fieldCache.get("traceId") !== false) formatted += `${cyan}[${entry.traceId}]${reset} `;
1800
1899
  if (entry.context && this._fieldCache.get("context") !== false) formatted += `${yellow}[${entry.context}]${reset} `;
1801
1900
  if (this._fieldCache.get("message") !== false) formatted += entry.message;
1802
- if (entry.payload !== void 0 && this._fieldCache.get("payload") !== false) formatted += ` ${JSON.stringify(entry.payload)}`;
1901
+ if (entry.payload !== void 0 && this._fieldCache.get("payload") !== false) formatted += ` ${require_safe_stringify.stringifyForLog(entry.payload)}`;
1803
1902
  return formatted;
1804
1903
  }
1805
1904
  colorize(text, color) {
@@ -1830,16 +1929,16 @@ var LogixiaLogger = class LogixiaLogger {
1830
1929
  /** Shared transport-failure handler: log internally, notify plugins, then fall
1831
1930
  * back to a direct stdout/stderr write so the entry is never lost. */
1832
1931
  async _handleOutputError(error, entry, level) {
1833
- require_transport_manager.internalError("Transport write failed", error);
1932
+ require_internal_log.internalError("Transport write failed", error);
1834
1933
  if (this._pluginRegistry.size > 0) await this._pluginRegistry.runOnError(error instanceof Error ? error : new Error(String(error)), entry);
1835
1934
  (level === LogLevel.ERROR ? process.stderr : process.stdout).write(this.formatLog(entry) + "\n");
1836
1935
  }
1837
1936
  };
1838
1937
  function createLogger(config, context) {
1839
- var _config$levelOptions2;
1938
+ var _config$levelOptions3;
1840
1939
  const logger = new LogixiaLogger(config, context);
1841
1940
  const mutableLogger = logger;
1842
- if ((_config$levelOptions2 = config.levelOptions) === null || _config$levelOptions2 === void 0 ? void 0 : _config$levelOptions2.levels) {
1941
+ if ((_config$levelOptions3 = config.levelOptions) === null || _config$levelOptions3 === void 0 ? void 0 : _config$levelOptions3.levels) {
1843
1942
  for (const levelName of Object.keys(config.levelOptions.levels)) if (!mutableLogger[levelName]) mutableLogger[levelName] = async (message, data) => {
1844
1943
  await logger.logLevel(levelName, message, data);
1845
1944
  };
@@ -1928,7 +2027,7 @@ let LogixiaLoggerService = _LogixiaLoggerService = class LogixiaLoggerService$1
1928
2027
  */
1929
2028
  log(message, context) {
1930
2029
  this.setContextIfProvided(context);
1931
- this.logger.info(this.formatMessage(message)).catch((err) => require_transport_manager.internalError("LogixiaLoggerService.log failed", err));
2030
+ this.logger.info(this.formatMessage(message)).catch((err) => require_internal_log.internalError("LogixiaLoggerService.log failed", err));
1932
2031
  }
1933
2032
  /**
1934
2033
  * Native async `info` — structured data, returns `Promise<void>`.
@@ -1943,22 +2042,22 @@ let LogixiaLoggerService = _LogixiaLoggerService = class LogixiaLoggerService$1
1943
2042
  this.setContextIfProvided(context);
1944
2043
  const errorData = {};
1945
2044
  if (typeof dataOrTrace === "string" && dataOrTrace) errorData.stack = dataOrTrace;
1946
- (message instanceof Error ? this.logger.error(message, errorData) : this.logger.error(this.formatMessage(message), errorData)).catch((err) => require_transport_manager.internalError("LogixiaLoggerService.error failed", err));
2045
+ (message instanceof Error ? this.logger.error(message, errorData) : this.logger.error(this.formatMessage(message), errorData)).catch((err) => require_internal_log.internalError("LogixiaLoggerService.error failed", err));
1947
2046
  }
1948
2047
  warn(message, dataOrContext) {
1949
2048
  if (typeof dataOrContext === "object" && dataOrContext !== null) return this.logger.warn(this.formatMessage(message), dataOrContext);
1950
2049
  this.setContextIfProvided(typeof dataOrContext === "string" ? dataOrContext : void 0);
1951
- this.logger.warn(this.formatMessage(message)).catch((err) => require_transport_manager.internalError("LogixiaLoggerService.warn failed", err));
2050
+ this.logger.warn(this.formatMessage(message)).catch((err) => require_internal_log.internalError("LogixiaLoggerService.warn failed", err));
1952
2051
  }
1953
2052
  debug(message, dataOrContext) {
1954
2053
  if (typeof dataOrContext === "object" && dataOrContext !== null) return this.logger.debug(this.formatMessage(message), dataOrContext);
1955
2054
  this.setContextIfProvided(typeof dataOrContext === "string" ? dataOrContext : void 0);
1956
- this.logger.debug(this.formatMessage(message)).catch((err) => require_transport_manager.internalError("LogixiaLoggerService.debug failed", err));
2055
+ this.logger.debug(this.formatMessage(message)).catch((err) => require_internal_log.internalError("LogixiaLoggerService.debug failed", err));
1957
2056
  }
1958
2057
  verbose(message, dataOrContext) {
1959
2058
  if (typeof dataOrContext === "object" && dataOrContext !== null) return this.logger.trace(this.formatMessage(message), dataOrContext);
1960
2059
  this.setContextIfProvided(typeof dataOrContext === "string" ? dataOrContext : void 0);
1961
- this.logger.trace(this.formatMessage(message)).catch((err) => require_transport_manager.internalError("LogixiaLoggerService.verbose failed", err));
2060
+ this.logger.trace(this.formatMessage(message)).catch((err) => require_internal_log.internalError("LogixiaLoggerService.verbose failed", err));
1962
2061
  }
1963
2062
  /**
1964
2063
  * Native async `trace` — lowest verbosity level, structured data.
@@ -1982,7 +2081,7 @@ let LogixiaLoggerService = _LogixiaLoggerService = class LogixiaLoggerService$1
1982
2081
  return this.logger.timeAsync(label, fn);
1983
2082
  }
1984
2083
  setContext(context) {
1985
- const coerced = typeof context === "string" ? context : require_transport_manager.safeToString(context);
2084
+ const coerced = typeof context === "string" ? context : require_coerce_utils.safeToString(context);
1986
2085
  this.context = coerced;
1987
2086
  this.logger.setContext(coerced);
1988
2087
  }
@@ -2023,7 +2122,7 @@ let LogixiaLoggerService = _LogixiaLoggerService = class LogixiaLoggerService$1
2023
2122
  }
2024
2123
  formatMessage(message) {
2025
2124
  if (typeof message === "string") return message;
2026
- return require_transport_manager.safeToString(message);
2125
+ return require_coerce_utils.safeToString(message);
2027
2126
  }
2028
2127
  };
2029
2128
  LogixiaLoggerService = _LogixiaLoggerService = __decorate([(0, __nestjs_common.Injectable)({ scope: __nestjs_common.Scope.TRANSIENT }), __decorateMetadata("design:paramtypes", [Object])], LogixiaLoggerService);
@@ -2184,7 +2283,7 @@ let TraceMiddleware = class TraceMiddleware$1 {
2184
2283
  if (!traceId && this.config.generator) {
2185
2284
  const candidate = this.config.generator();
2186
2285
  if (typeof candidate === "string" && candidate.trim().length > 0) traceId = candidate;
2187
- else process.stderr.write("[logixia] TraceIdConfig.generator returned a non-string/empty value — using built-in generator.\n");
2286
+ else require_internal_log.internalWarn("TraceIdConfig.generator returned a non-string/empty value — using built-in generator.");
2188
2287
  }
2189
2288
  if (!traceId) traceId = this.ctx.generate();
2190
2289
  req.traceId = traceId;
@@ -2273,6 +2372,7 @@ const DEFAULT_ROUTES = [{
2273
2372
  method: __nestjs_common.RequestMethod.ALL
2274
2373
  }];
2275
2374
  const LOGIXIA_LOGGER_CONFIG = "LOGIXIA_LOGGER_CONFIG";
2375
+ const LOGIXIA_TRACE_CONFIG = "TRACE_CONFIG";
2276
2376
  const LOGIXIA_LOGGER_PREFIX = "LOGIXIA_LOGGER_";
2277
2377
  let LogixiaLoggerModule = class LogixiaLoggerModule$1 {
2278
2378
  static {
@@ -2297,7 +2397,7 @@ let LogixiaLoggerModule = class LogixiaLoggerModule$1 {
2297
2397
  */
2298
2398
  static _setGlobalLogger(service) {
2299
2399
  if (_LogixiaLoggerModule._globalLogger !== null) {
2300
- 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");
2400
+ require_internal_log.internalWarn("LogixiaLoggerModule.forRoot() was called more than once — ignoring the second init. If this is intentional (e.g. in tests), call LogixiaLoggerModule._resetGlobalLogger() first.");
2301
2401
  return;
2302
2402
  }
2303
2403
  _LogixiaLoggerModule._globalLogger = service;
@@ -2355,7 +2455,7 @@ let LogixiaLoggerModule = class LogixiaLoggerModule$1 {
2355
2455
  useValue: config || {}
2356
2456
  },
2357
2457
  {
2358
- provide: "TRACE_CONFIG",
2458
+ provide: LOGIXIA_TRACE_CONFIG,
2359
2459
  useValue: traceConfig
2360
2460
  },
2361
2461
  {
@@ -2395,12 +2495,12 @@ let LogixiaLoggerModule = class LogixiaLoggerModule$1 {
2395
2495
  {
2396
2496
  provide: KafkaTraceInterceptor,
2397
2497
  useFactory: (traceConfig$1) => new KafkaTraceInterceptor(traceConfig$1),
2398
- inject: ["TRACE_CONFIG"]
2498
+ inject: [LOGIXIA_TRACE_CONFIG]
2399
2499
  },
2400
2500
  {
2401
2501
  provide: WebSocketTraceInterceptor,
2402
2502
  useFactory: (traceConfig$1) => new WebSocketTraceInterceptor(traceConfig$1),
2403
- inject: ["TRACE_CONFIG"]
2503
+ inject: [LOGIXIA_TRACE_CONFIG]
2404
2504
  }
2405
2505
  ],
2406
2506
  exports: [
@@ -2422,7 +2522,7 @@ let LogixiaLoggerModule = class LogixiaLoggerModule$1 {
2422
2522
  providers: [
2423
2523
  ...this.createAsyncProviders(options),
2424
2524
  {
2425
- provide: "TRACE_CONFIG",
2525
+ provide: LOGIXIA_TRACE_CONFIG,
2426
2526
  useFactory: (loggerConfig) => {
2427
2527
  return typeof (loggerConfig === null || loggerConfig === void 0 ? void 0 : loggerConfig.traceId) === "object" ? loggerConfig.traceId : { enabled: !!(loggerConfig === null || loggerConfig === void 0 ? void 0 : loggerConfig.traceId) };
2428
2528
  },
@@ -2467,12 +2567,12 @@ let LogixiaLoggerModule = class LogixiaLoggerModule$1 {
2467
2567
  {
2468
2568
  provide: KafkaTraceInterceptor,
2469
2569
  useFactory: (traceConfig) => new KafkaTraceInterceptor(traceConfig),
2470
- inject: ["TRACE_CONFIG"]
2570
+ inject: [LOGIXIA_TRACE_CONFIG]
2471
2571
  },
2472
2572
  {
2473
2573
  provide: WebSocketTraceInterceptor,
2474
2574
  useFactory: (traceConfig) => new WebSocketTraceInterceptor(traceConfig),
2475
- inject: ["TRACE_CONFIG"]
2575
+ inject: [LOGIXIA_TRACE_CONFIG]
2476
2576
  }
2477
2577
  ],
2478
2578
  exports: [
@@ -2560,16 +2660,16 @@ Object.defineProperty(exports, 'LOGIXIA_LOGGER_PREFIX', {
2560
2660
  return LOGIXIA_LOGGER_PREFIX;
2561
2661
  }
2562
2662
  });
2563
- Object.defineProperty(exports, 'LogLevel', {
2663
+ Object.defineProperty(exports, 'LOGIXIA_TRACE_CONFIG', {
2564
2664
  enumerable: true,
2565
2665
  get: function () {
2566
- return LogLevel;
2666
+ return LOGIXIA_TRACE_CONFIG;
2567
2667
  }
2568
2668
  });
2569
- Object.defineProperty(exports, 'LogixiaContext', {
2669
+ Object.defineProperty(exports, 'LogLevel', {
2570
2670
  enumerable: true,
2571
2671
  get: function () {
2572
- return LogixiaContext;
2672
+ return LogLevel;
2573
2673
  }
2574
2674
  });
2575
2675
  Object.defineProperty(exports, 'LogixiaLogger', {
@@ -2644,22 +2744,16 @@ Object.defineProperty(exports, '_setActiveContextKey', {
2644
2744
  return _setActiveContextKey;
2645
2745
  }
2646
2746
  });
2647
- Object.defineProperty(exports, 'applyRedaction', {
2648
- enumerable: true,
2649
- get: function () {
2650
- return applyRedaction;
2651
- }
2652
- });
2653
- Object.defineProperty(exports, 'createExpressContextMiddleware', {
2747
+ Object.defineProperty(exports, '_shutdownRegistrySize', {
2654
2748
  enumerable: true,
2655
2749
  get: function () {
2656
- return createExpressContextMiddleware;
2750
+ return _shutdownRegistrySize;
2657
2751
  }
2658
2752
  });
2659
- Object.defineProperty(exports, 'createFastifyContextHook', {
2753
+ Object.defineProperty(exports, 'applyRedaction', {
2660
2754
  enumerable: true,
2661
2755
  get: function () {
2662
- return createFastifyContextHook;
2756
+ return applyRedaction;
2663
2757
  }
2664
2758
  });
2665
2759
  Object.defineProperty(exports, 'createLogger', {
@@ -2800,4 +2894,4 @@ Object.defineProperty(exports, 'usePlugin', {
2800
2894
  return usePlugin;
2801
2895
  }
2802
2896
  });
2803
- //# sourceMappingURL=logitron-logger.module-BTxDpK6u.js.map
2897
+ //# sourceMappingURL=logitron-logger.module-BsDZR5BH.js.map