logixia 1.13.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +81 -16
- 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-Cn_3Usvu.d.ts} +2 -2
- package/dist/{azure-monitor.transport-CG7ClkYj.d.ts.map → azure-monitor.transport-Cn_3Usvu.d.ts.map} +1 -1
- package/dist/{azure-monitor.transport-Cm74kXZS.d.mts → azure-monitor.transport-D7Da4RAb.d.mts} +2 -2
- package/dist/{azure-monitor.transport-Cm74kXZS.d.mts.map → azure-monitor.transport-D7Da4RAb.d.mts.map} +1 -1
- package/dist/azure.d.mts +2 -2
- package/dist/azure.d.ts +2 -2
- package/dist/browser.d.mts +9 -0
- package/dist/browser.d.mts.map +1 -1
- package/dist/browser.d.ts +9 -0
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +43 -12
- package/dist/browser.js.map +1 -1
- package/dist/browser.mjs +43 -12
- package/dist/browser.mjs.map +1 -1
- package/dist/{logitron-logger.module-Bs3XYZgF.mjs → builder-0gEzRopq.mjs} +383 -1021
- package/dist/builder-0gEzRopq.mjs.map +1 -0
- package/dist/{logitron-logger.module-BsDZR5BH.js → builder-D44QktIo.js} +411 -1155
- package/dist/builder-D44QktIo.js.map +1 -0
- package/dist/cli/index.js +130 -65
- 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-pNBNWJLt.js → cloudwatch.transport-BO1ahxw-.js} +26 -19
- package/dist/cloudwatch.transport-BO1ahxw-.js.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/{cloudwatch.transport-CGHY4buE.d.mts → cloudwatch.transport-DsEq633o.d.ts} +9 -2
- package/dist/cloudwatch.transport-DsEq633o.d.ts.map +1 -0
- package/dist/{cloudwatch.transport-DK_8cKd3.d.ts → cloudwatch.transport-UlyZFWMn.d.mts} +9 -2
- package/dist/cloudwatch.transport-UlyZFWMn.d.mts.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-BOhkVKlI.d.ts → gcp.transport-B7oc97sG.d.ts} +2 -2
- package/dist/gcp.transport-B7oc97sG.d.ts.map +1 -0
- 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-Bi6CUqZR.d.mts → gcp.transport-GrJurKo8.d.mts} +2 -2
- package/dist/gcp.transport-GrJurKo8.d.mts.map +1 -0
- package/dist/{index-BPKwwERo.d.mts → index-3mw5gaCw.d.mts} +2 -2
- package/dist/{index-BPKwwERo.d.mts.map → index-3mw5gaCw.d.mts.map} +1 -1
- package/dist/{index-C1X-TE5I.d.ts → index-DhIoploR.d.ts} +2 -2
- package/dist/{index-C1X-TE5I.d.ts.map → index-DhIoploR.d.ts.map} +1 -1
- package/dist/index.d.mts +99 -137
- package/dist/index.d.mts.map +1 -1
- package/dist/index.d.ts +99 -137
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +146 -510
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +99 -431
- package/dist/index.mjs.map +1 -1
- package/dist/logitron-logger-BFDSO8Io.d.mts +257 -0
- package/dist/logitron-logger-BFDSO8Io.d.mts.map +1 -0
- package/dist/logitron-logger-UVeN-mQm.d.ts +257 -0
- package/dist/logitron-logger-UVeN-mQm.d.ts.map +1 -0
- 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 +481 -6
- package/dist/nest.d.mts.map +1 -1
- package/dist/nest.d.ts +481 -6
- package/dist/nest.d.ts.map +1 -1
- package/dist/nest.js +884 -13
- package/dist/nest.js.map +1 -0
- package/dist/nest.mjs +863 -6
- package/dist/nest.mjs.map +1 -0
- package/dist/{search-CFQRISUv.mjs → search-BFbu_oVn.mjs} +35 -12
- package/dist/search-BFbu_oVn.mjs.map +1 -0
- package/dist/{search-njTI2hdo.js → search-C4V0OMEn.js} +35 -12
- package/dist/search-C4V0OMEn.js.map +1 -0
- package/dist/{search-DujhR94O.d.ts → search-CNh9uVwR.d.ts} +2 -3
- package/dist/search-CNh9uVwR.d.ts.map +1 -0
- package/dist/{search-CQOo-Iq6.d.mts → search-DXANsQ2n.d.mts} +2 -3
- package/dist/search-DXANsQ2n.d.mts.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/slack.transport-BZzoXDPn.d.mts +112 -0
- package/dist/slack.transport-BZzoXDPn.d.mts.map +1 -0
- package/dist/slack.transport-BfJRouB2.js +654 -0
- package/dist/slack.transport-BfJRouB2.js.map +1 -0
- package/dist/slack.transport-Bzw7sucI.mjs +643 -0
- package/dist/slack.transport-Bzw7sucI.mjs.map +1 -0
- package/dist/slack.transport-CXjQYOes.d.ts +112 -0
- package/dist/slack.transport-CXjQYOes.d.ts.map +1 -0
- 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-BiuCAJd2.mjs} +526 -160
- package/dist/transport.manager-BiuCAJd2.mjs.map +1 -0
- package/dist/{transport.manager-BivyUTtU.js → transport.manager-CXbKKdVE.js} +537 -159
- package/dist/transport.manager-CXbKKdVE.js.map +1 -0
- package/dist/{transport.types-B5vcyv2k.d.mts → transport.types-BMnurPcc.d.mts} +23 -3
- package/dist/transport.types-BMnurPcc.d.mts.map +1 -0
- package/dist/{transport.types-BuY84TwO.d.ts → transport.types-CGoHpWQR.d.ts} +23 -3
- package/dist/transport.types-CGoHpWQR.d.ts.map +1 -0
- package/dist/transports.d.mts +50 -20
- package/dist/transports.d.mts.map +1 -1
- package/dist/transports.d.ts +50 -20
- package/dist/transports.d.ts.map +1 -1
- package/dist/transports.js +9 -5
- package/dist/transports.mjs +8 -6
- 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-CfH6z37Z.js → worker.transport-BdPxu3PN.js} +1 -1
- package/dist/{worker.transport-CfH6z37Z.js.map → worker.transport-BdPxu3PN.js.map} +1 -1
- package/dist/{worker.transport-mKXgNK0L.d.ts → worker.transport-CdzSZJmw.d.ts} +2 -2
- package/dist/{worker.transport-mKXgNK0L.d.ts.map → worker.transport-CdzSZJmw.d.ts.map} +1 -1
- package/dist/{worker.transport-BP8Q28Z2.d.mts → worker.transport-JvGPog3C.d.mts} +2 -2
- package/dist/{worker.transport-BP8Q28Z2.d.mts.map → worker.transport-JvGPog3C.d.mts.map} +1 -1
- package/dist/{worker.transport-BhMyvqQ2.mjs → worker.transport-lPxO2MVL.mjs} +1 -1
- package/dist/{worker.transport-BhMyvqQ2.mjs.map → worker.transport-lPxO2MVL.mjs.map} +1 -1
- package/package.json +27 -14
- 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 +0 -618
- 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 +0 -618
- 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,16 +1,86 @@
|
|
|
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 {
|
|
5
|
-
import { t as
|
|
6
|
-
import { t as
|
|
4
|
+
import { i as TraceContext } 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 { d as stripControlChars, t as TransportManager } from "./transport.manager-BiuCAJd2.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 crypto from "crypto";
|
|
11
|
-
import { Injectable, Module, Optional, RequestMethod, Scope } from "@nestjs/common";
|
|
12
|
-
import { EMPTY, Observable } from "rxjs";
|
|
13
10
|
|
|
11
|
+
//#region src/types/index.ts
|
|
12
|
+
const LogLevel = {
|
|
13
|
+
ERROR: "error",
|
|
14
|
+
WARN: "warn",
|
|
15
|
+
INFO: "info",
|
|
16
|
+
DEBUG: "debug",
|
|
17
|
+
TRACE: "trace",
|
|
18
|
+
VERBOSE: "verbose"
|
|
19
|
+
};
|
|
20
|
+
const DEFAULT_LOG_LEVELS = {
|
|
21
|
+
error: 0,
|
|
22
|
+
warn: 1,
|
|
23
|
+
info: 2,
|
|
24
|
+
debug: 3,
|
|
25
|
+
trace: 4,
|
|
26
|
+
verbose: 5
|
|
27
|
+
};
|
|
28
|
+
const DEFAULT_LOG_COLORS = {
|
|
29
|
+
error: "red",
|
|
30
|
+
warn: "yellow",
|
|
31
|
+
info: "green",
|
|
32
|
+
debug: "blue",
|
|
33
|
+
trace: "magenta",
|
|
34
|
+
verbose: "cyan"
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
//#endregion
|
|
38
|
+
//#region src/core/default-config.ts
|
|
39
|
+
/**
|
|
40
|
+
* Default configuration for Logixia logger
|
|
41
|
+
*/
|
|
42
|
+
const DEFAULT_CONFIG = {
|
|
43
|
+
appName: "App",
|
|
44
|
+
environment: "development",
|
|
45
|
+
traceId: true,
|
|
46
|
+
format: {
|
|
47
|
+
timestamp: true,
|
|
48
|
+
colorize: true,
|
|
49
|
+
json: false
|
|
50
|
+
},
|
|
51
|
+
silent: false,
|
|
52
|
+
levelOptions: {
|
|
53
|
+
level: LogLevel.INFO,
|
|
54
|
+
levels: {
|
|
55
|
+
[LogLevel.ERROR]: 0,
|
|
56
|
+
[LogLevel.WARN]: 1,
|
|
57
|
+
[LogLevel.INFO]: 2,
|
|
58
|
+
[LogLevel.DEBUG]: 3,
|
|
59
|
+
[LogLevel.TRACE]: 4,
|
|
60
|
+
[LogLevel.VERBOSE]: 5
|
|
61
|
+
},
|
|
62
|
+
colors: {
|
|
63
|
+
[LogLevel.ERROR]: "red",
|
|
64
|
+
[LogLevel.WARN]: "yellow",
|
|
65
|
+
[LogLevel.INFO]: "blue",
|
|
66
|
+
[LogLevel.DEBUG]: "green",
|
|
67
|
+
[LogLevel.TRACE]: "gray",
|
|
68
|
+
[LogLevel.VERBOSE]: "cyan"
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
fields: {
|
|
72
|
+
timestamp: true,
|
|
73
|
+
level: true,
|
|
74
|
+
appName: true,
|
|
75
|
+
traceId: true,
|
|
76
|
+
message: true,
|
|
77
|
+
payload: true,
|
|
78
|
+
timeTaken: true
|
|
79
|
+
},
|
|
80
|
+
outputs: ["console"]
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
//#endregion
|
|
14
84
|
//#region src/plugin.ts
|
|
15
85
|
/**
|
|
16
86
|
* Holds an ordered list of `LogixiaPlugin` instances and dispatches lifecycle
|
|
@@ -117,33 +187,6 @@ function usePlugin(plugin) {
|
|
|
117
187
|
globalPluginRegistry.register(plugin);
|
|
118
188
|
}
|
|
119
189
|
|
|
120
|
-
//#endregion
|
|
121
|
-
//#region src/types/index.ts
|
|
122
|
-
const LogLevel = {
|
|
123
|
-
ERROR: "error",
|
|
124
|
-
WARN: "warn",
|
|
125
|
-
INFO: "info",
|
|
126
|
-
DEBUG: "debug",
|
|
127
|
-
TRACE: "trace",
|
|
128
|
-
VERBOSE: "verbose"
|
|
129
|
-
};
|
|
130
|
-
const DEFAULT_LOG_LEVELS = {
|
|
131
|
-
error: 0,
|
|
132
|
-
warn: 1,
|
|
133
|
-
info: 2,
|
|
134
|
-
debug: 3,
|
|
135
|
-
trace: 4,
|
|
136
|
-
verbose: 5
|
|
137
|
-
};
|
|
138
|
-
const DEFAULT_LOG_COLORS = {
|
|
139
|
-
error: "red",
|
|
140
|
-
warn: "yellow",
|
|
141
|
-
info: "green",
|
|
142
|
-
debug: "blue",
|
|
143
|
-
trace: "magenta",
|
|
144
|
-
verbose: "cyan"
|
|
145
|
-
};
|
|
146
|
-
|
|
147
190
|
//#endregion
|
|
148
191
|
//#region src/utils/error.utils.ts
|
|
149
192
|
const EXTRA_FIELDS = [
|
|
@@ -386,16 +429,29 @@ function disableOtelBridge() {
|
|
|
386
429
|
//#endregion
|
|
387
430
|
//#region src/utils/redact.utils.ts
|
|
388
431
|
const DEFAULT_CENSOR = "[REDACTED]";
|
|
432
|
+
/** Maximum nesting depth walked; deeper values are replaced with a marker. */
|
|
433
|
+
const MAX_DEPTH = 32;
|
|
434
|
+
/** Maximum number of objects/arrays visited per redaction pass. */
|
|
435
|
+
const MAX_NODES = 1e4;
|
|
436
|
+
/**
|
|
437
|
+
* Strings longer than this are truncated before pattern scanning. The tail is
|
|
438
|
+
* dropped rather than emitted unscanned, so oversized input can never carry an
|
|
439
|
+
* unredacted secret past the patterns.
|
|
440
|
+
*/
|
|
441
|
+
const MAX_SCAN_LENGTH = 16384;
|
|
442
|
+
const MAX_DEPTH_MARKER = "[MaxDepth]";
|
|
443
|
+
const MAX_NODES_MARKER = "[MaxNodes]";
|
|
444
|
+
const REDACTION_FAILED = "[RedactionFailed]";
|
|
389
445
|
/**
|
|
390
446
|
* Conservative patterns: tokens and secrets that should NEVER appear in logs.
|
|
391
447
|
* Applied when `autoDetect: true` or `autoDetect: 'conservative'`.
|
|
392
448
|
*/
|
|
393
449
|
const PII_CONSERVATIVE_PATTERNS = [
|
|
394
|
-
/eyJ[A-Za-z0-9_-]
|
|
450
|
+
/eyJ[A-Za-z0-9_-]{1,1024}\.[A-Za-z0-9_-]{1,16384}\.[A-Za-z0-9_-]{0,1024}/g,
|
|
395
451
|
/Bearer\s+[A-Za-z0-9._~+/-]+=*/gi,
|
|
396
452
|
/\b(?:sk|pk|api|key|secret|token)-[A-Za-z0-9_-]{16,}/gi,
|
|
397
453
|
/\bAKIA[0-9A-Z]{16}\b/g,
|
|
398
|
-
|
|
454
|
+
/secret[_-]?(?:access[_-]?)?key["'\s:=]{1,6}[A-Za-z0-9/+]{40}(?![A-Za-z0-9/+])/gi
|
|
399
455
|
];
|
|
400
456
|
/**
|
|
401
457
|
* Conservative field-name paths auto-redacted by name regardless of value.
|
|
@@ -416,14 +472,24 @@ const PII_CONSERVATIVE_PATHS = [
|
|
|
416
472
|
"**.privateKey",
|
|
417
473
|
"**.private_key",
|
|
418
474
|
"**.clientSecret",
|
|
419
|
-
"**.client_secret"
|
|
475
|
+
"**.client_secret",
|
|
476
|
+
"**.cookie",
|
|
477
|
+
"**.set-cookie",
|
|
478
|
+
"**.x-api-key",
|
|
479
|
+
"**.session",
|
|
480
|
+
"**.proxy-authorization",
|
|
481
|
+
"**.x-auth-token",
|
|
482
|
+
"**.x-access-token",
|
|
483
|
+
"**.aws_secret_access_key",
|
|
484
|
+
"**.awsSecretAccessKey",
|
|
485
|
+
"**.secretAccessKey"
|
|
420
486
|
];
|
|
421
487
|
/**
|
|
422
488
|
* Aggressive patterns: also catch personal data that could identify a person.
|
|
423
489
|
* Applied when `autoDetect: 'aggressive'`.
|
|
424
490
|
*/
|
|
425
491
|
const PII_AGGRESSIVE_PATTERNS = [
|
|
426
|
-
/\b[A-Za-z0-9._%+-]
|
|
492
|
+
/\b[A-Za-z0-9._%+-]{1,64}@[A-Za-z0-9.-]{1,255}\.[A-Za-z]{2,24}\b/g,
|
|
427
493
|
/\b\d{3}-?\d{2}-?\d{4}\b/g,
|
|
428
494
|
/\b(?:\d[ -]?){13,19}\b/g,
|
|
429
495
|
/\b(?:\+?1[-.\s]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}\b/g,
|
|
@@ -520,32 +586,54 @@ function matchesPath(fullPath, pattern) {
|
|
|
520
586
|
}
|
|
521
587
|
return re.test(fullPath);
|
|
522
588
|
}
|
|
589
|
+
function isTokenChar(code) {
|
|
590
|
+
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;
|
|
591
|
+
}
|
|
523
592
|
function applyPatterns(value, patterns, censor) {
|
|
524
593
|
let redacted = value;
|
|
594
|
+
let suffix = "";
|
|
595
|
+
if (redacted.length > MAX_SCAN_LENGTH) {
|
|
596
|
+
let end = MAX_SCAN_LENGTH;
|
|
597
|
+
while (end > 0 && isTokenChar(redacted.charCodeAt(end - 1))) end--;
|
|
598
|
+
suffix = `…[truncated ${value.length - end} unscanned chars]`;
|
|
599
|
+
redacted = redacted.slice(0, end);
|
|
600
|
+
}
|
|
525
601
|
for (const pattern of patterns) redacted = redacted.replace(pattern, censor);
|
|
526
|
-
return redacted;
|
|
602
|
+
return redacted + suffix;
|
|
527
603
|
}
|
|
528
604
|
const CIRCULAR = "[Circular]";
|
|
529
605
|
function joinPath(parent, key) {
|
|
530
606
|
return parent ? `${parent}.${key}` : key;
|
|
531
607
|
}
|
|
532
|
-
function walkValue(value, state, fullPath, bare) {
|
|
608
|
+
function walkValue(value, state, fullPath, bare, depth) {
|
|
533
609
|
const { paths = [], excludePaths = [], patterns = [], censor = DEFAULT_CENSOR } = state.config;
|
|
534
610
|
if (paths.some((p) => matchesPath(fullPath, p) || matchesPath(bare, p))) return censor;
|
|
611
|
+
if (typeof value === "object" && value !== null) {
|
|
612
|
+
if (depth >= MAX_DEPTH) return MAX_DEPTH_MARKER;
|
|
613
|
+
if (++state.nodes > MAX_NODES) return MAX_NODES_MARKER;
|
|
614
|
+
}
|
|
535
615
|
if (typeof value === "string") {
|
|
536
616
|
if (patterns.length === 0) return value;
|
|
537
617
|
if (excludePaths.some((p) => matchesPath(fullPath, p) || matchesPath(bare, p))) return value;
|
|
538
618
|
return applyPatterns(value, patterns, censor);
|
|
539
619
|
}
|
|
540
|
-
if (Array.isArray(value)) return walkContainer(value, state, fullPath, bare, walkArray);
|
|
541
|
-
if (
|
|
620
|
+
if (Array.isArray(value)) return walkContainer(value, state, fullPath, bare, depth, walkArray);
|
|
621
|
+
if (value instanceof Error) return walkContainer(value, state, fullPath, bare, depth, walkError);
|
|
622
|
+
if (value instanceof URL) {
|
|
623
|
+
const url = new URL(value.href);
|
|
624
|
+
url.username = "";
|
|
625
|
+
url.password = "";
|
|
626
|
+
const redacted = walkValue(url.href, state, fullPath, bare, depth);
|
|
627
|
+
return redacted === value.href ? value : redacted;
|
|
628
|
+
}
|
|
629
|
+
if (isPlainObject(value)) return walkContainer(value, state, fullPath, bare, depth, typeof value.toJSON === "function" ? walkToJSON : walkRecord);
|
|
542
630
|
return value;
|
|
543
631
|
}
|
|
544
|
-
function walkContainer(value, state, fullPath, bare, walk) {
|
|
632
|
+
function walkContainer(value, state, fullPath, bare, depth, walk) {
|
|
545
633
|
if (state.ancestors.has(value)) return CIRCULAR;
|
|
546
634
|
state.ancestors.add(value);
|
|
547
635
|
try {
|
|
548
|
-
return walk(value, state, fullPath, bare);
|
|
636
|
+
return walk(value, state, fullPath, bare, depth + 1);
|
|
549
637
|
} finally {
|
|
550
638
|
state.ancestors.delete(value);
|
|
551
639
|
}
|
|
@@ -554,26 +642,51 @@ function walkContainer(value, state, fullPath, bare, walk) {
|
|
|
554
642
|
* Array elements are matched by their indexed path (`users.0.password`) and by
|
|
555
643
|
* the index-free path (`users.password`) that earlier versions used.
|
|
556
644
|
*/
|
|
557
|
-
function walkArray(arr, state, fullPath, bare) {
|
|
645
|
+
function walkArray(arr, state, fullPath, bare, depth) {
|
|
558
646
|
let result;
|
|
559
647
|
for (const [i, item] of arr.entries()) {
|
|
560
|
-
const next = walkValue(item, state, joinPath(fullPath, String(i)), bare);
|
|
648
|
+
const next = walkValue(item, state, joinPath(fullPath, String(i)), bare, depth);
|
|
561
649
|
if (next !== item && !result) result = arr.slice(0, i);
|
|
562
650
|
if (result) result.push(next);
|
|
563
651
|
}
|
|
564
652
|
return result ?? arr;
|
|
565
653
|
}
|
|
566
|
-
function walkRecord(obj, state, fullPath, bare) {
|
|
654
|
+
function walkRecord(obj, state, fullPath, bare, depth) {
|
|
567
655
|
let result;
|
|
568
656
|
const entries = Object.entries(obj);
|
|
569
657
|
for (const [index, [key, value]] of entries.entries()) {
|
|
570
658
|
const forbidden = key === "__proto__" || key === "constructor" || key === "prototype";
|
|
571
|
-
const next = forbidden ? void 0 : walkValue(value, state, joinPath(fullPath, key), joinPath(bare, key));
|
|
659
|
+
const next = forbidden ? void 0 : walkValue(value, state, joinPath(fullPath, key), joinPath(bare, key), depth);
|
|
572
660
|
if ((forbidden || next !== value) && !result) result = Object.fromEntries(entries.slice(0, index));
|
|
573
661
|
if (result && !forbidden) result[key] = next;
|
|
574
662
|
}
|
|
575
663
|
return result ?? obj;
|
|
576
664
|
}
|
|
665
|
+
/** Errors are serialized (own props + cause chain) and the result is walked. */
|
|
666
|
+
function walkError(err, state, fullPath, bare, depth) {
|
|
667
|
+
let serialized;
|
|
668
|
+
try {
|
|
669
|
+
serialized = serializeError(err);
|
|
670
|
+
} catch {
|
|
671
|
+
return {
|
|
672
|
+
name: err.name,
|
|
673
|
+
message: REDACTION_FAILED
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
const result = walkRecord(serialized, state, fullPath, bare, depth);
|
|
677
|
+
return result === serialized ? { ...serialized } : result;
|
|
678
|
+
}
|
|
679
|
+
/** Objects with `toJSON()` are redacted via the value they would serialize to. */
|
|
680
|
+
function walkToJSON(obj, state, fullPath, bare, depth) {
|
|
681
|
+
let json;
|
|
682
|
+
try {
|
|
683
|
+
json = obj.toJSON();
|
|
684
|
+
} catch {
|
|
685
|
+
return REDACTION_FAILED;
|
|
686
|
+
}
|
|
687
|
+
if (json === obj) return walkRecord(obj, state, fullPath, bare, depth);
|
|
688
|
+
return walkValue(json, state, fullPath, bare, depth);
|
|
689
|
+
}
|
|
577
690
|
/**
|
|
578
691
|
* Redact an object according to the given RedactConfig and return a new
|
|
579
692
|
* top-level object. Subtrees with nothing to redact are shared with the input,
|
|
@@ -582,8 +695,9 @@ function walkRecord(obj, state, fullPath, bare) {
|
|
|
582
695
|
function redactObject(obj, config, _currentPath = "") {
|
|
583
696
|
const result = walkRecord(obj, {
|
|
584
697
|
config,
|
|
585
|
-
ancestors: new Set([obj])
|
|
586
|
-
|
|
698
|
+
ancestors: new Set([obj]),
|
|
699
|
+
nodes: 0
|
|
700
|
+
}, _currentPath, _currentPath, 0);
|
|
587
701
|
return result === obj ? { ...obj } : result;
|
|
588
702
|
}
|
|
589
703
|
/**
|
|
@@ -594,12 +708,11 @@ function redactObject(obj, config, _currentPath = "") {
|
|
|
594
708
|
* stays allocation-free for the common no-redact case.
|
|
595
709
|
*/
|
|
596
710
|
function applyRedactionToString(value, config) {
|
|
597
|
-
|
|
711
|
+
const text = typeof value === "string" ? value : safeToString(value);
|
|
712
|
+
if (!config) return text;
|
|
598
713
|
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;
|
|
714
|
+
if (!resolved.patterns || resolved.patterns.length === 0) return text;
|
|
715
|
+
return applyPatterns(text, resolved.patterns, resolved.censor ?? DEFAULT_CENSOR);
|
|
603
716
|
}
|
|
604
717
|
/**
|
|
605
718
|
* Apply redaction to a log payload (top-level call convenience wrapper).
|
|
@@ -639,11 +752,21 @@ const ALWAYS_EMIT_LEVELS = new Set([
|
|
|
639
752
|
"warn",
|
|
640
753
|
"fatal"
|
|
641
754
|
]);
|
|
755
|
+
const MAX_CACHED_TRACE_ID_LENGTH = 256;
|
|
756
|
+
function isCacheableTraceId(id) {
|
|
757
|
+
if (typeof id !== "string" || id.length === 0 || id.length > MAX_CACHED_TRACE_ID_LENGTH) return false;
|
|
758
|
+
for (let i = 0; i < id.length; i++) {
|
|
759
|
+
const c = id.charCodeAt(i);
|
|
760
|
+
if (c < 32 || c >= 127 && c <= 159) return false;
|
|
761
|
+
}
|
|
762
|
+
return true;
|
|
763
|
+
}
|
|
642
764
|
var Sampler = class {
|
|
643
765
|
constructor(config, onStats) {
|
|
644
766
|
this.traceDecisions = /* @__PURE__ */ new Map();
|
|
645
767
|
this.maxTrackedTraces = 1e5;
|
|
646
768
|
this.traceTtlMs = 5 * 6e4;
|
|
769
|
+
this.traceMaxLifetimeMs = 60 * 6e4;
|
|
647
770
|
this._tokenBucket = 0;
|
|
648
771
|
this._lastRefillMs = Date.now();
|
|
649
772
|
this._adaptiveWindow = [];
|
|
@@ -763,13 +886,15 @@ var Sampler = class {
|
|
|
763
886
|
}
|
|
764
887
|
/**
|
|
765
888
|
* 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.
|
|
889
|
+
* idle past the TTL, or older than the hard lifetime, are re-decided; the least
|
|
890
|
+
* recently used entry is evicted once the cap is reached. IDs that are empty,
|
|
891
|
+
* too long or contain control characters are sampled independently and never cached.
|
|
768
892
|
*/
|
|
769
893
|
_decideForTrace(traceId, level) {
|
|
894
|
+
if (!isCacheableTraceId(traceId)) return this._sampleByRate(level);
|
|
770
895
|
const now = Date.now();
|
|
771
896
|
const known = this.traceDecisions.get(traceId);
|
|
772
|
-
if (known && now - known.seenAt <= this.traceTtlMs) {
|
|
897
|
+
if (known && now - known.seenAt <= this.traceTtlMs && now - known.firstAt <= this.traceMaxLifetimeMs) {
|
|
773
898
|
this.traceDecisions.delete(traceId);
|
|
774
899
|
known.seenAt = now;
|
|
775
900
|
this.traceDecisions.set(traceId, known);
|
|
@@ -779,6 +904,7 @@ var Sampler = class {
|
|
|
779
904
|
this.traceDecisions.delete(traceId);
|
|
780
905
|
this.traceDecisions.set(traceId, {
|
|
781
906
|
emit,
|
|
907
|
+
firstAt: now,
|
|
782
908
|
seenAt: now
|
|
783
909
|
});
|
|
784
910
|
if (this.traceDecisions.size > this.maxTrackedTraces) {
|
|
@@ -942,318 +1068,6 @@ function resetShutdownHandlers() {
|
|
|
942
1068
|
shutdownInProgress = false;
|
|
943
1069
|
}
|
|
944
1070
|
|
|
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
1071
|
//#endregion
|
|
1258
1072
|
//#region src/core/logitron-logger.ts
|
|
1259
1073
|
const _fastStringifyEntry = buildFastStringify({
|
|
@@ -1816,9 +1630,21 @@ var LogixiaLogger = class LogixiaLogger {
|
|
|
1816
1630
|
...mergedData
|
|
1817
1631
|
} : mergedData;
|
|
1818
1632
|
let payload;
|
|
1819
|
-
if (rawPayload !== void 0 && rawPayload !== null)
|
|
1633
|
+
if (rawPayload !== void 0 && rawPayload !== null) if (this._hasRedact) try {
|
|
1634
|
+
payload = applyRedaction(rawPayload, this.config.redact) ?? rawPayload;
|
|
1635
|
+
} catch (error) {
|
|
1636
|
+
internalError("Redaction failed", error);
|
|
1637
|
+
payload = { redaction: REDACTION_FAILED };
|
|
1638
|
+
}
|
|
1639
|
+
else payload = rawPayload;
|
|
1820
1640
|
const traceId = this.config.traceId ? TraceContext.instance.getCurrentTraceId() ?? this.fallbackTraceId : void 0;
|
|
1821
|
-
|
|
1641
|
+
let safeMessage = message;
|
|
1642
|
+
if (this._hasRedact) try {
|
|
1643
|
+
safeMessage = applyRedactionToString(message, this.config.redact);
|
|
1644
|
+
} catch (error) {
|
|
1645
|
+
internalError("Redaction failed", error);
|
|
1646
|
+
safeMessage = REDACTION_FAILED;
|
|
1647
|
+
}
|
|
1822
1648
|
const entry = {
|
|
1823
1649
|
timestamp: nowIso(),
|
|
1824
1650
|
level,
|
|
@@ -1889,9 +1715,9 @@ var LogixiaLogger = class LogixiaLogger {
|
|
|
1889
1715
|
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
1716
|
if (this._fieldCache.get("level") !== false) formatted += this._formattedLevels.get(entry.level) ?? `[${entry.level.toUpperCase()}] `;
|
|
1891
1717
|
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;
|
|
1718
|
+
if (entry.traceId && this._fieldCache.get("traceId") !== false) formatted += `${cyan}[${stripControlChars(String(entry.traceId))}]${reset} `;
|
|
1719
|
+
if (entry.context && this._fieldCache.get("context") !== false) formatted += `${yellow}[${stripControlChars(String(entry.context))}]${reset} `;
|
|
1720
|
+
if (this._fieldCache.get("message") !== false) formatted += stripControlChars(safeToString(entry.message));
|
|
1895
1721
|
if (entry.payload !== void 0 && this._fieldCache.get("payload") !== false) formatted += ` ${stringifyForLog(entry.payload)}`;
|
|
1896
1722
|
return formatted;
|
|
1897
1723
|
}
|
|
@@ -1941,682 +1767,218 @@ function createLogger(config, context) {
|
|
|
1941
1767
|
}
|
|
1942
1768
|
|
|
1943
1769
|
//#endregion
|
|
1944
|
-
//#region
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
}
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
//#endregion
|
|
1959
|
-
//#region src/core/logitron-nestjs.service.ts
|
|
1960
|
-
var _LogixiaLoggerService;
|
|
1961
|
-
let LogixiaLoggerService = _LogixiaLoggerService = class LogixiaLoggerService$1 {
|
|
1962
|
-
constructor(config) {
|
|
1963
|
-
this._mergedConfig = {
|
|
1964
|
-
appName: "NestJS-App",
|
|
1965
|
-
environment: "development",
|
|
1966
|
-
traceId: true,
|
|
1967
|
-
format: {
|
|
1968
|
-
timestamp: true,
|
|
1969
|
-
colorize: true,
|
|
1970
|
-
json: false
|
|
1971
|
-
},
|
|
1972
|
-
silent: false,
|
|
1973
|
-
levelOptions: {
|
|
1974
|
-
level: LogLevel.INFO,
|
|
1975
|
-
levels: {
|
|
1976
|
-
error: 0,
|
|
1977
|
-
warn: 1,
|
|
1978
|
-
log: 2,
|
|
1979
|
-
debug: 3,
|
|
1980
|
-
verbose: 4
|
|
1981
|
-
},
|
|
1982
|
-
colors: {
|
|
1983
|
-
error: "red",
|
|
1984
|
-
warn: "yellow",
|
|
1985
|
-
log: "green",
|
|
1986
|
-
debug: "blue",
|
|
1987
|
-
verbose: "cyan"
|
|
1988
|
-
}
|
|
1989
|
-
},
|
|
1990
|
-
fields: {
|
|
1991
|
-
timestamp: "[yyyy-mm-dd HH:MM:ss.MS]",
|
|
1992
|
-
level: "[log_level]",
|
|
1993
|
-
appName: "[app_name]",
|
|
1994
|
-
traceId: "[trace_id]",
|
|
1995
|
-
message: "[message]",
|
|
1996
|
-
payload: "[payload]",
|
|
1997
|
-
timeTaken: "[time_taken_MS]"
|
|
1998
|
-
},
|
|
1999
|
-
...config
|
|
2000
|
-
};
|
|
2001
|
-
this.logger = new LogixiaLogger(this._mergedConfig);
|
|
2002
|
-
this._createCustomLevelMethods();
|
|
2003
|
-
}
|
|
2004
|
-
_createCustomLevelMethods() {
|
|
2005
|
-
var _this$_mergedConfig$l;
|
|
2006
|
-
const levels = (_this$_mergedConfig$l = this._mergedConfig.levelOptions) === null || _this$_mergedConfig$l === void 0 ? void 0 : _this$_mergedConfig$l.levels;
|
|
2007
|
-
if (!levels) return;
|
|
2008
|
-
for (const levelName of Object.keys(levels)) {
|
|
2009
|
-
const lower = levelName.toLowerCase();
|
|
2010
|
-
if (typeof this[lower] !== "undefined") continue;
|
|
2011
|
-
this[lower] = async (message, data) => {
|
|
2012
|
-
return this.logger.logLevel(lower, message, data);
|
|
2013
|
-
};
|
|
2014
|
-
}
|
|
2015
|
-
}
|
|
2016
|
-
/**
|
|
2017
|
-
* NestJS `LoggerService.log` — void, string context.
|
|
2018
|
-
* Maps internally to `info`.
|
|
2019
|
-
*
|
|
2020
|
-
* @example `logger.log('User signed up', 'AuthService')`
|
|
2021
|
-
*/
|
|
2022
|
-
log(message, context) {
|
|
2023
|
-
this.setContextIfProvided(context);
|
|
2024
|
-
this.logger.info(this.formatMessage(message)).catch((err) => internalError("LogixiaLoggerService.log failed", err));
|
|
2025
|
-
}
|
|
2026
|
-
/**
|
|
2027
|
-
* Native async `info` — structured data, returns `Promise<void>`.
|
|
2028
|
-
*
|
|
2029
|
-
* @example `await logger.info('User signed up', { userId: 'u_abc' })`
|
|
2030
|
-
*/
|
|
2031
|
-
async info(message, data) {
|
|
2032
|
-
return this.logger.info(message, data);
|
|
2033
|
-
}
|
|
2034
|
-
error(message, dataOrTrace, context) {
|
|
2035
|
-
if (typeof dataOrTrace === "object" && dataOrTrace !== null) return message instanceof Error ? this.logger.error(message, dataOrTrace) : this.logger.error(this.formatMessage(message), dataOrTrace);
|
|
2036
|
-
this.setContextIfProvided(context);
|
|
2037
|
-
const errorData = {};
|
|
2038
|
-
if (typeof dataOrTrace === "string" && dataOrTrace) errorData.stack = dataOrTrace;
|
|
2039
|
-
(message instanceof Error ? this.logger.error(message, errorData) : this.logger.error(this.formatMessage(message), errorData)).catch((err) => internalError("LogixiaLoggerService.error failed", err));
|
|
2040
|
-
}
|
|
2041
|
-
warn(message, dataOrContext) {
|
|
2042
|
-
if (typeof dataOrContext === "object" && dataOrContext !== null) return this.logger.warn(this.formatMessage(message), dataOrContext);
|
|
2043
|
-
this.setContextIfProvided(typeof dataOrContext === "string" ? dataOrContext : void 0);
|
|
2044
|
-
this.logger.warn(this.formatMessage(message)).catch((err) => internalError("LogixiaLoggerService.warn failed", err));
|
|
2045
|
-
}
|
|
2046
|
-
debug(message, dataOrContext) {
|
|
2047
|
-
if (typeof dataOrContext === "object" && dataOrContext !== null) return this.logger.debug(this.formatMessage(message), dataOrContext);
|
|
2048
|
-
this.setContextIfProvided(typeof dataOrContext === "string" ? dataOrContext : void 0);
|
|
2049
|
-
this.logger.debug(this.formatMessage(message)).catch((err) => internalError("LogixiaLoggerService.debug failed", err));
|
|
2050
|
-
}
|
|
2051
|
-
verbose(message, dataOrContext) {
|
|
2052
|
-
if (typeof dataOrContext === "object" && dataOrContext !== null) return this.logger.trace(this.formatMessage(message), dataOrContext);
|
|
2053
|
-
this.setContextIfProvided(typeof dataOrContext === "string" ? dataOrContext : void 0);
|
|
2054
|
-
this.logger.trace(this.formatMessage(message)).catch((err) => internalError("LogixiaLoggerService.verbose failed", err));
|
|
2055
|
-
}
|
|
2056
|
-
/**
|
|
2057
|
-
* Native async `trace` — lowest verbosity level, structured data.
|
|
2058
|
-
*/
|
|
2059
|
-
async trace(message, data) {
|
|
2060
|
-
return this.logger.trace(message, data);
|
|
2061
|
-
}
|
|
2062
|
-
/**
|
|
2063
|
-
* Log at any named level with structured data.
|
|
2064
|
-
*/
|
|
2065
|
-
logLevel(level, message, data) {
|
|
2066
|
-
return this.logger.logLevel(level, message, data);
|
|
2067
|
-
}
|
|
2068
|
-
time(label) {
|
|
2069
|
-
this.logger.time(label);
|
|
2070
|
-
}
|
|
2071
|
-
async timeEnd(label) {
|
|
2072
|
-
return this.logger.timeEnd(label);
|
|
2073
|
-
}
|
|
2074
|
-
async timeAsync(label, fn) {
|
|
2075
|
-
return this.logger.timeAsync(label, fn);
|
|
2076
|
-
}
|
|
2077
|
-
setContext(context) {
|
|
2078
|
-
const coerced = typeof context === "string" ? context : safeToString(context);
|
|
2079
|
-
this.context = coerced;
|
|
2080
|
-
this.logger.setContext(coerced);
|
|
2081
|
-
}
|
|
2082
|
-
getContext() {
|
|
2083
|
-
return this.context;
|
|
2084
|
-
}
|
|
2085
|
-
setLevel(level) {
|
|
2086
|
-
this.logger.setLevel(level);
|
|
2087
|
-
}
|
|
2088
|
-
getLevel() {
|
|
2089
|
-
return this.logger.getLevel();
|
|
2090
|
-
}
|
|
2091
|
-
child(context, data) {
|
|
2092
|
-
const childService = new _LogixiaLoggerService(this._mergedConfig);
|
|
2093
|
-
childService.logger = this.logger.child(context, data);
|
|
2094
|
-
childService.context = context;
|
|
2095
|
-
return childService;
|
|
2096
|
-
}
|
|
2097
|
-
getCurrentTraceId() {
|
|
2098
|
-
return TraceContext.instance.getCurrentTraceId();
|
|
2099
|
-
}
|
|
2100
|
-
/** Returns the AsyncLocalStorage key currently used to store the trace ID. */
|
|
2101
|
-
get traceContextKey() {
|
|
2102
|
-
return getTraceContextKey();
|
|
2103
|
-
}
|
|
2104
|
-
async close() {
|
|
2105
|
-
return this.logger.close();
|
|
2106
|
-
}
|
|
2107
|
-
static create(config) {
|
|
2108
|
-
return new _LogixiaLoggerService(config);
|
|
2109
|
-
}
|
|
2110
|
-
getLogger() {
|
|
2111
|
-
return this.logger;
|
|
2112
|
-
}
|
|
2113
|
-
setContextIfProvided(context) {
|
|
2114
|
-
if (typeof context !== "string" || context.length === 0) return;
|
|
2115
|
-
if (context !== this.context) this.setContext(context);
|
|
2116
|
-
}
|
|
2117
|
-
formatMessage(message) {
|
|
2118
|
-
if (typeof message === "string") return message;
|
|
2119
|
-
return safeToString(message);
|
|
2120
|
-
}
|
|
2121
|
-
};
|
|
2122
|
-
LogixiaLoggerService = _LogixiaLoggerService = __decorate([Injectable({ scope: Scope.TRANSIENT }), __decorateMetadata("design:paramtypes", [Object])], LogixiaLoggerService);
|
|
2123
|
-
|
|
2124
|
-
//#endregion
|
|
2125
|
-
//#region src/core/kafka-trace.interceptor.ts
|
|
2126
|
-
var _KafkaTraceInterceptor;
|
|
2127
|
-
let KafkaTraceInterceptor = class KafkaTraceInterceptor$1 {
|
|
2128
|
-
static {
|
|
2129
|
-
_KafkaTraceInterceptor = this;
|
|
2130
|
-
}
|
|
2131
|
-
static #_ = this.metrics = {
|
|
2132
|
-
accepted: 0,
|
|
2133
|
-
acceptedWithoutTrace: 0,
|
|
2134
|
-
dropped: 0
|
|
2135
|
-
};
|
|
2136
|
-
/** Reset counters (tests). */
|
|
2137
|
-
static resetMetrics() {
|
|
2138
|
-
_KafkaTraceInterceptor.metrics.accepted = 0;
|
|
2139
|
-
_KafkaTraceInterceptor.metrics.acceptedWithoutTrace = 0;
|
|
2140
|
-
_KafkaTraceInterceptor.metrics.dropped = 0;
|
|
2141
|
-
}
|
|
2142
|
-
/**
|
|
2143
|
-
* @param config - TraceIdConfig options (extractor keys, contextKey, etc.)
|
|
2144
|
-
* @param requireTraceId - When true, messages with no traceId are silently skipped
|
|
2145
|
-
* (EMPTY Observable — message is ack'd, consumer stays alive).
|
|
2146
|
-
* A WARN is logged AND `KafkaTraceInterceptor.metrics.dropped`
|
|
2147
|
-
* increments so the missing traceId is observable end-to-end.
|
|
2148
|
-
* Default: false (handler runs without trace context).
|
|
2149
|
-
*/
|
|
2150
|
-
constructor(config, requireTraceId = false) {
|
|
2151
|
-
this.config = config;
|
|
2152
|
-
this.requireTraceId = requireTraceId;
|
|
2153
|
-
this.ctx = TraceContext.instance;
|
|
2154
|
-
this.config = {
|
|
2155
|
-
enabled: true,
|
|
2156
|
-
contextKey: "traceId",
|
|
2157
|
-
extractor: {
|
|
2158
|
-
body: [
|
|
2159
|
-
"traceId",
|
|
2160
|
-
"trace_id",
|
|
2161
|
-
"x-trace-id"
|
|
2162
|
-
],
|
|
2163
|
-
header: ["x-trace-id", "trace-id"]
|
|
2164
|
-
},
|
|
2165
|
-
...config
|
|
2166
|
-
};
|
|
2167
|
-
}
|
|
2168
|
-
intercept(context, next) {
|
|
2169
|
-
var _this$config;
|
|
2170
|
-
if (!((_this$config = this.config) === null || _this$config === void 0 ? void 0 : _this$config.enabled)) return next.handle();
|
|
2171
|
-
const rpcContext = context.switchToRpc();
|
|
2172
|
-
const data = rpcContext.getData();
|
|
2173
|
-
const rpcData = rpcContext.getContext();
|
|
2174
|
-
let traceId;
|
|
2175
|
-
if (this.config.extractor) traceId = extractTraceId({
|
|
2176
|
-
body: data,
|
|
2177
|
-
headers: (rpcData === null || rpcData === void 0 ? void 0 : rpcData.headers) ?? {},
|
|
2178
|
-
query: {},
|
|
2179
|
-
params: {}
|
|
2180
|
-
}, this.config.extractor);
|
|
2181
|
-
if (!traceId) traceId = this.ctx.getCurrentTraceId();
|
|
2182
|
-
if (!traceId) {
|
|
2183
|
-
if (this.requireTraceId) {
|
|
2184
|
-
var _LogixiaLoggerModule$;
|
|
2185
|
-
_KafkaTraceInterceptor.metrics.dropped++;
|
|
2186
|
-
(_LogixiaLoggerModule$ = LogixiaLoggerModule.getGlobalLogger()) === null || _LogixiaLoggerModule$ === void 0 || _LogixiaLoggerModule$.warn(`[KafkaTraceInterceptor] Missing traceId on topic "${rpcData === null || rpcData === void 0 ? void 0 : rpcData.topic}" — message skipped.`);
|
|
2187
|
-
return EMPTY;
|
|
2188
|
-
}
|
|
2189
|
-
_KafkaTraceInterceptor.metrics.acceptedWithoutTrace++;
|
|
2190
|
-
return next.handle();
|
|
2191
|
-
}
|
|
2192
|
-
_KafkaTraceInterceptor.metrics.accepted++;
|
|
2193
|
-
const kafkaContext = {
|
|
2194
|
-
messageType: "kafka",
|
|
2195
|
-
topic: rpcData === null || rpcData === void 0 ? void 0 : rpcData.topic,
|
|
2196
|
-
partition: rpcData === null || rpcData === void 0 ? void 0 : rpcData.partition,
|
|
2197
|
-
offset: rpcData === null || rpcData === void 0 ? void 0 : rpcData.offset,
|
|
2198
|
-
key: rpcData === null || rpcData === void 0 ? void 0 : rpcData.key,
|
|
2199
|
-
timestamp: rpcData === null || rpcData === void 0 ? void 0 : rpcData.timestamp
|
|
2200
|
-
};
|
|
2201
|
-
return new Observable((subscriber) => {
|
|
2202
|
-
let inner;
|
|
2203
|
-
this.ctx.run(traceId, () => {
|
|
2204
|
-
inner = next.handle().subscribe({
|
|
2205
|
-
next: (value) => subscriber.next(value),
|
|
2206
|
-
error: (err) => subscriber.error(err),
|
|
2207
|
-
complete: () => subscriber.complete()
|
|
2208
|
-
});
|
|
2209
|
-
}, kafkaContext);
|
|
2210
|
-
return () => inner === null || inner === void 0 ? void 0 : inner.unsubscribe();
|
|
2211
|
-
});
|
|
1770
|
+
//#region src/exceptions/exception.ts
|
|
1771
|
+
var LogixiaException = class extends Error {
|
|
1772
|
+
constructor(options) {
|
|
1773
|
+
super(options.message, { cause: options.cause });
|
|
1774
|
+
this.name = "LogixiaException";
|
|
1775
|
+
this.errorCode = options.code;
|
|
1776
|
+
this.errorType = options.type;
|
|
1777
|
+
this.httpStatus = options.httpStatus;
|
|
1778
|
+
this.param = options.param;
|
|
1779
|
+
this.details = options.details;
|
|
1780
|
+
this.docUrl = options.docUrl;
|
|
1781
|
+
this.metadata = options.metadata;
|
|
1782
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
2212
1783
|
}
|
|
2213
1784
|
};
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
1785
|
+
/**
|
|
1786
|
+
* Returns `true` when `value` is a `LogixiaException` instance.
|
|
1787
|
+
*
|
|
1788
|
+
* Useful in exception filters or middleware that need to distinguish a
|
|
1789
|
+
* `LogixiaException` from a plain `Error` or a framework `HttpException`.
|
|
1790
|
+
*
|
|
1791
|
+
* @example
|
|
1792
|
+
* ```ts
|
|
1793
|
+
* if (isLogixiaException(err)) {
|
|
1794
|
+
* console.log(err.errorCode, err.httpStatus);
|
|
1795
|
+
* }
|
|
1796
|
+
* ```
|
|
1797
|
+
*/
|
|
1798
|
+
function isLogixiaException(value) {
|
|
1799
|
+
return value instanceof LogixiaException;
|
|
2222
1800
|
}
|
|
2223
1801
|
|
|
2224
1802
|
//#endregion
|
|
2225
|
-
//#region src/
|
|
2226
|
-
/** Default response header used to echo the resolved traceId back to the caller. */
|
|
2227
|
-
const DEFAULT_TRACE_RESPONSE_HEADER = "X-Trace-Id";
|
|
1803
|
+
//#region src/exceptions/builder.ts
|
|
2228
1804
|
/**
|
|
2229
|
-
*
|
|
2230
|
-
*
|
|
2231
|
-
*
|
|
2232
|
-
*
|
|
1805
|
+
* Generates a trace ID via the shared {@link TraceContext} generator.
|
|
1806
|
+
*
|
|
1807
|
+
* Delegates to `TraceContext.instance.generate()` so any custom generator
|
|
1808
|
+
* configured on `TraceIdConfig.generator` is respected — avoids the silent
|
|
1809
|
+
* "builder has its own UUID source" divergence this module had previously.
|
|
1810
|
+
*
|
|
1811
|
+
* @example `'550e8400-e29b-41d4-a716-446655440000'`
|
|
2233
1812
|
*/
|
|
2234
|
-
function
|
|
2235
|
-
|
|
2236
|
-
return (config === null || config === void 0 ? void 0 : config.responseHeader) ?? DEFAULT_TRACE_RESPONSE_HEADER;
|
|
1813
|
+
function generateTraceId() {
|
|
1814
|
+
return TraceContext.instance.generate();
|
|
2237
1815
|
}
|
|
1816
|
+
/** @deprecated Use `generateTraceId` instead. */
|
|
1817
|
+
const generateRequestId = generateTraceId;
|
|
2238
1818
|
/**
|
|
2239
|
-
*
|
|
2240
|
-
*
|
|
2241
|
-
* res.setHeader()), and on a closed/sent response setHeader throws — neither
|
|
2242
|
-
* should crash the request. The trace ID is still propagated via async context.
|
|
1819
|
+
* Maps an HTTP status code to a human-friendly error type string.
|
|
1820
|
+
* Used as a fallback when the exception is a generic `HttpException`.
|
|
2243
1821
|
*/
|
|
2244
|
-
function
|
|
2245
|
-
|
|
2246
|
-
if (
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
1822
|
+
function httpStatusToType(status) {
|
|
1823
|
+
if (status === 400) return "api_error";
|
|
1824
|
+
if (status === 401) return "authentication_error";
|
|
1825
|
+
if (status === 402) return "payment_error";
|
|
1826
|
+
if (status === 403) return "authorization_error";
|
|
1827
|
+
if (status === 404) return "not_found_error";
|
|
1828
|
+
if (status === 408) return "timeout_error";
|
|
1829
|
+
if (status === 409) return "conflict_error";
|
|
1830
|
+
if (status === 422) return "validation_error";
|
|
1831
|
+
if (status === 429) return "rate_limit_error";
|
|
1832
|
+
if (status >= 500) return "server_error";
|
|
1833
|
+
if (status >= 400) return "api_error";
|
|
1834
|
+
return "server_error";
|
|
2251
1835
|
}
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
else internalWarn("TraceIdConfig.generator returned a non-string/empty value — using built-in generator.");
|
|
2281
|
-
}
|
|
2282
|
-
if (!traceId) traceId = this.ctx.generate();
|
|
2283
|
-
req.traceId = traceId;
|
|
2284
|
-
const header = resolveResponseHeader(this.config);
|
|
2285
|
-
if (header) writeTraceHeader(res, header, traceId);
|
|
2286
|
-
this.ctx.run(traceId, () => next(), {
|
|
2287
|
-
method: req.method,
|
|
2288
|
-
url: req.url,
|
|
2289
|
-
userAgent: req.get("User-Agent"),
|
|
2290
|
-
ip: req.ip || ((_req$socket = req.socket) === null || _req$socket === void 0 ? void 0 : _req$socket.remoteAddress) || ((_req$connection = req.connection) === null || _req$connection === void 0 ? void 0 : _req$connection.remoteAddress)
|
|
2291
|
-
});
|
|
2292
|
-
}
|
|
2293
|
-
};
|
|
2294
|
-
TraceMiddleware = __decorate([
|
|
2295
|
-
Injectable(),
|
|
2296
|
-
__decorateParam(0, Optional()),
|
|
2297
|
-
__decorateMetadata("design:paramtypes", [Object])
|
|
2298
|
-
], TraceMiddleware);
|
|
2299
|
-
|
|
2300
|
-
//#endregion
|
|
2301
|
-
//#region src/core/websocket-trace.interceptor.ts
|
|
2302
|
-
let WebSocketTraceInterceptor = class WebSocketTraceInterceptor$1 {
|
|
2303
|
-
constructor(config) {
|
|
2304
|
-
this.config = config;
|
|
2305
|
-
this.ctx = TraceContext.instance;
|
|
2306
|
-
this.config = {
|
|
2307
|
-
enabled: true,
|
|
2308
|
-
contextKey: "traceId",
|
|
2309
|
-
extractor: {
|
|
2310
|
-
body: [
|
|
2311
|
-
"traceId",
|
|
2312
|
-
"trace_id",
|
|
2313
|
-
"x-trace-id"
|
|
2314
|
-
],
|
|
2315
|
-
header: ["x-trace-id", "trace-id"],
|
|
2316
|
-
query: ["traceId", "trace_id"]
|
|
2317
|
-
},
|
|
2318
|
-
...config
|
|
2319
|
-
};
|
|
2320
|
-
}
|
|
2321
|
-
intercept(context, next) {
|
|
2322
|
-
var _this$config, _client$handshake3;
|
|
2323
|
-
if (!((_this$config = this.config) === null || _this$config === void 0 ? void 0 : _this$config.enabled)) return next.handle();
|
|
2324
|
-
const wsContext = context.switchToWs();
|
|
2325
|
-
const data = wsContext.getData();
|
|
2326
|
-
const client = wsContext.getClient();
|
|
2327
|
-
let traceId;
|
|
2328
|
-
if (this.config.extractor) {
|
|
2329
|
-
var _client$handshake, _client$handshake2;
|
|
2330
|
-
traceId = extractTraceId({
|
|
2331
|
-
body: data,
|
|
2332
|
-
headers: (client === null || client === void 0 || (_client$handshake = client.handshake) === null || _client$handshake === void 0 ? void 0 : _client$handshake.headers) || {},
|
|
2333
|
-
query: (client === null || client === void 0 || (_client$handshake2 = client.handshake) === null || _client$handshake2 === void 0 ? void 0 : _client$handshake2.query) || {},
|
|
2334
|
-
params: {}
|
|
2335
|
-
}, this.config.extractor);
|
|
2336
|
-
}
|
|
2337
|
-
if (!traceId) traceId = this.ctx.getCurrentTraceId();
|
|
2338
|
-
if (!traceId) return next.handle();
|
|
2339
|
-
const wsContextData = {
|
|
2340
|
-
messageType: "websocket",
|
|
2341
|
-
event: data === null || data === void 0 ? void 0 : data.event,
|
|
2342
|
-
socketId: client === null || client === void 0 ? void 0 : client.id,
|
|
2343
|
-
rooms: (client === null || client === void 0 ? void 0 : client.rooms) ? Array.from(client.rooms) : [],
|
|
2344
|
-
clientAddress: client === null || client === void 0 || (_client$handshake3 = client.handshake) === null || _client$handshake3 === void 0 ? void 0 : _client$handshake3.address
|
|
2345
|
-
};
|
|
2346
|
-
return new Observable((observer) => {
|
|
2347
|
-
let inner;
|
|
2348
|
-
this.ctx.run(traceId, () => {
|
|
2349
|
-
inner = next.handle().subscribe({
|
|
2350
|
-
next: (value) => observer.next(value),
|
|
2351
|
-
error: (err) => observer.error(err),
|
|
2352
|
-
complete: () => observer.complete()
|
|
2353
|
-
});
|
|
2354
|
-
}, wsContextData);
|
|
2355
|
-
return () => inner === null || inner === void 0 ? void 0 : inner.unsubscribe();
|
|
2356
|
-
});
|
|
2357
|
-
}
|
|
2358
|
-
};
|
|
2359
|
-
WebSocketTraceInterceptor = __decorate([Injectable(), __decorateMetadata("design:paramtypes", [Object])], WebSocketTraceInterceptor);
|
|
2360
|
-
|
|
2361
|
-
//#endregion
|
|
2362
|
-
//#region src/core/logitron-logger.module.ts
|
|
2363
|
-
var _LogixiaLoggerModule;
|
|
2364
|
-
const DEFAULT_ROUTES = [{
|
|
2365
|
-
path: "*",
|
|
2366
|
-
method: RequestMethod.ALL
|
|
2367
|
-
}];
|
|
2368
|
-
const LOGIXIA_LOGGER_CONFIG = "LOGIXIA_LOGGER_CONFIG";
|
|
2369
|
-
const LOGIXIA_TRACE_CONFIG = "TRACE_CONFIG";
|
|
2370
|
-
const LOGIXIA_LOGGER_PREFIX = "LOGIXIA_LOGGER_";
|
|
2371
|
-
let LogixiaLoggerModule = class LogixiaLoggerModule$1 {
|
|
2372
|
-
static {
|
|
2373
|
-
_LogixiaLoggerModule = this;
|
|
2374
|
-
}
|
|
2375
|
-
constructor() {
|
|
2376
|
-
this.config = {};
|
|
2377
|
-
}
|
|
2378
|
-
static #_ = this.loggerConfig = {};
|
|
2379
|
-
static #_2 = this._globalLogger = null;
|
|
1836
|
+
/**
|
|
1837
|
+
* Duck-type check for NestJS `HttpException`.
|
|
1838
|
+
* Avoids a hard import on `@nestjs/common` so the builder is usable outside NestJS.
|
|
1839
|
+
*/
|
|
1840
|
+
function isHttpException(value) {
|
|
1841
|
+
return typeof value === "object" && value !== null && typeof value["getStatus"] === "function" && typeof value["getResponse"] === "function";
|
|
1842
|
+
}
|
|
1843
|
+
/**
|
|
1844
|
+
* Builds the optional `debug` block from an error.
|
|
1845
|
+
* Returns `undefined` when there is nothing useful to include.
|
|
1846
|
+
*/
|
|
1847
|
+
function buildDebug(error, service, durationMs, expose) {
|
|
1848
|
+
if (expose.debug !== true) return void 0;
|
|
1849
|
+
const stack = error instanceof Error ? error.stack : void 0;
|
|
1850
|
+
const causeRaw = error instanceof Error ? error.cause : void 0;
|
|
1851
|
+
let cause;
|
|
1852
|
+
if (expose.cause !== true) cause = void 0;
|
|
1853
|
+
else if (causeRaw instanceof Error) cause = causeRaw.message;
|
|
1854
|
+
else if (causeRaw !== void 0 && causeRaw !== null) cause = String(causeRaw);
|
|
1855
|
+
if (!stack && !cause && !service && durationMs === void 0) return void 0;
|
|
1856
|
+
return {
|
|
1857
|
+
...stack !== void 0 ? { stack } : {},
|
|
1858
|
+
...cause !== void 0 ? { cause } : {},
|
|
1859
|
+
...service !== void 0 ? { service } : {},
|
|
1860
|
+
...durationMs !== void 0 ? { duration_ms: durationMs } : {}
|
|
1861
|
+
};
|
|
1862
|
+
}
|
|
1863
|
+
var ErrorResponseBuilder = class {
|
|
2380
1864
|
/**
|
|
2381
|
-
*
|
|
2382
|
-
*
|
|
2383
|
-
* Called from the module's forRoot / forRootAsync factory. If the module is
|
|
2384
|
-
* initialised more than once in the same process (nested DI context, test
|
|
2385
|
-
* harness creating multiple apps, hot reload, etc.) a warning is written to
|
|
2386
|
-
* stderr and the first logger wins — silently overwriting would allow the
|
|
2387
|
-
* newer instance's transport config to replace the live one while the old
|
|
2388
|
-
* one is still being used by registered shutdown hooks, decorators, etc.
|
|
1865
|
+
* Build a `LogixiaErrorResponse` from any thrown value.
|
|
2389
1866
|
*
|
|
2390
|
-
*
|
|
2391
|
-
|
|
2392
|
-
static _setGlobalLogger(service) {
|
|
2393
|
-
if (_LogixiaLoggerModule._globalLogger !== null) {
|
|
2394
|
-
internalWarn("LogixiaLoggerModule.forRoot() was called more than once — ignoring the second init. If this is intentional (e.g. in tests), call LogixiaLoggerModule._resetGlobalLogger() first.");
|
|
2395
|
-
return;
|
|
2396
|
-
}
|
|
2397
|
-
_LogixiaLoggerModule._globalLogger = service;
|
|
2398
|
-
}
|
|
2399
|
-
/** @internal Clear the global logger. Tests only. */
|
|
2400
|
-
static _resetGlobalLogger() {
|
|
2401
|
-
_LogixiaLoggerModule._globalLogger = null;
|
|
2402
|
-
}
|
|
2403
|
-
/**
|
|
2404
|
-
* Returns the global LogixiaLoggerService instance that was created when the
|
|
2405
|
-
* module booted. Useful for logging outside of NestJS DI — utility functions,
|
|
2406
|
-
* plain scripts, decorators — without injecting the service everywhere.
|
|
1867
|
+
* @param params - See `BuildParams`.
|
|
1868
|
+
* @returns The unified error response and the HTTP status code to send.
|
|
2407
1869
|
*
|
|
2408
|
-
*
|
|
2409
|
-
*
|
|
1870
|
+
* @remarks
|
|
1871
|
+
* `traceId` does not need to be supplied by the caller in most cases — the
|
|
1872
|
+
* builder reads `TraceContext.instance.getCurrentTraceId()` internally and
|
|
1873
|
+
* falls back to the explicit `traceId` argument only when AsyncLocalStorage
|
|
1874
|
+
* is empty. If neither source yields a value, `meta.trace_id` is omitted.
|
|
2410
1875
|
*
|
|
2411
|
-
* @example
|
|
1876
|
+
* @example In a NestJS exception filter
|
|
2412
1877
|
* ```ts
|
|
2413
|
-
*
|
|
2414
|
-
*
|
|
1878
|
+
* const { response, httpStatus } = ErrorResponseBuilder.build<AppCode, AppType>({
|
|
1879
|
+
* exception,
|
|
1880
|
+
* // Omit traceId — it will be picked up from ALS automatically.
|
|
1881
|
+
* path: request.url,
|
|
1882
|
+
* service: process.env.SERVICE_NAME,
|
|
1883
|
+
* startTime: request.startTime,
|
|
1884
|
+
* });
|
|
2415
1885
|
*
|
|
2416
|
-
*
|
|
2417
|
-
*
|
|
1886
|
+
* if (process.env.NODE_ENV === 'production') delete response.debug;
|
|
1887
|
+
* // Echo the resolved traceId back on whatever header your TraceIdConfig says —
|
|
1888
|
+
* // do NOT hardcode 'X-Trace-Id', use `resolveResponseHeader(config)` instead.
|
|
1889
|
+
* if (response.meta.trace_id) {
|
|
1890
|
+
* response.setHeader(resolveResponseHeader(config) ?? 'X-Trace-Id', response.meta.trace_id);
|
|
2418
1891
|
* }
|
|
1892
|
+
* response.status(httpStatus).json(response);
|
|
2419
1893
|
* ```
|
|
2420
1894
|
*/
|
|
2421
|
-
static
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
let resolvedTraceConfig;
|
|
2427
|
-
if (typeof _LogixiaLoggerModule.loggerConfig.traceId === "object") resolvedTraceConfig = _LogixiaLoggerModule.loggerConfig.traceId;
|
|
2428
|
-
else if (_LogixiaLoggerModule.loggerConfig.traceId === true) resolvedTraceConfig = {
|
|
2429
|
-
enabled: true,
|
|
2430
|
-
contextKey: "traceId",
|
|
2431
|
-
generator: () => TraceContext.instance.generate()
|
|
1895
|
+
static build(params) {
|
|
1896
|
+
const { exception, path, service, startTime, traceId: rawTraceId, exposeDebug, exposeCause } = params;
|
|
1897
|
+
const expose = {
|
|
1898
|
+
debug: exposeDebug,
|
|
1899
|
+
cause: exposeCause
|
|
2432
1900
|
};
|
|
2433
|
-
const
|
|
2434
|
-
const
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
{
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
{
|
|
2456
|
-
provide: LogixiaLoggerService,
|
|
2457
|
-
useFactory: (loggerConfig) => {
|
|
2458
|
-
const service = new LogixiaLoggerService({
|
|
2459
|
-
level: "info",
|
|
2460
|
-
service: "NestJSApp",
|
|
2461
|
-
environment: "development",
|
|
2462
|
-
fields: {},
|
|
2463
|
-
formatters: ["text"],
|
|
2464
|
-
outputs: ["console"],
|
|
2465
|
-
levelOptions: {
|
|
2466
|
-
level: "info",
|
|
2467
|
-
levels: {
|
|
2468
|
-
error: 0,
|
|
2469
|
-
warn: 1,
|
|
2470
|
-
info: 2,
|
|
2471
|
-
debug: 3,
|
|
2472
|
-
verbose: 4
|
|
2473
|
-
},
|
|
2474
|
-
colors: {
|
|
2475
|
-
error: "red",
|
|
2476
|
-
warn: "yellow",
|
|
2477
|
-
info: "green",
|
|
2478
|
-
debug: "blue",
|
|
2479
|
-
verbose: "cyan"
|
|
2480
|
-
}
|
|
2481
|
-
},
|
|
2482
|
-
...loggerConfig
|
|
2483
|
-
});
|
|
2484
|
-
_LogixiaLoggerModule._setGlobalLogger(service);
|
|
2485
|
-
return service;
|
|
1901
|
+
const traceId = TraceContext.instance.getCurrentTraceId() ?? rawTraceId;
|
|
1902
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
1903
|
+
const durationMs = startTime !== void 0 ? Date.now() - startTime : void 0;
|
|
1904
|
+
if (isLogixiaException(exception)) {
|
|
1905
|
+
const debug$1 = buildDebug(exception, service, durationMs, expose);
|
|
1906
|
+
const errorBlock = {
|
|
1907
|
+
type: exception.errorType,
|
|
1908
|
+
code: exception.errorCode,
|
|
1909
|
+
message: exception.message
|
|
1910
|
+
};
|
|
1911
|
+
if (exception.param !== void 0) errorBlock.param = exception.param;
|
|
1912
|
+
if (exception.details !== void 0 && exception.details.length > 0) errorBlock.details = exception.details;
|
|
1913
|
+
if (exception.docUrl !== void 0) errorBlock.doc_url = exception.docUrl;
|
|
1914
|
+
return {
|
|
1915
|
+
response: {
|
|
1916
|
+
success: false,
|
|
1917
|
+
error: errorBlock,
|
|
1918
|
+
meta: {
|
|
1919
|
+
...traceId !== void 0 ? { trace_id: traceId } : {},
|
|
1920
|
+
timestamp,
|
|
1921
|
+
path,
|
|
1922
|
+
status: exception.httpStatus
|
|
2486
1923
|
},
|
|
2487
|
-
|
|
1924
|
+
...debug$1 !== void 0 ? { debug: debug$1 } : {}
|
|
2488
1925
|
},
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
*/
|
|
2512
|
-
static forRootAsync(options) {
|
|
2513
|
-
return {
|
|
2514
|
-
module: _LogixiaLoggerModule,
|
|
2515
|
-
imports: options.imports || [],
|
|
2516
|
-
providers: [
|
|
2517
|
-
...this.createAsyncProviders(options),
|
|
2518
|
-
{
|
|
2519
|
-
provide: LOGIXIA_TRACE_CONFIG,
|
|
2520
|
-
useFactory: (loggerConfig) => {
|
|
2521
|
-
return typeof (loggerConfig === null || loggerConfig === void 0 ? void 0 : loggerConfig.traceId) === "object" ? loggerConfig.traceId : { enabled: !!(loggerConfig === null || loggerConfig === void 0 ? void 0 : loggerConfig.traceId) };
|
|
1926
|
+
httpStatus: exception.httpStatus
|
|
1927
|
+
};
|
|
1928
|
+
}
|
|
1929
|
+
if (isHttpException(exception)) {
|
|
1930
|
+
const status = exception.getStatus();
|
|
1931
|
+
const exResponse = exception.getResponse();
|
|
1932
|
+
let message;
|
|
1933
|
+
if (typeof exResponse === "string") message = exResponse;
|
|
1934
|
+
else if (typeof exResponse === "object" && exResponse !== null && "message" in exResponse) {
|
|
1935
|
+
const raw = exResponse.message;
|
|
1936
|
+
message = Array.isArray(raw) ? raw.join(", ") : String(raw);
|
|
1937
|
+
} else message = exception.message;
|
|
1938
|
+
const type = httpStatusToType(status);
|
|
1939
|
+
const code = `HTTP_${status}`;
|
|
1940
|
+
const debug$1 = buildDebug(exception, service, durationMs, expose);
|
|
1941
|
+
return {
|
|
1942
|
+
response: {
|
|
1943
|
+
success: false,
|
|
1944
|
+
error: {
|
|
1945
|
+
type,
|
|
1946
|
+
code,
|
|
1947
|
+
message
|
|
2522
1948
|
},
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
const defaultConfig = {
|
|
2529
|
-
level: "info",
|
|
2530
|
-
service: "NestJSApp",
|
|
2531
|
-
environment: "development",
|
|
2532
|
-
fields: {},
|
|
2533
|
-
formatters: ["text"],
|
|
2534
|
-
outputs: ["console"],
|
|
2535
|
-
levelOptions: {
|
|
2536
|
-
level: "info",
|
|
2537
|
-
levels: {
|
|
2538
|
-
error: 0,
|
|
2539
|
-
warn: 1,
|
|
2540
|
-
info: 2,
|
|
2541
|
-
debug: 3,
|
|
2542
|
-
verbose: 4
|
|
2543
|
-
},
|
|
2544
|
-
colors: {
|
|
2545
|
-
error: "red",
|
|
2546
|
-
warn: "yellow",
|
|
2547
|
-
info: "green",
|
|
2548
|
-
debug: "blue",
|
|
2549
|
-
verbose: "cyan"
|
|
2550
|
-
}
|
|
2551
|
-
},
|
|
2552
|
-
...loggerConfig
|
|
2553
|
-
};
|
|
2554
|
-
_LogixiaLoggerModule.loggerConfig = defaultConfig;
|
|
2555
|
-
const service = new LogixiaLoggerService(defaultConfig);
|
|
2556
|
-
_LogixiaLoggerModule._setGlobalLogger(service);
|
|
2557
|
-
return service;
|
|
1949
|
+
meta: {
|
|
1950
|
+
...traceId !== void 0 ? { trace_id: traceId } : {},
|
|
1951
|
+
timestamp,
|
|
1952
|
+
path,
|
|
1953
|
+
status
|
|
2558
1954
|
},
|
|
2559
|
-
|
|
2560
|
-
},
|
|
2561
|
-
{
|
|
2562
|
-
provide: KafkaTraceInterceptor,
|
|
2563
|
-
useFactory: (traceConfig) => new KafkaTraceInterceptor(traceConfig),
|
|
2564
|
-
inject: [LOGIXIA_TRACE_CONFIG]
|
|
1955
|
+
...debug$1 !== void 0 ? { debug: debug$1 } : {}
|
|
2565
1956
|
},
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
}
|
|
2571
|
-
],
|
|
2572
|
-
exports: [
|
|
2573
|
-
LogixiaLoggerService,
|
|
2574
|
-
LOGIXIA_LOGGER_CONFIG,
|
|
2575
|
-
KafkaTraceInterceptor,
|
|
2576
|
-
WebSocketTraceInterceptor
|
|
2577
|
-
],
|
|
2578
|
-
global: true
|
|
2579
|
-
};
|
|
2580
|
-
}
|
|
2581
|
-
/**
|
|
2582
|
-
* Create feature-specific logger instances
|
|
2583
|
-
*/
|
|
2584
|
-
static forFeature(context) {
|
|
2585
|
-
const providerToken = `${LOGIXIA_LOGGER_PREFIX}${context.toUpperCase()}`;
|
|
1957
|
+
httpStatus: status
|
|
1958
|
+
};
|
|
1959
|
+
}
|
|
1960
|
+
const debug = buildDebug(exception instanceof Error ? exception : new Error(String(exception)), service, durationMs, expose);
|
|
2586
1961
|
return {
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
1962
|
+
response: {
|
|
1963
|
+
success: false,
|
|
1964
|
+
error: {
|
|
1965
|
+
type: "server_error",
|
|
1966
|
+
code: "INTERNAL_SERVER_ERROR",
|
|
1967
|
+
message: "An unexpected error occurred."
|
|
2592
1968
|
},
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
useClass: options.useClass
|
|
2603
|
-
}];
|
|
2604
|
-
}
|
|
2605
|
-
static createAsyncOptionsProvider(options) {
|
|
2606
|
-
if (options.useFactory) return {
|
|
2607
|
-
provide: LOGIXIA_LOGGER_CONFIG,
|
|
2608
|
-
useFactory: options.useFactory,
|
|
2609
|
-
inject: options.inject || []
|
|
2610
|
-
};
|
|
2611
|
-
return {
|
|
2612
|
-
provide: LOGIXIA_LOGGER_CONFIG,
|
|
2613
|
-
useFactory: async (optionsFactory) => await optionsFactory.createLogixiaOptions(),
|
|
2614
|
-
inject: [options.useExisting || options.useClass]
|
|
1969
|
+
meta: {
|
|
1970
|
+
...traceId !== void 0 ? { trace_id: traceId } : {},
|
|
1971
|
+
timestamp,
|
|
1972
|
+
path,
|
|
1973
|
+
status: 500
|
|
1974
|
+
},
|
|
1975
|
+
...debug !== void 0 ? { debug } : {}
|
|
1976
|
+
},
|
|
1977
|
+
httpStatus: 500
|
|
2615
1978
|
};
|
|
2616
1979
|
}
|
|
2617
1980
|
};
|
|
2618
|
-
LogixiaLoggerModule = _LogixiaLoggerModule = __decorate([Module({})], LogixiaLoggerModule);
|
|
2619
1981
|
|
|
2620
1982
|
//#endregion
|
|
2621
|
-
export {
|
|
2622
|
-
//# sourceMappingURL=
|
|
1983
|
+
export { globalPluginRegistry as C, DEFAULT_LOG_LEVELS as D, DEFAULT_LOG_COLORS as E, LogLevel as O, PluginRegistry as S, DEFAULT_CONFIG as T, getOtelMetaFields as _, isLogixiaException as a, normalizeError as b, _shutdownRegistrySize as c, registerForShutdown as d, resetShutdownHandlers as f, getActiveOtelContext as g, disableOtelBridge as h, LogixiaException as i, deregisterFromShutdown as l, redactObject as m, generateRequestId as n, LogixiaLogger as o, applyRedaction as p, generateTraceId as r, createLogger as s, ErrorResponseBuilder as t, flushOnExit as u, initOtelBridge as v, usePlugin as w, serializeError as x, isError as y };
|
|
1984
|
+
//# sourceMappingURL=builder-0gEzRopq.mjs.map
|