logixia 1.8.2 → 1.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/{index-CthBT3t8.d.mts → index-DknhKCCg.d.ts} +12 -1
- package/dist/index-DknhKCCg.d.ts.map +1 -0
- package/dist/{index-ClPZrfIU.d.ts → index-DnhKoNBG.d.mts} +12 -1
- package/dist/index-DnhKoNBG.d.mts.map +1 -0
- package/dist/index.d.mts +87 -16
- package/dist/index.d.mts.map +1 -1
- package/dist/index.d.ts +86 -15
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +78 -40
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +77 -37
- package/dist/index.mjs.map +1 -1
- package/dist/{logitron-logger.module-Dx2mUz-g.d.ts → logitron-logger.module-BkPXi0He.d.ts} +97 -5
- package/dist/logitron-logger.module-BkPXi0He.d.ts.map +1 -0
- package/dist/logitron-logger.module-CMDM61Iz.js +2566 -0
- package/dist/logitron-logger.module-CMDM61Iz.js.map +1 -0
- package/dist/{logitron-logger.module-KU_L04y1.d.mts → logitron-logger.module-Cd5M_59H.d.mts} +97 -5
- package/dist/logitron-logger.module-Cd5M_59H.d.mts.map +1 -0
- package/dist/logitron-logger.module-uyg1-Khn.mjs +2285 -0
- package/dist/logitron-logger.module-uyg1-Khn.mjs.map +1 -0
- package/dist/middleware.d.mts +1 -1
- package/dist/middleware.d.mts.map +1 -1
- package/dist/middleware.d.ts +1 -1
- package/dist/middleware.d.ts.map +1 -1
- package/dist/middleware.js +4 -1
- package/dist/middleware.js.map +1 -1
- package/dist/middleware.mjs +4 -1
- package/dist/middleware.mjs.map +1 -1
- package/dist/nest.d.mts +4 -44
- package/dist/nest.d.mts.map +1 -1
- package/dist/nest.d.ts +4 -44
- package/dist/nest.d.ts.map +1 -1
- package/dist/nest.js +3 -93
- package/dist/nest.mjs +3 -92
- package/dist/search.d.mts +1 -1
- package/dist/search.js +1 -1
- package/dist/search.mjs +1 -1
- package/dist/testing.d.mts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/{transport.manager-BCnLEmOy.mjs → transport.manager-D3U03fJg.mjs} +21 -11
- package/dist/transport.manager-D3U03fJg.mjs.map +1 -0
- package/dist/{transport.manager-DU1W0wV3.js → transport.manager-DPjB-dFH.js} +49 -15
- package/dist/transport.manager-DPjB-dFH.js.map +1 -0
- package/dist/transports.d.mts +3 -1
- package/dist/transports.d.mts.map +1 -1
- package/dist/transports.d.ts +3 -1
- package/dist/transports.d.ts.map +1 -1
- package/dist/transports.js +1 -1
- package/dist/transports.mjs +1 -1
- package/package.json +24 -23
- package/dist/build-DOx-YxF1.js +0 -536
- package/dist/build-DOx-YxF1.js.map +0 -1
- package/dist/build-DWmxA6A2.mjs +0 -536
- package/dist/build-DWmxA6A2.mjs.map +0 -1
- package/dist/chunk-BTgCAUrQ.js +0 -53
- package/dist/chunk-uEZWKkIX.mjs +0 -32
- package/dist/esm-1Ra90uql.mjs +0 -4256
- package/dist/esm-1Ra90uql.mjs.map +0 -1
- package/dist/esm-FNhqFIqG.js +0 -4267
- package/dist/esm-FNhqFIqG.js.map +0 -1
- package/dist/index-ClPZrfIU.d.ts.map +0 -1
- package/dist/index-CthBT3t8.d.mts.map +0 -1
- package/dist/lib-8XKCHDOH.mjs +0 -66301
- package/dist/lib-8XKCHDOH.mjs.map +0 -1
- package/dist/lib-BNEYXXTQ.js +0 -66304
- package/dist/lib-BNEYXXTQ.js.map +0 -1
- package/dist/logitron-logger.module-DucvDnxZ.mjs +0 -10986
- package/dist/logitron-logger.module-DucvDnxZ.mjs.map +0 -1
- package/dist/logitron-logger.module-Dx2mUz-g.d.ts.map +0 -1
- package/dist/logitron-logger.module-Fof9Er2E.js +0 -11260
- package/dist/logitron-logger.module-Fof9Er2E.js.map +0 -1
- package/dist/logitron-logger.module-KU_L04y1.d.mts.map +0 -1
- package/dist/nest.js.map +0 -1
- package/dist/nest.mjs.map +0 -1
- package/dist/promise-BI-3eI4n.js +0 -22743
- package/dist/promise-BI-3eI4n.js.map +0 -1
- package/dist/promise-BrZcjavs.mjs +0 -22740
- package/dist/promise-BrZcjavs.mjs.map +0 -1
- package/dist/sqlite3-CSkpjC90.js +0 -420
- package/dist/sqlite3-CSkpjC90.js.map +0 -1
- package/dist/sqlite3-DD2_nRRH.mjs +0 -417
- package/dist/sqlite3-DD2_nRRH.mjs.map +0 -1
- package/dist/transport.manager-BCnLEmOy.mjs.map +0 -1
- package/dist/transport.manager-DU1W0wV3.js.map +0 -1
- /package/dist/{search-DanSf_yc.d.mts → search-DN676Dnz.d.mts} +0 -0
- /package/dist/{search-1txemGPh.mjs → search-DOvSI-mb.mjs} +0 -0
- /package/dist/{search-DeZHhWxB.js → search-DoZF3RZj.js} +0 -0
|
@@ -0,0 +1,2566 @@
|
|
|
1
|
+
const require_transport_manager = require('./transport.manager-DPjB-dFH.js');
|
|
2
|
+
let fast_json_stringify = require("fast-json-stringify");
|
|
3
|
+
fast_json_stringify = require_transport_manager.__toESM(fast_json_stringify);
|
|
4
|
+
let node_async_hooks = require("node:async_hooks");
|
|
5
|
+
node_async_hooks = require_transport_manager.__toESM(node_async_hooks);
|
|
6
|
+
let node_crypto = require("node:crypto");
|
|
7
|
+
node_crypto = require_transport_manager.__toESM(node_crypto);
|
|
8
|
+
let crypto = require("crypto");
|
|
9
|
+
crypto = require_transport_manager.__toESM(crypto);
|
|
10
|
+
let __nestjs_common = require("@nestjs/common");
|
|
11
|
+
__nestjs_common = require_transport_manager.__toESM(__nestjs_common);
|
|
12
|
+
let rxjs = require("rxjs");
|
|
13
|
+
rxjs = require_transport_manager.__toESM(rxjs);
|
|
14
|
+
|
|
15
|
+
//#region src/context/async-context.ts
|
|
16
|
+
/** Generates an 8-character random ID using Node's crypto module. */
|
|
17
|
+
function randomShortId() {
|
|
18
|
+
return (0, node_crypto.randomUUID)().slice(0, 8);
|
|
19
|
+
}
|
|
20
|
+
const _storage = new node_async_hooks.AsyncLocalStorage();
|
|
21
|
+
const LogixiaContext = {
|
|
22
|
+
run(store, callback) {
|
|
23
|
+
const parent = _storage.getStore() ?? {};
|
|
24
|
+
return _storage.run({
|
|
25
|
+
...parent,
|
|
26
|
+
...store
|
|
27
|
+
}, callback);
|
|
28
|
+
},
|
|
29
|
+
get() {
|
|
30
|
+
return _storage.getStore();
|
|
31
|
+
},
|
|
32
|
+
set(fields) {
|
|
33
|
+
const store = _storage.getStore();
|
|
34
|
+
if (!store) return;
|
|
35
|
+
Object.assign(store, fields);
|
|
36
|
+
},
|
|
37
|
+
getStorage() {
|
|
38
|
+
return _storage;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Create an Express/Connect-compatible middleware that wraps each request in
|
|
43
|
+
* a `LogixiaContext.run()` scope populated with common request fields.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```ts
|
|
47
|
+
* import { createExpressContextMiddleware } from 'logixia';
|
|
48
|
+
* app.use(createExpressContextMiddleware());
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
function createExpressContextMiddleware(options = {}) {
|
|
52
|
+
const { enrich, traceIdHeader = "x-trace-id" } = options;
|
|
53
|
+
return function logixiaContextMiddleware(req, _res, next) {
|
|
54
|
+
const base = { traceId: (req["headers"] ?? {})[traceIdHeader] ?? randomShortId() };
|
|
55
|
+
LogixiaContext.run({
|
|
56
|
+
...base,
|
|
57
|
+
...enrich ? enrich(req) : {}
|
|
58
|
+
}, next);
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Create a Fastify lifecycle hook that wraps each request in a context scope.
|
|
63
|
+
*
|
|
64
|
+
* Register with `fastify.addHook('onRequest', createFastifyContextHook())`.
|
|
65
|
+
*/
|
|
66
|
+
function createFastifyContextHook(options = {}) {
|
|
67
|
+
const { enrich, traceIdHeader = "x-trace-id" } = options;
|
|
68
|
+
return function logixiaFastifyHook(request, _reply, done) {
|
|
69
|
+
const base = { traceId: (request["headers"] ?? {})[traceIdHeader] ?? request["id"] ?? randomShortId() };
|
|
70
|
+
LogixiaContext.run({
|
|
71
|
+
...base,
|
|
72
|
+
...enrich ? enrich(request) : {}
|
|
73
|
+
}, done);
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
//#endregion
|
|
78
|
+
//#region src/plugin.ts
|
|
79
|
+
/**
|
|
80
|
+
* Holds an ordered list of `LogixiaPlugin` instances and dispatches lifecycle
|
|
81
|
+
* events to them. One registry is created per logger instance; a global
|
|
82
|
+
* singleton is also exported for process-wide registration.
|
|
83
|
+
*/
|
|
84
|
+
var PluginRegistry = class {
|
|
85
|
+
constructor() {
|
|
86
|
+
this._plugins = [];
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Register a plugin. Silently skips if a plugin with the same `name` is
|
|
90
|
+
* already registered on this registry.
|
|
91
|
+
*/
|
|
92
|
+
register(plugin) {
|
|
93
|
+
if (this._plugins.some((p) => p.name === plugin.name)) return;
|
|
94
|
+
this._plugins.push(plugin);
|
|
95
|
+
if (plugin.onInit) {
|
|
96
|
+
const result = plugin.onInit();
|
|
97
|
+
if (result instanceof Promise) result.catch(() => {});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/** Remove a previously registered plugin by name. No-op if not found. */
|
|
101
|
+
unregister(name) {
|
|
102
|
+
const idx = this._plugins.findIndex((p) => p.name === name);
|
|
103
|
+
if (idx !== -1) this._plugins.splice(idx, 1);
|
|
104
|
+
}
|
|
105
|
+
/** Returns `true` if a plugin with the given name is registered. */
|
|
106
|
+
has(name) {
|
|
107
|
+
return this._plugins.some((p) => p.name === name);
|
|
108
|
+
}
|
|
109
|
+
/** Number of currently registered plugins. */
|
|
110
|
+
get size() {
|
|
111
|
+
return this._plugins.length;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Run all `onLog` hooks in order.
|
|
115
|
+
* Returns `null` if any plugin cancels the entry; otherwise returns the
|
|
116
|
+
* (possibly transformed) entry.
|
|
117
|
+
*/
|
|
118
|
+
async runOnLog(entry) {
|
|
119
|
+
let current = entry;
|
|
120
|
+
for (const plugin of this._plugins) {
|
|
121
|
+
if (!plugin.onLog) continue;
|
|
122
|
+
current = await plugin.onLog(current);
|
|
123
|
+
if (current === null) return null;
|
|
124
|
+
}
|
|
125
|
+
return current;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Notify all `onError` hooks.
|
|
129
|
+
* Errors thrown inside hooks are swallowed to prevent error cascades.
|
|
130
|
+
*/
|
|
131
|
+
async runOnError(error, entry) {
|
|
132
|
+
for (const plugin of this._plugins) if (plugin.onError) {
|
|
133
|
+
const r = plugin.onError(error, entry);
|
|
134
|
+
if (r instanceof Promise) await r.catch(() => {});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/** Run all `onShutdown` hooks concurrently. Hook errors are swallowed. */
|
|
138
|
+
async runOnShutdown() {
|
|
139
|
+
await Promise.all(this._plugins.filter((p) => Boolean(p.onShutdown)).map((p) => {
|
|
140
|
+
const r = p.onShutdown();
|
|
141
|
+
return r instanceof Promise ? r.catch(() => {}) : Promise.resolve();
|
|
142
|
+
}));
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
/**
|
|
146
|
+
* Module-level singleton registry.
|
|
147
|
+
*
|
|
148
|
+
* Plugins registered here are automatically copied into every **new** logger
|
|
149
|
+
* instance created after the registration. Already-created loggers are not
|
|
150
|
+
* retroactively affected — use `logger.use(plugin)` for per-instance control.
|
|
151
|
+
*/
|
|
152
|
+
const globalPluginRegistry = new PluginRegistry();
|
|
153
|
+
/**
|
|
154
|
+
* Register a plugin in the global registry so it applies to every future
|
|
155
|
+
* logger instance.
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* ```ts
|
|
159
|
+
* import { usePlugin } from 'logixia';
|
|
160
|
+
*
|
|
161
|
+
* usePlugin({
|
|
162
|
+
* name: 'audit-sink',
|
|
163
|
+
* onLog(entry) {
|
|
164
|
+
* if (entry.level === 'error') auditQueue.push(entry);
|
|
165
|
+
* return entry;
|
|
166
|
+
* },
|
|
167
|
+
* });
|
|
168
|
+
* ```
|
|
169
|
+
*/
|
|
170
|
+
function usePlugin(plugin) {
|
|
171
|
+
globalPluginRegistry.register(plugin);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
//#endregion
|
|
175
|
+
//#region src/types/index.ts
|
|
176
|
+
const LogLevel = {
|
|
177
|
+
ERROR: "error",
|
|
178
|
+
WARN: "warn",
|
|
179
|
+
INFO: "info",
|
|
180
|
+
DEBUG: "debug",
|
|
181
|
+
TRACE: "trace",
|
|
182
|
+
VERBOSE: "verbose"
|
|
183
|
+
};
|
|
184
|
+
const DEFAULT_LOG_LEVELS = {
|
|
185
|
+
error: 0,
|
|
186
|
+
warn: 1,
|
|
187
|
+
info: 2,
|
|
188
|
+
debug: 3,
|
|
189
|
+
trace: 4,
|
|
190
|
+
verbose: 5
|
|
191
|
+
};
|
|
192
|
+
const DEFAULT_LOG_COLORS = {
|
|
193
|
+
error: "red",
|
|
194
|
+
warn: "yellow",
|
|
195
|
+
info: "green",
|
|
196
|
+
debug: "blue",
|
|
197
|
+
trace: "magenta",
|
|
198
|
+
verbose: "cyan"
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
//#endregion
|
|
202
|
+
//#region src/utils/error.utils.ts
|
|
203
|
+
const EXTRA_FIELDS = [
|
|
204
|
+
"code",
|
|
205
|
+
"statusCode",
|
|
206
|
+
"status",
|
|
207
|
+
"errno",
|
|
208
|
+
"syscall",
|
|
209
|
+
"path",
|
|
210
|
+
"address",
|
|
211
|
+
"port",
|
|
212
|
+
"type"
|
|
213
|
+
];
|
|
214
|
+
/**
|
|
215
|
+
* Serialize an Error into a plain JSON-safe object, including:
|
|
216
|
+
* - `name`, `message`, `stack`
|
|
217
|
+
* - `cause` (recursively serialized, full ES2022 chain)
|
|
218
|
+
* - `errors` (for AggregateError)
|
|
219
|
+
* - standard Node.js error fields (`code`, `statusCode`, `errno`, …)
|
|
220
|
+
* - any other enumerable own properties
|
|
221
|
+
*/
|
|
222
|
+
function serializeError(error, options = {}) {
|
|
223
|
+
const { includeStack = true, maxDepth = 5, excludeFields = [] } = options;
|
|
224
|
+
return _serializeError(error, includeStack, maxDepth, excludeFields, 0, /* @__PURE__ */ new WeakSet());
|
|
225
|
+
}
|
|
226
|
+
function _serializeError(error, includeStack, maxDepth, excludeFields, depth, seen) {
|
|
227
|
+
if (depth >= maxDepth) return {
|
|
228
|
+
name: error.name,
|
|
229
|
+
message: error.message,
|
|
230
|
+
_truncated: true
|
|
231
|
+
};
|
|
232
|
+
if (seen.has(error)) return {
|
|
233
|
+
name: error.name,
|
|
234
|
+
message: error.message,
|
|
235
|
+
_circular: true
|
|
236
|
+
};
|
|
237
|
+
seen.add(error);
|
|
238
|
+
const serialized = {
|
|
239
|
+
name: error.name,
|
|
240
|
+
message: error.message
|
|
241
|
+
};
|
|
242
|
+
if (includeStack && error.stack) serialized.stack = error.stack;
|
|
243
|
+
const errorWithCause = error;
|
|
244
|
+
if (errorWithCause.cause !== void 0) if (errorWithCause.cause instanceof Error) serialized.cause = _serializeError(errorWithCause.cause, includeStack, maxDepth, excludeFields, depth + 1, seen);
|
|
245
|
+
else serialized.cause = serializeValue(errorWithCause.cause, maxDepth - depth - 1);
|
|
246
|
+
const aggregateError = error;
|
|
247
|
+
if (Array.isArray(aggregateError.errors)) serialized.errors = aggregateError.errors.map((e) => e instanceof Error ? _serializeError(e, includeStack, maxDepth, excludeFields, depth + 1, seen) : serializeValue(e, maxDepth - depth - 1));
|
|
248
|
+
const errorRecord = error;
|
|
249
|
+
for (const field of EXTRA_FIELDS) if (!excludeFields.includes(field) && field in error && errorRecord[field] !== void 0) serialized[field] = errorRecord[field];
|
|
250
|
+
const skip = new Set([
|
|
251
|
+
"name",
|
|
252
|
+
"message",
|
|
253
|
+
"stack",
|
|
254
|
+
"cause",
|
|
255
|
+
"errors",
|
|
256
|
+
...EXTRA_FIELDS,
|
|
257
|
+
...excludeFields
|
|
258
|
+
]);
|
|
259
|
+
for (const key of Object.getOwnPropertyNames(error)) {
|
|
260
|
+
if (skip.has(key)) continue;
|
|
261
|
+
if (key === "__proto__" || key === "constructor" || key === "prototype") continue;
|
|
262
|
+
try {
|
|
263
|
+
serialized[key] = serializeValue(errorRecord[key], maxDepth - depth - 1);
|
|
264
|
+
} catch {
|
|
265
|
+
serialized[key] = "[Unserializable]";
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return serialized;
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Recursively serialize an arbitrary value to a JSON-safe representation.
|
|
272
|
+
*/
|
|
273
|
+
function serializeValue(value, remainingDepth) {
|
|
274
|
+
if (remainingDepth <= 0) return "[Max Depth]";
|
|
275
|
+
if (value === null || value === void 0) return value;
|
|
276
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return value;
|
|
277
|
+
if (value instanceof Date) return value.toISOString();
|
|
278
|
+
if (value instanceof Error) return _serializeError(value, true, remainingDepth, [], 0, /* @__PURE__ */ new WeakSet());
|
|
279
|
+
if (Array.isArray(value)) return value.map((item) => serializeValue(item, remainingDepth - 1));
|
|
280
|
+
if (typeof value === "object") {
|
|
281
|
+
const out = {};
|
|
282
|
+
for (const [k, v] of Object.entries(value)) {
|
|
283
|
+
if (k === "__proto__" || k === "constructor" || k === "prototype") continue;
|
|
284
|
+
try {
|
|
285
|
+
out[k] = serializeValue(v, remainingDepth - 1);
|
|
286
|
+
} catch {
|
|
287
|
+
out[k] = "[Unserializable]";
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return out;
|
|
291
|
+
}
|
|
292
|
+
return String(value);
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Type guard: returns true if the value looks like an Error object.
|
|
296
|
+
*/
|
|
297
|
+
function isError(value) {
|
|
298
|
+
return value instanceof Error || Boolean(value) && typeof value === "object" && "name" in value && "message" in value;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Coerce any thrown value into a proper Error instance.
|
|
302
|
+
*/
|
|
303
|
+
function normalizeError(error) {
|
|
304
|
+
if (isError(error)) return error;
|
|
305
|
+
if (typeof error === "string") return new Error(error);
|
|
306
|
+
if (typeof error === "object" && error !== null) {
|
|
307
|
+
const e = error;
|
|
308
|
+
const err = new Error(typeof e["message"] === "string" ? e["message"] : "Unknown error");
|
|
309
|
+
Object.assign(err, error);
|
|
310
|
+
return err;
|
|
311
|
+
}
|
|
312
|
+
return new Error(String(error));
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
//#endregion
|
|
316
|
+
//#region src/utils/otel.ts
|
|
317
|
+
let _otelApi;
|
|
318
|
+
function tryLoadOtelApi() {
|
|
319
|
+
if (_otelApi !== void 0) return _otelApi;
|
|
320
|
+
try {
|
|
321
|
+
_otelApi = require("@opentelemetry/api");
|
|
322
|
+
return _otelApi;
|
|
323
|
+
} catch {
|
|
324
|
+
_otelApi = null;
|
|
325
|
+
return null;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Read the currently active OTel span context (if any) and return its fields
|
|
330
|
+
* in a plain object suitable for spreading into a log entry.
|
|
331
|
+
*
|
|
332
|
+
* Returns `undefined` when:
|
|
333
|
+
* - `@opentelemetry/api` is not installed
|
|
334
|
+
* - No active span exists (root context)
|
|
335
|
+
* - The span context is invalid (all-zeros)
|
|
336
|
+
*/
|
|
337
|
+
function getActiveOtelContext(opts = {}) {
|
|
338
|
+
const api = tryLoadOtelApi();
|
|
339
|
+
if (!api) return void 0;
|
|
340
|
+
const ctx = api.context.active();
|
|
341
|
+
const sc = api.trace.getSpanContext(ctx);
|
|
342
|
+
if (!sc || !api.trace.isSpanContextValid(sc)) return void 0;
|
|
343
|
+
const isSampled = (sc.traceFlags & api.trace.TraceFlags.SAMPLED) === api.trace.TraceFlags.SAMPLED;
|
|
344
|
+
if (opts.sampledOnly && !isSampled) return void 0;
|
|
345
|
+
return {
|
|
346
|
+
traceId: sc.traceId,
|
|
347
|
+
spanId: sc.spanId,
|
|
348
|
+
traceFlags: sc.traceFlags,
|
|
349
|
+
isSampled
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Returns a metadata object with OTel context fields ready to merge into a log call,
|
|
354
|
+
* using the configured field names.
|
|
355
|
+
*
|
|
356
|
+
* Returns `{}` when no active span exists (safe to spread unconditionally).
|
|
357
|
+
*
|
|
358
|
+
* @example
|
|
359
|
+
* ```ts
|
|
360
|
+
* await logger.info('Payment processed', {
|
|
361
|
+
* ...getOtelMetaFields(),
|
|
362
|
+
* orderId: 'ord_123',
|
|
363
|
+
* });
|
|
364
|
+
* ```
|
|
365
|
+
*/
|
|
366
|
+
function getOtelMetaFields(opts = {}) {
|
|
367
|
+
const { traceIdField = "traceId", spanIdField = "spanId", traceFlagsField = "traceFlags" } = opts;
|
|
368
|
+
const ctx = getActiveOtelContext(opts);
|
|
369
|
+
if (!ctx) return {};
|
|
370
|
+
return {
|
|
371
|
+
[traceIdField]: ctx.traceId,
|
|
372
|
+
[spanIdField]: ctx.spanId,
|
|
373
|
+
[traceFlagsField]: ctx.traceFlags
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
let _bridgeOptions = null;
|
|
377
|
+
/**
|
|
378
|
+
* Initialise the global OTel bridge.
|
|
379
|
+
*
|
|
380
|
+
* Once called, logixia's internal log pipeline checks for an active OTel span
|
|
381
|
+
* on **every** log call and automatically merges the span context into the
|
|
382
|
+
* entry's metadata — no per-call wiring needed.
|
|
383
|
+
*
|
|
384
|
+
* Call once at app startup, **after** the OTel SDK has been initialised:
|
|
385
|
+
* ```ts
|
|
386
|
+
* import { initOtelBridge } from 'logixia';
|
|
387
|
+
* initOtelBridge();
|
|
388
|
+
* ```
|
|
389
|
+
*/
|
|
390
|
+
function initOtelBridge(opts = {}) {
|
|
391
|
+
_bridgeOptions = opts;
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* @internal
|
|
395
|
+
* Used by the core logger to inject OTel context when the bridge is active.
|
|
396
|
+
* Returns `{}` when the bridge is not initialised or no active span exists.
|
|
397
|
+
*/
|
|
398
|
+
function _getOtelPayloadIfEnabled() {
|
|
399
|
+
if (!_bridgeOptions) return {};
|
|
400
|
+
return getOtelMetaFields(_bridgeOptions);
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Disable the OTel bridge (useful for tests).
|
|
404
|
+
*/
|
|
405
|
+
function disableOtelBridge() {
|
|
406
|
+
_bridgeOptions = null;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
//#endregion
|
|
410
|
+
//#region src/utils/redact.utils.ts
|
|
411
|
+
const DEFAULT_CENSOR = "[REDACTED]";
|
|
412
|
+
/**
|
|
413
|
+
* Conservative patterns: tokens and secrets that should NEVER appear in logs.
|
|
414
|
+
* Applied when `autoDetect: true` or `autoDetect: 'conservative'`.
|
|
415
|
+
*/
|
|
416
|
+
const PII_CONSERVATIVE_PATTERNS = [
|
|
417
|
+
/eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]*/g,
|
|
418
|
+
/Bearer\s+[A-Za-z0-9._~+/-]+=*/gi,
|
|
419
|
+
/\b(?:sk|pk|api|key|secret|token)-[A-Za-z0-9_-]{16,}/gi,
|
|
420
|
+
/\bAKIA[0-9A-Z]{16}\b/g,
|
|
421
|
+
/\b[A-Za-z0-9/+]{40}\b(?=.*aws)/gi
|
|
422
|
+
];
|
|
423
|
+
/**
|
|
424
|
+
* Conservative field-name paths auto-redacted by name regardless of value.
|
|
425
|
+
*/
|
|
426
|
+
const PII_CONSERVATIVE_PATHS = [
|
|
427
|
+
"**.password",
|
|
428
|
+
"**.passwd",
|
|
429
|
+
"**.secret",
|
|
430
|
+
"**.token",
|
|
431
|
+
"**.apiKey",
|
|
432
|
+
"**.api_key",
|
|
433
|
+
"**.accessToken",
|
|
434
|
+
"**.access_token",
|
|
435
|
+
"**.refreshToken",
|
|
436
|
+
"**.refresh_token",
|
|
437
|
+
"**.authorization",
|
|
438
|
+
"**.credentials",
|
|
439
|
+
"**.privateKey",
|
|
440
|
+
"**.private_key",
|
|
441
|
+
"**.clientSecret",
|
|
442
|
+
"**.client_secret"
|
|
443
|
+
];
|
|
444
|
+
/**
|
|
445
|
+
* Aggressive patterns: also catch personal data that could identify a person.
|
|
446
|
+
* Applied when `autoDetect: 'aggressive'`.
|
|
447
|
+
*/
|
|
448
|
+
const PII_AGGRESSIVE_PATTERNS = [
|
|
449
|
+
/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g,
|
|
450
|
+
/\b\d{3}-?\d{2}-?\d{4}\b/g,
|
|
451
|
+
/\b(?:\d[ -]?){13,19}\b/g,
|
|
452
|
+
/\b(?:\+?1[-.\s]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}\b/g,
|
|
453
|
+
/\b(?:\d{1,3}\.){3}\d{1,3}\b/g
|
|
454
|
+
];
|
|
455
|
+
const PII_AGGRESSIVE_PATHS = [
|
|
456
|
+
...PII_CONSERVATIVE_PATHS,
|
|
457
|
+
"**.email",
|
|
458
|
+
"**.emailAddress",
|
|
459
|
+
"**.email_address",
|
|
460
|
+
"**.phone",
|
|
461
|
+
"**.phoneNumber",
|
|
462
|
+
"**.phone_number",
|
|
463
|
+
"**.mobile",
|
|
464
|
+
"**.ssn",
|
|
465
|
+
"**.sin",
|
|
466
|
+
"**.dob",
|
|
467
|
+
"**.dateOfBirth",
|
|
468
|
+
"**.date_of_birth",
|
|
469
|
+
"**.creditCard",
|
|
470
|
+
"**.credit_card",
|
|
471
|
+
"**.cardNumber",
|
|
472
|
+
"**.card_number",
|
|
473
|
+
"**.cvv",
|
|
474
|
+
"**.cvc",
|
|
475
|
+
"**.ipAddress",
|
|
476
|
+
"**.ip_address"
|
|
477
|
+
];
|
|
478
|
+
/**
|
|
479
|
+
* Build an effective config that merges `autoDetect` PII rules into the
|
|
480
|
+
* explicit `paths` and `patterns` the caller provided.
|
|
481
|
+
*/
|
|
482
|
+
function resolveConfig(config) {
|
|
483
|
+
const { autoDetect } = config;
|
|
484
|
+
if (!autoDetect) return config;
|
|
485
|
+
const aggressive = autoDetect === "aggressive";
|
|
486
|
+
const extraPaths = aggressive ? PII_AGGRESSIVE_PATHS : PII_CONSERVATIVE_PATHS;
|
|
487
|
+
const extraPatterns = aggressive ? [...PII_CONSERVATIVE_PATTERNS, ...PII_AGGRESSIVE_PATTERNS] : PII_CONSERVATIVE_PATTERNS;
|
|
488
|
+
const { paths = [], patterns = [] } = config;
|
|
489
|
+
return {
|
|
490
|
+
...config,
|
|
491
|
+
paths: [...paths, ...extraPaths],
|
|
492
|
+
patterns: [...patterns, ...extraPatterns]
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
/**
|
|
496
|
+
* Convert a dot-notation path pattern to a RegExp.
|
|
497
|
+
* Supports `*` (one segment) and `**` (zero or more segments).
|
|
498
|
+
*
|
|
499
|
+
* Examples:
|
|
500
|
+
* "password" → /^password$/
|
|
501
|
+
* "user.password" → /^user\.password$/
|
|
502
|
+
* "*.token" → /^[^.]+\.token$/
|
|
503
|
+
* "req.headers.*" → /^req\.headers\.[^.]+$/
|
|
504
|
+
* "**" → /^.*$/
|
|
505
|
+
*/
|
|
506
|
+
function pathToRegExp(pattern) {
|
|
507
|
+
const regexStr = pattern.split(".").map((segment) => {
|
|
508
|
+
if (segment === "**") return ".*";
|
|
509
|
+
if (segment === "*") return "[^.]+";
|
|
510
|
+
return segment.replace(/[$()*+.?[\\\]^{|}]/g, "\\$&");
|
|
511
|
+
}).join("\\.");
|
|
512
|
+
return /* @__PURE__ */ new RegExp(`^${regexStr}$`);
|
|
513
|
+
}
|
|
514
|
+
/** Pre-compiled path matchers keyed by pattern string for perf */
|
|
515
|
+
const patternCache = /* @__PURE__ */ new Map();
|
|
516
|
+
function matchesPath(fullPath, pattern) {
|
|
517
|
+
let re = patternCache.get(pattern);
|
|
518
|
+
if (!re) {
|
|
519
|
+
re = pathToRegExp(pattern);
|
|
520
|
+
patternCache.set(pattern, re);
|
|
521
|
+
}
|
|
522
|
+
return re.test(fullPath);
|
|
523
|
+
}
|
|
524
|
+
/**
|
|
525
|
+
* Deep-clone and redact an object according to the given RedactConfig.
|
|
526
|
+
* Non-objects are returned as-is (with pattern replacement on strings).
|
|
527
|
+
*
|
|
528
|
+
* The function is intentionally non-mutating — it returns a new object.
|
|
529
|
+
*/
|
|
530
|
+
function redactObject(obj, config, _currentPath = "") {
|
|
531
|
+
const { paths = [], patterns = [], censor = DEFAULT_CENSOR } = config;
|
|
532
|
+
const result = {};
|
|
533
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
534
|
+
if (key === "__proto__" || key === "constructor" || key === "prototype") continue;
|
|
535
|
+
const fullPath = _currentPath ? `${_currentPath}.${key}` : key;
|
|
536
|
+
if (paths.length > 0 && paths.some((p) => matchesPath(fullPath, p))) {
|
|
537
|
+
result[key] = censor;
|
|
538
|
+
continue;
|
|
539
|
+
}
|
|
540
|
+
if (isPlainObject(value)) {
|
|
541
|
+
result[key] = redactObject(value, config, fullPath);
|
|
542
|
+
continue;
|
|
543
|
+
}
|
|
544
|
+
if (typeof value === "string" && patterns.length > 0) {
|
|
545
|
+
let redacted = value;
|
|
546
|
+
for (const pattern of patterns) redacted = redacted.replace(pattern, censor);
|
|
547
|
+
result[key] = redacted;
|
|
548
|
+
continue;
|
|
549
|
+
}
|
|
550
|
+
if (Array.isArray(value)) {
|
|
551
|
+
result[key] = value.map((item) => {
|
|
552
|
+
if (isPlainObject(item)) return redactObject(item, config, fullPath);
|
|
553
|
+
if (typeof item === "string" && patterns.length > 0) return patterns.reduce((s, p) => s.replace(p, censor), item);
|
|
554
|
+
return item;
|
|
555
|
+
});
|
|
556
|
+
continue;
|
|
557
|
+
}
|
|
558
|
+
result[key] = value;
|
|
559
|
+
}
|
|
560
|
+
return result;
|
|
561
|
+
}
|
|
562
|
+
/**
|
|
563
|
+
* Apply redaction to a log payload (top-level call convenience wrapper).
|
|
564
|
+
* Returns a new object — never mutates the input.
|
|
565
|
+
*/
|
|
566
|
+
function applyRedaction(payload, config) {
|
|
567
|
+
if (!payload || !config) return payload;
|
|
568
|
+
const resolved = resolveConfig(config);
|
|
569
|
+
if ((!resolved.paths || resolved.paths.length === 0) && (!resolved.patterns || resolved.patterns.length === 0)) return payload;
|
|
570
|
+
return redactObject(payload, resolved);
|
|
571
|
+
}
|
|
572
|
+
function isPlainObject(value) {
|
|
573
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) && !(value instanceof Date) && !(value instanceof Error) && !(value instanceof RegExp);
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
//#endregion
|
|
577
|
+
//#region src/utils/sampling.utils.ts
|
|
578
|
+
const ALWAYS_EMIT_LEVELS = new Set(["error", "fatal"]);
|
|
579
|
+
var Sampler = class {
|
|
580
|
+
constructor(config, onStats) {
|
|
581
|
+
this.sampledTraces = /* @__PURE__ */ new Set();
|
|
582
|
+
this.droppedTraces = /* @__PURE__ */ new Set();
|
|
583
|
+
this._tokenBucket = 0;
|
|
584
|
+
this._lastRefillMs = Date.now();
|
|
585
|
+
this._stats = {
|
|
586
|
+
evaluated: 0,
|
|
587
|
+
emitted: 0,
|
|
588
|
+
dropped: 0,
|
|
589
|
+
byLevel: {},
|
|
590
|
+
windowStart: Date.now()
|
|
591
|
+
};
|
|
592
|
+
this.config = config;
|
|
593
|
+
if (config.maxLogsPerSecond && config.maxLogsPerSecond > 0) this._tokenBucket = config.maxLogsPerSecond;
|
|
594
|
+
const interval = config.statsIntervalMs ?? 6e4;
|
|
595
|
+
if (interval > 0 && onStats) {
|
|
596
|
+
this._statsTimer = setInterval(() => {
|
|
597
|
+
onStats(this.getStats());
|
|
598
|
+
this.resetStats();
|
|
599
|
+
}, interval);
|
|
600
|
+
if (this._statsTimer.unref) this._statsTimer.unref();
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
/**
|
|
604
|
+
* Decide whether a given log entry should be emitted.
|
|
605
|
+
*
|
|
606
|
+
* @param level Log level string (lowercase)
|
|
607
|
+
* @param traceId Active trace ID, if any
|
|
608
|
+
* @returns true → emit, false → drop
|
|
609
|
+
*/
|
|
610
|
+
shouldEmit(level, traceId) {
|
|
611
|
+
var _this$config$perLevel;
|
|
612
|
+
const lvl = level.toLowerCase();
|
|
613
|
+
this._trackEvaluated(lvl);
|
|
614
|
+
if (ALWAYS_EMIT_LEVELS.has(lvl) && ((_this$config$perLevel = this.config.perLevel) === null || _this$config$perLevel === void 0 ? void 0 : _this$config$perLevel[lvl]) === void 0) {
|
|
615
|
+
this._trackEmitted(lvl);
|
|
616
|
+
return true;
|
|
617
|
+
}
|
|
618
|
+
if (this.config.traceConsistent && traceId) {
|
|
619
|
+
if (this.sampledTraces.has(traceId)) {
|
|
620
|
+
this._trackEmitted(lvl);
|
|
621
|
+
return true;
|
|
622
|
+
}
|
|
623
|
+
if (this.droppedTraces.has(traceId)) {
|
|
624
|
+
this._trackDropped(lvl);
|
|
625
|
+
return false;
|
|
626
|
+
}
|
|
627
|
+
const emit = this._sampleByRate(lvl);
|
|
628
|
+
if (emit) this.sampledTraces.add(traceId);
|
|
629
|
+
else this.droppedTraces.add(traceId);
|
|
630
|
+
if (emit) this._trackEmitted(lvl);
|
|
631
|
+
else this._trackDropped(lvl);
|
|
632
|
+
return emit;
|
|
633
|
+
}
|
|
634
|
+
if (!this._sampleByRate(lvl)) {
|
|
635
|
+
this._trackDropped(lvl);
|
|
636
|
+
return false;
|
|
637
|
+
}
|
|
638
|
+
if (this.config.maxLogsPerSecond && this.config.maxLogsPerSecond > 0) {
|
|
639
|
+
if (!this._consumeToken()) {
|
|
640
|
+
this._trackDropped(lvl);
|
|
641
|
+
return false;
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
this._trackEmitted(lvl);
|
|
645
|
+
return true;
|
|
646
|
+
}
|
|
647
|
+
getStats() {
|
|
648
|
+
return {
|
|
649
|
+
...this._stats,
|
|
650
|
+
byLevel: { ...this._stats.byLevel }
|
|
651
|
+
};
|
|
652
|
+
}
|
|
653
|
+
resetStats() {
|
|
654
|
+
this._stats = {
|
|
655
|
+
evaluated: 0,
|
|
656
|
+
emitted: 0,
|
|
657
|
+
dropped: 0,
|
|
658
|
+
byLevel: {},
|
|
659
|
+
windowStart: Date.now()
|
|
660
|
+
};
|
|
661
|
+
this.sampledTraces.clear();
|
|
662
|
+
this.droppedTraces.clear();
|
|
663
|
+
}
|
|
664
|
+
destroy() {
|
|
665
|
+
if (this._statsTimer) clearInterval(this._statsTimer);
|
|
666
|
+
}
|
|
667
|
+
_sampleByRate(level) {
|
|
668
|
+
var _this$config$perLevel2, _this$config$perLevel3;
|
|
669
|
+
const rate = ((_this$config$perLevel2 = this.config.perLevel) === null || _this$config$perLevel2 === void 0 ? void 0 : _this$config$perLevel2[level]) ?? ((_this$config$perLevel3 = this.config.perLevel) === null || _this$config$perLevel3 === void 0 ? void 0 : _this$config$perLevel3["*"]) ?? this.config.rate ?? 1;
|
|
670
|
+
if (rate >= 1) return true;
|
|
671
|
+
if (rate <= 0) return false;
|
|
672
|
+
return Math.random() < rate;
|
|
673
|
+
}
|
|
674
|
+
_consumeToken() {
|
|
675
|
+
const now = Date.now();
|
|
676
|
+
const elapsed = (now - this._lastRefillMs) / 1e3;
|
|
677
|
+
const max = this.config.maxLogsPerSecond;
|
|
678
|
+
this._tokenBucket = Math.min(max, this._tokenBucket + elapsed * max);
|
|
679
|
+
this._lastRefillMs = now;
|
|
680
|
+
if (this._tokenBucket >= 1) {
|
|
681
|
+
this._tokenBucket -= 1;
|
|
682
|
+
return true;
|
|
683
|
+
}
|
|
684
|
+
return false;
|
|
685
|
+
}
|
|
686
|
+
_ensure(level) {
|
|
687
|
+
if (!this._stats.byLevel[level]) this._stats.byLevel[level] = {
|
|
688
|
+
evaluated: 0,
|
|
689
|
+
emitted: 0
|
|
690
|
+
};
|
|
691
|
+
}
|
|
692
|
+
_trackEvaluated(level) {
|
|
693
|
+
this._stats.evaluated++;
|
|
694
|
+
this._ensure(level);
|
|
695
|
+
this._stats.byLevel[level].evaluated++;
|
|
696
|
+
}
|
|
697
|
+
_trackEmitted(level) {
|
|
698
|
+
this._stats.emitted++;
|
|
699
|
+
this._ensure(level);
|
|
700
|
+
this._stats.byLevel[level].emitted++;
|
|
701
|
+
}
|
|
702
|
+
_trackDropped(_level) {
|
|
703
|
+
this._stats.dropped++;
|
|
704
|
+
}
|
|
705
|
+
};
|
|
706
|
+
|
|
707
|
+
//#endregion
|
|
708
|
+
//#region src/utils/shutdown.utils.ts
|
|
709
|
+
/** Module-level registry of all logger instances that have opted into graceful shutdown */
|
|
710
|
+
const registry = /* @__PURE__ */ new Set();
|
|
711
|
+
let shutdownHandlerRegistered = false;
|
|
712
|
+
/**
|
|
713
|
+
* Register a logger instance so it is included in the graceful shutdown flush.
|
|
714
|
+
* Called automatically when `gracefulShutdown: true` is set in logger config.
|
|
715
|
+
*/
|
|
716
|
+
function registerForShutdown(logger) {
|
|
717
|
+
registry.add(logger);
|
|
718
|
+
}
|
|
719
|
+
/**
|
|
720
|
+
* Deregister a logger (e.g. after `logger.close()` is called manually).
|
|
721
|
+
*/
|
|
722
|
+
function deregisterFromShutdown(logger) {
|
|
723
|
+
registry.delete(logger);
|
|
724
|
+
}
|
|
725
|
+
/**
|
|
726
|
+
* Register SIGTERM / SIGINT handlers that flush all registered loggers before
|
|
727
|
+
* the process exits. Idempotent — calling multiple times is safe.
|
|
728
|
+
*
|
|
729
|
+
* @example
|
|
730
|
+
* ```ts
|
|
731
|
+
* import { flushOnExit } from 'logixia';
|
|
732
|
+
* flushOnExit({ timeout: 5000 });
|
|
733
|
+
* ```
|
|
734
|
+
*/
|
|
735
|
+
function flushOnExit(options = {}) {
|
|
736
|
+
if (shutdownHandlerRegistered) return;
|
|
737
|
+
shutdownHandlerRegistered = true;
|
|
738
|
+
const { timeout = 5e3, signals = ["SIGTERM", "SIGINT"], beforeFlush, afterFlush } = options;
|
|
739
|
+
const handler = async (signal) => {
|
|
740
|
+
const forceExitTimer = setTimeout(() => {
|
|
741
|
+
process.stderr.write(`[logixia] Graceful shutdown timed out after ${timeout}ms on ${signal}. Force-exiting.\n`);
|
|
742
|
+
process.exit(1);
|
|
743
|
+
}, timeout).unref();
|
|
744
|
+
try {
|
|
745
|
+
if (beforeFlush) await beforeFlush();
|
|
746
|
+
await Promise.allSettled([...registry].map((logger) => logger.close()));
|
|
747
|
+
if (afterFlush) await afterFlush();
|
|
748
|
+
} finally {
|
|
749
|
+
clearTimeout(forceExitTimer);
|
|
750
|
+
process.exit(0);
|
|
751
|
+
}
|
|
752
|
+
};
|
|
753
|
+
for (const signal of signals) if (process.listenerCount(signal) === 0) process.on(signal, handler);
|
|
754
|
+
}
|
|
755
|
+
/**
|
|
756
|
+
* Remove all graceful shutdown handlers and clear the registry.
|
|
757
|
+
* Primarily useful in tests.
|
|
758
|
+
*/
|
|
759
|
+
function resetShutdownHandlers() {
|
|
760
|
+
registry.clear();
|
|
761
|
+
shutdownHandlerRegistered = false;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
//#endregion
|
|
765
|
+
//#region node_modules/uuid/dist/esm-node/rng.js
|
|
766
|
+
const rnds8Pool = new Uint8Array(256);
|
|
767
|
+
let poolPtr = rnds8Pool.length;
|
|
768
|
+
function rng() {
|
|
769
|
+
if (poolPtr > rnds8Pool.length - 16) {
|
|
770
|
+
crypto.default.randomFillSync(rnds8Pool);
|
|
771
|
+
poolPtr = 0;
|
|
772
|
+
}
|
|
773
|
+
return rnds8Pool.slice(poolPtr, poolPtr += 16);
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
//#endregion
|
|
777
|
+
//#region node_modules/uuid/dist/esm-node/stringify.js
|
|
778
|
+
/**
|
|
779
|
+
* Convert array of 16 byte values to UUID string format of the form:
|
|
780
|
+
* XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
|
|
781
|
+
*/
|
|
782
|
+
const byteToHex = [];
|
|
783
|
+
for (let i = 0; i < 256; ++i) byteToHex.push((i + 256).toString(16).slice(1));
|
|
784
|
+
function unsafeStringify(arr, offset = 0) {
|
|
785
|
+
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]];
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
//#endregion
|
|
789
|
+
//#region node_modules/uuid/dist/esm-node/native.js
|
|
790
|
+
var native_default = { randomUUID: crypto.default.randomUUID };
|
|
791
|
+
|
|
792
|
+
//#endregion
|
|
793
|
+
//#region node_modules/uuid/dist/esm-node/v4.js
|
|
794
|
+
function v4(options, buf, offset) {
|
|
795
|
+
if (native_default.randomUUID && !buf && !options) return native_default.randomUUID();
|
|
796
|
+
options = options || {};
|
|
797
|
+
const rnds = options.random || (options.rng || rng)();
|
|
798
|
+
rnds[6] = rnds[6] & 15 | 64;
|
|
799
|
+
rnds[8] = rnds[8] & 63 | 128;
|
|
800
|
+
if (buf) {
|
|
801
|
+
offset = offset || 0;
|
|
802
|
+
for (let i = 0; i < 16; ++i) buf[offset + i] = rnds[i];
|
|
803
|
+
return buf;
|
|
804
|
+
}
|
|
805
|
+
return unsafeStringify(rnds);
|
|
806
|
+
}
|
|
807
|
+
var v4_default = v4;
|
|
808
|
+
|
|
809
|
+
//#endregion
|
|
810
|
+
//#region src/utils/trace.utils.ts
|
|
811
|
+
/** Default key used to store the trace ID in AsyncLocalStorage. */
|
|
812
|
+
const TRACE_CONTEXT_KEY = "traceId";
|
|
813
|
+
/**
|
|
814
|
+
* Singleton that owns the AsyncLocalStorage and the active contextKey.
|
|
815
|
+
*
|
|
816
|
+
* Why a class instead of bare module-level variables?
|
|
817
|
+
* - The contextKey is user-configurable; encapsulating it here means there is
|
|
818
|
+
* exactly one place that reads and writes it.
|
|
819
|
+
* - All helpers (getCurrentTraceId, runWithTraceId, etc.) delegate to this
|
|
820
|
+
* instance, so the key is always in sync without hidden global state.
|
|
821
|
+
* - Easier to test: you can reset the singleton between test cases.
|
|
822
|
+
*
|
|
823
|
+
* Usage (advanced):
|
|
824
|
+
* import { TraceContext } from 'logixia';
|
|
825
|
+
* TraceContext.instance.contextKey // → 'traceId' (or custom)
|
|
826
|
+
* TraceContext.instance.getCurrentTraceId() // same as standalone fn
|
|
827
|
+
*/
|
|
828
|
+
var TraceContext = class TraceContext {
|
|
829
|
+
static #_ = this._instance = null;
|
|
830
|
+
constructor() {
|
|
831
|
+
this.storage = new node_async_hooks.AsyncLocalStorage();
|
|
832
|
+
this._contextKey = TRACE_CONTEXT_KEY;
|
|
833
|
+
}
|
|
834
|
+
/** The process-wide singleton. */
|
|
835
|
+
static get instance() {
|
|
836
|
+
if (!TraceContext._instance) TraceContext._instance = new TraceContext();
|
|
837
|
+
return TraceContext._instance;
|
|
838
|
+
}
|
|
839
|
+
/** @internal Reset the singleton (useful in tests). */
|
|
840
|
+
static _reset() {
|
|
841
|
+
TraceContext._instance = null;
|
|
842
|
+
}
|
|
843
|
+
/** The AsyncLocalStorage key that holds the trace ID value. */
|
|
844
|
+
get contextKey() {
|
|
845
|
+
return this._contextKey;
|
|
846
|
+
}
|
|
847
|
+
/** @internal Called by TraceMiddleware when it boots to register the user's key. */
|
|
848
|
+
setContextKey(key) {
|
|
849
|
+
this._contextKey = key;
|
|
850
|
+
}
|
|
851
|
+
/** UUID v4 generator (default). */
|
|
852
|
+
generate() {
|
|
853
|
+
return v4_default();
|
|
854
|
+
}
|
|
855
|
+
/** Read the trace ID from the current async context. */
|
|
856
|
+
getCurrentTraceId() {
|
|
857
|
+
var _this$storage$getStor;
|
|
858
|
+
return (_this$storage$getStor = this.storage.getStore()) === null || _this$storage$getStor === void 0 ? void 0 : _this$storage$getStor[this._contextKey];
|
|
859
|
+
}
|
|
860
|
+
/**
|
|
861
|
+
* Mutate the CURRENT async context in-place.
|
|
862
|
+
*
|
|
863
|
+
* ⚠️ DEPRECATED — unsafe for concurrent requests.
|
|
864
|
+
*
|
|
865
|
+
* Uses `AsyncLocalStorage.enterWith()`, which mutates the current async
|
|
866
|
+
* execution context and every Promise chain spawned from it. In a server
|
|
867
|
+
* processing overlapping requests this can cause a trace ID set for one
|
|
868
|
+
* request to bleed into *other* in-flight requests that share the same
|
|
869
|
+
* async parent (e.g. a module-level setup function or a cached handler).
|
|
870
|
+
*
|
|
871
|
+
* Use {@link run} instead — it scopes the context to a callback so there
|
|
872
|
+
* is no risk of cross-request leakage.
|
|
873
|
+
*
|
|
874
|
+
* @deprecated Use `TraceContext.instance.run(traceId, fn)` — do not call
|
|
875
|
+
* `setTraceId` from request-handling code.
|
|
876
|
+
*/
|
|
877
|
+
setTraceId(traceId, data) {
|
|
878
|
+
const current = this.storage.getStore() ?? {};
|
|
879
|
+
this.storage.enterWith({
|
|
880
|
+
...current,
|
|
881
|
+
[this._contextKey]: traceId,
|
|
882
|
+
...data
|
|
883
|
+
});
|
|
884
|
+
}
|
|
885
|
+
/** Run `fn` inside a new async context that carries `traceId`. */
|
|
886
|
+
run(traceId, fn, data) {
|
|
887
|
+
return this.storage.run({
|
|
888
|
+
[this._contextKey]: traceId,
|
|
889
|
+
...data
|
|
890
|
+
}, fn);
|
|
891
|
+
}
|
|
892
|
+
};
|
|
893
|
+
/**
|
|
894
|
+
* The shared AsyncLocalStorage instance.
|
|
895
|
+
* @deprecated Prefer `TraceContext.instance.storage` for new code.
|
|
896
|
+
*/
|
|
897
|
+
const traceStorage = TraceContext.instance.storage;
|
|
898
|
+
/** Returns the key currently used to store the trace ID in AsyncLocalStorage. */
|
|
899
|
+
function getTraceContextKey() {
|
|
900
|
+
return TraceContext.instance.contextKey;
|
|
901
|
+
}
|
|
902
|
+
/** @internal Called by TraceMiddleware / traceMiddleware() when they boot. */
|
|
903
|
+
function _setActiveContextKey(key) {
|
|
904
|
+
TraceContext.instance.setContextKey(key);
|
|
905
|
+
}
|
|
906
|
+
/** Generate a UUID v4 trace ID. */
|
|
907
|
+
function generateTraceId() {
|
|
908
|
+
return TraceContext.instance.generate();
|
|
909
|
+
}
|
|
910
|
+
/**
|
|
911
|
+
* Get the current trace ID from async context.
|
|
912
|
+
* Returns `undefined` when called outside a traced request.
|
|
913
|
+
*/
|
|
914
|
+
function getCurrentTraceId() {
|
|
915
|
+
return TraceContext.instance.getCurrentTraceId();
|
|
916
|
+
}
|
|
917
|
+
/**
|
|
918
|
+
* Set trace ID in the CURRENT async context without starting a new one.
|
|
919
|
+
*
|
|
920
|
+
* ⚠️ DEPRECATED — unsafe for concurrent requests.
|
|
921
|
+
*
|
|
922
|
+
* Uses `AsyncLocalStorage.enterWith()`, which mutates the current async
|
|
923
|
+
* execution context and every Promise chain spawned from it. Under load this
|
|
924
|
+
* can cause a trace ID from one request to bleed into others sharing the same
|
|
925
|
+
* async parent.
|
|
926
|
+
*
|
|
927
|
+
* Use {@link runWithTraceId} instead. Migration patterns:
|
|
928
|
+
*
|
|
929
|
+
* **Express / Fastify middleware — before:**
|
|
930
|
+
* ```ts
|
|
931
|
+
* app.use((req, _res, next) => {
|
|
932
|
+
* setTraceId(req.headers['x-trace-id'] ?? generateTraceId());
|
|
933
|
+
* next();
|
|
934
|
+
* });
|
|
935
|
+
* ```
|
|
936
|
+
* **after:**
|
|
937
|
+
* ```ts
|
|
938
|
+
* app.use((req, _res, next) => {
|
|
939
|
+
* runWithTraceId(req.headers['x-trace-id'] ?? generateTraceId(), () => next());
|
|
940
|
+
* });
|
|
941
|
+
* ```
|
|
942
|
+
*
|
|
943
|
+
* **Kafka / queue consumer — before:**
|
|
944
|
+
* ```ts
|
|
945
|
+
* async function handle(msg) {
|
|
946
|
+
* setTraceId(msg.headers['x-trace-id']);
|
|
947
|
+
* await processMessage(msg);
|
|
948
|
+
* }
|
|
949
|
+
* ```
|
|
950
|
+
* **after:**
|
|
951
|
+
* ```ts
|
|
952
|
+
* async function handle(msg) {
|
|
953
|
+
* await runWithTraceId(msg.headers['x-trace-id'], () => processMessage(msg));
|
|
954
|
+
* }
|
|
955
|
+
* ```
|
|
956
|
+
*
|
|
957
|
+
* **Background job — before:**
|
|
958
|
+
* ```ts
|
|
959
|
+
* setTraceId(generateTraceId(), { jobId: job.id });
|
|
960
|
+
* await job.run();
|
|
961
|
+
* ```
|
|
962
|
+
* **after:**
|
|
963
|
+
* ```ts
|
|
964
|
+
* await runWithTraceId(generateTraceId(), () => job.run(), { jobId: job.id });
|
|
965
|
+
* ```
|
|
966
|
+
*
|
|
967
|
+
* @deprecated Use `runWithTraceId(traceId, fn)` — do not call `setTraceId`
|
|
968
|
+
* from request-handling code.
|
|
969
|
+
*/
|
|
970
|
+
function setTraceId(traceId, data) {
|
|
971
|
+
TraceContext.instance.setTraceId(traceId, data);
|
|
972
|
+
}
|
|
973
|
+
/** Run `fn` inside a new async context carrying `traceId`. */
|
|
974
|
+
function runWithTraceId(traceId, fn, data) {
|
|
975
|
+
return TraceContext.instance.run(traceId, fn, data);
|
|
976
|
+
}
|
|
977
|
+
/**
|
|
978
|
+
* Coerce an arbitrary value to a non-empty trace ID string, or `undefined`.
|
|
979
|
+
* Rejects empty/whitespace-only strings, non-strings, and non-first array elements.
|
|
980
|
+
*/
|
|
981
|
+
function toValidTraceId(value) {
|
|
982
|
+
const first = Array.isArray(value) ? value[0] : value;
|
|
983
|
+
if (typeof first !== "string") return void 0;
|
|
984
|
+
const trimmed = first.trim();
|
|
985
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
986
|
+
}
|
|
987
|
+
/** Extract trace ID from request using configuration (header → query → body → params). */
|
|
988
|
+
function extractTraceId(request, config) {
|
|
989
|
+
const req = request;
|
|
990
|
+
if (config.header) {
|
|
991
|
+
const headers = Array.isArray(config.header) ? config.header : [config.header];
|
|
992
|
+
for (const header of headers) {
|
|
993
|
+
var _req$headers;
|
|
994
|
+
const value = toValidTraceId((_req$headers = req.headers) === null || _req$headers === void 0 ? void 0 : _req$headers[header.toLowerCase()]);
|
|
995
|
+
if (value) return value;
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
if (config.query) {
|
|
999
|
+
const queries = Array.isArray(config.query) ? config.query : [config.query];
|
|
1000
|
+
for (const query of queries) {
|
|
1001
|
+
var _req$query;
|
|
1002
|
+
const value = toValidTraceId((_req$query = req.query) === null || _req$query === void 0 ? void 0 : _req$query[query]);
|
|
1003
|
+
if (value) return value;
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
if (config.body) {
|
|
1007
|
+
const bodyFields = Array.isArray(config.body) ? config.body : [config.body];
|
|
1008
|
+
for (const field of bodyFields) {
|
|
1009
|
+
var _req$body;
|
|
1010
|
+
const value = toValidTraceId((_req$body = req.body) === null || _req$body === void 0 ? void 0 : _req$body[field]);
|
|
1011
|
+
if (value) return value;
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
if (config.params) {
|
|
1015
|
+
const paramFields = Array.isArray(config.params) ? config.params : [config.params];
|
|
1016
|
+
for (const param of paramFields) {
|
|
1017
|
+
var _req$params;
|
|
1018
|
+
const value = toValidTraceId((_req$params = req.params) === null || _req$params === void 0 ? void 0 : _req$params[param]);
|
|
1019
|
+
if (value) return value;
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
/**
|
|
1024
|
+
* Default headers checked for incoming trace ID propagation, in priority order:
|
|
1025
|
+
* traceparent (W3C/OTel) → x-trace-id → x-request-id → x-correlation-id → trace-id
|
|
1026
|
+
*/
|
|
1027
|
+
const DEFAULT_TRACE_HEADERS = [
|
|
1028
|
+
"traceparent",
|
|
1029
|
+
"x-trace-id",
|
|
1030
|
+
"x-request-id",
|
|
1031
|
+
"x-correlation-id",
|
|
1032
|
+
"trace-id"
|
|
1033
|
+
];
|
|
1034
|
+
/**
|
|
1035
|
+
* Create trace ID middleware for Express/NestJS
|
|
1036
|
+
*/
|
|
1037
|
+
function createTraceMiddleware(config) {
|
|
1038
|
+
const defaultExtractor = {
|
|
1039
|
+
header: DEFAULT_TRACE_HEADERS,
|
|
1040
|
+
query: ["traceId", "trace_id"]
|
|
1041
|
+
};
|
|
1042
|
+
const resolvedConfig = {
|
|
1043
|
+
...config,
|
|
1044
|
+
extractor: (config === null || config === void 0 ? void 0 : config.extractor) ? {
|
|
1045
|
+
...defaultExtractor,
|
|
1046
|
+
...config.extractor
|
|
1047
|
+
} : defaultExtractor
|
|
1048
|
+
};
|
|
1049
|
+
_setActiveContextKey(resolvedConfig.contextKey ?? TRACE_CONTEXT_KEY);
|
|
1050
|
+
return (req, res, next) => {
|
|
1051
|
+
let traceId;
|
|
1052
|
+
if (resolvedConfig.extractor) traceId = extractTraceId(req, resolvedConfig.extractor);
|
|
1053
|
+
if (!traceId) traceId = resolvedConfig.generator ? resolvedConfig.generator() : generateTraceId();
|
|
1054
|
+
req.traceId = traceId;
|
|
1055
|
+
res.setHeader("X-Trace-Id", traceId);
|
|
1056
|
+
runWithTraceId(traceId, () => next());
|
|
1057
|
+
};
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
//#endregion
|
|
1061
|
+
//#region src/core/logitron-logger.ts
|
|
1062
|
+
const _fastStringifyEntry = (0, fast_json_stringify.default)({
|
|
1063
|
+
type: "object",
|
|
1064
|
+
properties: {
|
|
1065
|
+
timestamp: { type: "string" },
|
|
1066
|
+
level: { type: "string" },
|
|
1067
|
+
appName: { type: "string" },
|
|
1068
|
+
environment: { type: "string" },
|
|
1069
|
+
message: { type: "string" },
|
|
1070
|
+
context: { type: "string" },
|
|
1071
|
+
traceId: { type: "string" },
|
|
1072
|
+
payload: {
|
|
1073
|
+
type: "object",
|
|
1074
|
+
additionalProperties: true
|
|
1075
|
+
}
|
|
1076
|
+
},
|
|
1077
|
+
additionalProperties: true
|
|
1078
|
+
});
|
|
1079
|
+
function namespacePatternToRegex(pattern) {
|
|
1080
|
+
const escaped = pattern.split(".").map((s) => s === "*" ? "[^.]+" : s.replace(/[$()*+.?[\\\]^{|}]/g, "\\$&")).join("\\.");
|
|
1081
|
+
return /* @__PURE__ */ new RegExp(`^${escaped}$`);
|
|
1082
|
+
}
|
|
1083
|
+
/** Max compiled patterns to keep in memory. Oldest entry is evicted when full. */
|
|
1084
|
+
const _NS_CACHE_MAX = 1e3;
|
|
1085
|
+
const _nsPatternCache = /* @__PURE__ */ new Map();
|
|
1086
|
+
/**
|
|
1087
|
+
* One-shot warning so operators notice runaway pattern growth.
|
|
1088
|
+
* If the cache is being thrashed (>N evictions) the namespace level config is
|
|
1089
|
+
* almost certainly wrong — likely dynamic/unique patterns being registered.
|
|
1090
|
+
*/
|
|
1091
|
+
let _nsCacheEvictionWarned = false;
|
|
1092
|
+
let _nsCacheEvictionCount = 0;
|
|
1093
|
+
function matchesNamespacePattern(ns, pattern) {
|
|
1094
|
+
let re = _nsPatternCache.get(pattern);
|
|
1095
|
+
if (!re) {
|
|
1096
|
+
re = namespacePatternToRegex(pattern);
|
|
1097
|
+
if (_nsPatternCache.size >= _NS_CACHE_MAX) {
|
|
1098
|
+
const firstKey = _nsPatternCache.keys().next().value;
|
|
1099
|
+
if (firstKey !== void 0) _nsPatternCache.delete(firstKey);
|
|
1100
|
+
_nsCacheEvictionCount++;
|
|
1101
|
+
if (!_nsCacheEvictionWarned) {
|
|
1102
|
+
_nsCacheEvictionWarned = true;
|
|
1103
|
+
process.stderr.write(`[logixia] namespace pattern cache hit ${_NS_CACHE_MAX} entries — evicting. This usually means dynamic/unique patterns are being registered at runtime; review your levelOptions.namespaces configuration.\n`);
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
_nsPatternCache.set(pattern, re);
|
|
1107
|
+
}
|
|
1108
|
+
return re.test(ns);
|
|
1109
|
+
}
|
|
1110
|
+
function resolveInitialLevel(config) {
|
|
1111
|
+
var _config$levelOptions;
|
|
1112
|
+
const envLevel = process.env["LOGIXIA_LEVEL"];
|
|
1113
|
+
if (envLevel) return envLevel;
|
|
1114
|
+
if ((_config$levelOptions = config.levelOptions) === null || _config$levelOptions === void 0 ? void 0 : _config$levelOptions.level) return config.levelOptions.level;
|
|
1115
|
+
const nodeEnv = process.env["NODE_ENV"];
|
|
1116
|
+
if (nodeEnv === "development") return LogLevel.DEBUG;
|
|
1117
|
+
if (nodeEnv === "test") return LogLevel.WARN;
|
|
1118
|
+
if (nodeEnv === "production") return LogLevel.INFO;
|
|
1119
|
+
if (process.env["CI"]) return LogLevel.INFO;
|
|
1120
|
+
return LogLevel.INFO;
|
|
1121
|
+
}
|
|
1122
|
+
var LogixiaLogger = class LogixiaLogger {
|
|
1123
|
+
constructor(config, context) {
|
|
1124
|
+
this.timers = /* @__PURE__ */ new Map();
|
|
1125
|
+
this.contextData = {};
|
|
1126
|
+
this.fieldState = /* @__PURE__ */ new Map();
|
|
1127
|
+
this.fallbackTraceId = TraceContext.instance.generate();
|
|
1128
|
+
this._levelValues = /* @__PURE__ */ new Map();
|
|
1129
|
+
this._minLevelValue = 2;
|
|
1130
|
+
this._colorMap = /* @__PURE__ */ new Map();
|
|
1131
|
+
this._fieldCache = /* @__PURE__ */ new Map();
|
|
1132
|
+
this._hasContextData = false;
|
|
1133
|
+
this._formattedLevels = /* @__PURE__ */ new Map();
|
|
1134
|
+
this._formattedAppName = "";
|
|
1135
|
+
this._hasRedact = false;
|
|
1136
|
+
this._pluginRegistry = new PluginRegistry();
|
|
1137
|
+
this.config = {
|
|
1138
|
+
appName: "App",
|
|
1139
|
+
environment: "development",
|
|
1140
|
+
traceId: true,
|
|
1141
|
+
format: {
|
|
1142
|
+
timestamp: true,
|
|
1143
|
+
colorize: true,
|
|
1144
|
+
json: false
|
|
1145
|
+
},
|
|
1146
|
+
silent: false,
|
|
1147
|
+
levelOptions: {
|
|
1148
|
+
level: LogLevel.INFO,
|
|
1149
|
+
levels: {
|
|
1150
|
+
[LogLevel.ERROR]: 0,
|
|
1151
|
+
[LogLevel.WARN]: 1,
|
|
1152
|
+
[LogLevel.INFO]: 2,
|
|
1153
|
+
[LogLevel.DEBUG]: 3,
|
|
1154
|
+
[LogLevel.TRACE]: 4,
|
|
1155
|
+
[LogLevel.VERBOSE]: 5
|
|
1156
|
+
},
|
|
1157
|
+
colors: {
|
|
1158
|
+
[LogLevel.ERROR]: "red",
|
|
1159
|
+
[LogLevel.WARN]: "yellow",
|
|
1160
|
+
[LogLevel.INFO]: "blue",
|
|
1161
|
+
[LogLevel.DEBUG]: "green",
|
|
1162
|
+
[LogLevel.TRACE]: "gray",
|
|
1163
|
+
[LogLevel.VERBOSE]: "cyan"
|
|
1164
|
+
}
|
|
1165
|
+
},
|
|
1166
|
+
...config
|
|
1167
|
+
};
|
|
1168
|
+
const resolvedLevel = resolveInitialLevel(this.config);
|
|
1169
|
+
this.config.levelOptions = {
|
|
1170
|
+
...this.config.levelOptions,
|
|
1171
|
+
level: resolvedLevel
|
|
1172
|
+
};
|
|
1173
|
+
if (!this.config.fields) this.config.fields = {
|
|
1174
|
+
timestamp: "[yyyy-mm-dd HH:MM:ss.MS]",
|
|
1175
|
+
level: "[log_level]",
|
|
1176
|
+
appName: "[app_name]",
|
|
1177
|
+
traceId: "[trace_id]",
|
|
1178
|
+
message: "[message]",
|
|
1179
|
+
payload: "[payload]",
|
|
1180
|
+
timeTaken: "[time_taken_MS]"
|
|
1181
|
+
};
|
|
1182
|
+
this.context = context ?? "";
|
|
1183
|
+
if (this.config.transports) {
|
|
1184
|
+
var _this$config$levelOpt;
|
|
1185
|
+
const transportsWithColors = { ...this.config.transports };
|
|
1186
|
+
const userColors = (_this$config$levelOpt = this.config.levelOptions) === null || _this$config$levelOpt === void 0 ? void 0 : _this$config$levelOpt.colors;
|
|
1187
|
+
if (userColors && transportsWithColors.console) transportsWithColors.console = {
|
|
1188
|
+
...typeof transportsWithColors.console === "object" ? transportsWithColors.console : {},
|
|
1189
|
+
levelColors: userColors
|
|
1190
|
+
};
|
|
1191
|
+
this.transportManager = new require_transport_manager.TransportManager(transportsWithColors);
|
|
1192
|
+
}
|
|
1193
|
+
if (this.config.sampling) this._sampler = new Sampler(this.config.sampling, (stats) => {
|
|
1194
|
+
process.stdout.write(JSON.stringify({
|
|
1195
|
+
level: "info",
|
|
1196
|
+
message: "[logixia/sampling] stats",
|
|
1197
|
+
...stats
|
|
1198
|
+
}) + "\n");
|
|
1199
|
+
});
|
|
1200
|
+
this.setupGracefulShutdown();
|
|
1201
|
+
this.createCustomLevelMethods();
|
|
1202
|
+
for (const p of globalPluginRegistry._plugins) this._pluginRegistry.register(p);
|
|
1203
|
+
this._buildPerfCaches();
|
|
1204
|
+
}
|
|
1205
|
+
setupGracefulShutdown() {
|
|
1206
|
+
const shutdownCfg = this.config.gracefulShutdown;
|
|
1207
|
+
if (!shutdownCfg) return;
|
|
1208
|
+
const normalized = shutdownCfg === true ? { enabled: true } : shutdownCfg;
|
|
1209
|
+
if (!normalized.enabled) return;
|
|
1210
|
+
registerForShutdown(this);
|
|
1211
|
+
flushOnExit({
|
|
1212
|
+
timeout: normalized.timeout ?? 5e3,
|
|
1213
|
+
signals: normalized.signals ?? ["SIGTERM", "SIGINT"]
|
|
1214
|
+
});
|
|
1215
|
+
}
|
|
1216
|
+
createCustomLevelMethods() {
|
|
1217
|
+
var _this$config$levelOpt2;
|
|
1218
|
+
if ((_this$config$levelOpt2 = this.config.levelOptions) === null || _this$config$levelOpt2 === void 0 ? void 0 : _this$config$levelOpt2.levels) {
|
|
1219
|
+
for (const levelName of Object.keys(this.config.levelOptions.levels)) if (!this[levelName.toLowerCase()]) this[levelName.toLowerCase()] = async (message, data) => {
|
|
1220
|
+
await this.logLevel(levelName.toLowerCase(), message, data);
|
|
1221
|
+
};
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
/**
|
|
1225
|
+
* Rebuild all hot-path caches after any config mutation or level change.
|
|
1226
|
+
* Keeps the actual log() call free of allocations in the common case.
|
|
1227
|
+
*/
|
|
1228
|
+
_buildPerfCaches() {
|
|
1229
|
+
var _this$config$levelOpt3, _this$config$format, _this$config$redact$p, _this$config$redact$p2;
|
|
1230
|
+
const customLevelEntries = Object.entries(((_this$config$levelOpt3 = this.config.levelOptions) === null || _this$config$levelOpt3 === void 0 ? void 0 : _this$config$levelOpt3.levels) ?? {});
|
|
1231
|
+
this._levelValues = new Map([
|
|
1232
|
+
[LogLevel.ERROR, 0],
|
|
1233
|
+
[LogLevel.WARN, 1],
|
|
1234
|
+
[LogLevel.INFO, 2],
|
|
1235
|
+
[LogLevel.DEBUG, 3],
|
|
1236
|
+
[LogLevel.TRACE, 4],
|
|
1237
|
+
[LogLevel.VERBOSE, 5],
|
|
1238
|
+
...customLevelEntries
|
|
1239
|
+
]);
|
|
1240
|
+
const effectiveLevel = this.resolveEffectiveLevel();
|
|
1241
|
+
this._minLevelValue = this._levelValues.get(effectiveLevel) ?? 2;
|
|
1242
|
+
this._colorMap = new Map([
|
|
1243
|
+
["black", "\x1B[30m"],
|
|
1244
|
+
["red", "\x1B[31m"],
|
|
1245
|
+
["green", "\x1B[32m"],
|
|
1246
|
+
["yellow", "\x1B[33m"],
|
|
1247
|
+
["blue", "\x1B[34m"],
|
|
1248
|
+
["magenta", "\x1B[35m"],
|
|
1249
|
+
["cyan", "\x1B[36m"],
|
|
1250
|
+
["white", "\x1B[37m"],
|
|
1251
|
+
["gray", "\x1B[90m"],
|
|
1252
|
+
["grey", "\x1B[90m"],
|
|
1253
|
+
["brightred", "\x1B[91m"],
|
|
1254
|
+
["brightgreen", "\x1B[92m"],
|
|
1255
|
+
["brightyellow", "\x1B[93m"],
|
|
1256
|
+
["brightblue", "\x1B[94m"],
|
|
1257
|
+
["brightmagenta", "\x1B[95m"],
|
|
1258
|
+
["brightcyan", "\x1B[96m"],
|
|
1259
|
+
["brightwhite", "\x1B[97m"],
|
|
1260
|
+
["reset", "\x1B[0m"]
|
|
1261
|
+
]);
|
|
1262
|
+
for (const f of [
|
|
1263
|
+
"timestamp",
|
|
1264
|
+
"level",
|
|
1265
|
+
"appName",
|
|
1266
|
+
"traceId",
|
|
1267
|
+
"context",
|
|
1268
|
+
"message",
|
|
1269
|
+
"payload"
|
|
1270
|
+
]) {
|
|
1271
|
+
var _this$config$fields;
|
|
1272
|
+
if (this.fieldState.has(f)) this._fieldCache.set(f, this.fieldState.get(f));
|
|
1273
|
+
else if (((_this$config$fields = this.config.fields) === null || _this$config$fields === void 0 ? void 0 : _this$config$fields[f]) !== void 0) this._fieldCache.set(f, this.config.fields[f] !== false);
|
|
1274
|
+
else this._fieldCache.set(f, true);
|
|
1275
|
+
}
|
|
1276
|
+
const colorize = ((_this$config$format = this.config.format) === null || _this$config$format === void 0 ? void 0 : _this$config$format.colorize) ?? true;
|
|
1277
|
+
this._formattedLevels = /* @__PURE__ */ new Map();
|
|
1278
|
+
const _AUTO_PALETTE = [
|
|
1279
|
+
"magenta",
|
|
1280
|
+
"cyan",
|
|
1281
|
+
"yellow",
|
|
1282
|
+
"green",
|
|
1283
|
+
"blue"
|
|
1284
|
+
];
|
|
1285
|
+
const _BUILTIN_LEVELS = new Set([
|
|
1286
|
+
"error",
|
|
1287
|
+
"warn",
|
|
1288
|
+
"info",
|
|
1289
|
+
"debug",
|
|
1290
|
+
"trace",
|
|
1291
|
+
"verbose"
|
|
1292
|
+
]);
|
|
1293
|
+
let _paletteIdx = 0;
|
|
1294
|
+
for (const [lvl] of this._levelValues) {
|
|
1295
|
+
const upper = lvl.toUpperCase();
|
|
1296
|
+
if (colorize && this._fieldCache.get("level") !== false) {
|
|
1297
|
+
var _this$config$levelOpt4;
|
|
1298
|
+
let colorName = (_this$config$levelOpt4 = this.config.levelOptions) === null || _this$config$levelOpt4 === void 0 || (_this$config$levelOpt4 = _this$config$levelOpt4.colors) === null || _this$config$levelOpt4 === void 0 ? void 0 : _this$config$levelOpt4[lvl];
|
|
1299
|
+
if (!colorName) if (_BUILTIN_LEVELS.has(lvl)) colorName = "white";
|
|
1300
|
+
else {
|
|
1301
|
+
colorName = _AUTO_PALETTE[_paletteIdx % _AUTO_PALETTE.length];
|
|
1302
|
+
_paletteIdx++;
|
|
1303
|
+
}
|
|
1304
|
+
const code = this._colorMap.get(colorName.toLowerCase()) ?? this._colorMap.get("white");
|
|
1305
|
+
const reset = this._colorMap.get("reset");
|
|
1306
|
+
this._formattedLevels.set(lvl, `[${code}${upper}${reset}] `);
|
|
1307
|
+
} else this._formattedLevels.set(lvl, `[${upper}] `);
|
|
1308
|
+
}
|
|
1309
|
+
const appNameRaw = `[${this.config.appName ?? "App"}]`;
|
|
1310
|
+
if (this._fieldCache.get("appName") !== false) this._formattedAppName = colorize ? `${this._colorMap.get("gray")}${appNameRaw}${this._colorMap.get("reset")} ` : `${appNameRaw} `;
|
|
1311
|
+
else this._formattedAppName = "";
|
|
1312
|
+
this._hasRedact = !!(this.config.redact && ((((_this$config$redact$p = this.config.redact.paths) === null || _this$config$redact$p === void 0 ? void 0 : _this$config$redact$p.length) ?? 0) > 0 || (((_this$config$redact$p2 = this.config.redact.patterns) === null || _this$config$redact$p2 === void 0 ? void 0 : _this$config$redact$p2.length) ?? 0) > 0));
|
|
1313
|
+
}
|
|
1314
|
+
async error(messageOrError, data) {
|
|
1315
|
+
if (isError(messageOrError)) await this.log("error", messageOrError.message, {
|
|
1316
|
+
...data,
|
|
1317
|
+
error: serializeError(messageOrError)
|
|
1318
|
+
});
|
|
1319
|
+
else await this.log("error", messageOrError, data);
|
|
1320
|
+
}
|
|
1321
|
+
async warn(message, data) {
|
|
1322
|
+
await this.log("warn", message, data);
|
|
1323
|
+
}
|
|
1324
|
+
async info(message, data) {
|
|
1325
|
+
await this.log("info", message, data);
|
|
1326
|
+
}
|
|
1327
|
+
async debug(message, data) {
|
|
1328
|
+
await this.log("debug", message, data);
|
|
1329
|
+
}
|
|
1330
|
+
async trace(message, data) {
|
|
1331
|
+
await this.log("trace", message, data);
|
|
1332
|
+
}
|
|
1333
|
+
async verbose(message, data) {
|
|
1334
|
+
await this.log("verbose", message, data);
|
|
1335
|
+
}
|
|
1336
|
+
async logLevel(level, message, data) {
|
|
1337
|
+
await this.log(level, message, data);
|
|
1338
|
+
}
|
|
1339
|
+
time(label) {
|
|
1340
|
+
this.timers.set(label, {
|
|
1341
|
+
label,
|
|
1342
|
+
startTime: Date.now()
|
|
1343
|
+
});
|
|
1344
|
+
}
|
|
1345
|
+
async timeEnd(label) {
|
|
1346
|
+
const timer = this.timers.get(label);
|
|
1347
|
+
if (!timer) {
|
|
1348
|
+
await this.warn(`Timer '${label}' does not exist`);
|
|
1349
|
+
return;
|
|
1350
|
+
}
|
|
1351
|
+
const endTime = Date.now();
|
|
1352
|
+
const duration = endTime - timer.startTime;
|
|
1353
|
+
timer.endTime = endTime;
|
|
1354
|
+
timer.duration = duration;
|
|
1355
|
+
await this.info(`Timer '${label}' finished`, {
|
|
1356
|
+
duration: `${duration}ms`,
|
|
1357
|
+
startTime: new Date(timer.startTime).toISOString(),
|
|
1358
|
+
endTime: new Date(endTime).toISOString()
|
|
1359
|
+
});
|
|
1360
|
+
this.timers.delete(label);
|
|
1361
|
+
return duration;
|
|
1362
|
+
}
|
|
1363
|
+
async timeAsync(label, fn) {
|
|
1364
|
+
this.time(label);
|
|
1365
|
+
try {
|
|
1366
|
+
const result = await fn();
|
|
1367
|
+
await this.timeEnd(label);
|
|
1368
|
+
return result;
|
|
1369
|
+
} catch (error) {
|
|
1370
|
+
await this.timeEnd(label);
|
|
1371
|
+
throw error;
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
setLevel(level) {
|
|
1375
|
+
this.config.levelOptions = this.config.levelOptions ?? {};
|
|
1376
|
+
this.config.levelOptions.level = level;
|
|
1377
|
+
this._minLevelValue = this._levelValues.get(level) ?? this._minLevelValue;
|
|
1378
|
+
this._buildPerfCaches();
|
|
1379
|
+
}
|
|
1380
|
+
getLevel() {
|
|
1381
|
+
var _this$config$levelOpt5;
|
|
1382
|
+
return ((_this$config$levelOpt5 = this.config.levelOptions) === null || _this$config$levelOpt5 === void 0 ? void 0 : _this$config$levelOpt5.level) ?? LogLevel.INFO;
|
|
1383
|
+
}
|
|
1384
|
+
setContext(context) {
|
|
1385
|
+
this.context = context;
|
|
1386
|
+
}
|
|
1387
|
+
getContext() {
|
|
1388
|
+
return this.context;
|
|
1389
|
+
}
|
|
1390
|
+
enableField(fieldName) {
|
|
1391
|
+
this.fieldState.set(fieldName, true);
|
|
1392
|
+
this._fieldCache.set(fieldName, true);
|
|
1393
|
+
if (fieldName === "level" || fieldName === "appName") this._buildPerfCaches();
|
|
1394
|
+
require_transport_manager.internalLog(`Field '${fieldName}' enabled`);
|
|
1395
|
+
}
|
|
1396
|
+
disableField(fieldName) {
|
|
1397
|
+
this.fieldState.set(fieldName, false);
|
|
1398
|
+
this._fieldCache.set(fieldName, false);
|
|
1399
|
+
if (fieldName === "level" || fieldName === "appName") this._buildPerfCaches();
|
|
1400
|
+
require_transport_manager.internalLog(`Field '${fieldName}' disabled`);
|
|
1401
|
+
}
|
|
1402
|
+
isFieldEnabled(fieldName) {
|
|
1403
|
+
var _this$config$fields2;
|
|
1404
|
+
if (this.fieldState.has(fieldName)) return this.fieldState.get(fieldName);
|
|
1405
|
+
if (((_this$config$fields2 = this.config.fields) === null || _this$config$fields2 === void 0 ? void 0 : _this$config$fields2[fieldName]) !== void 0) return this.config.fields[fieldName] !== false;
|
|
1406
|
+
return true;
|
|
1407
|
+
}
|
|
1408
|
+
getFieldState() {
|
|
1409
|
+
return Object.fromEntries([
|
|
1410
|
+
"timestamp",
|
|
1411
|
+
"level",
|
|
1412
|
+
"appName",
|
|
1413
|
+
"service",
|
|
1414
|
+
"traceId",
|
|
1415
|
+
"message",
|
|
1416
|
+
"payload",
|
|
1417
|
+
"timeTaken",
|
|
1418
|
+
"context",
|
|
1419
|
+
"userId",
|
|
1420
|
+
"sessionId",
|
|
1421
|
+
"environment"
|
|
1422
|
+
].map((f) => [f, this.isFieldEnabled(f)]));
|
|
1423
|
+
}
|
|
1424
|
+
resetFieldState() {
|
|
1425
|
+
this.fieldState.clear();
|
|
1426
|
+
require_transport_manager.internalLog("Field state reset to configuration defaults");
|
|
1427
|
+
}
|
|
1428
|
+
enableTransportLevelPrompting() {
|
|
1429
|
+
if (this.transportManager) this.transportManager.enableLevelPrompting();
|
|
1430
|
+
else require_transport_manager.internalWarn("Transport manager not initialized");
|
|
1431
|
+
}
|
|
1432
|
+
disableTransportLevelPrompting() {
|
|
1433
|
+
if (this.transportManager) this.transportManager.disableLevelPrompting();
|
|
1434
|
+
else require_transport_manager.internalWarn("Transport manager not initialized");
|
|
1435
|
+
}
|
|
1436
|
+
setTransportLevels(transportId, levels) {
|
|
1437
|
+
if (this.transportManager) this.transportManager.setTransportLevels(transportId, levels);
|
|
1438
|
+
else require_transport_manager.internalWarn("Transport manager not initialized");
|
|
1439
|
+
}
|
|
1440
|
+
getTransportLevels(transportId) {
|
|
1441
|
+
if (this.transportManager) return this.transportManager.getTransportLevels(transportId);
|
|
1442
|
+
require_transport_manager.internalWarn("Transport manager not initialized");
|
|
1443
|
+
}
|
|
1444
|
+
clearTransportLevelPreferences() {
|
|
1445
|
+
if (this.transportManager) this.transportManager.clearTransportLevelPreferences();
|
|
1446
|
+
else require_transport_manager.internalWarn("Transport manager not initialized");
|
|
1447
|
+
}
|
|
1448
|
+
getAvailableTransports() {
|
|
1449
|
+
var _this$transportManage;
|
|
1450
|
+
return ((_this$transportManage = this.transportManager) === null || _this$transportManage === void 0 ? void 0 : _this$transportManage.getTransports()) ?? [];
|
|
1451
|
+
}
|
|
1452
|
+
child(context, data) {
|
|
1453
|
+
const childLogger = new LogixiaLogger(this.config, context);
|
|
1454
|
+
if (data) childLogger.contextData = {
|
|
1455
|
+
...this.contextData,
|
|
1456
|
+
...data
|
|
1457
|
+
};
|
|
1458
|
+
return childLogger;
|
|
1459
|
+
}
|
|
1460
|
+
/**
|
|
1461
|
+
* Register a plugin on this logger instance.
|
|
1462
|
+
*
|
|
1463
|
+
* @example
|
|
1464
|
+
* ```ts
|
|
1465
|
+
* logger.use({
|
|
1466
|
+
* name: 'audit',
|
|
1467
|
+
* onLog(entry) { auditQueue.push(entry); return entry; },
|
|
1468
|
+
* });
|
|
1469
|
+
* ```
|
|
1470
|
+
*/
|
|
1471
|
+
use(plugin) {
|
|
1472
|
+
this._pluginRegistry.register(plugin);
|
|
1473
|
+
return this;
|
|
1474
|
+
}
|
|
1475
|
+
/**
|
|
1476
|
+
* Remove a previously registered plugin by name.
|
|
1477
|
+
* No-op if the plugin is not registered on this instance.
|
|
1478
|
+
*/
|
|
1479
|
+
unuse(pluginName) {
|
|
1480
|
+
this._pluginRegistry.unregister(pluginName);
|
|
1481
|
+
return this;
|
|
1482
|
+
}
|
|
1483
|
+
async flush() {
|
|
1484
|
+
if (this.transportManager) await this.transportManager.flush();
|
|
1485
|
+
}
|
|
1486
|
+
async healthCheck() {
|
|
1487
|
+
if (!this.transportManager) return {
|
|
1488
|
+
healthy: false,
|
|
1489
|
+
details: { error: "TransportManager not initialized" }
|
|
1490
|
+
};
|
|
1491
|
+
return this.transportManager.healthCheck();
|
|
1492
|
+
}
|
|
1493
|
+
async close() {
|
|
1494
|
+
var _this$_sampler;
|
|
1495
|
+
for (const [label, timer] of this.timers) await this.warn(`Timer '${label}' was not ended properly`, {
|
|
1496
|
+
startTime: new Date(timer.startTime).toISOString(),
|
|
1497
|
+
duration: `${Date.now() - timer.startTime}ms (incomplete)`
|
|
1498
|
+
});
|
|
1499
|
+
this.timers.clear();
|
|
1500
|
+
if (this.transportManager) {
|
|
1501
|
+
await this.transportManager.flush();
|
|
1502
|
+
await this.transportManager.close();
|
|
1503
|
+
}
|
|
1504
|
+
(_this$_sampler = this._sampler) === null || _this$_sampler === void 0 || _this$_sampler.destroy();
|
|
1505
|
+
await this._pluginRegistry.runOnShutdown();
|
|
1506
|
+
deregisterFromShutdown(this);
|
|
1507
|
+
}
|
|
1508
|
+
async log(level, message, data) {
|
|
1509
|
+
if (this.config.silent) return;
|
|
1510
|
+
if (!this.shouldLog(level)) return;
|
|
1511
|
+
if (this._sampler) {
|
|
1512
|
+
const traceId$1 = this.config.traceId ? TraceContext.instance.getCurrentTraceId() ?? this.fallbackTraceId : void 0;
|
|
1513
|
+
if (!this._sampler.shouldEmit(level, traceId$1)) return;
|
|
1514
|
+
}
|
|
1515
|
+
const alsContext = LogixiaContext.get();
|
|
1516
|
+
const otelFields = _getOtelPayloadIfEnabled();
|
|
1517
|
+
const hasOtel = Object.keys(otelFields).length > 0;
|
|
1518
|
+
let mergedData;
|
|
1519
|
+
if (alsContext && Object.keys(alsContext).length > 0) mergedData = {
|
|
1520
|
+
...alsContext,
|
|
1521
|
+
...hasOtel ? otelFields : {},
|
|
1522
|
+
...data
|
|
1523
|
+
};
|
|
1524
|
+
else if (hasOtel) mergedData = {
|
|
1525
|
+
...otelFields,
|
|
1526
|
+
...data
|
|
1527
|
+
};
|
|
1528
|
+
else mergedData = data;
|
|
1529
|
+
const rawPayload = this._hasContextData ? {
|
|
1530
|
+
...this.contextData,
|
|
1531
|
+
...mergedData
|
|
1532
|
+
} : mergedData;
|
|
1533
|
+
let payload;
|
|
1534
|
+
if (rawPayload !== void 0 && rawPayload !== null) payload = this._hasRedact ? applyRedaction(rawPayload, this.config.redact) ?? rawPayload : rawPayload;
|
|
1535
|
+
const traceId = this.config.traceId ? TraceContext.instance.getCurrentTraceId() ?? this.fallbackTraceId : void 0;
|
|
1536
|
+
const entry = {
|
|
1537
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1538
|
+
level,
|
|
1539
|
+
appName: this.config.appName ?? "App",
|
|
1540
|
+
environment: this.config.environment ?? "development",
|
|
1541
|
+
message
|
|
1542
|
+
};
|
|
1543
|
+
if (this.context) entry.context = this.context;
|
|
1544
|
+
if (payload !== void 0) entry.payload = payload;
|
|
1545
|
+
if (traceId !== void 0) entry.traceId = traceId;
|
|
1546
|
+
let finalEntry = entry;
|
|
1547
|
+
if (this._pluginRegistry.size > 0) {
|
|
1548
|
+
finalEntry = await this._pluginRegistry.runOnLog(entry);
|
|
1549
|
+
if (finalEntry === null) return;
|
|
1550
|
+
}
|
|
1551
|
+
const formattedLog = this.formatLog(finalEntry);
|
|
1552
|
+
await this.output(formattedLog, level, finalEntry);
|
|
1553
|
+
}
|
|
1554
|
+
/**
|
|
1555
|
+
* Hot-path level check: a single Map lookup + integer compare.
|
|
1556
|
+
* The level map and threshold are pre-built in _buildPerfCaches().
|
|
1557
|
+
*/
|
|
1558
|
+
shouldLog(level) {
|
|
1559
|
+
const v = this._levelValues.get(level);
|
|
1560
|
+
return v !== void 0 && v <= this._minLevelValue;
|
|
1561
|
+
}
|
|
1562
|
+
/**
|
|
1563
|
+
* Feature 3: Resolve the effective log level for this logger instance.
|
|
1564
|
+
*
|
|
1565
|
+
* Priority:
|
|
1566
|
+
* 1. ENV `LOGIXIA_LEVEL_<NS_UPPER>` (e.g. LOGIXIA_LEVEL_DB for ns "db" or "db.queries")
|
|
1567
|
+
* 2. Matching `namespaceLevels` config entry (longer pattern = more specific, wins)
|
|
1568
|
+
* 3. Global `LOGIXIA_LEVEL` ENV override
|
|
1569
|
+
* 4. `levelOptions.level` (resolved via Feature 5 in constructor)
|
|
1570
|
+
*/
|
|
1571
|
+
resolveEffectiveLevel() {
|
|
1572
|
+
const ns = this.context;
|
|
1573
|
+
if (ns) {
|
|
1574
|
+
const nsKey = ns.split(".")[0].toUpperCase();
|
|
1575
|
+
const envNsLevel = process.env[`LOGIXIA_LEVEL_${nsKey}`];
|
|
1576
|
+
if (envNsLevel) return envNsLevel;
|
|
1577
|
+
const namespaceLevels = this.config.namespaceLevels;
|
|
1578
|
+
if (namespaceLevels) {
|
|
1579
|
+
const sortedPatterns = Object.keys(namespaceLevels).sort((a, b) => b.length - a.length);
|
|
1580
|
+
for (const pattern of sortedPatterns) if (matchesNamespacePattern(ns, pattern)) return namespaceLevels[pattern];
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
const globalEnv = process.env["LOGIXIA_LEVEL"];
|
|
1584
|
+
if (globalEnv) return globalEnv;
|
|
1585
|
+
return this.getLevel();
|
|
1586
|
+
}
|
|
1587
|
+
formatLog(entry) {
|
|
1588
|
+
var _this$config$format2, _this$config$format3, _this$config$format4;
|
|
1589
|
+
if ((_this$config$format2 = this.config.format) === null || _this$config$format2 === void 0 ? void 0 : _this$config$format2.json) return _fastStringifyEntry(entry);
|
|
1590
|
+
let formatted = "";
|
|
1591
|
+
const doColorize = ((_this$config$format3 = this.config.format) === null || _this$config$format3 === void 0 ? void 0 : _this$config$format3.colorize) ?? true;
|
|
1592
|
+
const gray = doColorize ? this._colorMap.get("gray") : "";
|
|
1593
|
+
const cyan = doColorize ? this._colorMap.get("cyan") : "";
|
|
1594
|
+
const yellow = doColorize ? this._colorMap.get("yellow") : "";
|
|
1595
|
+
const reset = doColorize ? this._colorMap.get("reset") : "";
|
|
1596
|
+
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} `;
|
|
1597
|
+
if (this._fieldCache.get("level") !== false) formatted += this._formattedLevels.get(entry.level) ?? `[${entry.level.toUpperCase()}] `;
|
|
1598
|
+
formatted += this._formattedAppName;
|
|
1599
|
+
if (entry.traceId && this._fieldCache.get("traceId") !== false) formatted += `${cyan}[${entry.traceId}]${reset} `;
|
|
1600
|
+
if (entry.context && this._fieldCache.get("context") !== false) formatted += `${yellow}[${entry.context}]${reset} `;
|
|
1601
|
+
if (this._fieldCache.get("message") !== false) formatted += entry.message;
|
|
1602
|
+
if (entry.payload !== void 0 && this._fieldCache.get("payload") !== false) formatted += ` ${JSON.stringify(entry.payload)}`;
|
|
1603
|
+
return formatted;
|
|
1604
|
+
}
|
|
1605
|
+
colorize(text, color) {
|
|
1606
|
+
var _this$config$format5;
|
|
1607
|
+
if (!((_this$config$format5 = this.config.format) === null || _this$config$format5 === void 0 ? void 0 : _this$config$format5.colorize)) return text;
|
|
1608
|
+
return `${this._colorMap.get(color.toLowerCase()) ?? this._colorMap.get("white")}${text}${this._colorMap.get("reset")}`;
|
|
1609
|
+
}
|
|
1610
|
+
async output(message, level, entry) {
|
|
1611
|
+
if (this.transportManager) try {
|
|
1612
|
+
await this.transportManager.write(entry);
|
|
1613
|
+
return;
|
|
1614
|
+
} catch (error) {
|
|
1615
|
+
require_transport_manager.internalError("Transport write failed", error);
|
|
1616
|
+
}
|
|
1617
|
+
(level === LogLevel.ERROR ? process.stderr : process.stdout).write(message + "\n");
|
|
1618
|
+
}
|
|
1619
|
+
};
|
|
1620
|
+
function createLogger(config, context) {
|
|
1621
|
+
var _config$levelOptions2;
|
|
1622
|
+
const logger = new LogixiaLogger(config, context);
|
|
1623
|
+
const mutableLogger = logger;
|
|
1624
|
+
if ((_config$levelOptions2 = config.levelOptions) === null || _config$levelOptions2 === void 0 ? void 0 : _config$levelOptions2.levels) {
|
|
1625
|
+
for (const levelName of Object.keys(config.levelOptions.levels)) if (!mutableLogger[levelName]) mutableLogger[levelName] = async (message, data) => {
|
|
1626
|
+
await logger.logLevel(levelName, message, data);
|
|
1627
|
+
};
|
|
1628
|
+
}
|
|
1629
|
+
return logger;
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1632
|
+
//#endregion
|
|
1633
|
+
//#region \0@oxc-project+runtime@0.95.0/helpers/decorateMetadata.js
|
|
1634
|
+
function __decorateMetadata(k, v) {
|
|
1635
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1638
|
+
//#endregion
|
|
1639
|
+
//#region \0@oxc-project+runtime@0.95.0/helpers/decorate.js
|
|
1640
|
+
function __decorate(decorators, target, key, desc) {
|
|
1641
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1642
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1643
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1644
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1645
|
+
}
|
|
1646
|
+
|
|
1647
|
+
//#endregion
|
|
1648
|
+
//#region src/core/logitron-nestjs.service.ts
|
|
1649
|
+
var _LogixiaLoggerService;
|
|
1650
|
+
let LogixiaLoggerService = _LogixiaLoggerService = class LogixiaLoggerService$1 {
|
|
1651
|
+
constructor(config) {
|
|
1652
|
+
this._mergedConfig = {
|
|
1653
|
+
appName: "NestJS-App",
|
|
1654
|
+
environment: "development",
|
|
1655
|
+
traceId: true,
|
|
1656
|
+
format: {
|
|
1657
|
+
timestamp: true,
|
|
1658
|
+
colorize: true,
|
|
1659
|
+
json: false
|
|
1660
|
+
},
|
|
1661
|
+
silent: false,
|
|
1662
|
+
levelOptions: {
|
|
1663
|
+
level: LogLevel.INFO,
|
|
1664
|
+
levels: {
|
|
1665
|
+
error: 0,
|
|
1666
|
+
warn: 1,
|
|
1667
|
+
log: 2,
|
|
1668
|
+
debug: 3,
|
|
1669
|
+
verbose: 4
|
|
1670
|
+
},
|
|
1671
|
+
colors: {
|
|
1672
|
+
error: "red",
|
|
1673
|
+
warn: "yellow",
|
|
1674
|
+
log: "green",
|
|
1675
|
+
debug: "blue",
|
|
1676
|
+
verbose: "cyan"
|
|
1677
|
+
}
|
|
1678
|
+
},
|
|
1679
|
+
fields: {
|
|
1680
|
+
timestamp: "[yyyy-mm-dd HH:MM:ss.MS]",
|
|
1681
|
+
level: "[log_level]",
|
|
1682
|
+
appName: "[app_name]",
|
|
1683
|
+
traceId: "[trace_id]",
|
|
1684
|
+
message: "[message]",
|
|
1685
|
+
payload: "[payload]",
|
|
1686
|
+
timeTaken: "[time_taken_MS]"
|
|
1687
|
+
},
|
|
1688
|
+
...config
|
|
1689
|
+
};
|
|
1690
|
+
this.logger = new LogixiaLogger(this._mergedConfig);
|
|
1691
|
+
this._createCustomLevelMethods();
|
|
1692
|
+
}
|
|
1693
|
+
_createCustomLevelMethods() {
|
|
1694
|
+
var _this$_mergedConfig$l;
|
|
1695
|
+
const levels = (_this$_mergedConfig$l = this._mergedConfig.levelOptions) === null || _this$_mergedConfig$l === void 0 ? void 0 : _this$_mergedConfig$l.levels;
|
|
1696
|
+
if (!levels) return;
|
|
1697
|
+
for (const levelName of Object.keys(levels)) {
|
|
1698
|
+
const lower = levelName.toLowerCase();
|
|
1699
|
+
if (typeof this[lower] !== "undefined") continue;
|
|
1700
|
+
this[lower] = async (message, data) => {
|
|
1701
|
+
return this.logger.logLevel(lower, message, data);
|
|
1702
|
+
};
|
|
1703
|
+
}
|
|
1704
|
+
}
|
|
1705
|
+
/**
|
|
1706
|
+
* NestJS `LoggerService.log` — void, string context.
|
|
1707
|
+
* Maps internally to `info`.
|
|
1708
|
+
*
|
|
1709
|
+
* @example `logger.log('User signed up', 'AuthService')`
|
|
1710
|
+
*/
|
|
1711
|
+
log(message, context) {
|
|
1712
|
+
this.setContextIfProvided(context);
|
|
1713
|
+
this.logger.info(this.formatMessage(message)).catch((err) => require_transport_manager.internalError("LogixiaLoggerService.log failed", err));
|
|
1714
|
+
}
|
|
1715
|
+
/**
|
|
1716
|
+
* Native async `info` — structured data, returns `Promise<void>`.
|
|
1717
|
+
*
|
|
1718
|
+
* @example `await logger.info('User signed up', { userId: 'u_abc' })`
|
|
1719
|
+
*/
|
|
1720
|
+
async info(message, data) {
|
|
1721
|
+
return this.logger.info(message, data);
|
|
1722
|
+
}
|
|
1723
|
+
error(message, dataOrTrace, context) {
|
|
1724
|
+
if (typeof dataOrTrace === "object" && dataOrTrace !== null) return message instanceof Error ? this.logger.error(message, dataOrTrace) : this.logger.error(this.formatMessage(message), dataOrTrace);
|
|
1725
|
+
this.setContextIfProvided(context);
|
|
1726
|
+
const errorData = {};
|
|
1727
|
+
if (typeof dataOrTrace === "string" && dataOrTrace) errorData.stack = dataOrTrace;
|
|
1728
|
+
(message instanceof Error ? this.logger.error(message, errorData) : this.logger.error(this.formatMessage(message), errorData)).catch((err) => require_transport_manager.internalError("LogixiaLoggerService.error failed", err));
|
|
1729
|
+
}
|
|
1730
|
+
warn(message, dataOrContext) {
|
|
1731
|
+
if (typeof dataOrContext === "object" && dataOrContext !== null) return this.logger.warn(this.formatMessage(message), dataOrContext);
|
|
1732
|
+
this.setContextIfProvided(typeof dataOrContext === "string" ? dataOrContext : void 0);
|
|
1733
|
+
this.logger.warn(this.formatMessage(message)).catch((err) => require_transport_manager.internalError("LogixiaLoggerService.warn failed", err));
|
|
1734
|
+
}
|
|
1735
|
+
debug(message, dataOrContext) {
|
|
1736
|
+
if (typeof dataOrContext === "object" && dataOrContext !== null) return this.logger.debug(this.formatMessage(message), dataOrContext);
|
|
1737
|
+
this.setContextIfProvided(typeof dataOrContext === "string" ? dataOrContext : void 0);
|
|
1738
|
+
this.logger.debug(this.formatMessage(message)).catch((err) => require_transport_manager.internalError("LogixiaLoggerService.debug failed", err));
|
|
1739
|
+
}
|
|
1740
|
+
verbose(message, dataOrContext) {
|
|
1741
|
+
if (typeof dataOrContext === "object" && dataOrContext !== null) return this.logger.trace(this.formatMessage(message), dataOrContext);
|
|
1742
|
+
this.setContextIfProvided(typeof dataOrContext === "string" ? dataOrContext : void 0);
|
|
1743
|
+
this.logger.trace(this.formatMessage(message)).catch((err) => require_transport_manager.internalError("LogixiaLoggerService.verbose failed", err));
|
|
1744
|
+
}
|
|
1745
|
+
/**
|
|
1746
|
+
* Native async `trace` — lowest verbosity level, structured data.
|
|
1747
|
+
*/
|
|
1748
|
+
async trace(message, data) {
|
|
1749
|
+
return this.logger.trace(message, data);
|
|
1750
|
+
}
|
|
1751
|
+
/**
|
|
1752
|
+
* Log at any named level with structured data.
|
|
1753
|
+
*/
|
|
1754
|
+
logLevel(level, message, data) {
|
|
1755
|
+
return this.logger.logLevel(level, message, data);
|
|
1756
|
+
}
|
|
1757
|
+
time(label) {
|
|
1758
|
+
this.logger.time(label);
|
|
1759
|
+
}
|
|
1760
|
+
async timeEnd(label) {
|
|
1761
|
+
return this.logger.timeEnd(label);
|
|
1762
|
+
}
|
|
1763
|
+
async timeAsync(label, fn) {
|
|
1764
|
+
return this.logger.timeAsync(label, fn);
|
|
1765
|
+
}
|
|
1766
|
+
setContext(context) {
|
|
1767
|
+
this.context = context;
|
|
1768
|
+
this.logger.setContext(context);
|
|
1769
|
+
}
|
|
1770
|
+
getContext() {
|
|
1771
|
+
return this.context;
|
|
1772
|
+
}
|
|
1773
|
+
setLevel(level) {
|
|
1774
|
+
this.logger.setLevel(level);
|
|
1775
|
+
}
|
|
1776
|
+
getLevel() {
|
|
1777
|
+
return this.logger.getLevel();
|
|
1778
|
+
}
|
|
1779
|
+
child(context, data) {
|
|
1780
|
+
const childService = new _LogixiaLoggerService(this._mergedConfig);
|
|
1781
|
+
childService.logger = this.logger.child(context, data);
|
|
1782
|
+
childService.context = context;
|
|
1783
|
+
return childService;
|
|
1784
|
+
}
|
|
1785
|
+
getCurrentTraceId() {
|
|
1786
|
+
return TraceContext.instance.getCurrentTraceId();
|
|
1787
|
+
}
|
|
1788
|
+
/** Returns the AsyncLocalStorage key currently used to store the trace ID. */
|
|
1789
|
+
get traceContextKey() {
|
|
1790
|
+
return getTraceContextKey();
|
|
1791
|
+
}
|
|
1792
|
+
async close() {
|
|
1793
|
+
return this.logger.close();
|
|
1794
|
+
}
|
|
1795
|
+
static create(config) {
|
|
1796
|
+
return new _LogixiaLoggerService(config);
|
|
1797
|
+
}
|
|
1798
|
+
getLogger() {
|
|
1799
|
+
return this.logger;
|
|
1800
|
+
}
|
|
1801
|
+
setContextIfProvided(context) {
|
|
1802
|
+
if (context && context !== this.context) this.setContext(context);
|
|
1803
|
+
}
|
|
1804
|
+
formatMessage(message) {
|
|
1805
|
+
if (typeof message === "string") return message;
|
|
1806
|
+
if (typeof message === "object") return JSON.stringify(message);
|
|
1807
|
+
return String(message);
|
|
1808
|
+
}
|
|
1809
|
+
};
|
|
1810
|
+
LogixiaLoggerService = _LogixiaLoggerService = __decorate([(0, __nestjs_common.Injectable)({ scope: __nestjs_common.Scope.TRANSIENT }), __decorateMetadata("design:paramtypes", [Object])], LogixiaLoggerService);
|
|
1811
|
+
|
|
1812
|
+
//#endregion
|
|
1813
|
+
//#region src/core/kafka-trace.interceptor.ts
|
|
1814
|
+
var _KafkaTraceInterceptor;
|
|
1815
|
+
let KafkaTraceInterceptor = class KafkaTraceInterceptor$1 {
|
|
1816
|
+
static {
|
|
1817
|
+
_KafkaTraceInterceptor = this;
|
|
1818
|
+
}
|
|
1819
|
+
static #_ = this.metrics = {
|
|
1820
|
+
accepted: 0,
|
|
1821
|
+
acceptedWithoutTrace: 0,
|
|
1822
|
+
dropped: 0
|
|
1823
|
+
};
|
|
1824
|
+
/** Reset counters (tests). */
|
|
1825
|
+
static resetMetrics() {
|
|
1826
|
+
_KafkaTraceInterceptor.metrics.accepted = 0;
|
|
1827
|
+
_KafkaTraceInterceptor.metrics.acceptedWithoutTrace = 0;
|
|
1828
|
+
_KafkaTraceInterceptor.metrics.dropped = 0;
|
|
1829
|
+
}
|
|
1830
|
+
/**
|
|
1831
|
+
* @param config - TraceIdConfig options (extractor keys, contextKey, etc.)
|
|
1832
|
+
* @param requireTraceId - When true, messages with no traceId are silently skipped
|
|
1833
|
+
* (EMPTY Observable — message is ack'd, consumer stays alive).
|
|
1834
|
+
* A WARN is logged AND `KafkaTraceInterceptor.metrics.dropped`
|
|
1835
|
+
* increments so the missing traceId is observable end-to-end.
|
|
1836
|
+
* Default: false (handler runs without trace context).
|
|
1837
|
+
*/
|
|
1838
|
+
constructor(config, requireTraceId = false) {
|
|
1839
|
+
this.config = config;
|
|
1840
|
+
this.requireTraceId = requireTraceId;
|
|
1841
|
+
this.ctx = TraceContext.instance;
|
|
1842
|
+
this.config = {
|
|
1843
|
+
enabled: true,
|
|
1844
|
+
contextKey: "traceId",
|
|
1845
|
+
extractor: {
|
|
1846
|
+
body: [
|
|
1847
|
+
"traceId",
|
|
1848
|
+
"trace_id",
|
|
1849
|
+
"x-trace-id"
|
|
1850
|
+
],
|
|
1851
|
+
header: ["x-trace-id", "trace-id"]
|
|
1852
|
+
},
|
|
1853
|
+
...config
|
|
1854
|
+
};
|
|
1855
|
+
}
|
|
1856
|
+
intercept(context, next) {
|
|
1857
|
+
var _this$config;
|
|
1858
|
+
if (!((_this$config = this.config) === null || _this$config === void 0 ? void 0 : _this$config.enabled)) return next.handle();
|
|
1859
|
+
const rpcContext = context.switchToRpc();
|
|
1860
|
+
const data = rpcContext.getData();
|
|
1861
|
+
const rpcData = rpcContext.getContext();
|
|
1862
|
+
let traceId;
|
|
1863
|
+
if (this.config.extractor) traceId = extractTraceId({
|
|
1864
|
+
body: data,
|
|
1865
|
+
headers: (rpcData === null || rpcData === void 0 ? void 0 : rpcData.headers) ?? {},
|
|
1866
|
+
query: {},
|
|
1867
|
+
params: {}
|
|
1868
|
+
}, this.config.extractor);
|
|
1869
|
+
if (!traceId) traceId = this.ctx.getCurrentTraceId();
|
|
1870
|
+
if (!traceId) {
|
|
1871
|
+
if (this.requireTraceId) {
|
|
1872
|
+
var _LogixiaLoggerModule$;
|
|
1873
|
+
_KafkaTraceInterceptor.metrics.dropped++;
|
|
1874
|
+
(_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.`);
|
|
1875
|
+
return rxjs.EMPTY;
|
|
1876
|
+
}
|
|
1877
|
+
_KafkaTraceInterceptor.metrics.acceptedWithoutTrace++;
|
|
1878
|
+
return next.handle();
|
|
1879
|
+
}
|
|
1880
|
+
_KafkaTraceInterceptor.metrics.accepted++;
|
|
1881
|
+
const kafkaContext = {
|
|
1882
|
+
messageType: "kafka",
|
|
1883
|
+
topic: rpcData === null || rpcData === void 0 ? void 0 : rpcData.topic,
|
|
1884
|
+
partition: rpcData === null || rpcData === void 0 ? void 0 : rpcData.partition,
|
|
1885
|
+
offset: rpcData === null || rpcData === void 0 ? void 0 : rpcData.offset,
|
|
1886
|
+
key: rpcData === null || rpcData === void 0 ? void 0 : rpcData.key,
|
|
1887
|
+
timestamp: rpcData === null || rpcData === void 0 ? void 0 : rpcData.timestamp
|
|
1888
|
+
};
|
|
1889
|
+
return new rxjs.Observable((subscriber) => {
|
|
1890
|
+
this.ctx.run(traceId, () => {
|
|
1891
|
+
next.handle().subscribe({
|
|
1892
|
+
next: (value) => subscriber.next(value),
|
|
1893
|
+
error: (err) => subscriber.error(err),
|
|
1894
|
+
complete: () => subscriber.complete()
|
|
1895
|
+
});
|
|
1896
|
+
}, kafkaContext);
|
|
1897
|
+
});
|
|
1898
|
+
}
|
|
1899
|
+
};
|
|
1900
|
+
KafkaTraceInterceptor = _KafkaTraceInterceptor = __decorate([(0, __nestjs_common.Injectable)(), __decorateMetadata("design:paramtypes", [Object, Boolean])], KafkaTraceInterceptor);
|
|
1901
|
+
|
|
1902
|
+
//#endregion
|
|
1903
|
+
//#region \0@oxc-project+runtime@0.95.0/helpers/decorateParam.js
|
|
1904
|
+
function __decorateParam(paramIndex, decorator) {
|
|
1905
|
+
return function(target, key) {
|
|
1906
|
+
decorator(target, key, paramIndex);
|
|
1907
|
+
};
|
|
1908
|
+
}
|
|
1909
|
+
|
|
1910
|
+
//#endregion
|
|
1911
|
+
//#region src/core/trace.middleware.ts
|
|
1912
|
+
/** Default response header used to echo the resolved traceId back to the caller. */
|
|
1913
|
+
const DEFAULT_TRACE_RESPONSE_HEADER = "X-Trace-Id";
|
|
1914
|
+
/**
|
|
1915
|
+
* Resolve the response header name from config.
|
|
1916
|
+
* - `undefined` → default `'X-Trace-Id'`
|
|
1917
|
+
* - `string` → user's custom header
|
|
1918
|
+
* - `false` → `null` (suppress entirely)
|
|
1919
|
+
*/
|
|
1920
|
+
function resolveResponseHeader(config) {
|
|
1921
|
+
if ((config === null || config === void 0 ? void 0 : config.responseHeader) === false) return null;
|
|
1922
|
+
return (config === null || config === void 0 ? void 0 : config.responseHeader) ?? DEFAULT_TRACE_RESPONSE_HEADER;
|
|
1923
|
+
}
|
|
1924
|
+
let TraceMiddleware = class TraceMiddleware$1 {
|
|
1925
|
+
constructor(config) {
|
|
1926
|
+
this.config = config;
|
|
1927
|
+
this.ctx = TraceContext.instance;
|
|
1928
|
+
const defaultExtractor = {
|
|
1929
|
+
header: DEFAULT_TRACE_HEADERS,
|
|
1930
|
+
query: ["traceId", "trace_id"]
|
|
1931
|
+
};
|
|
1932
|
+
this.config = {
|
|
1933
|
+
enabled: true,
|
|
1934
|
+
generator: () => this.ctx.generate(),
|
|
1935
|
+
contextKey: "traceId",
|
|
1936
|
+
...config,
|
|
1937
|
+
extractor: (config === null || config === void 0 ? void 0 : config.extractor) ? {
|
|
1938
|
+
...defaultExtractor,
|
|
1939
|
+
...config.extractor
|
|
1940
|
+
} : defaultExtractor
|
|
1941
|
+
};
|
|
1942
|
+
if (this.config.enabled) this.ctx.setContextKey(this.config.contextKey ?? "traceId");
|
|
1943
|
+
}
|
|
1944
|
+
use(req, res, next) {
|
|
1945
|
+
var _this$config;
|
|
1946
|
+
if (!((_this$config = this.config) === null || _this$config === void 0 ? void 0 : _this$config.enabled)) return next();
|
|
1947
|
+
let traceId;
|
|
1948
|
+
if (this.config.extractor) traceId = extractTraceId(req, this.config.extractor);
|
|
1949
|
+
if (!traceId && this.config.generator) {
|
|
1950
|
+
const candidate = this.config.generator();
|
|
1951
|
+
if (typeof candidate === "string" && candidate.trim().length > 0) traceId = candidate;
|
|
1952
|
+
else process.stderr.write("[logixia] TraceIdConfig.generator returned a non-string/empty value — using built-in generator.\n");
|
|
1953
|
+
}
|
|
1954
|
+
if (!traceId) traceId = this.ctx.generate();
|
|
1955
|
+
req.traceId = traceId;
|
|
1956
|
+
const header = resolveResponseHeader(this.config);
|
|
1957
|
+
if (header) res.setHeader(header, traceId);
|
|
1958
|
+
this.ctx.run(traceId, () => next(), {
|
|
1959
|
+
method: req.method,
|
|
1960
|
+
url: req.url,
|
|
1961
|
+
userAgent: req.get("User-Agent"),
|
|
1962
|
+
ip: req.ip || req.connection.remoteAddress
|
|
1963
|
+
});
|
|
1964
|
+
}
|
|
1965
|
+
};
|
|
1966
|
+
TraceMiddleware = __decorate([
|
|
1967
|
+
(0, __nestjs_common.Injectable)(),
|
|
1968
|
+
__decorateParam(0, (0, __nestjs_common.Optional)()),
|
|
1969
|
+
__decorateMetadata("design:paramtypes", [Object])
|
|
1970
|
+
], TraceMiddleware);
|
|
1971
|
+
|
|
1972
|
+
//#endregion
|
|
1973
|
+
//#region src/core/websocket-trace.interceptor.ts
|
|
1974
|
+
let WebSocketTraceInterceptor = class WebSocketTraceInterceptor$1 {
|
|
1975
|
+
constructor(config) {
|
|
1976
|
+
this.config = config;
|
|
1977
|
+
this.ctx = TraceContext.instance;
|
|
1978
|
+
this.config = {
|
|
1979
|
+
enabled: true,
|
|
1980
|
+
contextKey: "traceId",
|
|
1981
|
+
extractor: {
|
|
1982
|
+
body: [
|
|
1983
|
+
"traceId",
|
|
1984
|
+
"trace_id",
|
|
1985
|
+
"x-trace-id"
|
|
1986
|
+
],
|
|
1987
|
+
header: ["x-trace-id", "trace-id"],
|
|
1988
|
+
query: ["traceId", "trace_id"]
|
|
1989
|
+
},
|
|
1990
|
+
...config
|
|
1991
|
+
};
|
|
1992
|
+
}
|
|
1993
|
+
intercept(context, next) {
|
|
1994
|
+
var _this$config, _client$handshake3;
|
|
1995
|
+
if (!((_this$config = this.config) === null || _this$config === void 0 ? void 0 : _this$config.enabled)) return next.handle();
|
|
1996
|
+
const wsContext = context.switchToWs();
|
|
1997
|
+
const data = wsContext.getData();
|
|
1998
|
+
const client = wsContext.getClient();
|
|
1999
|
+
let traceId;
|
|
2000
|
+
if (this.config.extractor) {
|
|
2001
|
+
var _client$handshake, _client$handshake2;
|
|
2002
|
+
traceId = extractTraceId({
|
|
2003
|
+
body: data,
|
|
2004
|
+
headers: (client === null || client === void 0 || (_client$handshake = client.handshake) === null || _client$handshake === void 0 ? void 0 : _client$handshake.headers) || {},
|
|
2005
|
+
query: (client === null || client === void 0 || (_client$handshake2 = client.handshake) === null || _client$handshake2 === void 0 ? void 0 : _client$handshake2.query) || {},
|
|
2006
|
+
params: {}
|
|
2007
|
+
}, this.config.extractor);
|
|
2008
|
+
}
|
|
2009
|
+
if (!traceId) traceId = this.ctx.getCurrentTraceId();
|
|
2010
|
+
if (!traceId) return next.handle();
|
|
2011
|
+
const wsContextData = {
|
|
2012
|
+
messageType: "websocket",
|
|
2013
|
+
event: data === null || data === void 0 ? void 0 : data.event,
|
|
2014
|
+
socketId: client === null || client === void 0 ? void 0 : client.id,
|
|
2015
|
+
rooms: (client === null || client === void 0 ? void 0 : client.rooms) ? Array.from(client.rooms) : [],
|
|
2016
|
+
clientAddress: client === null || client === void 0 || (_client$handshake3 = client.handshake) === null || _client$handshake3 === void 0 ? void 0 : _client$handshake3.address
|
|
2017
|
+
};
|
|
2018
|
+
return new rxjs.Observable((observer) => {
|
|
2019
|
+
this.ctx.run(traceId, () => {
|
|
2020
|
+
next.handle().subscribe({
|
|
2021
|
+
next: (value) => observer.next(value),
|
|
2022
|
+
error: (err) => observer.error(err),
|
|
2023
|
+
complete: () => observer.complete()
|
|
2024
|
+
});
|
|
2025
|
+
}, wsContextData);
|
|
2026
|
+
});
|
|
2027
|
+
}
|
|
2028
|
+
};
|
|
2029
|
+
WebSocketTraceInterceptor = __decorate([(0, __nestjs_common.Injectable)(), __decorateMetadata("design:paramtypes", [Object])], WebSocketTraceInterceptor);
|
|
2030
|
+
|
|
2031
|
+
//#endregion
|
|
2032
|
+
//#region src/core/logitron-logger.module.ts
|
|
2033
|
+
var _LogixiaLoggerModule;
|
|
2034
|
+
const DEFAULT_ROUTES = [{
|
|
2035
|
+
path: "*",
|
|
2036
|
+
method: __nestjs_common.RequestMethod.ALL
|
|
2037
|
+
}];
|
|
2038
|
+
const LOGIXIA_LOGGER_CONFIG = "LOGIXIA_LOGGER_CONFIG";
|
|
2039
|
+
const LOGIXIA_LOGGER_PREFIX = "LOGIXIA_LOGGER_";
|
|
2040
|
+
let LogixiaLoggerModule = class LogixiaLoggerModule$1 {
|
|
2041
|
+
static {
|
|
2042
|
+
_LogixiaLoggerModule = this;
|
|
2043
|
+
}
|
|
2044
|
+
constructor() {
|
|
2045
|
+
this.config = {};
|
|
2046
|
+
}
|
|
2047
|
+
static #_ = this.loggerConfig = {};
|
|
2048
|
+
static #_2 = this._globalLogger = null;
|
|
2049
|
+
/**
|
|
2050
|
+
* @internal Set the global logger exactly once.
|
|
2051
|
+
*
|
|
2052
|
+
* Called from the module's forRoot / forRootAsync factory. If the module is
|
|
2053
|
+
* initialised more than once in the same process (nested DI context, test
|
|
2054
|
+
* harness creating multiple apps, hot reload, etc.) a warning is written to
|
|
2055
|
+
* stderr and the first logger wins — silently overwriting would allow the
|
|
2056
|
+
* newer instance's transport config to replace the live one while the old
|
|
2057
|
+
* one is still being used by registered shutdown hooks, decorators, etc.
|
|
2058
|
+
*
|
|
2059
|
+
* Use {@link _resetGlobalLogger} in tests to reset between runs.
|
|
2060
|
+
*/
|
|
2061
|
+
static _setGlobalLogger(service) {
|
|
2062
|
+
if (_LogixiaLoggerModule._globalLogger !== null) {
|
|
2063
|
+
process.stderr.write("[logixia] LogixiaLoggerModule.forRoot() was called more than once — ignoring the second init. If this is intentional (e.g. in tests), call LogixiaLoggerModule._resetGlobalLogger() first.\n");
|
|
2064
|
+
return;
|
|
2065
|
+
}
|
|
2066
|
+
_LogixiaLoggerModule._globalLogger = service;
|
|
2067
|
+
}
|
|
2068
|
+
/** @internal Clear the global logger. Tests only. */
|
|
2069
|
+
static _resetGlobalLogger() {
|
|
2070
|
+
_LogixiaLoggerModule._globalLogger = null;
|
|
2071
|
+
}
|
|
2072
|
+
/**
|
|
2073
|
+
* Returns the global LogixiaLoggerService instance that was created when the
|
|
2074
|
+
* module booted. Useful for logging outside of NestJS DI — utility functions,
|
|
2075
|
+
* plain scripts, decorators — without injecting the service everywhere.
|
|
2076
|
+
*
|
|
2077
|
+
* Returns `null` if called before `LogixiaLoggerModule.forRoot[Async]()` has
|
|
2078
|
+
* been initialised (i.e. before the NestJS app has started).
|
|
2079
|
+
*
|
|
2080
|
+
* @example
|
|
2081
|
+
* ```ts
|
|
2082
|
+
* // some-util.ts
|
|
2083
|
+
* import { LogixiaLoggerModule } from 'logixia/nest';
|
|
2084
|
+
*
|
|
2085
|
+
* export function doSomething() {
|
|
2086
|
+
* LogixiaLoggerModule.getGlobalLogger()?.info('doing something');
|
|
2087
|
+
* }
|
|
2088
|
+
* ```
|
|
2089
|
+
*/
|
|
2090
|
+
static getGlobalLogger() {
|
|
2091
|
+
return _LogixiaLoggerModule._globalLogger;
|
|
2092
|
+
}
|
|
2093
|
+
configure(consumer) {
|
|
2094
|
+
const { forRoutes = DEFAULT_ROUTES, exclude } = this.config;
|
|
2095
|
+
let resolvedTraceConfig;
|
|
2096
|
+
if (typeof _LogixiaLoggerModule.loggerConfig.traceId === "object") resolvedTraceConfig = _LogixiaLoggerModule.loggerConfig.traceId;
|
|
2097
|
+
else if (_LogixiaLoggerModule.loggerConfig.traceId === true) resolvedTraceConfig = {
|
|
2098
|
+
enabled: true,
|
|
2099
|
+
contextKey: "traceId",
|
|
2100
|
+
generator: () => TraceContext.instance.generate()
|
|
2101
|
+
};
|
|
2102
|
+
const middleware = new TraceMiddleware(resolvedTraceConfig);
|
|
2103
|
+
const middlewareConfig = (req, res, next) => middleware.use(req, res, next);
|
|
2104
|
+
if (exclude) consumer.apply(middlewareConfig).exclude(...exclude).forRoutes(...forRoutes);
|
|
2105
|
+
else consumer.apply(middlewareConfig).forRoutes(...forRoutes);
|
|
2106
|
+
}
|
|
2107
|
+
/**
|
|
2108
|
+
* Configure the module with synchronous options
|
|
2109
|
+
*/
|
|
2110
|
+
static forRoot(config) {
|
|
2111
|
+
_LogixiaLoggerModule.loggerConfig = config || {};
|
|
2112
|
+
const traceConfig = (config === null || config === void 0 ? void 0 : config.traceId) && typeof config.traceId === "object" ? config.traceId : { enabled: !!(config === null || config === void 0 ? void 0 : config.traceId) };
|
|
2113
|
+
return {
|
|
2114
|
+
module: _LogixiaLoggerModule,
|
|
2115
|
+
providers: [
|
|
2116
|
+
{
|
|
2117
|
+
provide: LOGIXIA_LOGGER_CONFIG,
|
|
2118
|
+
useValue: config || {}
|
|
2119
|
+
},
|
|
2120
|
+
{
|
|
2121
|
+
provide: "TRACE_CONFIG",
|
|
2122
|
+
useValue: traceConfig
|
|
2123
|
+
},
|
|
2124
|
+
{
|
|
2125
|
+
provide: LogixiaLoggerService,
|
|
2126
|
+
useFactory: (loggerConfig) => {
|
|
2127
|
+
const service = new LogixiaLoggerService({
|
|
2128
|
+
level: "info",
|
|
2129
|
+
service: "NestJSApp",
|
|
2130
|
+
environment: "development",
|
|
2131
|
+
fields: {},
|
|
2132
|
+
formatters: ["text"],
|
|
2133
|
+
outputs: ["console"],
|
|
2134
|
+
levelOptions: {
|
|
2135
|
+
level: "info",
|
|
2136
|
+
levels: {
|
|
2137
|
+
error: 0,
|
|
2138
|
+
warn: 1,
|
|
2139
|
+
info: 2,
|
|
2140
|
+
debug: 3,
|
|
2141
|
+
verbose: 4
|
|
2142
|
+
},
|
|
2143
|
+
colors: {
|
|
2144
|
+
error: "red",
|
|
2145
|
+
warn: "yellow",
|
|
2146
|
+
info: "green",
|
|
2147
|
+
debug: "blue",
|
|
2148
|
+
verbose: "cyan"
|
|
2149
|
+
}
|
|
2150
|
+
},
|
|
2151
|
+
...loggerConfig
|
|
2152
|
+
});
|
|
2153
|
+
_LogixiaLoggerModule._setGlobalLogger(service);
|
|
2154
|
+
return service;
|
|
2155
|
+
},
|
|
2156
|
+
inject: [LOGIXIA_LOGGER_CONFIG]
|
|
2157
|
+
},
|
|
2158
|
+
{
|
|
2159
|
+
provide: KafkaTraceInterceptor,
|
|
2160
|
+
useFactory: (traceConfig$1) => new KafkaTraceInterceptor(traceConfig$1),
|
|
2161
|
+
inject: ["TRACE_CONFIG"]
|
|
2162
|
+
},
|
|
2163
|
+
{
|
|
2164
|
+
provide: WebSocketTraceInterceptor,
|
|
2165
|
+
useFactory: (traceConfig$1) => new WebSocketTraceInterceptor(traceConfig$1),
|
|
2166
|
+
inject: ["TRACE_CONFIG"]
|
|
2167
|
+
}
|
|
2168
|
+
],
|
|
2169
|
+
exports: [
|
|
2170
|
+
LogixiaLoggerService,
|
|
2171
|
+
LOGIXIA_LOGGER_CONFIG,
|
|
2172
|
+
KafkaTraceInterceptor,
|
|
2173
|
+
WebSocketTraceInterceptor
|
|
2174
|
+
],
|
|
2175
|
+
global: true
|
|
2176
|
+
};
|
|
2177
|
+
}
|
|
2178
|
+
/**
|
|
2179
|
+
* Configure the module with asynchronous options
|
|
2180
|
+
*/
|
|
2181
|
+
static forRootAsync(options) {
|
|
2182
|
+
return {
|
|
2183
|
+
module: _LogixiaLoggerModule,
|
|
2184
|
+
imports: options.imports || [],
|
|
2185
|
+
providers: [
|
|
2186
|
+
...this.createAsyncProviders(options),
|
|
2187
|
+
{
|
|
2188
|
+
provide: "TRACE_CONFIG",
|
|
2189
|
+
useFactory: (loggerConfig) => {
|
|
2190
|
+
return typeof (loggerConfig === null || loggerConfig === void 0 ? void 0 : loggerConfig.traceId) === "object" ? loggerConfig.traceId : { enabled: !!(loggerConfig === null || loggerConfig === void 0 ? void 0 : loggerConfig.traceId) };
|
|
2191
|
+
},
|
|
2192
|
+
inject: [LOGIXIA_LOGGER_CONFIG]
|
|
2193
|
+
},
|
|
2194
|
+
{
|
|
2195
|
+
provide: LogixiaLoggerService,
|
|
2196
|
+
useFactory: (loggerConfig) => {
|
|
2197
|
+
const defaultConfig = {
|
|
2198
|
+
level: "info",
|
|
2199
|
+
service: "NestJSApp",
|
|
2200
|
+
environment: "development",
|
|
2201
|
+
fields: {},
|
|
2202
|
+
formatters: ["text"],
|
|
2203
|
+
outputs: ["console"],
|
|
2204
|
+
levelOptions: {
|
|
2205
|
+
level: "info",
|
|
2206
|
+
levels: {
|
|
2207
|
+
error: 0,
|
|
2208
|
+
warn: 1,
|
|
2209
|
+
info: 2,
|
|
2210
|
+
debug: 3,
|
|
2211
|
+
verbose: 4
|
|
2212
|
+
},
|
|
2213
|
+
colors: {
|
|
2214
|
+
error: "red",
|
|
2215
|
+
warn: "yellow",
|
|
2216
|
+
info: "green",
|
|
2217
|
+
debug: "blue",
|
|
2218
|
+
verbose: "cyan"
|
|
2219
|
+
}
|
|
2220
|
+
},
|
|
2221
|
+
...loggerConfig
|
|
2222
|
+
};
|
|
2223
|
+
_LogixiaLoggerModule.loggerConfig = defaultConfig;
|
|
2224
|
+
const service = new LogixiaLoggerService(defaultConfig);
|
|
2225
|
+
_LogixiaLoggerModule._setGlobalLogger(service);
|
|
2226
|
+
return service;
|
|
2227
|
+
},
|
|
2228
|
+
inject: [LOGIXIA_LOGGER_CONFIG]
|
|
2229
|
+
},
|
|
2230
|
+
{
|
|
2231
|
+
provide: KafkaTraceInterceptor,
|
|
2232
|
+
useFactory: (traceConfig) => new KafkaTraceInterceptor(traceConfig),
|
|
2233
|
+
inject: ["TRACE_CONFIG"]
|
|
2234
|
+
},
|
|
2235
|
+
{
|
|
2236
|
+
provide: WebSocketTraceInterceptor,
|
|
2237
|
+
useFactory: (traceConfig) => new WebSocketTraceInterceptor(traceConfig),
|
|
2238
|
+
inject: ["TRACE_CONFIG"]
|
|
2239
|
+
}
|
|
2240
|
+
],
|
|
2241
|
+
exports: [
|
|
2242
|
+
LogixiaLoggerService,
|
|
2243
|
+
LOGIXIA_LOGGER_CONFIG,
|
|
2244
|
+
KafkaTraceInterceptor,
|
|
2245
|
+
WebSocketTraceInterceptor
|
|
2246
|
+
],
|
|
2247
|
+
global: true
|
|
2248
|
+
};
|
|
2249
|
+
}
|
|
2250
|
+
/**
|
|
2251
|
+
* Create feature-specific logger instances
|
|
2252
|
+
*/
|
|
2253
|
+
static forFeature(context) {
|
|
2254
|
+
const providerToken = `${LOGIXIA_LOGGER_PREFIX}${context.toUpperCase()}`;
|
|
2255
|
+
return {
|
|
2256
|
+
module: _LogixiaLoggerModule,
|
|
2257
|
+
providers: [{
|
|
2258
|
+
provide: providerToken,
|
|
2259
|
+
useFactory: (baseLogger) => {
|
|
2260
|
+
return baseLogger.child(context);
|
|
2261
|
+
},
|
|
2262
|
+
inject: [LogixiaLoggerService]
|
|
2263
|
+
}],
|
|
2264
|
+
exports: [providerToken]
|
|
2265
|
+
};
|
|
2266
|
+
}
|
|
2267
|
+
static createAsyncProviders(options) {
|
|
2268
|
+
if (options.useExisting || options.useFactory) return [this.createAsyncOptionsProvider(options)];
|
|
2269
|
+
return [this.createAsyncOptionsProvider(options), {
|
|
2270
|
+
provide: options.useClass,
|
|
2271
|
+
useClass: options.useClass
|
|
2272
|
+
}];
|
|
2273
|
+
}
|
|
2274
|
+
static createAsyncOptionsProvider(options) {
|
|
2275
|
+
if (options.useFactory) return {
|
|
2276
|
+
provide: LOGIXIA_LOGGER_CONFIG,
|
|
2277
|
+
useFactory: options.useFactory,
|
|
2278
|
+
inject: options.inject || []
|
|
2279
|
+
};
|
|
2280
|
+
return {
|
|
2281
|
+
provide: LOGIXIA_LOGGER_CONFIG,
|
|
2282
|
+
useFactory: async (optionsFactory) => await optionsFactory.createLogixiaOptions(),
|
|
2283
|
+
inject: [options.useExisting || options.useClass]
|
|
2284
|
+
};
|
|
2285
|
+
}
|
|
2286
|
+
};
|
|
2287
|
+
LogixiaLoggerModule = _LogixiaLoggerModule = __decorate([(0, __nestjs_common.Module)({})], LogixiaLoggerModule);
|
|
2288
|
+
|
|
2289
|
+
//#endregion
|
|
2290
|
+
Object.defineProperty(exports, 'DEFAULT_LOG_COLORS', {
|
|
2291
|
+
enumerable: true,
|
|
2292
|
+
get: function () {
|
|
2293
|
+
return DEFAULT_LOG_COLORS;
|
|
2294
|
+
}
|
|
2295
|
+
});
|
|
2296
|
+
Object.defineProperty(exports, 'DEFAULT_LOG_LEVELS', {
|
|
2297
|
+
enumerable: true,
|
|
2298
|
+
get: function () {
|
|
2299
|
+
return DEFAULT_LOG_LEVELS;
|
|
2300
|
+
}
|
|
2301
|
+
});
|
|
2302
|
+
Object.defineProperty(exports, 'DEFAULT_TRACE_HEADERS', {
|
|
2303
|
+
enumerable: true,
|
|
2304
|
+
get: function () {
|
|
2305
|
+
return DEFAULT_TRACE_HEADERS;
|
|
2306
|
+
}
|
|
2307
|
+
});
|
|
2308
|
+
Object.defineProperty(exports, 'KafkaTraceInterceptor', {
|
|
2309
|
+
enumerable: true,
|
|
2310
|
+
get: function () {
|
|
2311
|
+
return KafkaTraceInterceptor;
|
|
2312
|
+
}
|
|
2313
|
+
});
|
|
2314
|
+
Object.defineProperty(exports, 'LOGIXIA_LOGGER_CONFIG', {
|
|
2315
|
+
enumerable: true,
|
|
2316
|
+
get: function () {
|
|
2317
|
+
return LOGIXIA_LOGGER_CONFIG;
|
|
2318
|
+
}
|
|
2319
|
+
});
|
|
2320
|
+
Object.defineProperty(exports, 'LOGIXIA_LOGGER_PREFIX', {
|
|
2321
|
+
enumerable: true,
|
|
2322
|
+
get: function () {
|
|
2323
|
+
return LOGIXIA_LOGGER_PREFIX;
|
|
2324
|
+
}
|
|
2325
|
+
});
|
|
2326
|
+
Object.defineProperty(exports, 'LogLevel', {
|
|
2327
|
+
enumerable: true,
|
|
2328
|
+
get: function () {
|
|
2329
|
+
return LogLevel;
|
|
2330
|
+
}
|
|
2331
|
+
});
|
|
2332
|
+
Object.defineProperty(exports, 'LogixiaContext', {
|
|
2333
|
+
enumerable: true,
|
|
2334
|
+
get: function () {
|
|
2335
|
+
return LogixiaContext;
|
|
2336
|
+
}
|
|
2337
|
+
});
|
|
2338
|
+
Object.defineProperty(exports, 'LogixiaLogger', {
|
|
2339
|
+
enumerable: true,
|
|
2340
|
+
get: function () {
|
|
2341
|
+
return LogixiaLogger;
|
|
2342
|
+
}
|
|
2343
|
+
});
|
|
2344
|
+
Object.defineProperty(exports, 'LogixiaLoggerModule', {
|
|
2345
|
+
enumerable: true,
|
|
2346
|
+
get: function () {
|
|
2347
|
+
return LogixiaLoggerModule;
|
|
2348
|
+
}
|
|
2349
|
+
});
|
|
2350
|
+
Object.defineProperty(exports, 'LogixiaLoggerService', {
|
|
2351
|
+
enumerable: true,
|
|
2352
|
+
get: function () {
|
|
2353
|
+
return LogixiaLoggerService;
|
|
2354
|
+
}
|
|
2355
|
+
});
|
|
2356
|
+
Object.defineProperty(exports, 'PluginRegistry', {
|
|
2357
|
+
enumerable: true,
|
|
2358
|
+
get: function () {
|
|
2359
|
+
return PluginRegistry;
|
|
2360
|
+
}
|
|
2361
|
+
});
|
|
2362
|
+
Object.defineProperty(exports, 'TRACE_CONTEXT_KEY', {
|
|
2363
|
+
enumerable: true,
|
|
2364
|
+
get: function () {
|
|
2365
|
+
return TRACE_CONTEXT_KEY;
|
|
2366
|
+
}
|
|
2367
|
+
});
|
|
2368
|
+
Object.defineProperty(exports, 'TraceContext', {
|
|
2369
|
+
enumerable: true,
|
|
2370
|
+
get: function () {
|
|
2371
|
+
return TraceContext;
|
|
2372
|
+
}
|
|
2373
|
+
});
|
|
2374
|
+
Object.defineProperty(exports, 'TraceMiddleware', {
|
|
2375
|
+
enumerable: true,
|
|
2376
|
+
get: function () {
|
|
2377
|
+
return TraceMiddleware;
|
|
2378
|
+
}
|
|
2379
|
+
});
|
|
2380
|
+
Object.defineProperty(exports, 'WebSocketTraceInterceptor', {
|
|
2381
|
+
enumerable: true,
|
|
2382
|
+
get: function () {
|
|
2383
|
+
return WebSocketTraceInterceptor;
|
|
2384
|
+
}
|
|
2385
|
+
});
|
|
2386
|
+
Object.defineProperty(exports, '__decorate', {
|
|
2387
|
+
enumerable: true,
|
|
2388
|
+
get: function () {
|
|
2389
|
+
return __decorate;
|
|
2390
|
+
}
|
|
2391
|
+
});
|
|
2392
|
+
Object.defineProperty(exports, '__decorateMetadata', {
|
|
2393
|
+
enumerable: true,
|
|
2394
|
+
get: function () {
|
|
2395
|
+
return __decorateMetadata;
|
|
2396
|
+
}
|
|
2397
|
+
});
|
|
2398
|
+
Object.defineProperty(exports, '__decorateParam', {
|
|
2399
|
+
enumerable: true,
|
|
2400
|
+
get: function () {
|
|
2401
|
+
return __decorateParam;
|
|
2402
|
+
}
|
|
2403
|
+
});
|
|
2404
|
+
Object.defineProperty(exports, '_setActiveContextKey', {
|
|
2405
|
+
enumerable: true,
|
|
2406
|
+
get: function () {
|
|
2407
|
+
return _setActiveContextKey;
|
|
2408
|
+
}
|
|
2409
|
+
});
|
|
2410
|
+
Object.defineProperty(exports, 'applyRedaction', {
|
|
2411
|
+
enumerable: true,
|
|
2412
|
+
get: function () {
|
|
2413
|
+
return applyRedaction;
|
|
2414
|
+
}
|
|
2415
|
+
});
|
|
2416
|
+
Object.defineProperty(exports, 'createExpressContextMiddleware', {
|
|
2417
|
+
enumerable: true,
|
|
2418
|
+
get: function () {
|
|
2419
|
+
return createExpressContextMiddleware;
|
|
2420
|
+
}
|
|
2421
|
+
});
|
|
2422
|
+
Object.defineProperty(exports, 'createFastifyContextHook', {
|
|
2423
|
+
enumerable: true,
|
|
2424
|
+
get: function () {
|
|
2425
|
+
return createFastifyContextHook;
|
|
2426
|
+
}
|
|
2427
|
+
});
|
|
2428
|
+
Object.defineProperty(exports, 'createLogger', {
|
|
2429
|
+
enumerable: true,
|
|
2430
|
+
get: function () {
|
|
2431
|
+
return createLogger;
|
|
2432
|
+
}
|
|
2433
|
+
});
|
|
2434
|
+
Object.defineProperty(exports, 'createTraceMiddleware', {
|
|
2435
|
+
enumerable: true,
|
|
2436
|
+
get: function () {
|
|
2437
|
+
return createTraceMiddleware;
|
|
2438
|
+
}
|
|
2439
|
+
});
|
|
2440
|
+
Object.defineProperty(exports, 'deregisterFromShutdown', {
|
|
2441
|
+
enumerable: true,
|
|
2442
|
+
get: function () {
|
|
2443
|
+
return deregisterFromShutdown;
|
|
2444
|
+
}
|
|
2445
|
+
});
|
|
2446
|
+
Object.defineProperty(exports, 'disableOtelBridge', {
|
|
2447
|
+
enumerable: true,
|
|
2448
|
+
get: function () {
|
|
2449
|
+
return disableOtelBridge;
|
|
2450
|
+
}
|
|
2451
|
+
});
|
|
2452
|
+
Object.defineProperty(exports, 'extractTraceId', {
|
|
2453
|
+
enumerable: true,
|
|
2454
|
+
get: function () {
|
|
2455
|
+
return extractTraceId;
|
|
2456
|
+
}
|
|
2457
|
+
});
|
|
2458
|
+
Object.defineProperty(exports, 'flushOnExit', {
|
|
2459
|
+
enumerable: true,
|
|
2460
|
+
get: function () {
|
|
2461
|
+
return flushOnExit;
|
|
2462
|
+
}
|
|
2463
|
+
});
|
|
2464
|
+
Object.defineProperty(exports, 'getActiveOtelContext', {
|
|
2465
|
+
enumerable: true,
|
|
2466
|
+
get: function () {
|
|
2467
|
+
return getActiveOtelContext;
|
|
2468
|
+
}
|
|
2469
|
+
});
|
|
2470
|
+
Object.defineProperty(exports, 'getCurrentTraceId', {
|
|
2471
|
+
enumerable: true,
|
|
2472
|
+
get: function () {
|
|
2473
|
+
return getCurrentTraceId;
|
|
2474
|
+
}
|
|
2475
|
+
});
|
|
2476
|
+
Object.defineProperty(exports, 'getOtelMetaFields', {
|
|
2477
|
+
enumerable: true,
|
|
2478
|
+
get: function () {
|
|
2479
|
+
return getOtelMetaFields;
|
|
2480
|
+
}
|
|
2481
|
+
});
|
|
2482
|
+
Object.defineProperty(exports, 'getTraceContextKey', {
|
|
2483
|
+
enumerable: true,
|
|
2484
|
+
get: function () {
|
|
2485
|
+
return getTraceContextKey;
|
|
2486
|
+
}
|
|
2487
|
+
});
|
|
2488
|
+
Object.defineProperty(exports, 'globalPluginRegistry', {
|
|
2489
|
+
enumerable: true,
|
|
2490
|
+
get: function () {
|
|
2491
|
+
return globalPluginRegistry;
|
|
2492
|
+
}
|
|
2493
|
+
});
|
|
2494
|
+
Object.defineProperty(exports, 'initOtelBridge', {
|
|
2495
|
+
enumerable: true,
|
|
2496
|
+
get: function () {
|
|
2497
|
+
return initOtelBridge;
|
|
2498
|
+
}
|
|
2499
|
+
});
|
|
2500
|
+
Object.defineProperty(exports, 'isError', {
|
|
2501
|
+
enumerable: true,
|
|
2502
|
+
get: function () {
|
|
2503
|
+
return isError;
|
|
2504
|
+
}
|
|
2505
|
+
});
|
|
2506
|
+
Object.defineProperty(exports, 'normalizeError', {
|
|
2507
|
+
enumerable: true,
|
|
2508
|
+
get: function () {
|
|
2509
|
+
return normalizeError;
|
|
2510
|
+
}
|
|
2511
|
+
});
|
|
2512
|
+
Object.defineProperty(exports, 'redactObject', {
|
|
2513
|
+
enumerable: true,
|
|
2514
|
+
get: function () {
|
|
2515
|
+
return redactObject;
|
|
2516
|
+
}
|
|
2517
|
+
});
|
|
2518
|
+
Object.defineProperty(exports, 'registerForShutdown', {
|
|
2519
|
+
enumerable: true,
|
|
2520
|
+
get: function () {
|
|
2521
|
+
return registerForShutdown;
|
|
2522
|
+
}
|
|
2523
|
+
});
|
|
2524
|
+
Object.defineProperty(exports, 'resetShutdownHandlers', {
|
|
2525
|
+
enumerable: true,
|
|
2526
|
+
get: function () {
|
|
2527
|
+
return resetShutdownHandlers;
|
|
2528
|
+
}
|
|
2529
|
+
});
|
|
2530
|
+
Object.defineProperty(exports, 'resolveResponseHeader', {
|
|
2531
|
+
enumerable: true,
|
|
2532
|
+
get: function () {
|
|
2533
|
+
return resolveResponseHeader;
|
|
2534
|
+
}
|
|
2535
|
+
});
|
|
2536
|
+
Object.defineProperty(exports, 'runWithTraceId', {
|
|
2537
|
+
enumerable: true,
|
|
2538
|
+
get: function () {
|
|
2539
|
+
return runWithTraceId;
|
|
2540
|
+
}
|
|
2541
|
+
});
|
|
2542
|
+
Object.defineProperty(exports, 'serializeError', {
|
|
2543
|
+
enumerable: true,
|
|
2544
|
+
get: function () {
|
|
2545
|
+
return serializeError;
|
|
2546
|
+
}
|
|
2547
|
+
});
|
|
2548
|
+
Object.defineProperty(exports, 'setTraceId', {
|
|
2549
|
+
enumerable: true,
|
|
2550
|
+
get: function () {
|
|
2551
|
+
return setTraceId;
|
|
2552
|
+
}
|
|
2553
|
+
});
|
|
2554
|
+
Object.defineProperty(exports, 'traceStorage', {
|
|
2555
|
+
enumerable: true,
|
|
2556
|
+
get: function () {
|
|
2557
|
+
return traceStorage;
|
|
2558
|
+
}
|
|
2559
|
+
});
|
|
2560
|
+
Object.defineProperty(exports, 'usePlugin', {
|
|
2561
|
+
enumerable: true,
|
|
2562
|
+
get: function () {
|
|
2563
|
+
return usePlugin;
|
|
2564
|
+
}
|
|
2565
|
+
});
|
|
2566
|
+
//# sourceMappingURL=logitron-logger.module-CMDM61Iz.js.map
|