@mks2508/better-logger 0.18.2-alpha.1 → 0.18.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -336
- package/dist/Logger.d.ts +356 -157
- package/dist/Logger.d.ts.map +1 -1
- package/dist/ScopedLogger.d.ts +549 -9
- package/dist/ScopedLogger.d.ts.map +1 -1
- package/dist/chunks/HookBridge-C-AvXmPD.cjs +504 -0
- package/dist/chunks/HookBridge-C-AvXmPD.cjs.map +1 -0
- package/dist/chunks/HookBridge-CI2PH79S.js +487 -0
- package/dist/chunks/HookBridge-CI2PH79S.js.map +1 -0
- package/dist/chunks/{LogContext-L7HzynFw.cjs → LogContext-BaMXleWj.cjs} +19 -4
- package/dist/chunks/LogContext-BaMXleWj.cjs.map +1 -0
- package/dist/chunks/LogContext-DZasm_P5.cjs +141 -0
- package/dist/chunks/LogContext-DZasm_P5.cjs.map +1 -0
- package/dist/chunks/{LogContext-Cwn-1Zzb.js → LogContext-DjlITOzZ.js} +19 -4
- package/dist/chunks/LogContext-DjlITOzZ.js.map +1 -0
- package/dist/chunks/LogContext-Dyzs61XG.js +136 -0
- package/dist/chunks/LogContext-Dyzs61XG.js.map +1 -0
- package/dist/chunks/SerializerBridge-Ba43Mk7j.js +393 -0
- package/dist/chunks/SerializerBridge-Ba43Mk7j.js.map +1 -0
- package/dist/chunks/SerializerBridge-C4a9Z37F.cjs +410 -0
- package/dist/chunks/SerializerBridge-C4a9Z37F.cjs.map +1 -0
- package/dist/chunks/{StyleManager-CIpd6wbO.cjs → StyleManager-DQ6UNRB-.cjs} +37 -11
- package/dist/chunks/StyleManager-DQ6UNRB-.cjs.map +1 -0
- package/dist/chunks/StyleManager-DjwAYbxE.js +113 -0
- package/dist/chunks/StyleManager-DjwAYbxE.js.map +1 -0
- package/dist/chunks/{core-PoT7RrTK.js → core-Blfi2klP.js} +1 -4
- package/dist/chunks/core-Blfi2klP.js.map +1 -0
- package/dist/chunks/{core-Dzz7agGa.cjs → core-CqS_UBzJ.cjs} +1 -4
- package/dist/chunks/core-CqS_UBzJ.cjs.map +1 -0
- package/dist/chunks/{environment-detector-CI3TrWK_.js → environment-detector-7NvnYUfr.js} +11 -11
- package/dist/chunks/environment-detector-7NvnYUfr.js.map +1 -0
- package/dist/chunks/{environment-detector-Cnn6wr6O.cjs → environment-detector-D-tHkKWA.cjs} +11 -11
- package/dist/chunks/environment-detector-D-tHkKWA.cjs.map +1 -0
- package/dist/chunks/server-fallback-CaCPjWby.cjs +119 -0
- package/dist/chunks/server-fallback-CaCPjWby.cjs.map +1 -0
- package/dist/chunks/server-fallback-jj0T6XaK.js +114 -0
- package/dist/chunks/server-fallback-jj0T6XaK.js.map +1 -0
- package/dist/chunks/{spinner-DNvxbM9a.cjs → spinner-BHyYEXsM.cjs} +319 -37
- package/dist/chunks/spinner-BHyYEXsM.cjs.map +1 -0
- package/dist/chunks/{spinner-D3FsF78o.js → spinner-BtkwpzYv.js} +319 -37
- package/dist/chunks/spinner-BtkwpzYv.js.map +1 -0
- package/dist/chunks/styling-CRw3KQW4.js +1592 -0
- package/dist/chunks/styling-CRw3KQW4.js.map +1 -0
- package/dist/chunks/styling-Cel2wPRy.cjs +1645 -0
- package/dist/chunks/styling-Cel2wPRy.cjs.map +1 -0
- package/dist/chunks/transports-BGfwwakw.js +1237 -0
- package/dist/chunks/transports-BGfwwakw.js.map +1 -0
- package/dist/chunks/transports-BZ-Mc2IT.cjs +1450 -0
- package/dist/chunks/transports-BZ-Mc2IT.cjs.map +1 -0
- package/dist/chunks/transports-DvaLAeGJ.js +1403 -0
- package/dist/chunks/transports-DvaLAeGJ.js.map +1 -0
- package/dist/chunks/transports-yK6CL0Ml.cjs +1278 -0
- package/dist/chunks/transports-yK6CL0Ml.cjs.map +1 -0
- package/dist/chunks/{utils-BqlFYocD.cjs → utils-W_cxqriN.cjs} +44 -37
- package/dist/chunks/utils-W_cxqriN.cjs.map +1 -0
- package/dist/chunks/{utils-VETbVpkR.js → utils-tKfBAWUM.js} +44 -37
- package/dist/chunks/utils-tKfBAWUM.js.map +1 -0
- package/dist/cli/CommandProcessor.d.ts +166 -19
- package/dist/cli/CommandProcessor.d.ts.map +1 -1
- package/dist/cli/commands/ConfigCommand.d.ts +36 -1
- package/dist/cli/commands/ConfigCommand.d.ts.map +1 -1
- package/dist/cli/commands/ExportCommand.d.ts +49 -3
- package/dist/cli/commands/ExportCommand.d.ts.map +1 -1
- package/dist/cli/commands/ThemeCommand.d.ts +62 -3
- package/dist/cli/commands/ThemeCommand.d.ts.map +1 -1
- package/dist/cli/help.d.ts +30 -2
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/index.d.ts +29 -2
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli.cjs +2 -2
- package/dist/cli.js +2 -2
- package/dist/context/LogContext.d.ts +167 -70
- package/dist/context/LogContext.d.ts.map +1 -1
- package/dist/context.cjs +1 -1
- package/dist/context.js +1 -1
- package/dist/core.cjs +52 -29
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.ts +50 -27
- package/dist/core.d.ts.map +1 -1
- package/dist/core.js +52 -29
- package/dist/core.js.map +1 -1
- package/dist/hooks/HookBridge.d.ts +15 -9
- package/dist/hooks/HookBridge.d.ts.map +1 -1
- package/dist/hooks/HookManager.d.ts +295 -2
- package/dist/hooks/HookManager.d.ts.map +1 -1
- package/dist/hooks.cjs +1 -1
- package/dist/hooks.js +1 -1
- package/dist/index.cjs +1415 -214
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1413 -215
- package/dist/index.js.map +1 -1
- package/dist/playground/TerminalBridge.d.ts +23 -16
- package/dist/playground/TerminalBridge.d.ts.map +1 -1
- package/dist/playground/box.d.ts +36 -5
- package/dist/playground/box.d.ts.map +1 -1
- package/dist/playground/cli-table.d.ts +41 -5
- package/dist/playground/cli-table.d.ts.map +1 -1
- package/dist/playground/divider.d.ts +22 -3
- package/dist/playground/divider.d.ts.map +1 -1
- package/dist/playground/header.d.ts +21 -4
- package/dist/playground/header.d.ts.map +1 -1
- package/dist/playground/server-fallback.d.ts +96 -9
- package/dist/playground/server-fallback.d.ts.map +1 -1
- package/dist/playground/spinner.d.ts +159 -10
- package/dist/playground/spinner.d.ts.map +1 -1
- package/dist/playground/step.d.ts +25 -6
- package/dist/playground/step.d.ts.map +1 -1
- package/dist/playground.cjs +1 -1
- package/dist/playground.js +1 -1
- package/dist/serializers/SerializerBridge.d.ts +13 -6
- package/dist/serializers/SerializerBridge.d.ts.map +1 -1
- package/dist/serializers/SerializerRegistry.d.ts +236 -0
- package/dist/serializers/SerializerRegistry.d.ts.map +1 -1
- package/dist/serializers.cjs +1 -1
- package/dist/serializers.js +1 -1
- package/dist/styles/StyleManager.d.ts +138 -31
- package/dist/styles/StyleManager.d.ts.map +1 -1
- package/dist/styles.cjs +2 -2
- package/dist/styles.js +2 -2
- package/dist/styling/SmartPresets.d.ts +100 -6
- package/dist/styling/SmartPresets.d.ts.map +1 -1
- package/dist/styling/StyleBuilder.d.ts +453 -32
- package/dist/styling/StyleBuilder.d.ts.map +1 -1
- package/dist/styling/banners.d.ts +83 -7
- package/dist/styling/banners.d.ts.map +1 -1
- package/dist/styling/themes.d.ts +41 -2
- package/dist/styling/themes.d.ts.map +1 -1
- package/dist/transports/ConsoleTransport.d.ts +95 -0
- package/dist/transports/ConsoleTransport.d.ts.map +1 -1
- package/dist/transports/FileTransport.d.ts +99 -18
- package/dist/transports/FileTransport.d.ts.map +1 -1
- package/dist/transports/HttpTransport.d.ts +135 -22
- package/dist/transports/HttpTransport.d.ts.map +1 -1
- package/dist/transports/OtlpTraceTransport.d.ts +118 -0
- package/dist/transports/OtlpTraceTransport.d.ts.map +1 -0
- package/dist/transports/OtlpTransport.d.ts +80 -37
- package/dist/transports/OtlpTransport.d.ts.map +1 -1
- package/dist/transports/SpanRuntime.d.ts +73 -0
- package/dist/transports/SpanRuntime.d.ts.map +1 -0
- package/dist/transports/TransportBridge.d.ts +19 -13
- package/dist/transports/TransportBridge.d.ts.map +1 -1
- package/dist/transports/TransportManager.d.ts +232 -10
- package/dist/transports/TransportManager.d.ts.map +1 -1
- package/dist/transports/index.d.ts +1 -0
- package/dist/transports/index.d.ts.map +1 -1
- package/dist/transports-module.d.ts +3 -1
- package/dist/transports-module.d.ts.map +1 -1
- package/dist/transports.cjs +2 -1
- package/dist/transports.js +2 -2
- package/dist/types/core.d.ts +155 -59
- package/dist/types/core.d.ts.map +1 -1
- package/dist/types/hooks.d.ts +92 -14
- package/dist/types/hooks.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/serializers.d.ts +72 -0
- package/dist/types/serializers.d.ts.map +1 -1
- package/dist/types/transports.d.ts +163 -39
- package/dist/types/transports.d.ts.map +1 -1
- package/dist/utils/ansi-colors.d.ts +15 -15
- package/dist/utils/asyncLocalStorage.d.ts +33 -0
- package/dist/utils/asyncLocalStorage.d.ts.map +1 -0
- package/dist/utils/environment-detector.d.ts +11 -11
- package/dist/utils/formatting.d.ts +8 -8
- package/dist/utils/output.d.ts +9 -9
- package/dist/utils/output.d.ts.map +1 -1
- package/dist/utils/stackTrace.d.ts +2 -2
- package/package.json +24 -25
- package/dist/chunks/HookBridge-CiRfR67f.cjs +0 -190
- package/dist/chunks/HookBridge-CiRfR67f.cjs.map +0 -1
- package/dist/chunks/HookBridge-SgMmbXZB.js +0 -173
- package/dist/chunks/HookBridge-SgMmbXZB.js.map +0 -1
- package/dist/chunks/LogContext-Cwn-1Zzb.js.map +0 -1
- package/dist/chunks/LogContext-L7HzynFw.cjs.map +0 -1
- package/dist/chunks/SerializerBridge-BaOQOb8q.cjs +0 -166
- package/dist/chunks/SerializerBridge-BaOQOb8q.cjs.map +0 -1
- package/dist/chunks/SerializerBridge-BkpQu5c9.js +0 -149
- package/dist/chunks/SerializerBridge-BkpQu5c9.js.map +0 -1
- package/dist/chunks/StyleManager-CIpd6wbO.cjs.map +0 -1
- package/dist/chunks/StyleManager-LCvVlVdx.js +0 -87
- package/dist/chunks/StyleManager-LCvVlVdx.js.map +0 -1
- package/dist/chunks/core-Dzz7agGa.cjs.map +0 -1
- package/dist/chunks/core-PoT7RrTK.js.map +0 -1
- package/dist/chunks/environment-detector-CI3TrWK_.js.map +0 -1
- package/dist/chunks/environment-detector-Cnn6wr6O.cjs.map +0 -1
- package/dist/chunks/server-fallback-BUKjdLS7.cjs +0 -42
- package/dist/chunks/server-fallback-BUKjdLS7.cjs.map +0 -1
- package/dist/chunks/server-fallback-BsuWH1Dk.js +0 -37
- package/dist/chunks/server-fallback-BsuWH1Dk.js.map +0 -1
- package/dist/chunks/spinner-D3FsF78o.js.map +0 -1
- package/dist/chunks/spinner-DNvxbM9a.cjs.map +0 -1
- package/dist/chunks/styling-84N8T97t.js +0 -941
- package/dist/chunks/styling-84N8T97t.js.map +0 -1
- package/dist/chunks/styling-Cg5saQ46.cjs +0 -994
- package/dist/chunks/styling-Cg5saQ46.cjs.map +0 -1
- package/dist/chunks/transports-BiDk345e.js +0 -715
- package/dist/chunks/transports-BiDk345e.js.map +0 -1
- package/dist/chunks/transports-COPWmlF1.cjs +0 -756
- package/dist/chunks/transports-COPWmlF1.cjs.map +0 -1
- package/dist/chunks/utils-BqlFYocD.cjs.map +0 -1
- package/dist/chunks/utils-VETbVpkR.js.map +0 -1
- package/dist/example.d.ts +0 -18
- package/dist/example.d.ts.map +0 -1
- package/dist/main.d.ts +0 -2
- package/dist/main.d.ts.map +0 -1
|
@@ -1,756 +0,0 @@
|
|
|
1
|
-
const require_core = require("./core-Dzz7agGa.cjs");
|
|
2
|
-
//#region src/types/transports.ts
|
|
3
|
-
/**
|
|
4
|
-
* Map a `LogLevel` to the OpenTelemetry numeric severity (1-24) used by
|
|
5
|
-
* SigNoz / any OTLP/HTTP backend. Spec-compliant banded values:
|
|
6
|
-
* TRACE=1-4, DEBUG=5-8, INFO=9-12, WARN=13-16, ERROR=17-20, FATAL=21-24
|
|
7
|
-
* We use the canonical mid-band value per level.
|
|
8
|
-
*
|
|
9
|
-
* @see https://opentelemetry.io/docs/specs/otel/logs/data-model/#severity-fields
|
|
10
|
-
*/
|
|
11
|
-
const LOG_LEVEL_TO_SEVERITY_NUMBER = {
|
|
12
|
-
trace: 1,
|
|
13
|
-
debug: 5,
|
|
14
|
-
info: 9,
|
|
15
|
-
warn: 13,
|
|
16
|
-
error: 17,
|
|
17
|
-
critical: 21
|
|
18
|
-
};
|
|
19
|
-
/**
|
|
20
|
-
* Map a `LogLevel` to its OpenTelemetry severity name (uppercase, OTel spec).
|
|
21
|
-
*/
|
|
22
|
-
const LOG_LEVEL_TO_SEVERITY_TEXT = {
|
|
23
|
-
trace: "TRACE",
|
|
24
|
-
debug: "DEBUG",
|
|
25
|
-
info: "INFO",
|
|
26
|
-
warn: "WARN",
|
|
27
|
-
error: "ERROR",
|
|
28
|
-
critical: "FATAL"
|
|
29
|
-
};
|
|
30
|
-
//#endregion
|
|
31
|
-
//#region src/transports/ConsoleTransport.ts
|
|
32
|
-
var ConsoleTransport = class {
|
|
33
|
-
options;
|
|
34
|
-
name = "console";
|
|
35
|
-
constructor(options) {
|
|
36
|
-
this.options = options;
|
|
37
|
-
}
|
|
38
|
-
write(record) {
|
|
39
|
-
const method = this.getConsoleMethod(record.level);
|
|
40
|
-
const prefix = record.prefix ? `[${record.prefix}] ` : "";
|
|
41
|
-
const location = record.location ? ` (${record.location.file}:${record.location.line})` : "";
|
|
42
|
-
console[method](`[${record.level.toUpperCase()}]${prefix} ${record.msg}${location}`);
|
|
43
|
-
}
|
|
44
|
-
getConsoleMethod(level) {
|
|
45
|
-
switch (level) {
|
|
46
|
-
case "debug": return "log";
|
|
47
|
-
case "info": return "info";
|
|
48
|
-
case "warn": return "warn";
|
|
49
|
-
case "error":
|
|
50
|
-
case "critical": return "error";
|
|
51
|
-
default: return "log";
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
//#endregion
|
|
56
|
-
//#region src/transports/FileTransport.ts
|
|
57
|
-
const MAX_BUFFER_DEFAULT = 1e4;
|
|
58
|
-
const BATCH_SIZE_DEFAULT = 100;
|
|
59
|
-
const FS_PROMISES_LOAD_TIMEOUT_MS = 50;
|
|
60
|
-
const LOCAL_STORAGE_KEY_PREFIX = "better-logger:";
|
|
61
|
-
/**
|
|
62
|
-
* File-based transport.
|
|
63
|
-
*
|
|
64
|
-
* - In Node, writes batches via `fs.promises.appendFile` (non-blocking).
|
|
65
|
-
* - In the browser, writes batches into `localStorage` (fallback no-op if
|
|
66
|
-
* `localStorage` is unavailable — e.g. private mode, sandboxed iframes).
|
|
67
|
-
*
|
|
68
|
-
* Fixed in 5.1.0:
|
|
69
|
-
* - BUG-N3: uses async `fs.promises.appendFile` instead of sync `appendFileSync`.
|
|
70
|
-
* - BUG-N4: destination is sanitised to reject path traversal (`..`, `~`, abs paths).
|
|
71
|
-
* - BUG-N5: dynamic `import('node:fs/promises')` instead of CJS `require('fs')`.
|
|
72
|
-
* - BUG-N6: browser case uses `localStorage` with try/catch (was silent no-op).
|
|
73
|
-
*
|
|
74
|
-
*/
|
|
75
|
-
var FileTransport = class {
|
|
76
|
-
name = "file";
|
|
77
|
-
buffer = [];
|
|
78
|
-
flushTimer;
|
|
79
|
-
options;
|
|
80
|
-
closed = false;
|
|
81
|
-
constructor(options) {
|
|
82
|
-
this.options = {
|
|
83
|
-
batchSize: BATCH_SIZE_DEFAULT,
|
|
84
|
-
maxBufferSize: MAX_BUFFER_DEFAULT,
|
|
85
|
-
...options ?? {}
|
|
86
|
-
};
|
|
87
|
-
if (this.options.flushInterval) this.flushTimer = setInterval(() => {
|
|
88
|
-
this.flush();
|
|
89
|
-
}, this.options.flushInterval);
|
|
90
|
-
}
|
|
91
|
-
get bufferSize() {
|
|
92
|
-
return this.buffer.length;
|
|
93
|
-
}
|
|
94
|
-
get maxBufferSize() {
|
|
95
|
-
return this.options.maxBufferSize ?? MAX_BUFFER_DEFAULT;
|
|
96
|
-
}
|
|
97
|
-
isReady() {
|
|
98
|
-
return !this.closed;
|
|
99
|
-
}
|
|
100
|
-
write(record) {
|
|
101
|
-
if (this.closed) return;
|
|
102
|
-
if (this.buffer.length >= this.maxBufferSize) {
|
|
103
|
-
const dropped = this.buffer.shift();
|
|
104
|
-
if (dropped && this.options.onError) {
|
|
105
|
-
const entry = {
|
|
106
|
-
level: "warn",
|
|
107
|
-
message: "FileTransport buffer overflow: oldest record dropped",
|
|
108
|
-
args: [],
|
|
109
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
110
|
-
hookEvent: "onError",
|
|
111
|
-
error: /* @__PURE__ */ new Error("FileTransport buffer overflow"),
|
|
112
|
-
extra: { droppedRecord: dropped }
|
|
113
|
-
};
|
|
114
|
-
this.options.onError(entry);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
this.buffer.push(JSON.stringify(record) + "\n");
|
|
118
|
-
const batchSize = this.options.batchSize ?? BATCH_SIZE_DEFAULT;
|
|
119
|
-
if (this.buffer.length >= batchSize) this.flush();
|
|
120
|
-
}
|
|
121
|
-
async flush() {
|
|
122
|
-
if (this.closed || this.buffer.length === 0) return;
|
|
123
|
-
const payload = this.buffer.join("");
|
|
124
|
-
this.buffer = [];
|
|
125
|
-
if (isNodeLike()) await this.flushNode(payload);
|
|
126
|
-
else await this.flushBrowser(payload);
|
|
127
|
-
}
|
|
128
|
-
async flushNode(payload) {
|
|
129
|
-
const destination = this.resolveNodeDestination();
|
|
130
|
-
try {
|
|
131
|
-
await (await loadNodeFsPromises()).appendFile(destination, payload, "utf8");
|
|
132
|
-
} catch (error) {
|
|
133
|
-
this.emitError("FileTransport failed to write to disk", error);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
async flushBrowser(payload) {
|
|
137
|
-
if (typeof localStorage === "undefined") {
|
|
138
|
-
this.emitError("FileTransport: localStorage is not available in this environment", null);
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
try {
|
|
142
|
-
const key = LOCAL_STORAGE_KEY_PREFIX + this.resolveBrowserKey();
|
|
143
|
-
const existing = localStorage.getItem(key) ?? "";
|
|
144
|
-
localStorage.setItem(key, existing + payload);
|
|
145
|
-
} catch (error) {
|
|
146
|
-
this.emitError("FileTransport: localStorage write failed (quota? private mode?)", error);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
async close() {
|
|
150
|
-
this.closed = true;
|
|
151
|
-
if (this.flushTimer) {
|
|
152
|
-
clearInterval(this.flushTimer);
|
|
153
|
-
this.flushTimer = void 0;
|
|
154
|
-
}
|
|
155
|
-
await this.flush();
|
|
156
|
-
}
|
|
157
|
-
resolveNodeDestination() {
|
|
158
|
-
const requested = this.options.destination ?? "app.log";
|
|
159
|
-
const sanitised = sanitiseNodePath(requested);
|
|
160
|
-
if (sanitised === null) {
|
|
161
|
-
this.emitError(`FileTransport: refusing destination with traversal segment: ${requested}`, null);
|
|
162
|
-
return "app.log";
|
|
163
|
-
}
|
|
164
|
-
return sanitised;
|
|
165
|
-
}
|
|
166
|
-
resolveBrowserKey() {
|
|
167
|
-
return sanitiseBrowserKey(this.options.destination ?? "default");
|
|
168
|
-
}
|
|
169
|
-
emitError(message, cause) {
|
|
170
|
-
if (!this.options.onError) return;
|
|
171
|
-
const entry = {
|
|
172
|
-
level: "error",
|
|
173
|
-
message,
|
|
174
|
-
args: [],
|
|
175
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
176
|
-
hookEvent: "onError",
|
|
177
|
-
error: cause instanceof Error ? cause : new Error(String(cause))
|
|
178
|
-
};
|
|
179
|
-
this.options.onError(entry);
|
|
180
|
-
}
|
|
181
|
-
};
|
|
182
|
-
function isNodeLike() {
|
|
183
|
-
return typeof process !== "undefined" && process.versions != null && process.versions.node != null;
|
|
184
|
-
}
|
|
185
|
-
/**
|
|
186
|
-
* Reject paths that escape the working directory. Allows relative paths
|
|
187
|
-
* under `cwd/`. Absolute paths are rejected by default — if a caller needs
|
|
188
|
-
* an absolute location, pass it through a documented escape hatch (not
|
|
189
|
-
* exposed here on purpose).
|
|
190
|
-
*/
|
|
191
|
-
function sanitiseNodePath(input) {
|
|
192
|
-
if (!input) return null;
|
|
193
|
-
const normalised = input.replace(/\\/g, "/").trim();
|
|
194
|
-
if (normalised.length === 0) return null;
|
|
195
|
-
if (normalised.startsWith("/") || /^[a-zA-Z]:\//.test(normalised)) return null;
|
|
196
|
-
const segments = normalised.split("/").filter((s) => s.length > 0 && s !== ".");
|
|
197
|
-
if (segments.some((s) => s === ".." || s === "~")) return null;
|
|
198
|
-
return segments.join("/");
|
|
199
|
-
}
|
|
200
|
-
function sanitiseBrowserKey(input) {
|
|
201
|
-
return input.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 64) || "default";
|
|
202
|
-
}
|
|
203
|
-
/**
|
|
204
|
-
* Cached dynamic import of `node:fs/promises`. The cache is intentionally
|
|
205
|
-
* module-scoped so subsequent flushes don't pay the import cost.
|
|
206
|
-
*/
|
|
207
|
-
let _fsPromisesPromise = null;
|
|
208
|
-
async function loadNodeFsPromises() {
|
|
209
|
-
if (_fsPromisesPromise) return _fsPromisesPromise;
|
|
210
|
-
const importPromise = import("node:fs/promises");
|
|
211
|
-
const timeoutPromise = new Promise((_, reject) => {
|
|
212
|
-
setTimeout(() => reject(/* @__PURE__ */ new Error(`fs/promises import timed out after ${FS_PROMISES_LOAD_TIMEOUT_MS}ms`)), FS_PROMISES_LOAD_TIMEOUT_MS);
|
|
213
|
-
});
|
|
214
|
-
_fsPromisesPromise = Promise.race([importPromise, timeoutPromise]).catch((err) => {
|
|
215
|
-
_fsPromisesPromise = null;
|
|
216
|
-
throw err;
|
|
217
|
-
});
|
|
218
|
-
return _fsPromisesPromise;
|
|
219
|
-
}
|
|
220
|
-
//#endregion
|
|
221
|
-
//#region src/transports/HttpTransport.ts
|
|
222
|
-
const DEFAULT_MAX_BUFFER = 1e4;
|
|
223
|
-
const DEFAULT_BATCH_SIZE = 50;
|
|
224
|
-
const DEFAULT_MAX_RETRIES = 3;
|
|
225
|
-
const DEFAULT_INITIAL_BACKOFF = 250;
|
|
226
|
-
const DEFAULT_MAX_BACKOFF = 5e3;
|
|
227
|
-
const DEFAULT_FETCH_TIMEOUT = 1e4;
|
|
228
|
-
/**
|
|
229
|
-
* HTTP-based transport. Buffers records, batches them on size or interval,
|
|
230
|
-
* POSTs the batch as JSON, and surfaces failures via retry, bounded buffer,
|
|
231
|
-
* and an `onError` hook — never a silent `.catch(() => {})`.
|
|
232
|
-
*
|
|
233
|
-
* Extending this class is the recommended way to ship a new transport:
|
|
234
|
-
* see {@link OtlpTransport}.
|
|
235
|
-
*
|
|
236
|
-
*/
|
|
237
|
-
var HttpTransport = class {
|
|
238
|
-
name = "http";
|
|
239
|
-
buffer = [];
|
|
240
|
-
flushTimer;
|
|
241
|
-
closed = false;
|
|
242
|
-
/** Options bag — `protected` so subclasses (e.g. {@link OtlpTransport}) can read or extend it. */
|
|
243
|
-
options;
|
|
244
|
-
constructor(options) {
|
|
245
|
-
this.options = {
|
|
246
|
-
batchSize: DEFAULT_BATCH_SIZE,
|
|
247
|
-
maxBufferSize: DEFAULT_MAX_BUFFER,
|
|
248
|
-
maxRetries: DEFAULT_MAX_RETRIES,
|
|
249
|
-
initialBackoffMs: DEFAULT_INITIAL_BACKOFF,
|
|
250
|
-
maxBackoffMs: DEFAULT_MAX_BACKOFF,
|
|
251
|
-
fetchTimeoutMs: DEFAULT_FETCH_TIMEOUT,
|
|
252
|
-
...options ?? {}
|
|
253
|
-
};
|
|
254
|
-
if (this.options.flushInterval) this.flushTimer = setInterval(() => {
|
|
255
|
-
this.flush();
|
|
256
|
-
}, this.options.flushInterval);
|
|
257
|
-
}
|
|
258
|
-
get bufferSize() {
|
|
259
|
-
return this.buffer.length;
|
|
260
|
-
}
|
|
261
|
-
get maxBufferSize() {
|
|
262
|
-
return this.options.maxBufferSize ?? DEFAULT_MAX_BUFFER;
|
|
263
|
-
}
|
|
264
|
-
isReady() {
|
|
265
|
-
return !this.closed && Boolean(this.options.url);
|
|
266
|
-
}
|
|
267
|
-
write(record) {
|
|
268
|
-
if (this.closed) return;
|
|
269
|
-
if (this.buffer.length >= this.maxBufferSize) this.applyOverflowPolicy();
|
|
270
|
-
this.buffer.push(record);
|
|
271
|
-
const batchSize = this.options.batchSize ?? DEFAULT_BATCH_SIZE;
|
|
272
|
-
if (this.buffer.length >= batchSize) this.flush();
|
|
273
|
-
}
|
|
274
|
-
/**
|
|
275
|
-
* Serialises a batch into the request body. Subclasses override to
|
|
276
|
-
* switch encodings (e.g. {@link OtlpTransport} produces OTLP/HTTP JSON
|
|
277
|
-
* instead of the default `{ logs: [...] }` envelope).
|
|
278
|
-
*
|
|
279
|
-
*/
|
|
280
|
-
serializeBody(records) {
|
|
281
|
-
return JSON.stringify({ logs: records });
|
|
282
|
-
}
|
|
283
|
-
/**
|
|
284
|
-
* Builds the request headers. Subclasses may prepend transport-specific
|
|
285
|
-
* headers (e.g. `signoz-ingestion-key`).
|
|
286
|
-
*
|
|
287
|
-
*/
|
|
288
|
-
buildHeaders() {
|
|
289
|
-
return {
|
|
290
|
-
"Content-Type": "application/json",
|
|
291
|
-
...this.options.headers ?? {}
|
|
292
|
-
};
|
|
293
|
-
}
|
|
294
|
-
applyOverflowPolicy() {
|
|
295
|
-
const dropped = this.buffer.shift();
|
|
296
|
-
if (dropped && this.options.onError) {
|
|
297
|
-
const entry = {
|
|
298
|
-
level: "warn",
|
|
299
|
-
message: "HttpTransport buffer overflow: oldest record dropped",
|
|
300
|
-
args: [dropped],
|
|
301
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
302
|
-
hookEvent: "onError",
|
|
303
|
-
error: /* @__PURE__ */ new Error("HttpTransport buffer overflow"),
|
|
304
|
-
extra: { droppedRecord: dropped }
|
|
305
|
-
};
|
|
306
|
-
this.options.onError(entry);
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
async flush() {
|
|
310
|
-
if (this.closed || this.buffer.length === 0 || !this.options.url) return;
|
|
311
|
-
const records = [...this.buffer];
|
|
312
|
-
this.buffer = [];
|
|
313
|
-
if (!await this.sendWithRetry(records)) {
|
|
314
|
-
const combined = records.concat(this.buffer);
|
|
315
|
-
if (combined.length > this.maxBufferSize) {
|
|
316
|
-
const trimmed = combined.slice(combined.length - this.maxBufferSize);
|
|
317
|
-
const droppedCount = combined.length - trimmed.length;
|
|
318
|
-
if (droppedCount > 0 && this.options.onError) {
|
|
319
|
-
const entry = {
|
|
320
|
-
level: "error",
|
|
321
|
-
message: `HttpTransport dropped ${droppedCount} records after retry exhaustion`,
|
|
322
|
-
args: [],
|
|
323
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
324
|
-
hookEvent: "onError",
|
|
325
|
-
error: /* @__PURE__ */ new Error("HttpTransport retry exhaustion"),
|
|
326
|
-
extra: { droppedCount }
|
|
327
|
-
};
|
|
328
|
-
this.options.onError(entry);
|
|
329
|
-
}
|
|
330
|
-
this.buffer = trimmed;
|
|
331
|
-
} else this.buffer = combined;
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
async sendWithRetry(records) {
|
|
335
|
-
const url = this.options.url;
|
|
336
|
-
if (!url) return false;
|
|
337
|
-
const maxRetries = this.options.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
338
|
-
const initialBackoff = this.options.initialBackoffMs ?? DEFAULT_INITIAL_BACKOFF;
|
|
339
|
-
const maxBackoff = this.options.maxBackoffMs ?? DEFAULT_MAX_BACKOFF;
|
|
340
|
-
const fetchTimeout = this.options.fetchTimeoutMs ?? DEFAULT_FETCH_TIMEOUT;
|
|
341
|
-
const body = this.serializeBody(records);
|
|
342
|
-
const headers = this.buildHeaders();
|
|
343
|
-
let attempt = 0;
|
|
344
|
-
let backoff = initialBackoff;
|
|
345
|
-
while (attempt <= maxRetries) {
|
|
346
|
-
try {
|
|
347
|
-
const controller = new AbortController();
|
|
348
|
-
const timeoutId = setTimeout(() => controller.abort(), fetchTimeout);
|
|
349
|
-
const response = await fetch(url, {
|
|
350
|
-
method: "POST",
|
|
351
|
-
headers,
|
|
352
|
-
body,
|
|
353
|
-
signal: controller.signal
|
|
354
|
-
});
|
|
355
|
-
clearTimeout(timeoutId);
|
|
356
|
-
if (response.ok) return true;
|
|
357
|
-
if (response.status >= 400 && response.status < 500) {
|
|
358
|
-
if (this.options.onError) {
|
|
359
|
-
const entry = {
|
|
360
|
-
level: "error",
|
|
361
|
-
message: `HttpTransport ${response.status} ${response.statusText} (not retried)`,
|
|
362
|
-
args: [],
|
|
363
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
364
|
-
hookEvent: "onError",
|
|
365
|
-
error: /* @__PURE__ */ new Error(`HTTP ${response.status}`),
|
|
366
|
-
extra: { responseStatus: response.status }
|
|
367
|
-
};
|
|
368
|
-
this.options.onError(entry);
|
|
369
|
-
}
|
|
370
|
-
return false;
|
|
371
|
-
}
|
|
372
|
-
if (attempt === maxRetries) break;
|
|
373
|
-
await sleep(backoff);
|
|
374
|
-
backoff = Math.min(backoff * 2, maxBackoff);
|
|
375
|
-
} catch (error) {
|
|
376
|
-
if (attempt === maxRetries) {
|
|
377
|
-
if (this.options.onError) {
|
|
378
|
-
const entry = {
|
|
379
|
-
level: "error",
|
|
380
|
-
message: `HttpTransport fetch failed after ${maxRetries + 1} attempts`,
|
|
381
|
-
args: [],
|
|
382
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
383
|
-
hookEvent: "onError",
|
|
384
|
-
error: error instanceof Error ? error : new Error(String(error))
|
|
385
|
-
};
|
|
386
|
-
this.options.onError(entry);
|
|
387
|
-
}
|
|
388
|
-
return false;
|
|
389
|
-
}
|
|
390
|
-
await sleep(backoff);
|
|
391
|
-
backoff = Math.min(backoff * 2, maxBackoff);
|
|
392
|
-
}
|
|
393
|
-
attempt++;
|
|
394
|
-
}
|
|
395
|
-
return false;
|
|
396
|
-
}
|
|
397
|
-
async close() {
|
|
398
|
-
this.closed = true;
|
|
399
|
-
if (this.flushTimer) {
|
|
400
|
-
clearInterval(this.flushTimer);
|
|
401
|
-
this.flushTimer = void 0;
|
|
402
|
-
}
|
|
403
|
-
await this.flush();
|
|
404
|
-
}
|
|
405
|
-
};
|
|
406
|
-
function sleep(ms) {
|
|
407
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
408
|
-
}
|
|
409
|
-
//#endregion
|
|
410
|
-
//#region src/transports/OtlpTransport.ts
|
|
411
|
-
/**
|
|
412
|
-
* OTLP/HTTP transport for SigNoz (or any OTLP-compliant backend).
|
|
413
|
-
*
|
|
414
|
-
* Extends {@link HttpTransport} — inherits retry, bounded buffer, status
|
|
415
|
-
* check, async close, and the on-error hook. Overrides only the payload
|
|
416
|
-
* shape and the request headers.
|
|
417
|
-
*
|
|
418
|
-
* ```ts
|
|
419
|
-
* logger.addTransport({
|
|
420
|
-
* target: new OtlpTransport({
|
|
421
|
-
* endpoint: 'https://otelcollector.example.com:4318',
|
|
422
|
-
* serviceName: 'my-app',
|
|
423
|
-
* serviceVersion: '1.2.3',
|
|
424
|
-
* environment: 'production',
|
|
425
|
-
* ingestKeyEnvVar: 'SIGNOZ_KEY'
|
|
426
|
-
* })
|
|
427
|
-
* });
|
|
428
|
-
* ```
|
|
429
|
-
*
|
|
430
|
-
*/
|
|
431
|
-
var OtlpTransport = class extends HttpTransport {
|
|
432
|
-
name = "otlp";
|
|
433
|
-
resource;
|
|
434
|
-
/** Resolved at construction. Never logged, never written to source. */
|
|
435
|
-
ingestKeyValue;
|
|
436
|
-
constructor(options) {
|
|
437
|
-
if (!options.endpoint) throw new Error("OtlpTransport: `endpoint` is required");
|
|
438
|
-
if (!options.serviceName) throw new Error("OtlpTransport: `serviceName` is required");
|
|
439
|
-
const ingestKey = readIngestKey(options.ingestKeyEnvVar);
|
|
440
|
-
const httpOptions = {
|
|
441
|
-
url: `${stripTrailingSlash(options.endpoint)}/v1/logs`,
|
|
442
|
-
headers: {
|
|
443
|
-
...ingestKey ? { "signoz-ingestion-key": ingestKey } : {},
|
|
444
|
-
...options.headers ?? {}
|
|
445
|
-
},
|
|
446
|
-
batchSize: options.batchSize,
|
|
447
|
-
flushInterval: options.flushInterval,
|
|
448
|
-
maxBufferSize: options.maxBufferSize,
|
|
449
|
-
maxRetries: options.maxRetries,
|
|
450
|
-
initialBackoffMs: options.initialBackoffMs,
|
|
451
|
-
maxBackoffMs: options.maxBackoffMs,
|
|
452
|
-
fetchTimeoutMs: options.fetchTimeoutMs,
|
|
453
|
-
onError: options.onError
|
|
454
|
-
};
|
|
455
|
-
super(httpOptions);
|
|
456
|
-
this.resource = {
|
|
457
|
-
"service.name": options.serviceName,
|
|
458
|
-
...options.serviceVersion ? { "service.version": options.serviceVersion } : {},
|
|
459
|
-
...options.environment ? { "deployment.environment": options.environment } : {},
|
|
460
|
-
...options.resourceAttributes ?? {}
|
|
461
|
-
};
|
|
462
|
-
this.ingestKeyValue = ingestKey;
|
|
463
|
-
}
|
|
464
|
-
/**
|
|
465
|
-
* Builds the OTLP/HTTP JSON payload from the currently buffered records.
|
|
466
|
-
* One `resourceLogs` block per batch (matches OTel collector batching
|
|
467
|
-
* guidance). Exposed for tests + custom transport subclasses.
|
|
468
|
-
*
|
|
469
|
-
*/
|
|
470
|
-
buildPayload(records) {
|
|
471
|
-
return { resourceLogs: [{
|
|
472
|
-
resource: { attributes: Object.entries(this.resource).filter((entry) => typeof entry[1] === "string").map(([key, value]) => ({
|
|
473
|
-
key,
|
|
474
|
-
value: { stringValue: value }
|
|
475
|
-
})) },
|
|
476
|
-
scopeLogs: [{
|
|
477
|
-
scope: {
|
|
478
|
-
name: "better-logger",
|
|
479
|
-
version: "5.1.0"
|
|
480
|
-
},
|
|
481
|
-
logRecords: records.map((r) => this.toLogRecord(r))
|
|
482
|
-
}]
|
|
483
|
-
}] };
|
|
484
|
-
}
|
|
485
|
-
/**
|
|
486
|
-
* Serialises a batch into the OTLP/HTTP JSON request body. Overrides
|
|
487
|
-
* {@link HttpTransport.serializeBody}.
|
|
488
|
-
*
|
|
489
|
-
*/
|
|
490
|
-
serializeBody(records) {
|
|
491
|
-
return JSON.stringify(this.buildPayload(records));
|
|
492
|
-
}
|
|
493
|
-
/**
|
|
494
|
-
* Builds request headers. Adds `signoz-ingestion-key` from the value
|
|
495
|
-
* resolved at construction time (never logged, never written to source).
|
|
496
|
-
*
|
|
497
|
-
*/
|
|
498
|
-
buildHeaders() {
|
|
499
|
-
return {
|
|
500
|
-
"Content-Type": "application/json",
|
|
501
|
-
...this.ingestKeyValue ? { "signoz-ingestion-key": this.ingestKeyValue } : {},
|
|
502
|
-
...this.options.headers ?? {}
|
|
503
|
-
};
|
|
504
|
-
}
|
|
505
|
-
toLogRecord(record) {
|
|
506
|
-
const timeUnixNano = String(BigInt(record.time) * 1000000n);
|
|
507
|
-
const base = {
|
|
508
|
-
timeUnixNano,
|
|
509
|
-
observedTimeUnixNano: timeUnixNano,
|
|
510
|
-
severityNumber: LOG_LEVEL_TO_SEVERITY_NUMBER[record.level],
|
|
511
|
-
severityText: record.severityText,
|
|
512
|
-
body: { stringValue: record.msg }
|
|
513
|
-
};
|
|
514
|
-
const attributes = collectAttributes(record);
|
|
515
|
-
if (attributes.length > 0) base.attributes = attributes;
|
|
516
|
-
if (record.traceId) base.traceId = record.traceId;
|
|
517
|
-
if (record.spanId) base.spanId = record.spanId;
|
|
518
|
-
return base;
|
|
519
|
-
}
|
|
520
|
-
};
|
|
521
|
-
function stripTrailingSlash(value) {
|
|
522
|
-
return value.endsWith("/") ? value.slice(0, -1) : value;
|
|
523
|
-
}
|
|
524
|
-
/**
|
|
525
|
-
* Reads the ingest API key from `process.env[name]`. Returns undefined
|
|
526
|
-
* silently if `process` is unavailable (strict browser bundles) or the
|
|
527
|
-
* variable is unset. Never throws, never logs the value.
|
|
528
|
-
*/
|
|
529
|
-
function readIngestKey(envVarName) {
|
|
530
|
-
if (!envVarName) return void 0;
|
|
531
|
-
if (typeof process === "undefined") return void 0;
|
|
532
|
-
const value = process.env?.[envVarName];
|
|
533
|
-
if (!value) return void 0;
|
|
534
|
-
return value;
|
|
535
|
-
}
|
|
536
|
-
function collectAttributes(record) {
|
|
537
|
-
const out = [];
|
|
538
|
-
if (record.prefix) out.push({
|
|
539
|
-
key: "logger.prefix",
|
|
540
|
-
value: { stringValue: record.prefix }
|
|
541
|
-
});
|
|
542
|
-
if (record.tag) out.push({
|
|
543
|
-
key: "logger.tag",
|
|
544
|
-
value: { stringValue: record.tag }
|
|
545
|
-
});
|
|
546
|
-
if (record.location) {
|
|
547
|
-
out.push({
|
|
548
|
-
key: "code.filepath",
|
|
549
|
-
value: { stringValue: record.location.file }
|
|
550
|
-
});
|
|
551
|
-
out.push({
|
|
552
|
-
key: "code.lineno",
|
|
553
|
-
value: { intValue: record.location.line }
|
|
554
|
-
});
|
|
555
|
-
if (record.location.function) out.push({
|
|
556
|
-
key: "code.function",
|
|
557
|
-
value: { stringValue: record.location.function }
|
|
558
|
-
});
|
|
559
|
-
}
|
|
560
|
-
if (record.attributes) for (const [key, value] of Object.entries(record.attributes)) {
|
|
561
|
-
const mapped = toOtlpAttribute(value);
|
|
562
|
-
if (mapped) out.push({
|
|
563
|
-
key,
|
|
564
|
-
value: mapped
|
|
565
|
-
});
|
|
566
|
-
}
|
|
567
|
-
return out;
|
|
568
|
-
}
|
|
569
|
-
function toOtlpAttribute(value) {
|
|
570
|
-
if (value === null || value === void 0) return null;
|
|
571
|
-
if (typeof value === "string") return { stringValue: value };
|
|
572
|
-
if (typeof value === "number") {
|
|
573
|
-
if (Number.isInteger(value)) return { intValue: value };
|
|
574
|
-
return { doubleValue: value };
|
|
575
|
-
}
|
|
576
|
-
if (typeof value === "boolean") return { boolValue: value };
|
|
577
|
-
if (Array.isArray(value)) return { arrayValue: { values: value.map((v) => toOtlpAttribute(v)).filter((v) => v !== null) } };
|
|
578
|
-
return { stringValue: JSON.stringify(value) };
|
|
579
|
-
}
|
|
580
|
-
//#endregion
|
|
581
|
-
//#region src/transports/TransportManager.ts
|
|
582
|
-
function generateTransportId() {
|
|
583
|
-
return `transport-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
584
|
-
}
|
|
585
|
-
/**
|
|
586
|
-
* Built-in registry of named transports. Users can call
|
|
587
|
-
* {@link TransportManager.register} to add their own (e.g. a custom
|
|
588
|
-
* Datadog or Loki transport) and then instantiate it via
|
|
589
|
-
* `addTransport({ target: 'datadog', options })`.
|
|
590
|
-
*
|
|
591
|
-
* The four built-ins are registered automatically:
|
|
592
|
-
* - `'console'` → {@link ConsoleTransport}
|
|
593
|
-
* - `'file'` → {@link FileTransport}
|
|
594
|
-
* - `'http'` → {@link HttpTransport}
|
|
595
|
-
* - `'otlp'` → {@link OtlpTransport}
|
|
596
|
-
*/
|
|
597
|
-
const BUILTIN_REGISTRY = /* @__PURE__ */ new Map([
|
|
598
|
-
["console", ConsoleTransport],
|
|
599
|
-
["file", FileTransport],
|
|
600
|
-
["http", HttpTransport],
|
|
601
|
-
["otlp", OtlpTransport]
|
|
602
|
-
]);
|
|
603
|
-
var TransportManager = class {
|
|
604
|
-
transports = /* @__PURE__ */ new Map();
|
|
605
|
-
defaultLevel = "info";
|
|
606
|
-
registry = new Map(BUILTIN_REGISTRY);
|
|
607
|
-
constructor(defaultLevel) {
|
|
608
|
-
if (defaultLevel) this.defaultLevel = defaultLevel;
|
|
609
|
-
}
|
|
610
|
-
/**
|
|
611
|
-
* Registers a custom transport under a string name. Once registered,
|
|
612
|
-
* `addTransport({ target: 'name', options })` instantiates it.
|
|
613
|
-
*
|
|
614
|
-
* @example
|
|
615
|
-
* transportManager.register('datadog', DatadogTransport);
|
|
616
|
-
* transportManager.add({ target: 'datadog', options: { apiKey: env('DD_KEY') } });
|
|
617
|
-
*
|
|
618
|
-
*/
|
|
619
|
-
register(name, ctor) {
|
|
620
|
-
if (BUILTIN_REGISTRY.has(name)) throw new Error(`TransportManager.register: '${name}' is a built-in and cannot be overridden`);
|
|
621
|
-
this.registry.set(name, ctor);
|
|
622
|
-
}
|
|
623
|
-
/**
|
|
624
|
-
* Lists all registered transport names (built-ins + custom).
|
|
625
|
-
*
|
|
626
|
-
*/
|
|
627
|
-
listRegistered() {
|
|
628
|
-
return [...this.registry.keys()];
|
|
629
|
-
}
|
|
630
|
-
add(target) {
|
|
631
|
-
const id = generateTransportId();
|
|
632
|
-
const level = target.level || this.defaultLevel;
|
|
633
|
-
let transport;
|
|
634
|
-
if (typeof target.target === "string") {
|
|
635
|
-
const ctor = this.registry.get(target.target);
|
|
636
|
-
if (!ctor) throw new Error(`TransportManager.add: unknown transport name '${target.target}'. Registered: ${this.listRegistered().join(", ")}`);
|
|
637
|
-
transport = new ctor(target.options ?? {});
|
|
638
|
-
} else transport = target.target;
|
|
639
|
-
const entry = {
|
|
640
|
-
id,
|
|
641
|
-
transport,
|
|
642
|
-
options: target.options || {},
|
|
643
|
-
level,
|
|
644
|
-
levelValue: require_core.LOG_LEVELS[level]
|
|
645
|
-
};
|
|
646
|
-
this.transports.set(id, entry);
|
|
647
|
-
return id;
|
|
648
|
-
}
|
|
649
|
-
remove(id) {
|
|
650
|
-
const entry = this.transports.get(id);
|
|
651
|
-
if (entry) {
|
|
652
|
-
const closeResult = entry.transport.close?.();
|
|
653
|
-
if (closeResult instanceof Promise) closeResult.catch(() => {});
|
|
654
|
-
return this.transports.delete(id);
|
|
655
|
-
}
|
|
656
|
-
return false;
|
|
657
|
-
}
|
|
658
|
-
async write(record) {
|
|
659
|
-
const promises = [];
|
|
660
|
-
for (const entry of this.transports.values()) {
|
|
661
|
-
if (record.levelValue < entry.levelValue) continue;
|
|
662
|
-
let transformedRecord = record;
|
|
663
|
-
if (entry.options.transform) {
|
|
664
|
-
const result = entry.options.transform(record);
|
|
665
|
-
if (result === null) continue;
|
|
666
|
-
transformedRecord = result;
|
|
667
|
-
}
|
|
668
|
-
try {
|
|
669
|
-
const result = entry.transport.write(transformedRecord);
|
|
670
|
-
if (result instanceof Promise) promises.push(result.catch((err) => {
|
|
671
|
-
console.error("TransportManager.write: transport failed:", err);
|
|
672
|
-
}));
|
|
673
|
-
} catch (error) {
|
|
674
|
-
console.error("TransportManager.write: transport threw synchronously:", error);
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
await Promise.all(promises);
|
|
678
|
-
}
|
|
679
|
-
async flush() {
|
|
680
|
-
const promises = [];
|
|
681
|
-
for (const entry of this.transports.values()) if (entry.transport.flush) try {
|
|
682
|
-
const result = entry.transport.flush();
|
|
683
|
-
if (result instanceof Promise) promises.push(result.catch((err) => {
|
|
684
|
-
console.error("TransportManager.flush: transport failed:", err);
|
|
685
|
-
}));
|
|
686
|
-
} catch (error) {
|
|
687
|
-
console.error("TransportManager.flush: transport threw synchronously:", error);
|
|
688
|
-
}
|
|
689
|
-
await Promise.all(promises);
|
|
690
|
-
}
|
|
691
|
-
async close() {
|
|
692
|
-
await this.flush();
|
|
693
|
-
const promises = [];
|
|
694
|
-
for (const entry of this.transports.values()) if (entry.transport.close) try {
|
|
695
|
-
const result = entry.transport.close();
|
|
696
|
-
if (result instanceof Promise) promises.push(result.catch((err) => {
|
|
697
|
-
console.error("TransportManager.close: transport failed:", err);
|
|
698
|
-
}));
|
|
699
|
-
} catch (error) {
|
|
700
|
-
console.error("TransportManager.close: transport threw synchronously:", error);
|
|
701
|
-
}
|
|
702
|
-
await Promise.all(promises);
|
|
703
|
-
this.transports.clear();
|
|
704
|
-
}
|
|
705
|
-
get count() {
|
|
706
|
-
return this.transports.size;
|
|
707
|
-
}
|
|
708
|
-
list() {
|
|
709
|
-
return Array.from(this.transports.keys());
|
|
710
|
-
}
|
|
711
|
-
};
|
|
712
|
-
//#endregion
|
|
713
|
-
Object.defineProperty(exports, "ConsoleTransport", {
|
|
714
|
-
enumerable: true,
|
|
715
|
-
get: function() {
|
|
716
|
-
return ConsoleTransport;
|
|
717
|
-
}
|
|
718
|
-
});
|
|
719
|
-
Object.defineProperty(exports, "FileTransport", {
|
|
720
|
-
enumerable: true,
|
|
721
|
-
get: function() {
|
|
722
|
-
return FileTransport;
|
|
723
|
-
}
|
|
724
|
-
});
|
|
725
|
-
Object.defineProperty(exports, "HttpTransport", {
|
|
726
|
-
enumerable: true,
|
|
727
|
-
get: function() {
|
|
728
|
-
return HttpTransport;
|
|
729
|
-
}
|
|
730
|
-
});
|
|
731
|
-
Object.defineProperty(exports, "LOG_LEVEL_TO_SEVERITY_NUMBER", {
|
|
732
|
-
enumerable: true,
|
|
733
|
-
get: function() {
|
|
734
|
-
return LOG_LEVEL_TO_SEVERITY_NUMBER;
|
|
735
|
-
}
|
|
736
|
-
});
|
|
737
|
-
Object.defineProperty(exports, "LOG_LEVEL_TO_SEVERITY_TEXT", {
|
|
738
|
-
enumerable: true,
|
|
739
|
-
get: function() {
|
|
740
|
-
return LOG_LEVEL_TO_SEVERITY_TEXT;
|
|
741
|
-
}
|
|
742
|
-
});
|
|
743
|
-
Object.defineProperty(exports, "OtlpTransport", {
|
|
744
|
-
enumerable: true,
|
|
745
|
-
get: function() {
|
|
746
|
-
return OtlpTransport;
|
|
747
|
-
}
|
|
748
|
-
});
|
|
749
|
-
Object.defineProperty(exports, "TransportManager", {
|
|
750
|
-
enumerable: true,
|
|
751
|
-
get: function() {
|
|
752
|
-
return TransportManager;
|
|
753
|
-
}
|
|
754
|
-
});
|
|
755
|
-
|
|
756
|
-
//# sourceMappingURL=transports-COPWmlF1.cjs.map
|