logixia 1.13.0 → 1.13.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -0
- package/dist/{async-context-CwBNMm2E.mjs → async-context-BzJrbfQs.mjs} +8 -4
- package/dist/async-context-BzJrbfQs.mjs.map +1 -0
- package/dist/{async-context-CSHWoHMB.js → async-context-DyQQYq3I.js} +8 -4
- package/dist/async-context-DyQQYq3I.js.map +1 -0
- package/dist/{azure-monitor.transport-CG7ClkYj.d.ts → azure-monitor.transport-BDFO4F-i.d.ts} +2 -2
- package/dist/{azure-monitor.transport-CG7ClkYj.d.ts.map → azure-monitor.transport-BDFO4F-i.d.ts.map} +1 -1
- package/dist/{azure-monitor.transport-Cm74kXZS.d.mts → azure-monitor.transport-D5wQEH04.d.mts} +2 -2
- package/dist/{azure-monitor.transport-Cm74kXZS.d.mts.map → azure-monitor.transport-D5wQEH04.d.mts.map} +1 -1
- package/dist/azure.d.mts +2 -2
- package/dist/azure.d.ts +2 -2
- package/dist/cli/index.js +98 -52
- package/dist/cloudwatch.d.mts +2 -2
- package/dist/cloudwatch.d.ts +2 -2
- package/dist/cloudwatch.js +2 -1
- package/dist/cloudwatch.mjs +2 -1
- package/dist/{cloudwatch.transport-CGHY4buE.d.mts → cloudwatch.transport-B00st6Xv.d.ts} +9 -2
- package/dist/cloudwatch.transport-B00st6Xv.d.ts.map +1 -0
- package/dist/{cloudwatch.transport-pNBNWJLt.js → cloudwatch.transport-BO1ahxw-.js} +26 -19
- package/dist/cloudwatch.transport-BO1ahxw-.js.map +1 -0
- package/dist/{cloudwatch.transport-DK_8cKd3.d.ts → cloudwatch.transport-Blc7Gtxt.d.mts} +9 -2
- package/dist/cloudwatch.transport-Blc7Gtxt.d.mts.map +1 -0
- package/dist/{cloudwatch.transport-yBwm4OeO.mjs → cloudwatch.transport-DZ6ies7g.mjs} +26 -19
- package/dist/cloudwatch.transport-DZ6ies7g.mjs.map +1 -0
- package/dist/{coerce.utils-BN980Y9V.js → coerce.utils-B-LilukN.js} +1 -1
- package/dist/{coerce.utils-BN980Y9V.js.map → coerce.utils-B-LilukN.js.map} +1 -1
- package/dist/{coerce.utils-Dxv4_ikC.mjs → coerce.utils-Cu6IUTgX.mjs} +1 -1
- package/dist/{coerce.utils-Dxv4_ikC.mjs.map → coerce.utils-Cu6IUTgX.mjs.map} +1 -1
- package/dist/correlation.d.mts +24 -6
- package/dist/correlation.d.mts.map +1 -1
- package/dist/correlation.d.ts +24 -6
- package/dist/correlation.d.ts.map +1 -1
- package/dist/correlation.js +41 -16
- package/dist/correlation.js.map +1 -1
- package/dist/correlation.mjs +41 -16
- package/dist/correlation.mjs.map +1 -1
- package/dist/entry-fields-BJkuPnIg.mjs +30 -0
- package/dist/entry-fields-BJkuPnIg.mjs.map +1 -0
- package/dist/entry-fields-BvOLFlJ4.js +36 -0
- package/dist/entry-fields-BvOLFlJ4.js.map +1 -0
- package/dist/gcp.d.mts +2 -2
- package/dist/gcp.d.ts +2 -2
- package/dist/gcp.js +2 -1
- package/dist/gcp.mjs +2 -1
- package/dist/{gcp.transport-SHdtc1n0.js → gcp.transport-CHV8MGgz.js} +5 -5
- package/dist/gcp.transport-CHV8MGgz.js.map +1 -0
- package/dist/{gcp.transport-BJuNRFe_.mjs → gcp.transport-DBX5TPIy.mjs} +5 -5
- package/dist/gcp.transport-DBX5TPIy.mjs.map +1 -0
- package/dist/{gcp.transport-BOhkVKlI.d.ts → gcp.transport-m4fVw0b1.d.ts} +2 -2
- package/dist/gcp.transport-m4fVw0b1.d.ts.map +1 -0
- package/dist/{gcp.transport-Bi6CUqZR.d.mts → gcp.transport-zzNyIoih.d.mts} +2 -2
- package/dist/gcp.transport-zzNyIoih.d.mts.map +1 -0
- package/dist/{index-BPKwwERo.d.mts → index-BPwEisy4.d.mts} +2 -2
- package/dist/{index-BPKwwERo.d.mts.map → index-BPwEisy4.d.mts.map} +1 -1
- package/dist/{index-C1X-TE5I.d.ts → index-nZEeCr3X.d.ts} +2 -2
- package/dist/{index-C1X-TE5I.d.ts.map → index-nZEeCr3X.d.ts.map} +1 -1
- package/dist/index.d.mts +63 -98
- package/dist/index.d.mts.map +1 -1
- package/dist/index.d.ts +63 -98
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +167 -443
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +98 -377
- package/dist/index.mjs.map +1 -1
- package/dist/middleware.d.mts +11 -4
- package/dist/middleware.d.mts.map +1 -1
- package/dist/middleware.d.ts +11 -4
- package/dist/middleware.d.ts.map +1 -1
- package/dist/middleware.js +148 -24
- package/dist/middleware.js.map +1 -1
- package/dist/middleware.mjs +148 -24
- package/dist/middleware.mjs.map +1 -1
- package/dist/nest.d.mts +4 -4
- package/dist/nest.d.ts +4 -4
- package/dist/nest.js +20 -11
- package/dist/nest.mjs +7 -5
- package/dist/{logitron-logger.module-BsDZR5BH.js → nestjs-extras-DnJ6vrIC.js} +562 -444
- package/dist/nestjs-extras-DnJ6vrIC.js.map +1 -0
- package/dist/{logitron-logger.module-Bs3XYZgF.mjs → nestjs-extras-ImbuDhs1.mjs} +505 -349
- package/dist/nestjs-extras-ImbuDhs1.mjs.map +1 -0
- package/dist/{logitron-logger.module-CbXy2gfW.d.ts → nestjs-extras-OkC796py.d.mts} +111 -4
- package/dist/nestjs-extras-OkC796py.d.mts.map +1 -0
- package/dist/{logitron-logger.module-BdG1Jnpk.d.mts → nestjs-extras-mKrHE9S6.d.ts} +111 -4
- package/dist/nestjs-extras-mKrHE9S6.d.ts.map +1 -0
- package/dist/{search-njTI2hdo.js → search-B0MH1SJJ.js} +23 -10
- package/dist/search-B0MH1SJJ.js.map +1 -0
- package/dist/{search-DujhR94O.d.ts → search-BfBzDIT9.d.mts} +2 -3
- package/dist/search-BfBzDIT9.d.mts.map +1 -0
- package/dist/{search-CQOo-Iq6.d.mts → search-CHUZPl0h.d.ts} +2 -3
- package/dist/search-CHUZPl0h.d.ts.map +1 -0
- package/dist/{search-CFQRISUv.mjs → search-DjXSn6v5.mjs} +23 -10
- package/dist/search-DjXSn6v5.mjs.map +1 -0
- package/dist/search.d.mts +3 -3
- package/dist/search.d.ts +3 -3
- package/dist/search.js +2 -2
- package/dist/search.mjs +2 -2
- package/dist/testing.d.mts +2 -2
- package/dist/testing.d.ts +2 -2
- package/dist/trace.utils-CvXgaiQT.mjs +278 -0
- package/dist/trace.utils-CvXgaiQT.mjs.map +1 -0
- package/dist/trace.utils-DpBOLDtq.js +358 -0
- package/dist/trace.utils-DpBOLDtq.js.map +1 -0
- package/dist/{transport.manager-D6KL3t9V.mjs → transport.manager-CpdVHEGP.mjs} +365 -86
- package/dist/transport.manager-CpdVHEGP.mjs.map +1 -0
- package/dist/{transport.manager-BivyUTtU.js → transport.manager-Crau3Rle.js} +370 -85
- package/dist/transport.manager-Crau3Rle.js.map +1 -0
- package/dist/{transport.types-B5vcyv2k.d.mts → transport.types-CtNr3D7S.d.mts} +19 -2
- package/dist/transport.types-CtNr3D7S.d.mts.map +1 -0
- package/dist/{transport.types-BuY84TwO.d.ts → transport.types-DqVLZTyf.d.ts} +19 -2
- package/dist/transport.types-DqVLZTyf.d.ts.map +1 -0
- package/dist/transports.d.mts +38 -13
- package/dist/transports.d.mts.map +1 -1
- package/dist/transports.d.ts +38 -13
- package/dist/transports.d.ts.map +1 -1
- package/dist/transports.js +6 -5
- package/dist/transports.mjs +6 -5
- package/dist/worker-entry.js +307 -55
- package/dist/worker.d.mts +2 -2
- package/dist/worker.d.ts +2 -2
- package/dist/worker.js +1 -1
- package/dist/worker.mjs +1 -1
- package/dist/{worker.transport-BP8Q28Z2.d.mts → worker.transport-Bgv9heDI.d.mts} +2 -2
- package/dist/{worker.transport-BP8Q28Z2.d.mts.map → worker.transport-Bgv9heDI.d.mts.map} +1 -1
- package/dist/{worker.transport-mKXgNK0L.d.ts → worker.transport-Bj-i0P9V.d.ts} +2 -2
- package/dist/{worker.transport-mKXgNK0L.d.ts.map → worker.transport-Bj-i0P9V.d.ts.map} +1 -1
- package/dist/{worker.transport-CfH6z37Z.js → worker.transport-JP8YHBuU.js} +1 -1
- package/dist/{worker.transport-CfH6z37Z.js.map → worker.transport-JP8YHBuU.js.map} +1 -1
- package/dist/{worker.transport-BhMyvqQ2.mjs → worker.transport-otwhJ_Et.mjs} +1 -1
- package/dist/{worker.transport-BhMyvqQ2.mjs.map → worker.transport-otwhJ_Et.mjs.map} +1 -1
- package/package.json +10 -6
- package/dist/.tsbuildinfo +0 -1
- package/dist/async-context-CSHWoHMB.js.map +0 -1
- package/dist/async-context-CwBNMm2E.mjs.map +0 -1
- package/dist/cloudwatch.transport-CGHY4buE.d.mts.map +0 -1
- package/dist/cloudwatch.transport-DK_8cKd3.d.ts.map +0 -1
- package/dist/cloudwatch.transport-pNBNWJLt.js.map +0 -1
- package/dist/cloudwatch.transport-yBwm4OeO.mjs.map +0 -1
- package/dist/gcp.transport-BJuNRFe_.mjs.map +0 -1
- package/dist/gcp.transport-BOhkVKlI.d.ts.map +0 -1
- package/dist/gcp.transport-Bi6CUqZR.d.mts.map +0 -1
- package/dist/gcp.transport-SHdtc1n0.js.map +0 -1
- package/dist/logitron-logger.module-BdG1Jnpk.d.mts.map +0 -1
- package/dist/logitron-logger.module-Bs3XYZgF.mjs.map +0 -1
- package/dist/logitron-logger.module-BsDZR5BH.js.map +0 -1
- package/dist/logitron-logger.module-CbXy2gfW.d.ts.map +0 -1
- package/dist/search-CFQRISUv.mjs.map +0 -1
- package/dist/search-CQOo-Iq6.d.mts.map +0 -1
- package/dist/search-DujhR94O.d.ts.map +0 -1
- package/dist/search-njTI2hdo.js.map +0 -1
- package/dist/transport.manager-BivyUTtU.js.map +0 -1
- package/dist/transport.manager-D6KL3t9V.mjs.map +0 -1
- package/dist/transport.types-B5vcyv2k.d.mts.map +0 -1
- package/dist/transport.types-BuY84TwO.d.ts.map +0 -1
- package/scripts/postinstall.js +0 -61
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { t as __require } from "./chunk-DLSkYcPk.mjs";
|
|
2
2
|
import { n as internalLog, r as internalWarn, t as internalError } from "./internal-log-Cm8SOWSV.mjs";
|
|
3
3
|
import { i as stringifyForLog } from "./safe-stringify-DJ66tW5I.mjs";
|
|
4
|
-
import { t as
|
|
5
|
-
import { t as
|
|
6
|
-
import { t as
|
|
4
|
+
import { d as sanitizeIncomingId, i as TraceContext, l as getTraceContextKey, s as extractTraceId, t as DEFAULT_TRACE_HEADERS } from "./trace.utils-CvXgaiQT.mjs";
|
|
5
|
+
import { t as LogixiaContext } from "./async-context-BzJrbfQs.mjs";
|
|
6
|
+
import { t as safeToString } from "./coerce.utils-Cu6IUTgX.mjs";
|
|
7
|
+
import { t as TransportManager, u as stripControlChars } from "./transport.manager-CpdVHEGP.mjs";
|
|
7
8
|
import { constants } from "node:os";
|
|
8
|
-
import { AsyncLocalStorage } from "node:async_hooks";
|
|
9
9
|
import buildFastStringify from "fast-json-stringify";
|
|
10
|
-
import
|
|
11
|
-
import { Injectable, Module, Optional, RequestMethod, Scope } from "@nestjs/common";
|
|
10
|
+
import { Catch, Inject, Injectable, Module, Optional, RequestMethod, Scope } from "@nestjs/common";
|
|
12
11
|
import { EMPTY, Observable } from "rxjs";
|
|
13
12
|
|
|
14
13
|
//#region src/plugin.ts
|
|
@@ -386,16 +385,29 @@ function disableOtelBridge() {
|
|
|
386
385
|
//#endregion
|
|
387
386
|
//#region src/utils/redact.utils.ts
|
|
388
387
|
const DEFAULT_CENSOR = "[REDACTED]";
|
|
388
|
+
/** Maximum nesting depth walked; deeper values are replaced with a marker. */
|
|
389
|
+
const MAX_DEPTH = 32;
|
|
390
|
+
/** Maximum number of objects/arrays visited per redaction pass. */
|
|
391
|
+
const MAX_NODES = 1e4;
|
|
392
|
+
/**
|
|
393
|
+
* Strings longer than this are truncated before pattern scanning. The tail is
|
|
394
|
+
* dropped rather than emitted unscanned, so oversized input can never carry an
|
|
395
|
+
* unredacted secret past the patterns.
|
|
396
|
+
*/
|
|
397
|
+
const MAX_SCAN_LENGTH = 16384;
|
|
398
|
+
const MAX_DEPTH_MARKER = "[MaxDepth]";
|
|
399
|
+
const MAX_NODES_MARKER = "[MaxNodes]";
|
|
400
|
+
const REDACTION_FAILED = "[RedactionFailed]";
|
|
389
401
|
/**
|
|
390
402
|
* Conservative patterns: tokens and secrets that should NEVER appear in logs.
|
|
391
403
|
* Applied when `autoDetect: true` or `autoDetect: 'conservative'`.
|
|
392
404
|
*/
|
|
393
405
|
const PII_CONSERVATIVE_PATTERNS = [
|
|
394
|
-
/eyJ[A-Za-z0-9_-]
|
|
406
|
+
/eyJ[A-Za-z0-9_-]{1,1024}\.[A-Za-z0-9_-]{1,16384}\.[A-Za-z0-9_-]{0,1024}/g,
|
|
395
407
|
/Bearer\s+[A-Za-z0-9._~+/-]+=*/gi,
|
|
396
408
|
/\b(?:sk|pk|api|key|secret|token)-[A-Za-z0-9_-]{16,}/gi,
|
|
397
409
|
/\bAKIA[0-9A-Z]{16}\b/g,
|
|
398
|
-
|
|
410
|
+
/secret[_-]?(?:access[_-]?)?key["'\s:=]{1,6}[A-Za-z0-9/+]{40}(?![A-Za-z0-9/+])/gi
|
|
399
411
|
];
|
|
400
412
|
/**
|
|
401
413
|
* Conservative field-name paths auto-redacted by name regardless of value.
|
|
@@ -416,14 +428,24 @@ const PII_CONSERVATIVE_PATHS = [
|
|
|
416
428
|
"**.privateKey",
|
|
417
429
|
"**.private_key",
|
|
418
430
|
"**.clientSecret",
|
|
419
|
-
"**.client_secret"
|
|
431
|
+
"**.client_secret",
|
|
432
|
+
"**.cookie",
|
|
433
|
+
"**.set-cookie",
|
|
434
|
+
"**.x-api-key",
|
|
435
|
+
"**.session",
|
|
436
|
+
"**.proxy-authorization",
|
|
437
|
+
"**.x-auth-token",
|
|
438
|
+
"**.x-access-token",
|
|
439
|
+
"**.aws_secret_access_key",
|
|
440
|
+
"**.awsSecretAccessKey",
|
|
441
|
+
"**.secretAccessKey"
|
|
420
442
|
];
|
|
421
443
|
/**
|
|
422
444
|
* Aggressive patterns: also catch personal data that could identify a person.
|
|
423
445
|
* Applied when `autoDetect: 'aggressive'`.
|
|
424
446
|
*/
|
|
425
447
|
const PII_AGGRESSIVE_PATTERNS = [
|
|
426
|
-
/\b[A-Za-z0-9._%+-]
|
|
448
|
+
/\b[A-Za-z0-9._%+-]{1,64}@[A-Za-z0-9.-]{1,255}\.[A-Za-z]{2,24}\b/g,
|
|
427
449
|
/\b\d{3}-?\d{2}-?\d{4}\b/g,
|
|
428
450
|
/\b(?:\d[ -]?){13,19}\b/g,
|
|
429
451
|
/\b(?:\+?1[-.\s]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}\b/g,
|
|
@@ -520,32 +542,54 @@ function matchesPath(fullPath, pattern) {
|
|
|
520
542
|
}
|
|
521
543
|
return re.test(fullPath);
|
|
522
544
|
}
|
|
545
|
+
function isTokenChar(code) {
|
|
546
|
+
return code >= 48 && code <= 57 || code >= 65 && code <= 90 || code >= 97 && code <= 122 || code === 46 || code === 95 || code === 126 || code === 43 || code === 47 || code === 61 || code === 45;
|
|
547
|
+
}
|
|
523
548
|
function applyPatterns(value, patterns, censor) {
|
|
524
549
|
let redacted = value;
|
|
550
|
+
let suffix = "";
|
|
551
|
+
if (redacted.length > MAX_SCAN_LENGTH) {
|
|
552
|
+
let end = MAX_SCAN_LENGTH;
|
|
553
|
+
while (end > 0 && isTokenChar(redacted.charCodeAt(end - 1))) end--;
|
|
554
|
+
suffix = `…[truncated ${value.length - end} unscanned chars]`;
|
|
555
|
+
redacted = redacted.slice(0, end);
|
|
556
|
+
}
|
|
525
557
|
for (const pattern of patterns) redacted = redacted.replace(pattern, censor);
|
|
526
|
-
return redacted;
|
|
558
|
+
return redacted + suffix;
|
|
527
559
|
}
|
|
528
560
|
const CIRCULAR = "[Circular]";
|
|
529
561
|
function joinPath(parent, key) {
|
|
530
562
|
return parent ? `${parent}.${key}` : key;
|
|
531
563
|
}
|
|
532
|
-
function walkValue(value, state, fullPath, bare) {
|
|
564
|
+
function walkValue(value, state, fullPath, bare, depth) {
|
|
533
565
|
const { paths = [], excludePaths = [], patterns = [], censor = DEFAULT_CENSOR } = state.config;
|
|
534
566
|
if (paths.some((p) => matchesPath(fullPath, p) || matchesPath(bare, p))) return censor;
|
|
567
|
+
if (typeof value === "object" && value !== null) {
|
|
568
|
+
if (depth >= MAX_DEPTH) return MAX_DEPTH_MARKER;
|
|
569
|
+
if (++state.nodes > MAX_NODES) return MAX_NODES_MARKER;
|
|
570
|
+
}
|
|
535
571
|
if (typeof value === "string") {
|
|
536
572
|
if (patterns.length === 0) return value;
|
|
537
573
|
if (excludePaths.some((p) => matchesPath(fullPath, p) || matchesPath(bare, p))) return value;
|
|
538
574
|
return applyPatterns(value, patterns, censor);
|
|
539
575
|
}
|
|
540
|
-
if (Array.isArray(value)) return walkContainer(value, state, fullPath, bare, walkArray);
|
|
541
|
-
if (
|
|
576
|
+
if (Array.isArray(value)) return walkContainer(value, state, fullPath, bare, depth, walkArray);
|
|
577
|
+
if (value instanceof Error) return walkContainer(value, state, fullPath, bare, depth, walkError);
|
|
578
|
+
if (value instanceof URL) {
|
|
579
|
+
const url = new URL(value.href);
|
|
580
|
+
url.username = "";
|
|
581
|
+
url.password = "";
|
|
582
|
+
const redacted = walkValue(url.href, state, fullPath, bare, depth);
|
|
583
|
+
return redacted === value.href ? value : redacted;
|
|
584
|
+
}
|
|
585
|
+
if (isPlainObject(value)) return walkContainer(value, state, fullPath, bare, depth, typeof value.toJSON === "function" ? walkToJSON : walkRecord);
|
|
542
586
|
return value;
|
|
543
587
|
}
|
|
544
|
-
function walkContainer(value, state, fullPath, bare, walk) {
|
|
588
|
+
function walkContainer(value, state, fullPath, bare, depth, walk) {
|
|
545
589
|
if (state.ancestors.has(value)) return CIRCULAR;
|
|
546
590
|
state.ancestors.add(value);
|
|
547
591
|
try {
|
|
548
|
-
return walk(value, state, fullPath, bare);
|
|
592
|
+
return walk(value, state, fullPath, bare, depth + 1);
|
|
549
593
|
} finally {
|
|
550
594
|
state.ancestors.delete(value);
|
|
551
595
|
}
|
|
@@ -554,26 +598,51 @@ function walkContainer(value, state, fullPath, bare, walk) {
|
|
|
554
598
|
* Array elements are matched by their indexed path (`users.0.password`) and by
|
|
555
599
|
* the index-free path (`users.password`) that earlier versions used.
|
|
556
600
|
*/
|
|
557
|
-
function walkArray(arr, state, fullPath, bare) {
|
|
601
|
+
function walkArray(arr, state, fullPath, bare, depth) {
|
|
558
602
|
let result;
|
|
559
603
|
for (const [i, item] of arr.entries()) {
|
|
560
|
-
const next = walkValue(item, state, joinPath(fullPath, String(i)), bare);
|
|
604
|
+
const next = walkValue(item, state, joinPath(fullPath, String(i)), bare, depth);
|
|
561
605
|
if (next !== item && !result) result = arr.slice(0, i);
|
|
562
606
|
if (result) result.push(next);
|
|
563
607
|
}
|
|
564
608
|
return result ?? arr;
|
|
565
609
|
}
|
|
566
|
-
function walkRecord(obj, state, fullPath, bare) {
|
|
610
|
+
function walkRecord(obj, state, fullPath, bare, depth) {
|
|
567
611
|
let result;
|
|
568
612
|
const entries = Object.entries(obj);
|
|
569
613
|
for (const [index, [key, value]] of entries.entries()) {
|
|
570
614
|
const forbidden = key === "__proto__" || key === "constructor" || key === "prototype";
|
|
571
|
-
const next = forbidden ? void 0 : walkValue(value, state, joinPath(fullPath, key), joinPath(bare, key));
|
|
615
|
+
const next = forbidden ? void 0 : walkValue(value, state, joinPath(fullPath, key), joinPath(bare, key), depth);
|
|
572
616
|
if ((forbidden || next !== value) && !result) result = Object.fromEntries(entries.slice(0, index));
|
|
573
617
|
if (result && !forbidden) result[key] = next;
|
|
574
618
|
}
|
|
575
619
|
return result ?? obj;
|
|
576
620
|
}
|
|
621
|
+
/** Errors are serialized (own props + cause chain) and the result is walked. */
|
|
622
|
+
function walkError(err, state, fullPath, bare, depth) {
|
|
623
|
+
let serialized;
|
|
624
|
+
try {
|
|
625
|
+
serialized = serializeError(err);
|
|
626
|
+
} catch {
|
|
627
|
+
return {
|
|
628
|
+
name: err.name,
|
|
629
|
+
message: REDACTION_FAILED
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
const result = walkRecord(serialized, state, fullPath, bare, depth);
|
|
633
|
+
return result === serialized ? { ...serialized } : result;
|
|
634
|
+
}
|
|
635
|
+
/** Objects with `toJSON()` are redacted via the value they would serialize to. */
|
|
636
|
+
function walkToJSON(obj, state, fullPath, bare, depth) {
|
|
637
|
+
let json;
|
|
638
|
+
try {
|
|
639
|
+
json = obj.toJSON();
|
|
640
|
+
} catch {
|
|
641
|
+
return REDACTION_FAILED;
|
|
642
|
+
}
|
|
643
|
+
if (json === obj) return walkRecord(obj, state, fullPath, bare, depth);
|
|
644
|
+
return walkValue(json, state, fullPath, bare, depth);
|
|
645
|
+
}
|
|
577
646
|
/**
|
|
578
647
|
* Redact an object according to the given RedactConfig and return a new
|
|
579
648
|
* top-level object. Subtrees with nothing to redact are shared with the input,
|
|
@@ -582,8 +651,9 @@ function walkRecord(obj, state, fullPath, bare) {
|
|
|
582
651
|
function redactObject(obj, config, _currentPath = "") {
|
|
583
652
|
const result = walkRecord(obj, {
|
|
584
653
|
config,
|
|
585
|
-
ancestors: new Set([obj])
|
|
586
|
-
|
|
654
|
+
ancestors: new Set([obj]),
|
|
655
|
+
nodes: 0
|
|
656
|
+
}, _currentPath, _currentPath, 0);
|
|
587
657
|
return result === obj ? { ...obj } : result;
|
|
588
658
|
}
|
|
589
659
|
/**
|
|
@@ -594,12 +664,11 @@ function redactObject(obj, config, _currentPath = "") {
|
|
|
594
664
|
* stays allocation-free for the common no-redact case.
|
|
595
665
|
*/
|
|
596
666
|
function applyRedactionToString(value, config) {
|
|
597
|
-
|
|
667
|
+
const text = typeof value === "string" ? value : safeToString(value);
|
|
668
|
+
if (!config) return text;
|
|
598
669
|
const resolved = resolveConfig(config);
|
|
599
|
-
if (!resolved.patterns || resolved.patterns.length === 0) return
|
|
600
|
-
|
|
601
|
-
for (const pattern of resolved.patterns) redacted = redacted.replace(pattern, resolved.censor ?? DEFAULT_CENSOR);
|
|
602
|
-
return redacted;
|
|
670
|
+
if (!resolved.patterns || resolved.patterns.length === 0) return text;
|
|
671
|
+
return applyPatterns(text, resolved.patterns, resolved.censor ?? DEFAULT_CENSOR);
|
|
603
672
|
}
|
|
604
673
|
/**
|
|
605
674
|
* Apply redaction to a log payload (top-level call convenience wrapper).
|
|
@@ -639,11 +708,21 @@ const ALWAYS_EMIT_LEVELS = new Set([
|
|
|
639
708
|
"warn",
|
|
640
709
|
"fatal"
|
|
641
710
|
]);
|
|
711
|
+
const MAX_CACHED_TRACE_ID_LENGTH = 256;
|
|
712
|
+
function isCacheableTraceId(id) {
|
|
713
|
+
if (typeof id !== "string" || id.length === 0 || id.length > MAX_CACHED_TRACE_ID_LENGTH) return false;
|
|
714
|
+
for (let i = 0; i < id.length; i++) {
|
|
715
|
+
const c = id.charCodeAt(i);
|
|
716
|
+
if (c < 32 || c >= 127 && c <= 159) return false;
|
|
717
|
+
}
|
|
718
|
+
return true;
|
|
719
|
+
}
|
|
642
720
|
var Sampler = class {
|
|
643
721
|
constructor(config, onStats) {
|
|
644
722
|
this.traceDecisions = /* @__PURE__ */ new Map();
|
|
645
723
|
this.maxTrackedTraces = 1e5;
|
|
646
724
|
this.traceTtlMs = 5 * 6e4;
|
|
725
|
+
this.traceMaxLifetimeMs = 60 * 6e4;
|
|
647
726
|
this._tokenBucket = 0;
|
|
648
727
|
this._lastRefillMs = Date.now();
|
|
649
728
|
this._adaptiveWindow = [];
|
|
@@ -763,13 +842,15 @@ var Sampler = class {
|
|
|
763
842
|
}
|
|
764
843
|
/**
|
|
765
844
|
* 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
|
|
767
|
-
* once the cap is reached.
|
|
845
|
+
* idle past the TTL, or older than the hard lifetime, are re-decided; the least
|
|
846
|
+
* recently used entry is evicted once the cap is reached. IDs that are empty,
|
|
847
|
+
* too long or contain control characters are sampled independently and never cached.
|
|
768
848
|
*/
|
|
769
849
|
_decideForTrace(traceId, level) {
|
|
850
|
+
if (!isCacheableTraceId(traceId)) return this._sampleByRate(level);
|
|
770
851
|
const now = Date.now();
|
|
771
852
|
const known = this.traceDecisions.get(traceId);
|
|
772
|
-
if (known && now - known.seenAt <= this.traceTtlMs) {
|
|
853
|
+
if (known && now - known.seenAt <= this.traceTtlMs && now - known.firstAt <= this.traceMaxLifetimeMs) {
|
|
773
854
|
this.traceDecisions.delete(traceId);
|
|
774
855
|
known.seenAt = now;
|
|
775
856
|
this.traceDecisions.set(traceId, known);
|
|
@@ -779,6 +860,7 @@ var Sampler = class {
|
|
|
779
860
|
this.traceDecisions.delete(traceId);
|
|
780
861
|
this.traceDecisions.set(traceId, {
|
|
781
862
|
emit,
|
|
863
|
+
firstAt: now,
|
|
782
864
|
seenAt: now
|
|
783
865
|
});
|
|
784
866
|
if (this.traceDecisions.size > this.maxTrackedTraces) {
|
|
@@ -942,318 +1024,6 @@ function resetShutdownHandlers() {
|
|
|
942
1024
|
shutdownInProgress = false;
|
|
943
1025
|
}
|
|
944
1026
|
|
|
945
|
-
//#endregion
|
|
946
|
-
//#region node_modules/uuid/dist/esm-node/rng.js
|
|
947
|
-
const rnds8Pool = new Uint8Array(256);
|
|
948
|
-
let poolPtr = rnds8Pool.length;
|
|
949
|
-
function rng() {
|
|
950
|
-
if (poolPtr > rnds8Pool.length - 16) {
|
|
951
|
-
crypto.randomFillSync(rnds8Pool);
|
|
952
|
-
poolPtr = 0;
|
|
953
|
-
}
|
|
954
|
-
return rnds8Pool.slice(poolPtr, poolPtr += 16);
|
|
955
|
-
}
|
|
956
|
-
|
|
957
|
-
//#endregion
|
|
958
|
-
//#region node_modules/uuid/dist/esm-node/stringify.js
|
|
959
|
-
/**
|
|
960
|
-
* Convert array of 16 byte values to UUID string format of the form:
|
|
961
|
-
* XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
|
|
962
|
-
*/
|
|
963
|
-
const byteToHex = [];
|
|
964
|
-
for (let i = 0; i < 256; ++i) byteToHex.push((i + 256).toString(16).slice(1));
|
|
965
|
-
function unsafeStringify(arr, offset = 0) {
|
|
966
|
-
return byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]];
|
|
967
|
-
}
|
|
968
|
-
|
|
969
|
-
//#endregion
|
|
970
|
-
//#region node_modules/uuid/dist/esm-node/native.js
|
|
971
|
-
var native_default = { randomUUID: crypto.randomUUID };
|
|
972
|
-
|
|
973
|
-
//#endregion
|
|
974
|
-
//#region node_modules/uuid/dist/esm-node/v4.js
|
|
975
|
-
function v4(options, buf, offset) {
|
|
976
|
-
if (native_default.randomUUID && !buf && !options) return native_default.randomUUID();
|
|
977
|
-
options = options || {};
|
|
978
|
-
const rnds = options.random || (options.rng || rng)();
|
|
979
|
-
rnds[6] = rnds[6] & 15 | 64;
|
|
980
|
-
rnds[8] = rnds[8] & 63 | 128;
|
|
981
|
-
if (buf) {
|
|
982
|
-
offset = offset || 0;
|
|
983
|
-
for (let i = 0; i < 16; ++i) buf[offset + i] = rnds[i];
|
|
984
|
-
return buf;
|
|
985
|
-
}
|
|
986
|
-
return unsafeStringify(rnds);
|
|
987
|
-
}
|
|
988
|
-
var v4_default = v4;
|
|
989
|
-
|
|
990
|
-
//#endregion
|
|
991
|
-
//#region src/utils/trace.utils.ts
|
|
992
|
-
/** Default key used to store the trace ID in AsyncLocalStorage. */
|
|
993
|
-
const TRACE_CONTEXT_KEY = "traceId";
|
|
994
|
-
/**
|
|
995
|
-
* Singleton that owns the AsyncLocalStorage and the active contextKey.
|
|
996
|
-
*
|
|
997
|
-
* Why a class instead of bare module-level variables?
|
|
998
|
-
* - The contextKey is user-configurable; encapsulating it here means there is
|
|
999
|
-
* exactly one place that reads and writes it.
|
|
1000
|
-
* - All helpers (getCurrentTraceId, runWithTraceId, etc.) delegate to this
|
|
1001
|
-
* instance, so the key is always in sync without hidden global state.
|
|
1002
|
-
* - Easier to test: you can reset the singleton between test cases.
|
|
1003
|
-
*
|
|
1004
|
-
* Usage (advanced):
|
|
1005
|
-
* import { TraceContext } from 'logixia';
|
|
1006
|
-
* TraceContext.instance.contextKey // → 'traceId' (or custom)
|
|
1007
|
-
* TraceContext.instance.getCurrentTraceId() // same as standalone fn
|
|
1008
|
-
*/
|
|
1009
|
-
var TraceContext = class TraceContext {
|
|
1010
|
-
static #_ = this._instance = null;
|
|
1011
|
-
constructor() {
|
|
1012
|
-
this.storage = new AsyncLocalStorage();
|
|
1013
|
-
this._contextKey = TRACE_CONTEXT_KEY;
|
|
1014
|
-
}
|
|
1015
|
-
/** The process-wide singleton. */
|
|
1016
|
-
static get instance() {
|
|
1017
|
-
if (!TraceContext._instance) TraceContext._instance = new TraceContext();
|
|
1018
|
-
return TraceContext._instance;
|
|
1019
|
-
}
|
|
1020
|
-
/** @internal Reset the singleton (useful in tests). */
|
|
1021
|
-
static _reset() {
|
|
1022
|
-
TraceContext._instance = null;
|
|
1023
|
-
}
|
|
1024
|
-
/** The AsyncLocalStorage key that holds the trace ID value. */
|
|
1025
|
-
get contextKey() {
|
|
1026
|
-
return this._contextKey;
|
|
1027
|
-
}
|
|
1028
|
-
/** @internal Called by TraceMiddleware when it boots to register the user's key. */
|
|
1029
|
-
setContextKey(key) {
|
|
1030
|
-
this._contextKey = key;
|
|
1031
|
-
}
|
|
1032
|
-
/** UUID v4 generator (default). */
|
|
1033
|
-
generate() {
|
|
1034
|
-
return v4_default();
|
|
1035
|
-
}
|
|
1036
|
-
/** Read the trace ID from the current async context. */
|
|
1037
|
-
getCurrentTraceId() {
|
|
1038
|
-
var _this$storage$getStor;
|
|
1039
|
-
return (_this$storage$getStor = this.storage.getStore()) === null || _this$storage$getStor === void 0 ? void 0 : _this$storage$getStor[this._contextKey];
|
|
1040
|
-
}
|
|
1041
|
-
/**
|
|
1042
|
-
* Mutate the CURRENT async context in-place.
|
|
1043
|
-
*
|
|
1044
|
-
* ⚠️ DEPRECATED — unsafe for concurrent requests.
|
|
1045
|
-
*
|
|
1046
|
-
* Uses `AsyncLocalStorage.enterWith()`, which mutates the current async
|
|
1047
|
-
* execution context and every Promise chain spawned from it. In a server
|
|
1048
|
-
* processing overlapping requests this can cause a trace ID set for one
|
|
1049
|
-
* request to bleed into *other* in-flight requests that share the same
|
|
1050
|
-
* async parent (e.g. a module-level setup function or a cached handler).
|
|
1051
|
-
*
|
|
1052
|
-
* Use {@link run} instead — it scopes the context to a callback so there
|
|
1053
|
-
* is no risk of cross-request leakage.
|
|
1054
|
-
*
|
|
1055
|
-
* @deprecated Use `TraceContext.instance.run(traceId, fn)` — do not call
|
|
1056
|
-
* `setTraceId` from request-handling code.
|
|
1057
|
-
*/
|
|
1058
|
-
setTraceId(traceId, data) {
|
|
1059
|
-
const current = this.storage.getStore() ?? {};
|
|
1060
|
-
this.storage.enterWith({
|
|
1061
|
-
...current,
|
|
1062
|
-
[this._contextKey]: traceId,
|
|
1063
|
-
...data
|
|
1064
|
-
});
|
|
1065
|
-
}
|
|
1066
|
-
/** Run `fn` inside a new async context that carries `traceId`. */
|
|
1067
|
-
run(traceId, fn, data) {
|
|
1068
|
-
return this.storage.run({
|
|
1069
|
-
[this._contextKey]: traceId,
|
|
1070
|
-
...data
|
|
1071
|
-
}, fn);
|
|
1072
|
-
}
|
|
1073
|
-
};
|
|
1074
|
-
/**
|
|
1075
|
-
* The shared AsyncLocalStorage instance.
|
|
1076
|
-
* @deprecated Prefer `TraceContext.instance.storage` for new code.
|
|
1077
|
-
*/
|
|
1078
|
-
const traceStorage = TraceContext.instance.storage;
|
|
1079
|
-
/** Returns the key currently used to store the trace ID in AsyncLocalStorage. */
|
|
1080
|
-
function getTraceContextKey() {
|
|
1081
|
-
return TraceContext.instance.contextKey;
|
|
1082
|
-
}
|
|
1083
|
-
/** @internal Called by TraceMiddleware / traceMiddleware() when they boot. */
|
|
1084
|
-
function _setActiveContextKey(key) {
|
|
1085
|
-
TraceContext.instance.setContextKey(key);
|
|
1086
|
-
}
|
|
1087
|
-
/** Generate a UUID v4 trace ID. */
|
|
1088
|
-
function generateTraceId() {
|
|
1089
|
-
return TraceContext.instance.generate();
|
|
1090
|
-
}
|
|
1091
|
-
/**
|
|
1092
|
-
* Get the current trace ID from async context.
|
|
1093
|
-
* Returns `undefined` when called outside a traced request.
|
|
1094
|
-
*/
|
|
1095
|
-
function getCurrentTraceId() {
|
|
1096
|
-
return TraceContext.instance.getCurrentTraceId();
|
|
1097
|
-
}
|
|
1098
|
-
/**
|
|
1099
|
-
* Set trace ID in the CURRENT async context without starting a new one.
|
|
1100
|
-
*
|
|
1101
|
-
* ⚠️ DEPRECATED — unsafe for concurrent requests.
|
|
1102
|
-
*
|
|
1103
|
-
* Uses `AsyncLocalStorage.enterWith()`, which mutates the current async
|
|
1104
|
-
* execution context and every Promise chain spawned from it. Under load this
|
|
1105
|
-
* can cause a trace ID from one request to bleed into others sharing the same
|
|
1106
|
-
* async parent.
|
|
1107
|
-
*
|
|
1108
|
-
* Use {@link runWithTraceId} instead. Migration patterns:
|
|
1109
|
-
*
|
|
1110
|
-
* **Express / Fastify middleware — before:**
|
|
1111
|
-
* ```ts
|
|
1112
|
-
* app.use((req, _res, next) => {
|
|
1113
|
-
* setTraceId(req.headers['x-trace-id'] ?? generateTraceId());
|
|
1114
|
-
* next();
|
|
1115
|
-
* });
|
|
1116
|
-
* ```
|
|
1117
|
-
* **after:**
|
|
1118
|
-
* ```ts
|
|
1119
|
-
* app.use((req, _res, next) => {
|
|
1120
|
-
* runWithTraceId(req.headers['x-trace-id'] ?? generateTraceId(), () => next());
|
|
1121
|
-
* });
|
|
1122
|
-
* ```
|
|
1123
|
-
*
|
|
1124
|
-
* **Kafka / queue consumer — before:**
|
|
1125
|
-
* ```ts
|
|
1126
|
-
* async function handle(msg) {
|
|
1127
|
-
* setTraceId(msg.headers['x-trace-id']);
|
|
1128
|
-
* await processMessage(msg);
|
|
1129
|
-
* }
|
|
1130
|
-
* ```
|
|
1131
|
-
* **after:**
|
|
1132
|
-
* ```ts
|
|
1133
|
-
* async function handle(msg) {
|
|
1134
|
-
* await runWithTraceId(msg.headers['x-trace-id'], () => processMessage(msg));
|
|
1135
|
-
* }
|
|
1136
|
-
* ```
|
|
1137
|
-
*
|
|
1138
|
-
* **Background job — before:**
|
|
1139
|
-
* ```ts
|
|
1140
|
-
* setTraceId(generateTraceId(), { jobId: job.id });
|
|
1141
|
-
* await job.run();
|
|
1142
|
-
* ```
|
|
1143
|
-
* **after:**
|
|
1144
|
-
* ```ts
|
|
1145
|
-
* await runWithTraceId(generateTraceId(), () => job.run(), { jobId: job.id });
|
|
1146
|
-
* ```
|
|
1147
|
-
*
|
|
1148
|
-
* @deprecated Use `runWithTraceId(traceId, fn)` — do not call `setTraceId`
|
|
1149
|
-
* from request-handling code.
|
|
1150
|
-
*/
|
|
1151
|
-
function setTraceId(traceId, data) {
|
|
1152
|
-
TraceContext.instance.setTraceId(traceId, data);
|
|
1153
|
-
}
|
|
1154
|
-
/** Run `fn` inside a new async context carrying `traceId`. */
|
|
1155
|
-
function runWithTraceId(traceId, fn, data) {
|
|
1156
|
-
return TraceContext.instance.run(traceId, fn, data);
|
|
1157
|
-
}
|
|
1158
|
-
/**
|
|
1159
|
-
* Coerce an arbitrary value to a non-empty trace ID string, or `undefined`.
|
|
1160
|
-
* Rejects empty/whitespace-only strings, non-strings, and non-first array elements.
|
|
1161
|
-
*/
|
|
1162
|
-
function toValidTraceId(value) {
|
|
1163
|
-
const first = Array.isArray(value) ? value[0] : value;
|
|
1164
|
-
if (typeof first !== "string") return void 0;
|
|
1165
|
-
const trimmed = first.trim();
|
|
1166
|
-
return trimmed.length > 0 ? trimmed : void 0;
|
|
1167
|
-
}
|
|
1168
|
-
/** W3C trace-context: `version-traceId(32hex)-spanId(16hex)-flags(2hex)`. */
|
|
1169
|
-
const W3C_TRACEPARENT_RE = /^[\da-f]{2}-([\da-f]{32})-[\da-f]{16}-[\da-f]{2}$/i;
|
|
1170
|
-
/**
|
|
1171
|
-
* Extract the 32-hex trace-id segment from a W3C `traceparent` header value.
|
|
1172
|
-
* Returns the parsed trace ID, or the original value unchanged when it is not a
|
|
1173
|
-
* well-formed traceparent (so non-W3C propagation still works).
|
|
1174
|
-
*/
|
|
1175
|
-
function parseTraceparent(value) {
|
|
1176
|
-
const m = W3C_TRACEPARENT_RE.exec(value);
|
|
1177
|
-
return m ? m[1] : value;
|
|
1178
|
-
}
|
|
1179
|
-
/** Extract trace ID from request using configuration (header → query → body → params). */
|
|
1180
|
-
function extractTraceId(request, config) {
|
|
1181
|
-
const req = request;
|
|
1182
|
-
if (config.header) {
|
|
1183
|
-
const headers = Array.isArray(config.header) ? config.header : [config.header];
|
|
1184
|
-
for (const header of headers) {
|
|
1185
|
-
var _req$headers;
|
|
1186
|
-
const lower = header.toLowerCase();
|
|
1187
|
-
const value = toValidTraceId((_req$headers = req.headers) === null || _req$headers === void 0 ? void 0 : _req$headers[lower]);
|
|
1188
|
-
if (value) return lower === "traceparent" ? parseTraceparent(value) : value;
|
|
1189
|
-
}
|
|
1190
|
-
}
|
|
1191
|
-
if (config.query) {
|
|
1192
|
-
const queries = Array.isArray(config.query) ? config.query : [config.query];
|
|
1193
|
-
for (const query of queries) {
|
|
1194
|
-
var _req$query;
|
|
1195
|
-
const value = toValidTraceId((_req$query = req.query) === null || _req$query === void 0 ? void 0 : _req$query[query]);
|
|
1196
|
-
if (value) return value;
|
|
1197
|
-
}
|
|
1198
|
-
}
|
|
1199
|
-
if (config.body) {
|
|
1200
|
-
const bodyFields = Array.isArray(config.body) ? config.body : [config.body];
|
|
1201
|
-
for (const field of bodyFields) {
|
|
1202
|
-
var _req$body;
|
|
1203
|
-
const value = toValidTraceId((_req$body = req.body) === null || _req$body === void 0 ? void 0 : _req$body[field]);
|
|
1204
|
-
if (value) return value;
|
|
1205
|
-
}
|
|
1206
|
-
}
|
|
1207
|
-
if (config.params) {
|
|
1208
|
-
const paramFields = Array.isArray(config.params) ? config.params : [config.params];
|
|
1209
|
-
for (const param of paramFields) {
|
|
1210
|
-
var _req$params;
|
|
1211
|
-
const value = toValidTraceId((_req$params = req.params) === null || _req$params === void 0 ? void 0 : _req$params[param]);
|
|
1212
|
-
if (value) return value;
|
|
1213
|
-
}
|
|
1214
|
-
}
|
|
1215
|
-
}
|
|
1216
|
-
/**
|
|
1217
|
-
* Default headers checked for incoming trace ID propagation, in priority order:
|
|
1218
|
-
* traceparent (W3C/OTel) → x-trace-id → x-request-id → x-correlation-id → trace-id
|
|
1219
|
-
*/
|
|
1220
|
-
const DEFAULT_TRACE_HEADERS = [
|
|
1221
|
-
"traceparent",
|
|
1222
|
-
"x-trace-id",
|
|
1223
|
-
"x-request-id",
|
|
1224
|
-
"x-correlation-id",
|
|
1225
|
-
"trace-id"
|
|
1226
|
-
];
|
|
1227
|
-
/**
|
|
1228
|
-
* Create trace ID middleware for Express/NestJS
|
|
1229
|
-
*/
|
|
1230
|
-
function createTraceMiddleware(config) {
|
|
1231
|
-
const defaultExtractor = {
|
|
1232
|
-
header: DEFAULT_TRACE_HEADERS,
|
|
1233
|
-
query: ["traceId", "trace_id"]
|
|
1234
|
-
};
|
|
1235
|
-
const resolvedConfig = {
|
|
1236
|
-
...config,
|
|
1237
|
-
extractor: (config === null || config === void 0 ? void 0 : config.extractor) ? {
|
|
1238
|
-
...defaultExtractor,
|
|
1239
|
-
...config.extractor
|
|
1240
|
-
} : defaultExtractor
|
|
1241
|
-
};
|
|
1242
|
-
_setActiveContextKey(resolvedConfig.contextKey ?? TRACE_CONTEXT_KEY);
|
|
1243
|
-
return (req, res, next) => {
|
|
1244
|
-
let traceId;
|
|
1245
|
-
if (resolvedConfig.extractor) traceId = extractTraceId(req, resolvedConfig.extractor);
|
|
1246
|
-
if (!traceId) traceId = resolvedConfig.generator ? resolvedConfig.generator() : generateTraceId();
|
|
1247
|
-
req.traceId = traceId;
|
|
1248
|
-
const resObj = res;
|
|
1249
|
-
if (!resObj.headersSent) try {
|
|
1250
|
-
if (typeof resObj.setHeader === "function") resObj.setHeader("X-Trace-Id", traceId);
|
|
1251
|
-
else if (typeof resObj.header === "function") resObj.header("X-Trace-Id", traceId);
|
|
1252
|
-
} catch {}
|
|
1253
|
-
runWithTraceId(traceId, () => next());
|
|
1254
|
-
};
|
|
1255
|
-
}
|
|
1256
|
-
|
|
1257
1027
|
//#endregion
|
|
1258
1028
|
//#region src/core/logitron-logger.ts
|
|
1259
1029
|
const _fastStringifyEntry = buildFastStringify({
|
|
@@ -1816,9 +1586,21 @@ var LogixiaLogger = class LogixiaLogger {
|
|
|
1816
1586
|
...mergedData
|
|
1817
1587
|
} : mergedData;
|
|
1818
1588
|
let payload;
|
|
1819
|
-
if (rawPayload !== void 0 && rawPayload !== null)
|
|
1589
|
+
if (rawPayload !== void 0 && rawPayload !== null) if (this._hasRedact) try {
|
|
1590
|
+
payload = applyRedaction(rawPayload, this.config.redact) ?? rawPayload;
|
|
1591
|
+
} catch (error) {
|
|
1592
|
+
internalError("Redaction failed", error);
|
|
1593
|
+
payload = { redaction: REDACTION_FAILED };
|
|
1594
|
+
}
|
|
1595
|
+
else payload = rawPayload;
|
|
1820
1596
|
const traceId = this.config.traceId ? TraceContext.instance.getCurrentTraceId() ?? this.fallbackTraceId : void 0;
|
|
1821
|
-
|
|
1597
|
+
let safeMessage = message;
|
|
1598
|
+
if (this._hasRedact) try {
|
|
1599
|
+
safeMessage = applyRedactionToString(message, this.config.redact);
|
|
1600
|
+
} catch (error) {
|
|
1601
|
+
internalError("Redaction failed", error);
|
|
1602
|
+
safeMessage = REDACTION_FAILED;
|
|
1603
|
+
}
|
|
1822
1604
|
const entry = {
|
|
1823
1605
|
timestamp: nowIso(),
|
|
1824
1606
|
level,
|
|
@@ -1889,9 +1671,9 @@ var LogixiaLogger = class LogixiaLogger {
|
|
|
1889
1671
|
if (((_this$config$format4 = this.config.format) === null || _this$config$format4 === void 0 ? void 0 : _this$config$format4.timestamp) !== false && this._fieldCache.get("timestamp") !== false) formatted += `${gray}[${entry.timestamp}]${reset} `;
|
|
1890
1672
|
if (this._fieldCache.get("level") !== false) formatted += this._formattedLevels.get(entry.level) ?? `[${entry.level.toUpperCase()}] `;
|
|
1891
1673
|
formatted += this._formattedAppName;
|
|
1892
|
-
if (entry.traceId && this._fieldCache.get("traceId") !== false) formatted += `${cyan}[${entry.traceId}]${reset} `;
|
|
1893
|
-
if (entry.context && this._fieldCache.get("context") !== false) formatted += `${yellow}[${entry.context}]${reset} `;
|
|
1894
|
-
if (this._fieldCache.get("message") !== false) formatted += entry.message;
|
|
1674
|
+
if (entry.traceId && this._fieldCache.get("traceId") !== false) formatted += `${cyan}[${stripControlChars(String(entry.traceId))}]${reset} `;
|
|
1675
|
+
if (entry.context && this._fieldCache.get("context") !== false) formatted += `${yellow}[${stripControlChars(String(entry.context))}]${reset} `;
|
|
1676
|
+
if (this._fieldCache.get("message") !== false) formatted += stripControlChars(safeToString(entry.message));
|
|
1895
1677
|
if (entry.payload !== void 0 && this._fieldCache.get("payload") !== false) formatted += ` ${stringifyForLog(entry.payload)}`;
|
|
1896
1678
|
return formatted;
|
|
1897
1679
|
}
|
|
@@ -2618,5 +2400,379 @@ let LogixiaLoggerModule = class LogixiaLoggerModule$1 {
|
|
|
2618
2400
|
LogixiaLoggerModule = _LogixiaLoggerModule = __decorate([Module({})], LogixiaLoggerModule);
|
|
2619
2401
|
|
|
2620
2402
|
//#endregion
|
|
2621
|
-
|
|
2622
|
-
|
|
2403
|
+
//#region src/exceptions/exception.ts
|
|
2404
|
+
var LogixiaException = class extends Error {
|
|
2405
|
+
constructor(options) {
|
|
2406
|
+
super(options.message, { cause: options.cause });
|
|
2407
|
+
this.name = "LogixiaException";
|
|
2408
|
+
this.errorCode = options.code;
|
|
2409
|
+
this.errorType = options.type;
|
|
2410
|
+
this.httpStatus = options.httpStatus;
|
|
2411
|
+
this.param = options.param;
|
|
2412
|
+
this.details = options.details;
|
|
2413
|
+
this.docUrl = options.docUrl;
|
|
2414
|
+
this.metadata = options.metadata;
|
|
2415
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
2416
|
+
}
|
|
2417
|
+
};
|
|
2418
|
+
/**
|
|
2419
|
+
* Returns `true` when `value` is a `LogixiaException` instance.
|
|
2420
|
+
*
|
|
2421
|
+
* Useful in exception filters or middleware that need to distinguish a
|
|
2422
|
+
* `LogixiaException` from a plain `Error` or a framework `HttpException`.
|
|
2423
|
+
*
|
|
2424
|
+
* @example
|
|
2425
|
+
* ```ts
|
|
2426
|
+
* if (isLogixiaException(err)) {
|
|
2427
|
+
* console.log(err.errorCode, err.httpStatus);
|
|
2428
|
+
* }
|
|
2429
|
+
* ```
|
|
2430
|
+
*/
|
|
2431
|
+
function isLogixiaException(value) {
|
|
2432
|
+
return value instanceof LogixiaException;
|
|
2433
|
+
}
|
|
2434
|
+
|
|
2435
|
+
//#endregion
|
|
2436
|
+
//#region src/exceptions/builder.ts
|
|
2437
|
+
/**
|
|
2438
|
+
* Generates a trace ID via the shared {@link TraceContext} generator.
|
|
2439
|
+
*
|
|
2440
|
+
* Delegates to `TraceContext.instance.generate()` so any custom generator
|
|
2441
|
+
* configured on `TraceIdConfig.generator` is respected — avoids the silent
|
|
2442
|
+
* "builder has its own UUID source" divergence this module had previously.
|
|
2443
|
+
*
|
|
2444
|
+
* @example `'550e8400-e29b-41d4-a716-446655440000'`
|
|
2445
|
+
*/
|
|
2446
|
+
function generateTraceId() {
|
|
2447
|
+
return TraceContext.instance.generate();
|
|
2448
|
+
}
|
|
2449
|
+
/** @deprecated Use `generateTraceId` instead. */
|
|
2450
|
+
const generateRequestId = generateTraceId;
|
|
2451
|
+
/**
|
|
2452
|
+
* Maps an HTTP status code to a human-friendly error type string.
|
|
2453
|
+
* Used as a fallback when the exception is a generic `HttpException`.
|
|
2454
|
+
*/
|
|
2455
|
+
function httpStatusToType(status) {
|
|
2456
|
+
if (status === 400) return "api_error";
|
|
2457
|
+
if (status === 401) return "authentication_error";
|
|
2458
|
+
if (status === 402) return "payment_error";
|
|
2459
|
+
if (status === 403) return "authorization_error";
|
|
2460
|
+
if (status === 404) return "not_found_error";
|
|
2461
|
+
if (status === 408) return "timeout_error";
|
|
2462
|
+
if (status === 409) return "conflict_error";
|
|
2463
|
+
if (status === 422) return "validation_error";
|
|
2464
|
+
if (status === 429) return "rate_limit_error";
|
|
2465
|
+
if (status >= 500) return "server_error";
|
|
2466
|
+
if (status >= 400) return "api_error";
|
|
2467
|
+
return "server_error";
|
|
2468
|
+
}
|
|
2469
|
+
/**
|
|
2470
|
+
* Duck-type check for NestJS `HttpException`.
|
|
2471
|
+
* Avoids a hard import on `@nestjs/common` so the builder is usable outside NestJS.
|
|
2472
|
+
*/
|
|
2473
|
+
function isHttpException(value) {
|
|
2474
|
+
return typeof value === "object" && value !== null && typeof value["getStatus"] === "function" && typeof value["getResponse"] === "function";
|
|
2475
|
+
}
|
|
2476
|
+
/**
|
|
2477
|
+
* Builds the optional `debug` block from an error.
|
|
2478
|
+
* Returns `undefined` when there is nothing useful to include.
|
|
2479
|
+
*/
|
|
2480
|
+
function buildDebug(error, service, durationMs, expose) {
|
|
2481
|
+
if (expose.debug !== true) return void 0;
|
|
2482
|
+
const stack = error instanceof Error ? error.stack : void 0;
|
|
2483
|
+
const causeRaw = error instanceof Error ? error.cause : void 0;
|
|
2484
|
+
let cause;
|
|
2485
|
+
if (expose.cause !== true) cause = void 0;
|
|
2486
|
+
else if (causeRaw instanceof Error) cause = causeRaw.message;
|
|
2487
|
+
else if (causeRaw !== void 0 && causeRaw !== null) cause = String(causeRaw);
|
|
2488
|
+
if (!stack && !cause && !service && durationMs === void 0) return void 0;
|
|
2489
|
+
return {
|
|
2490
|
+
...stack !== void 0 ? { stack } : {},
|
|
2491
|
+
...cause !== void 0 ? { cause } : {},
|
|
2492
|
+
...service !== void 0 ? { service } : {},
|
|
2493
|
+
...durationMs !== void 0 ? { duration_ms: durationMs } : {}
|
|
2494
|
+
};
|
|
2495
|
+
}
|
|
2496
|
+
var ErrorResponseBuilder = class {
|
|
2497
|
+
/**
|
|
2498
|
+
* Build a `LogixiaErrorResponse` from any thrown value.
|
|
2499
|
+
*
|
|
2500
|
+
* @param params - See `BuildParams`.
|
|
2501
|
+
* @returns The unified error response and the HTTP status code to send.
|
|
2502
|
+
*
|
|
2503
|
+
* @remarks
|
|
2504
|
+
* `traceId` does not need to be supplied by the caller in most cases — the
|
|
2505
|
+
* builder reads `TraceContext.instance.getCurrentTraceId()` internally and
|
|
2506
|
+
* falls back to the explicit `traceId` argument only when AsyncLocalStorage
|
|
2507
|
+
* is empty. If neither source yields a value, `meta.trace_id` is omitted.
|
|
2508
|
+
*
|
|
2509
|
+
* @example In a NestJS exception filter
|
|
2510
|
+
* ```ts
|
|
2511
|
+
* const { response, httpStatus } = ErrorResponseBuilder.build<AppCode, AppType>({
|
|
2512
|
+
* exception,
|
|
2513
|
+
* // Omit traceId — it will be picked up from ALS automatically.
|
|
2514
|
+
* path: request.url,
|
|
2515
|
+
* service: process.env.SERVICE_NAME,
|
|
2516
|
+
* startTime: request.startTime,
|
|
2517
|
+
* });
|
|
2518
|
+
*
|
|
2519
|
+
* if (process.env.NODE_ENV === 'production') delete response.debug;
|
|
2520
|
+
* // Echo the resolved traceId back on whatever header your TraceIdConfig says —
|
|
2521
|
+
* // do NOT hardcode 'X-Trace-Id', use `resolveResponseHeader(config)` instead.
|
|
2522
|
+
* if (response.meta.trace_id) {
|
|
2523
|
+
* response.setHeader(resolveResponseHeader(config) ?? 'X-Trace-Id', response.meta.trace_id);
|
|
2524
|
+
* }
|
|
2525
|
+
* response.status(httpStatus).json(response);
|
|
2526
|
+
* ```
|
|
2527
|
+
*/
|
|
2528
|
+
static build(params) {
|
|
2529
|
+
const { exception, path, service, startTime, traceId: rawTraceId, exposeDebug, exposeCause } = params;
|
|
2530
|
+
const expose = {
|
|
2531
|
+
debug: exposeDebug,
|
|
2532
|
+
cause: exposeCause
|
|
2533
|
+
};
|
|
2534
|
+
const traceId = TraceContext.instance.getCurrentTraceId() ?? rawTraceId;
|
|
2535
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
2536
|
+
const durationMs = startTime !== void 0 ? Date.now() - startTime : void 0;
|
|
2537
|
+
if (isLogixiaException(exception)) {
|
|
2538
|
+
const debug$1 = buildDebug(exception, service, durationMs, expose);
|
|
2539
|
+
const errorBlock = {
|
|
2540
|
+
type: exception.errorType,
|
|
2541
|
+
code: exception.errorCode,
|
|
2542
|
+
message: exception.message
|
|
2543
|
+
};
|
|
2544
|
+
if (exception.param !== void 0) errorBlock.param = exception.param;
|
|
2545
|
+
if (exception.details !== void 0 && exception.details.length > 0) errorBlock.details = exception.details;
|
|
2546
|
+
if (exception.docUrl !== void 0) errorBlock.doc_url = exception.docUrl;
|
|
2547
|
+
return {
|
|
2548
|
+
response: {
|
|
2549
|
+
success: false,
|
|
2550
|
+
error: errorBlock,
|
|
2551
|
+
meta: {
|
|
2552
|
+
...traceId !== void 0 ? { trace_id: traceId } : {},
|
|
2553
|
+
timestamp,
|
|
2554
|
+
path,
|
|
2555
|
+
status: exception.httpStatus
|
|
2556
|
+
},
|
|
2557
|
+
...debug$1 !== void 0 ? { debug: debug$1 } : {}
|
|
2558
|
+
},
|
|
2559
|
+
httpStatus: exception.httpStatus
|
|
2560
|
+
};
|
|
2561
|
+
}
|
|
2562
|
+
if (isHttpException(exception)) {
|
|
2563
|
+
const status = exception.getStatus();
|
|
2564
|
+
const exResponse = exception.getResponse();
|
|
2565
|
+
let message;
|
|
2566
|
+
if (typeof exResponse === "string") message = exResponse;
|
|
2567
|
+
else if (typeof exResponse === "object" && exResponse !== null && "message" in exResponse) {
|
|
2568
|
+
const raw = exResponse.message;
|
|
2569
|
+
message = Array.isArray(raw) ? raw.join(", ") : String(raw);
|
|
2570
|
+
} else message = exception.message;
|
|
2571
|
+
const type = httpStatusToType(status);
|
|
2572
|
+
const code = `HTTP_${status}`;
|
|
2573
|
+
const debug$1 = buildDebug(exception, service, durationMs, expose);
|
|
2574
|
+
return {
|
|
2575
|
+
response: {
|
|
2576
|
+
success: false,
|
|
2577
|
+
error: {
|
|
2578
|
+
type,
|
|
2579
|
+
code,
|
|
2580
|
+
message
|
|
2581
|
+
},
|
|
2582
|
+
meta: {
|
|
2583
|
+
...traceId !== void 0 ? { trace_id: traceId } : {},
|
|
2584
|
+
timestamp,
|
|
2585
|
+
path,
|
|
2586
|
+
status
|
|
2587
|
+
},
|
|
2588
|
+
...debug$1 !== void 0 ? { debug: debug$1 } : {}
|
|
2589
|
+
},
|
|
2590
|
+
httpStatus: status
|
|
2591
|
+
};
|
|
2592
|
+
}
|
|
2593
|
+
const debug = buildDebug(exception instanceof Error ? exception : new Error(String(exception)), service, durationMs, expose);
|
|
2594
|
+
return {
|
|
2595
|
+
response: {
|
|
2596
|
+
success: false,
|
|
2597
|
+
error: {
|
|
2598
|
+
type: "server_error",
|
|
2599
|
+
code: "INTERNAL_SERVER_ERROR",
|
|
2600
|
+
message: "An unexpected error occurred."
|
|
2601
|
+
},
|
|
2602
|
+
meta: {
|
|
2603
|
+
...traceId !== void 0 ? { trace_id: traceId } : {},
|
|
2604
|
+
timestamp,
|
|
2605
|
+
path,
|
|
2606
|
+
status: 500
|
|
2607
|
+
},
|
|
2608
|
+
...debug !== void 0 ? { debug } : {}
|
|
2609
|
+
},
|
|
2610
|
+
httpStatus: 500
|
|
2611
|
+
};
|
|
2612
|
+
}
|
|
2613
|
+
};
|
|
2614
|
+
|
|
2615
|
+
//#endregion
|
|
2616
|
+
//#region src/core/nestjs-extras.ts
|
|
2617
|
+
var _ref;
|
|
2618
|
+
/**
|
|
2619
|
+
* Inject the Logixia logger registered in the current NestJS DI container.
|
|
2620
|
+
*
|
|
2621
|
+
* Equivalent to `@Inject(LOGIXIA_LOGGER_TOKEN)` but without needing to import
|
|
2622
|
+
* the internal token constant yourself.
|
|
2623
|
+
*
|
|
2624
|
+
* @example
|
|
2625
|
+
* ```ts
|
|
2626
|
+
* constructor(@InjectLogger() private readonly logger: LogixiaLoggerService) {}
|
|
2627
|
+
* ```
|
|
2628
|
+
*/
|
|
2629
|
+
const InjectLogger = () => Inject(`${LOGIXIA_LOGGER_PREFIX}SERVICE`);
|
|
2630
|
+
/**
|
|
2631
|
+
* Method decorator that auto-logs entry, exit, duration, and errors.
|
|
2632
|
+
*
|
|
2633
|
+
* Preserves the original method's sync/async contract: a synchronous method
|
|
2634
|
+
* stays synchronous (returns its value directly, with logs emitted
|
|
2635
|
+
* fire-and-forget), and an async method is awaited so exit/error logs reflect
|
|
2636
|
+
* the resolved result. Attaches to the logger found on the class instance via a
|
|
2637
|
+
* `logger` property (the conventional NestJS name).
|
|
2638
|
+
*
|
|
2639
|
+
* @example
|
|
2640
|
+
* ```ts
|
|
2641
|
+
* @LogMethod({ level: 'info', logArgs: true })
|
|
2642
|
+
* async processPayment(orderId: string): Promise<void> { … }
|
|
2643
|
+
* ```
|
|
2644
|
+
*/
|
|
2645
|
+
function LogMethod(options = {}) {
|
|
2646
|
+
const { level = "debug", logArgs = true, logResult = false, logErrors = true } = options;
|
|
2647
|
+
return function(target, propertyKey, descriptor) {
|
|
2648
|
+
var _constructor;
|
|
2649
|
+
const originalMethod = descriptor.value;
|
|
2650
|
+
if (typeof originalMethod !== "function") return descriptor;
|
|
2651
|
+
const methodName = String(propertyKey);
|
|
2652
|
+
const className = ((_constructor = target.constructor) === null || _constructor === void 0 ? void 0 : _constructor.name) ?? "Unknown";
|
|
2653
|
+
const label = options.label ?? `${className}.${methodName}`;
|
|
2654
|
+
let _warnedNoLogger = false;
|
|
2655
|
+
const reportLogFailure = (phase, err) => {
|
|
2656
|
+
internalError(`@LogMethod(${label}) ${phase} log failed: ${String(err)}`);
|
|
2657
|
+
};
|
|
2658
|
+
const emit = (logger, phase, message, data) => {
|
|
2659
|
+
const logFnRaw = logger[level];
|
|
2660
|
+
const p = (typeof logFnRaw === "function" ? logFnRaw : logger.debug).bind(logger)(message, data);
|
|
2661
|
+
if (p && typeof p.catch === "function") p.catch((e) => reportLogFailure(phase, e));
|
|
2662
|
+
};
|
|
2663
|
+
const emitError = (logger, error, start) => {
|
|
2664
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
2665
|
+
const errLog = logger.error(err, {
|
|
2666
|
+
method: label,
|
|
2667
|
+
durationMs: Date.now() - start
|
|
2668
|
+
});
|
|
2669
|
+
if (errLog && typeof errLog.catch === "function") errLog.catch((e) => reportLogFailure("error", e));
|
|
2670
|
+
};
|
|
2671
|
+
descriptor.value = function(...args) {
|
|
2672
|
+
const logger = this.logger ?? LogixiaLoggerModule._globalLogger ?? void 0;
|
|
2673
|
+
if (!logger && !_warnedNoLogger) {
|
|
2674
|
+
_warnedNoLogger = true;
|
|
2675
|
+
internalWarn(`@LogMethod on ${label}: no logger available. Either inject LogixiaLoggerService as this.logger or ensure LogixiaLoggerModule is initialised.`);
|
|
2676
|
+
}
|
|
2677
|
+
const start = Date.now();
|
|
2678
|
+
const entry = { method: label };
|
|
2679
|
+
if (logArgs && args.length > 0) entry["args"] = args;
|
|
2680
|
+
if (logger) emit(logger, "entry", `→ ${label}`, entry);
|
|
2681
|
+
const buildExit = (result$1) => {
|
|
2682
|
+
const exit = {
|
|
2683
|
+
method: label,
|
|
2684
|
+
durationMs: Date.now() - start
|
|
2685
|
+
};
|
|
2686
|
+
if (logResult) exit["result"] = result$1;
|
|
2687
|
+
return exit;
|
|
2688
|
+
};
|
|
2689
|
+
let result;
|
|
2690
|
+
try {
|
|
2691
|
+
result = originalMethod.apply(this, args);
|
|
2692
|
+
} catch (error) {
|
|
2693
|
+
if (logger && logErrors) emitError(logger, error, start);
|
|
2694
|
+
throw error;
|
|
2695
|
+
}
|
|
2696
|
+
if (result && typeof result.then === "function") return result.then((resolved) => {
|
|
2697
|
+
if (logger) emit(logger, "exit", `← ${label}`, buildExit(resolved));
|
|
2698
|
+
return resolved;
|
|
2699
|
+
}, (error) => {
|
|
2700
|
+
if (logger && logErrors) emitError(logger, error, start);
|
|
2701
|
+
throw error;
|
|
2702
|
+
});
|
|
2703
|
+
if (logger) emit(logger, "exit", `← ${label}`, buildExit(result));
|
|
2704
|
+
return result;
|
|
2705
|
+
};
|
|
2706
|
+
return descriptor;
|
|
2707
|
+
};
|
|
2708
|
+
}
|
|
2709
|
+
/** Injection token for {@link LogixiaExceptionFilterOptions}. */
|
|
2710
|
+
const LOGIXIA_EXCEPTION_FILTER_OPTIONS = "LOGIXIA_EXCEPTION_FILTER_OPTIONS";
|
|
2711
|
+
let LogixiaExceptionFilter = class LogixiaExceptionFilter$1 {
|
|
2712
|
+
constructor(logger, loggerConfig, options) {
|
|
2713
|
+
this._options = options ?? {};
|
|
2714
|
+
this._logger = logger ?? LogixiaLoggerModule._globalLogger ?? void 0;
|
|
2715
|
+
this._traceConfig = typeof (loggerConfig === null || loggerConfig === void 0 ? void 0 : loggerConfig.traceId) === "object" ? loggerConfig.traceId : void 0;
|
|
2716
|
+
}
|
|
2717
|
+
catch(exception, host) {
|
|
2718
|
+
var _request$headers;
|
|
2719
|
+
const ctx = host.switchToHttp();
|
|
2720
|
+
const request = ctx.getRequest();
|
|
2721
|
+
const response = ctx.getResponse();
|
|
2722
|
+
const traceId = TraceContext.instance.getCurrentTraceId() ?? sanitizeIncomingId((_request$headers = request.headers) === null || _request$headers === void 0 ? void 0 : _request$headers["x-trace-id"]) ?? sanitizeIncomingId(request.id) ?? void 0;
|
|
2723
|
+
const { response: errorResponse, httpStatus } = ErrorResponseBuilder.build({
|
|
2724
|
+
exception,
|
|
2725
|
+
traceId,
|
|
2726
|
+
path: request.url ?? "/",
|
|
2727
|
+
startTime: request.startTime,
|
|
2728
|
+
exposeDebug: this._options.exposeDebug === true,
|
|
2729
|
+
exposeCause: this._options.exposeCause === true
|
|
2730
|
+
});
|
|
2731
|
+
if (this._logger) {
|
|
2732
|
+
const requestMeta = {
|
|
2733
|
+
method: request.method ?? "",
|
|
2734
|
+
url: request.url ?? "",
|
|
2735
|
+
status: httpStatus,
|
|
2736
|
+
...errorResponse.meta.trace_id !== void 0 ? { trace_id: errorResponse.meta.trace_id } : {}
|
|
2737
|
+
};
|
|
2738
|
+
const onLogFailure = (err) => {
|
|
2739
|
+
internalError(`ExceptionFilter failed to write log entry: ${String(err)}`);
|
|
2740
|
+
};
|
|
2741
|
+
let logPromise;
|
|
2742
|
+
if (httpStatus >= 500) {
|
|
2743
|
+
const err = exception instanceof Error ? exception : new Error(String(exception));
|
|
2744
|
+
logPromise = this._logger.error(err, requestMeta);
|
|
2745
|
+
} else if (isLogixiaException(exception)) logPromise = this._logger.warn(`[${errorResponse.error.code}] ${errorResponse.error.message}`, requestMeta);
|
|
2746
|
+
else logPromise = this._logger.warn(`[${httpStatus}] ${errorResponse.error.message}`, requestMeta);
|
|
2747
|
+
if (logPromise && typeof logPromise.catch === "function") logPromise.catch(onLogFailure);
|
|
2748
|
+
}
|
|
2749
|
+
if (errorResponse.meta.trace_id) {
|
|
2750
|
+
const traceHeader = resolveResponseHeader(this._traceConfig);
|
|
2751
|
+
if (traceHeader) try {
|
|
2752
|
+
response.setHeader(traceHeader, errorResponse.meta.trace_id);
|
|
2753
|
+
} catch {}
|
|
2754
|
+
}
|
|
2755
|
+
if (httpStatus === 429) try {
|
|
2756
|
+
response.setHeader("Retry-After", "60");
|
|
2757
|
+
} catch {}
|
|
2758
|
+
response.status(httpStatus).json(errorResponse);
|
|
2759
|
+
}
|
|
2760
|
+
};
|
|
2761
|
+
LogixiaExceptionFilter = __decorate([
|
|
2762
|
+
Catch(),
|
|
2763
|
+
__decorateParam(0, Optional()),
|
|
2764
|
+
__decorateParam(0, Inject(`${LOGIXIA_LOGGER_PREFIX}SERVICE`)),
|
|
2765
|
+
__decorateParam(1, Optional()),
|
|
2766
|
+
__decorateParam(1, Inject(LOGIXIA_LOGGER_CONFIG)),
|
|
2767
|
+
__decorateParam(2, Optional()),
|
|
2768
|
+
__decorateParam(2, Inject(LOGIXIA_EXCEPTION_FILTER_OPTIONS)),
|
|
2769
|
+
__decorateMetadata("design:paramtypes", [
|
|
2770
|
+
Object,
|
|
2771
|
+
typeof (_ref = typeof Partial !== "undefined" && Partial) === "function" ? _ref : Object,
|
|
2772
|
+
Object
|
|
2773
|
+
])
|
|
2774
|
+
], LogixiaExceptionFilter);
|
|
2775
|
+
|
|
2776
|
+
//#endregion
|
|
2777
|
+
export { initOtelBridge as A, registerForShutdown as C, disableOtelBridge as D, redactObject as E, DEFAULT_LOG_LEVELS as F, LogLevel as I, PluginRegistry as L, normalizeError as M, serializeError as N, getActiveOtelContext as O, DEFAULT_LOG_COLORS as P, globalPluginRegistry as R, flushOnExit as S, applyRedaction as T, LogixiaLoggerService as _, ErrorResponseBuilder as a, _shutdownRegistrySize as b, LogixiaException as c, LOGIXIA_LOGGER_PREFIX as d, LOGIXIA_TRACE_CONFIG as f, KafkaTraceInterceptor as g, TraceMiddleware as h, LogixiaExceptionFilter as i, isError as j, getOtelMetaFields as k, isLogixiaException as l, WebSocketTraceInterceptor as m, LOGIXIA_EXCEPTION_FILTER_OPTIONS as n, generateRequestId as o, LogixiaLoggerModule as p, LogMethod as r, generateTraceId as s, InjectLogger as t, LOGIXIA_LOGGER_CONFIG as u, LogixiaLogger as v, resetShutdownHandlers as w, deregisterFromShutdown as x, createLogger as y, usePlugin as z };
|
|
2778
|
+
//# sourceMappingURL=nestjs-extras-ImbuDhs1.mjs.map
|