@loggerjs/node 0.1.0 → 0.3.1
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 +25 -5
- package/dist/file-transport.d.ts +6 -2
- package/dist/file-transport.d.ts.map +1 -1
- package/dist/index.cjs +445 -95
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +447 -98
- package/dist/index.js.map +1 -1
- package/dist/internal-types.d.ts +2 -0
- package/dist/internal-types.d.ts.map +1 -1
- package/dist/logger-diagnostics.d.ts +14 -0
- package/dist/logger-diagnostics.d.ts.map +1 -0
- package/dist/node-destination.d.ts +32 -0
- package/dist/node-destination.d.ts.map +1 -0
- package/dist/rotating-file-transport.d.ts +2 -0
- package/dist/rotating-file-transport.d.ts.map +1 -1
- package/dist/stdout-transport.d.ts +2 -0
- package/dist/stdout-transport.d.ts.map +1 -1
- package/dist/worker-transport.d.ts +16 -2
- package/dist/worker-transport.d.ts.map +1 -1
- package/package.json +7 -2
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
let _loggerjs_core = require("@loggerjs/core");
|
|
3
3
|
let fs = require("fs");
|
|
4
|
+
let path = require("path");
|
|
4
5
|
let node_zlib = require("node:zlib");
|
|
5
6
|
let dgram = require("dgram");
|
|
6
7
|
let net = require("net");
|
|
@@ -8,66 +9,116 @@ let os = require("os");
|
|
|
8
9
|
let node_worker_threads = require("node:worker_threads");
|
|
9
10
|
let node_async_hooks = require("node:async_hooks");
|
|
10
11
|
let node_module = require("node:module");
|
|
11
|
-
//#region src/
|
|
12
|
+
//#region src/node-destination.ts
|
|
13
|
+
const encoder = new TextEncoder();
|
|
12
14
|
const normalizeError = (error) => error instanceof Error ? error : new Error(String(error));
|
|
13
|
-
function
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
function byteLength(payload) {
|
|
16
|
+
return typeof payload === "string" ? encoder.encode(payload).byteLength : payload.byteLength;
|
|
17
|
+
}
|
|
18
|
+
function coalescePayloads(payloads) {
|
|
19
|
+
if (payloads.every((payload) => typeof payload === "string")) return payloads.join("");
|
|
20
|
+
const buffers = payloads.map((payload) => typeof payload === "string" ? Buffer.from(payload) : Buffer.from(payload));
|
|
21
|
+
return Buffer.concat(buffers);
|
|
22
|
+
}
|
|
23
|
+
function isEpipe(error) {
|
|
24
|
+
return Boolean(error) && typeof error === "object" && error.code === "EPIPE";
|
|
25
|
+
}
|
|
26
|
+
function normalizeMinLength(value) {
|
|
27
|
+
if (value === void 0 || !Number.isFinite(value) || value <= 0) return 0;
|
|
28
|
+
return Math.floor(value);
|
|
29
|
+
}
|
|
30
|
+
function createNodeStreamDestination(options) {
|
|
31
|
+
const minLength = normalizeMinLength(options.minLength);
|
|
32
|
+
const ignoreEpipe = options.ignoreEpipe ?? false;
|
|
17
33
|
const waiters = [];
|
|
34
|
+
const buffer = [];
|
|
35
|
+
const pendingPayloads = [];
|
|
36
|
+
let bufferedBytes = 0;
|
|
18
37
|
let pendingWrites = 0;
|
|
19
38
|
let pendingDrains = 0;
|
|
20
39
|
let lastError;
|
|
21
40
|
let lastContext;
|
|
41
|
+
let closed = false;
|
|
22
42
|
const reportInternalError = (error, operation) => {
|
|
43
|
+
if (ignoreEpipe && isEpipe(error)) return;
|
|
23
44
|
lastContext?.reportInternalError(error, {
|
|
24
45
|
phase: "transport",
|
|
25
|
-
transport:
|
|
46
|
+
transport: options.name,
|
|
26
47
|
operation
|
|
27
48
|
});
|
|
28
49
|
};
|
|
29
50
|
const settleWaitersIfIdle = () => {
|
|
30
51
|
if (pendingWrites + pendingDrains > 0) return;
|
|
52
|
+
if (waiters.length === 0) return;
|
|
31
53
|
const error = lastError;
|
|
32
54
|
lastError = void 0;
|
|
33
55
|
for (const waiter of waiters.splice(0)) if (error) waiter.reject(error);
|
|
34
56
|
else waiter.resolve();
|
|
35
57
|
};
|
|
36
58
|
const recordError = (error, operation) => {
|
|
59
|
+
if (ignoreEpipe && isEpipe(error)) {
|
|
60
|
+
closed = true;
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
37
63
|
lastError = normalizeError(error);
|
|
38
64
|
reportInternalError(lastError, operation);
|
|
39
65
|
};
|
|
66
|
+
const onStreamError = (error) => {
|
|
67
|
+
recordError(error, "stream-error");
|
|
68
|
+
settleWaitersIfIdle();
|
|
69
|
+
};
|
|
70
|
+
const offError = () => options.stream.off?.("error", onStreamError);
|
|
71
|
+
options.stream.on?.("error", onStreamError);
|
|
40
72
|
const waitForDrain = () => {
|
|
41
|
-
if (!stream.once) return;
|
|
73
|
+
if (!options.stream.once) return;
|
|
42
74
|
pendingDrains += 1;
|
|
43
|
-
stream.once("drain", () => {
|
|
75
|
+
options.stream.once("drain", () => {
|
|
44
76
|
pendingDrains -= 1;
|
|
45
77
|
settleWaitersIfIdle();
|
|
46
78
|
});
|
|
47
79
|
};
|
|
48
|
-
const
|
|
80
|
+
const removePending = (payload) => {
|
|
81
|
+
const index = pendingPayloads.indexOf(payload);
|
|
82
|
+
if (index >= 0) pendingPayloads.splice(index, 1);
|
|
83
|
+
};
|
|
84
|
+
const writeNow = (payload) => {
|
|
85
|
+
if (closed) return;
|
|
86
|
+
pendingPayloads.push(payload);
|
|
49
87
|
pendingWrites += 1;
|
|
50
88
|
try {
|
|
51
|
-
if (stream.write(payload, (error) => {
|
|
89
|
+
if (options.stream.write(payload, (error) => {
|
|
90
|
+
removePending(payload);
|
|
52
91
|
pendingWrites -= 1;
|
|
53
|
-
if (error) recordError(error, "write");
|
|
92
|
+
if (error) recordError(error, options.reportOperation ?? "write");
|
|
54
93
|
settleWaitersIfIdle();
|
|
55
94
|
}) === false) waitForDrain();
|
|
56
95
|
} catch (error) {
|
|
96
|
+
removePending(payload);
|
|
57
97
|
pendingWrites -= 1;
|
|
58
|
-
recordError(error, "write");
|
|
98
|
+
recordError(error, options.reportOperation ?? "write");
|
|
59
99
|
settleWaitersIfIdle();
|
|
60
100
|
}
|
|
61
101
|
};
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
102
|
+
const flushBuffered = () => {
|
|
103
|
+
if (buffer.length === 0) return;
|
|
104
|
+
const payload = coalescePayloads(buffer.splice(0));
|
|
105
|
+
bufferedBytes = 0;
|
|
106
|
+
writeNow(payload);
|
|
107
|
+
};
|
|
108
|
+
const destination = {
|
|
109
|
+
write(payload, context) {
|
|
110
|
+
if (closed) return;
|
|
67
111
|
lastContext = context;
|
|
68
|
-
|
|
112
|
+
if (minLength > 0) {
|
|
113
|
+
buffer.push(payload);
|
|
114
|
+
bufferedBytes += byteLength(payload);
|
|
115
|
+
if (bufferedBytes >= minLength) flushBuffered();
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
writeNow(payload);
|
|
69
119
|
},
|
|
70
120
|
flush() {
|
|
121
|
+
flushBuffered();
|
|
71
122
|
if (pendingWrites + pendingDrains === 0) {
|
|
72
123
|
const error = lastError;
|
|
73
124
|
lastError = void 0;
|
|
@@ -80,8 +131,133 @@ function stdoutTransport(options = {}) {
|
|
|
80
131
|
reject
|
|
81
132
|
});
|
|
82
133
|
});
|
|
134
|
+
},
|
|
135
|
+
flushSync() {
|
|
136
|
+
if (!options.syncWrite) {
|
|
137
|
+
flushBuffered();
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
for (const payload of buffer.splice(0)) options.syncWrite(payload);
|
|
141
|
+
bufferedBytes = 0;
|
|
142
|
+
for (const payload of pendingPayloads.splice(0)) options.syncWrite(payload);
|
|
143
|
+
},
|
|
144
|
+
close() {
|
|
145
|
+
return destination.flush().then(() => new Promise((resolve, reject) => {
|
|
146
|
+
if (!options.stream.end) {
|
|
147
|
+
closed = true;
|
|
148
|
+
offError();
|
|
149
|
+
resolve();
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
options.stream.end((error) => {
|
|
153
|
+
closed = true;
|
|
154
|
+
offError();
|
|
155
|
+
if (error && !(ignoreEpipe && isEpipe(error))) reject(error);
|
|
156
|
+
else resolve();
|
|
157
|
+
});
|
|
158
|
+
}), (error) => {
|
|
159
|
+
offError();
|
|
160
|
+
return Promise.reject(error);
|
|
161
|
+
});
|
|
162
|
+
},
|
|
163
|
+
closeSync() {
|
|
164
|
+
destination.flushSync();
|
|
165
|
+
closed = true;
|
|
166
|
+
offError();
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
return destination;
|
|
170
|
+
}
|
|
171
|
+
function createNodeFileDestination(options) {
|
|
172
|
+
const flags = options.flags ?? (options.append === false ? "w" : "a");
|
|
173
|
+
if (options.mkdir) (0, fs.mkdirSync)((0, path.dirname)(options.path), { recursive: true });
|
|
174
|
+
let fd;
|
|
175
|
+
const getFd = () => {
|
|
176
|
+
fd ??= (0, fs.openSync)(options.path, flags);
|
|
177
|
+
return fd;
|
|
178
|
+
};
|
|
179
|
+
const syncWrite = (payload) => {
|
|
180
|
+
if (typeof payload === "string") (0, fs.writeSync)(getFd(), payload);
|
|
181
|
+
else (0, fs.writeSync)(getFd(), payload);
|
|
182
|
+
};
|
|
183
|
+
if (options.sync) {
|
|
184
|
+
let closed = false;
|
|
185
|
+
const releaseSync = () => {
|
|
186
|
+
if (fd !== void 0) {
|
|
187
|
+
(0, fs.closeSync)(fd);
|
|
188
|
+
fd = void 0;
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
return {
|
|
192
|
+
write(payload) {
|
|
193
|
+
if (closed) return;
|
|
194
|
+
syncWrite(payload);
|
|
195
|
+
},
|
|
196
|
+
flush() {
|
|
197
|
+
return Promise.resolve();
|
|
198
|
+
},
|
|
199
|
+
flushSync() {},
|
|
200
|
+
close() {
|
|
201
|
+
releaseSync();
|
|
202
|
+
closed = true;
|
|
203
|
+
return Promise.resolve();
|
|
204
|
+
},
|
|
205
|
+
closeSync() {
|
|
206
|
+
releaseSync();
|
|
207
|
+
closed = true;
|
|
208
|
+
},
|
|
209
|
+
releaseSync
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
const stream = (0, fs.createWriteStream)(options.path, { flags });
|
|
213
|
+
const destination = createNodeStreamDestination({
|
|
214
|
+
name: options.name,
|
|
215
|
+
stream,
|
|
216
|
+
minLength: options.minLength,
|
|
217
|
+
syncWrite
|
|
218
|
+
});
|
|
219
|
+
const releaseSync = () => {
|
|
220
|
+
if (fd !== void 0) {
|
|
221
|
+
(0, fs.closeSync)(fd);
|
|
222
|
+
fd = void 0;
|
|
83
223
|
}
|
|
84
224
|
};
|
|
225
|
+
return {
|
|
226
|
+
...destination,
|
|
227
|
+
stream,
|
|
228
|
+
close() {
|
|
229
|
+
return destination.close().finally(releaseSync);
|
|
230
|
+
},
|
|
231
|
+
closeSync() {
|
|
232
|
+
destination.closeSync();
|
|
233
|
+
releaseSync();
|
|
234
|
+
},
|
|
235
|
+
releaseSync
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
//#endregion
|
|
239
|
+
//#region src/stdout-transport.ts
|
|
240
|
+
function stdoutTransport(options = {}) {
|
|
241
|
+
const codec = options.codec ?? (0, _loggerjs_core.ndjsonCodec)();
|
|
242
|
+
const stream = options.stream ?? process.stdout;
|
|
243
|
+
const transportName = options.name ?? "stdout";
|
|
244
|
+
const destination = createNodeStreamDestination({
|
|
245
|
+
name: transportName,
|
|
246
|
+
stream,
|
|
247
|
+
minLength: options.minLength,
|
|
248
|
+
ignoreEpipe: options.ignoreEpipe ?? true
|
|
249
|
+
});
|
|
250
|
+
return {
|
|
251
|
+
name: transportName,
|
|
252
|
+
minLevel: options.minLevel,
|
|
253
|
+
log(event, context) {
|
|
254
|
+
if (options.minLevel !== void 0 && event.level < (0, _loggerjs_core.toLevelValue)(options.minLevel)) return;
|
|
255
|
+
destination.write(codec.encode(event), context);
|
|
256
|
+
},
|
|
257
|
+
flush: destination.flush,
|
|
258
|
+
flushSync: destination.flushSync,
|
|
259
|
+
close: destination.close
|
|
260
|
+
};
|
|
85
261
|
}
|
|
86
262
|
function stderrTransport(options = {}) {
|
|
87
263
|
return stdoutTransport({
|
|
@@ -94,60 +270,26 @@ function stderrTransport(options = {}) {
|
|
|
94
270
|
//#region src/file-transport.ts
|
|
95
271
|
function fileTransport(options) {
|
|
96
272
|
const codec = options.codec ?? (0, _loggerjs_core.ndjsonCodec)();
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
syncFd ??= (0, fs.openSync)(options.path, flags);
|
|
107
|
-
return syncFd;
|
|
108
|
-
};
|
|
273
|
+
const destination = createNodeFileDestination({
|
|
274
|
+
name: options.name ?? "file",
|
|
275
|
+
path: options.path,
|
|
276
|
+
flags: options.flags,
|
|
277
|
+
append: options.append,
|
|
278
|
+
mkdir: options.mkdir,
|
|
279
|
+
sync: options.sync,
|
|
280
|
+
minLength: options.minLength
|
|
281
|
+
});
|
|
109
282
|
return {
|
|
110
283
|
name: options.name ?? "file",
|
|
111
284
|
minLevel: options.minLevel,
|
|
112
|
-
stream,
|
|
113
|
-
log(event) {
|
|
285
|
+
stream: destination.stream,
|
|
286
|
+
log(event, context) {
|
|
114
287
|
if (options.minLevel !== void 0 && event.level < (0, _loggerjs_core.toLevelValue)(options.minLevel)) return;
|
|
115
|
-
|
|
116
|
-
pending.push(payload);
|
|
117
|
-
stream.write(payload, (error) => {
|
|
118
|
-
if (!error) removePending(payload);
|
|
119
|
-
});
|
|
288
|
+
destination.write(codec.encode(event), context);
|
|
120
289
|
},
|
|
121
|
-
flush
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
if (error) {
|
|
125
|
-
reject(error);
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
pending.splice(0, pending.length);
|
|
129
|
-
resolve();
|
|
130
|
-
});
|
|
131
|
-
});
|
|
132
|
-
},
|
|
133
|
-
flushSync() {
|
|
134
|
-
if (pending.length === 0) return;
|
|
135
|
-
const fd = getSyncFd();
|
|
136
|
-
for (const payload of pending.splice(0)) if (typeof payload === "string") (0, fs.writeSync)(fd, payload);
|
|
137
|
-
else (0, fs.writeSync)(fd, payload);
|
|
138
|
-
},
|
|
139
|
-
close() {
|
|
140
|
-
return new Promise((resolve, reject) => {
|
|
141
|
-
stream.end?.((error) => {
|
|
142
|
-
if (syncFd !== void 0) {
|
|
143
|
-
(0, fs.closeSync)(syncFd);
|
|
144
|
-
syncFd = void 0;
|
|
145
|
-
}
|
|
146
|
-
if (error) reject(error);
|
|
147
|
-
else resolve();
|
|
148
|
-
});
|
|
149
|
-
});
|
|
150
|
-
}
|
|
290
|
+
flush: destination.flush,
|
|
291
|
+
flushSync: destination.flushSync,
|
|
292
|
+
close: destination.close
|
|
151
293
|
};
|
|
152
294
|
}
|
|
153
295
|
//#endregion
|
|
@@ -176,23 +318,20 @@ function fileSize(path) {
|
|
|
176
318
|
}
|
|
177
319
|
function rotatingFileTransport(options) {
|
|
178
320
|
const codec = options.codec ?? (0, _loggerjs_core.ndjsonCodec)();
|
|
179
|
-
const flags = options.flags ?? "a";
|
|
180
321
|
const maxBytes = normalizePositiveInteger(options.maxBytes, 10 * 1024 * 1024);
|
|
181
322
|
const maxFiles = normalizeNonNegativeInteger(options.maxFiles, 5);
|
|
182
323
|
const archivePath = options.archivePath ?? defaultArchivePath;
|
|
183
|
-
|
|
324
|
+
const destination = createNodeFileDestination({
|
|
325
|
+
name: options.name ?? "rotating-file",
|
|
326
|
+
path: options.path,
|
|
327
|
+
flags: options.flags,
|
|
328
|
+
append: options.append,
|
|
329
|
+
mkdir: options.mkdir,
|
|
330
|
+
sync: true
|
|
331
|
+
});
|
|
184
332
|
let bytes = fileSize(options.path);
|
|
185
|
-
const closeFd = () => {
|
|
186
|
-
if (fd === void 0) return;
|
|
187
|
-
(0, fs.closeSync)(fd);
|
|
188
|
-
fd = void 0;
|
|
189
|
-
};
|
|
190
|
-
const getFd = () => {
|
|
191
|
-
fd ??= (0, fs.openSync)(options.path, flags);
|
|
192
|
-
return fd;
|
|
193
|
-
};
|
|
194
333
|
const rotate = () => {
|
|
195
|
-
|
|
334
|
+
destination.releaseSync?.();
|
|
196
335
|
if (maxFiles === 0) {
|
|
197
336
|
if ((0, fs.existsSync)(options.path)) (0, fs.unlinkSync)(options.path);
|
|
198
337
|
bytes = 0;
|
|
@@ -210,8 +349,7 @@ function rotatingFileTransport(options) {
|
|
|
210
349
|
const writePayload = (payload) => {
|
|
211
350
|
const size = payloadBytes(payload);
|
|
212
351
|
if (bytes > 0 && bytes + size > maxBytes) rotate();
|
|
213
|
-
|
|
214
|
-
else (0, fs.writeSync)(getFd(), payload);
|
|
352
|
+
destination.write(payload);
|
|
215
353
|
bytes += size;
|
|
216
354
|
};
|
|
217
355
|
return {
|
|
@@ -228,12 +366,11 @@ function rotatingFileTransport(options) {
|
|
|
228
366
|
}
|
|
229
367
|
},
|
|
230
368
|
flush() {
|
|
231
|
-
return
|
|
369
|
+
return destination.flush();
|
|
232
370
|
},
|
|
233
|
-
flushSync
|
|
371
|
+
flushSync: destination.flushSync,
|
|
234
372
|
close() {
|
|
235
|
-
|
|
236
|
-
return Promise.resolve();
|
|
373
|
+
return destination.close();
|
|
237
374
|
},
|
|
238
375
|
rotate,
|
|
239
376
|
currentBytes: () => bytes
|
|
@@ -455,13 +592,58 @@ function transferablePayload(payload) {
|
|
|
455
592
|
transferList: [copy.buffer]
|
|
456
593
|
};
|
|
457
594
|
}
|
|
595
|
+
function normalizePositiveTimeout(value) {
|
|
596
|
+
if (value === void 0 || !Number.isFinite(value) || value <= 0) return 0;
|
|
597
|
+
return Math.floor(value);
|
|
598
|
+
}
|
|
599
|
+
function protocolMessage(value) {
|
|
600
|
+
if (!value || typeof value !== "object") return void 0;
|
|
601
|
+
const message = value;
|
|
602
|
+
if (message.type === "loggerjs:ready") return { type: "loggerjs:ready" };
|
|
603
|
+
if (message.type === "loggerjs:batch:ack") {
|
|
604
|
+
const id = value.id;
|
|
605
|
+
if (typeof id === "number") return {
|
|
606
|
+
type: "loggerjs:batch:ack",
|
|
607
|
+
id
|
|
608
|
+
};
|
|
609
|
+
}
|
|
610
|
+
if (message.type === "loggerjs:error") {
|
|
611
|
+
const item = value;
|
|
612
|
+
return {
|
|
613
|
+
type: "loggerjs:error",
|
|
614
|
+
error: item.error,
|
|
615
|
+
message: typeof item.message === "string" ? item.message : void 0
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
function dropBatch(events, reason) {
|
|
620
|
+
(0, _loggerjs_core.incrementLoggerMetaCounter)("transport.dropped", events.length);
|
|
621
|
+
(0, _loggerjs_core.incrementLoggerMetaCounter)(`transport.dropped.${reason}`, events.length);
|
|
622
|
+
}
|
|
458
623
|
function workerTransport(options = {}) {
|
|
459
624
|
const codec = options.codec ?? (0, _loggerjs_core.safeJsonCodec)();
|
|
460
625
|
const transportName = options.name ?? "worker";
|
|
461
626
|
const fallback = options.fallback;
|
|
627
|
+
const readyTimeoutMs = normalizePositiveTimeout(options.readyTimeoutMs);
|
|
628
|
+
const ackTimeoutMs = normalizePositiveTimeout(options.ackTimeoutMs);
|
|
629
|
+
const autoEnd = options.autoEnd ?? true;
|
|
462
630
|
let worker;
|
|
463
631
|
let failed = false;
|
|
632
|
+
let failedError;
|
|
464
633
|
let lastContext;
|
|
634
|
+
let ready = readyTimeoutMs === 0;
|
|
635
|
+
let readyPromise;
|
|
636
|
+
let readyTimer;
|
|
637
|
+
let readyResolve;
|
|
638
|
+
let readyReject;
|
|
639
|
+
let nextBatchId = 1;
|
|
640
|
+
const pendingBatches = /* @__PURE__ */ new Map();
|
|
641
|
+
const setPendingGauge = () => {
|
|
642
|
+
(0, _loggerjs_core.setLoggerMetaGauge)(`transport.queue.depth.${transportName}`, pendingBatches.size);
|
|
643
|
+
};
|
|
644
|
+
const setReadyGauge = (value) => {
|
|
645
|
+
(0, _loggerjs_core.setLoggerMetaGauge)(`transport.ready.${transportName}`, value);
|
|
646
|
+
};
|
|
465
647
|
const reportInternalError = (error, operation) => {
|
|
466
648
|
lastContext?.reportInternalError(error, {
|
|
467
649
|
phase: "transport",
|
|
@@ -470,14 +652,82 @@ function workerTransport(options = {}) {
|
|
|
470
652
|
});
|
|
471
653
|
};
|
|
472
654
|
const markFailed = (error, operation) => {
|
|
655
|
+
if (failed) return;
|
|
473
656
|
failed = true;
|
|
657
|
+
failedError = error instanceof Error ? error : new Error(String(error));
|
|
658
|
+
setReadyGauge(0);
|
|
474
659
|
(0, _loggerjs_core.incrementLoggerMetaCounter)("transport.worker.failed");
|
|
660
|
+
(0, _loggerjs_core.emitLoggerDiagnostic)({
|
|
661
|
+
stage: "worker",
|
|
662
|
+
phase: "error",
|
|
663
|
+
transport: transportName,
|
|
664
|
+
operation,
|
|
665
|
+
error
|
|
666
|
+
});
|
|
475
667
|
reportInternalError(error, operation);
|
|
668
|
+
readyReject?.(failedError);
|
|
669
|
+
failPendingBatches(operation);
|
|
476
670
|
};
|
|
477
671
|
const onWorkerError = (error) => markFailed(error, "worker-error");
|
|
478
672
|
const onWorkerExit = (code) => {
|
|
479
673
|
if (typeof code === "number" && code !== 0) markFailed(code, "worker-exit");
|
|
480
674
|
};
|
|
675
|
+
const onWorkerMessage = (value) => {
|
|
676
|
+
const message = protocolMessage(value);
|
|
677
|
+
if (!message) return;
|
|
678
|
+
if (message.type === "loggerjs:ready") {
|
|
679
|
+
ready = true;
|
|
680
|
+
setReadyGauge(1);
|
|
681
|
+
(0, _loggerjs_core.emitLoggerDiagnostic)({
|
|
682
|
+
stage: "worker",
|
|
683
|
+
phase: "end",
|
|
684
|
+
transport: transportName,
|
|
685
|
+
operation: "ready"
|
|
686
|
+
});
|
|
687
|
+
if (readyTimer) clearTimeout(readyTimer);
|
|
688
|
+
readyResolve?.();
|
|
689
|
+
return;
|
|
690
|
+
}
|
|
691
|
+
if (message.type === "loggerjs:batch:ack") {
|
|
692
|
+
const pending = pendingBatches.get(message.id);
|
|
693
|
+
if (!pending) return;
|
|
694
|
+
pendingBatches.delete(message.id);
|
|
695
|
+
setPendingGauge();
|
|
696
|
+
if (pending.timer) clearTimeout(pending.timer);
|
|
697
|
+
pending.resolve();
|
|
698
|
+
(0, _loggerjs_core.incrementLoggerMetaCounter)("transport.worker.ack");
|
|
699
|
+
return;
|
|
700
|
+
}
|
|
701
|
+
markFailed(message.error ?? new Error(message.message ?? "Worker reported an error"), "worker-message");
|
|
702
|
+
};
|
|
703
|
+
const fallbackOrDropBatch = async (events, context, reason) => {
|
|
704
|
+
if (fallback) {
|
|
705
|
+
await fallbackBatch(events, context);
|
|
706
|
+
return;
|
|
707
|
+
}
|
|
708
|
+
dropBatch(events, reason);
|
|
709
|
+
};
|
|
710
|
+
const failPendingBatch = (pending, reason) => {
|
|
711
|
+
pendingBatches.delete(pending.id);
|
|
712
|
+
setPendingGauge();
|
|
713
|
+
if (pending.timer) clearTimeout(pending.timer);
|
|
714
|
+
(0, _loggerjs_core.incrementLoggerMetaCounter)("transport.worker.pending-dropped", pending.events.length);
|
|
715
|
+
fallbackOrDropBatch(pending.events, pending.context, reason).finally(pending.resolve);
|
|
716
|
+
};
|
|
717
|
+
function failPendingBatches(reason) {
|
|
718
|
+
for (const pending of Array.from(pendingBatches.values())) failPendingBatch(pending, reason);
|
|
719
|
+
}
|
|
720
|
+
const waitForReady = async () => {
|
|
721
|
+
if (ready) return;
|
|
722
|
+
readyPromise ??= new Promise((resolve, reject) => {
|
|
723
|
+
readyResolve = resolve;
|
|
724
|
+
readyReject = reject;
|
|
725
|
+
readyTimer = setTimeout(() => {
|
|
726
|
+
reject(/* @__PURE__ */ new Error(`workerTransport ready timeout after ${readyTimeoutMs}ms`));
|
|
727
|
+
}, readyTimeoutMs);
|
|
728
|
+
});
|
|
729
|
+
await readyPromise;
|
|
730
|
+
};
|
|
481
731
|
const getWorker = () => {
|
|
482
732
|
if (failed) return void 0;
|
|
483
733
|
if (worker) return worker;
|
|
@@ -485,6 +735,8 @@ function workerTransport(options = {}) {
|
|
|
485
735
|
worker = options.worker ?? options.workerFactory?.() ?? createDefaultWorker(options);
|
|
486
736
|
worker.on?.("error", onWorkerError);
|
|
487
737
|
worker.on?.("exit", onWorkerExit);
|
|
738
|
+
worker.on?.("message", onWorkerMessage);
|
|
739
|
+
if (ready) setReadyGauge(1);
|
|
488
740
|
return worker;
|
|
489
741
|
} catch (error) {
|
|
490
742
|
markFailed(error, "create-worker");
|
|
@@ -502,7 +754,14 @@ function workerTransport(options = {}) {
|
|
|
502
754
|
lastContext = context;
|
|
503
755
|
const currentWorker = getWorker();
|
|
504
756
|
if (!currentWorker) {
|
|
505
|
-
await
|
|
757
|
+
await fallbackOrDropBatch(events, context, "worker-unavailable");
|
|
758
|
+
return;
|
|
759
|
+
}
|
|
760
|
+
try {
|
|
761
|
+
await waitForReady();
|
|
762
|
+
} catch (error) {
|
|
763
|
+
markFailed(error, "worker-ready-timeout");
|
|
764
|
+
await fallbackOrDropBatch(events, context, "worker-ready-timeout");
|
|
506
765
|
return;
|
|
507
766
|
}
|
|
508
767
|
const encoded = payloadToBytes(codec.encode(events));
|
|
@@ -517,16 +776,53 @@ function workerTransport(options = {}) {
|
|
|
517
776
|
count: events.length,
|
|
518
777
|
payload: transferable.payload
|
|
519
778
|
};
|
|
779
|
+
let pending;
|
|
780
|
+
if (ackTimeoutMs > 0) {
|
|
781
|
+
const id = nextBatchId;
|
|
782
|
+
nextBatchId += 1;
|
|
783
|
+
message.id = id;
|
|
784
|
+
pending = {
|
|
785
|
+
id,
|
|
786
|
+
events,
|
|
787
|
+
context,
|
|
788
|
+
resolve: () => {}
|
|
789
|
+
};
|
|
790
|
+
pending.timer = setTimeout(() => {
|
|
791
|
+
if (!pending) return;
|
|
792
|
+
markFailed(/* @__PURE__ */ new Error(`workerTransport ack timeout after ${ackTimeoutMs}ms`), "worker-ack-timeout");
|
|
793
|
+
}, ackTimeoutMs);
|
|
794
|
+
pendingBatches.set(id, pending);
|
|
795
|
+
setPendingGauge();
|
|
796
|
+
}
|
|
520
797
|
try {
|
|
521
798
|
currentWorker.postMessage(message, transferable.transferList);
|
|
522
799
|
} catch (error) {
|
|
523
800
|
markFailed(error, "post-message");
|
|
524
|
-
await
|
|
801
|
+
if (!pending) await fallbackOrDropBatch(events, context, "worker-post-message");
|
|
525
802
|
}
|
|
526
803
|
};
|
|
527
|
-
|
|
804
|
+
const transport = {
|
|
528
805
|
name: transportName,
|
|
529
806
|
minLevel: options.minLevel,
|
|
807
|
+
async ready() {
|
|
808
|
+
if (!getWorker()) {
|
|
809
|
+
if (fallback) {
|
|
810
|
+
await fallback.ready?.();
|
|
811
|
+
return;
|
|
812
|
+
}
|
|
813
|
+
throw failedError ?? /* @__PURE__ */ new Error("workerTransport is unavailable");
|
|
814
|
+
}
|
|
815
|
+
try {
|
|
816
|
+
await waitForReady();
|
|
817
|
+
} catch (error) {
|
|
818
|
+
markFailed(error, "worker-ready-timeout");
|
|
819
|
+
if (fallback) {
|
|
820
|
+
await fallback.ready?.();
|
|
821
|
+
return;
|
|
822
|
+
}
|
|
823
|
+
throw error;
|
|
824
|
+
}
|
|
825
|
+
},
|
|
530
826
|
log(event, context) {
|
|
531
827
|
if (options.minLevel !== void 0 && event.level < (0, _loggerjs_core.toLevelValue)(options.minLevel)) return;
|
|
532
828
|
return postBatch([event], context);
|
|
@@ -535,15 +831,28 @@ function workerTransport(options = {}) {
|
|
|
535
831
|
return postBatch(events, context);
|
|
536
832
|
},
|
|
537
833
|
async flush() {
|
|
834
|
+
await Promise.all(Array.from(pendingBatches.values(), (pending) => new Promise((resolve) => {
|
|
835
|
+
const originalResolve = pending.resolve;
|
|
836
|
+
pending.resolve = () => {
|
|
837
|
+
originalResolve();
|
|
838
|
+
resolve();
|
|
839
|
+
};
|
|
840
|
+
})));
|
|
538
841
|
await fallback?.flush?.();
|
|
539
842
|
},
|
|
540
843
|
async close() {
|
|
844
|
+
await transport.flush?.();
|
|
541
845
|
worker?.off?.("error", onWorkerError);
|
|
542
846
|
worker?.off?.("exit", onWorkerExit);
|
|
847
|
+
worker?.off?.("message", onWorkerMessage);
|
|
543
848
|
await fallback?.close?.();
|
|
544
|
-
await worker?.terminate?.();
|
|
849
|
+
if (autoEnd) await worker?.terminate?.();
|
|
850
|
+
if (readyTimer) clearTimeout(readyTimer);
|
|
851
|
+
readyReject = void 0;
|
|
852
|
+
readyResolve = void 0;
|
|
545
853
|
}
|
|
546
854
|
};
|
|
855
|
+
return transport;
|
|
547
856
|
}
|
|
548
857
|
//#endregion
|
|
549
858
|
//#region src/context.ts
|
|
@@ -1441,16 +1750,16 @@ function nodeFetchIntegration(options = {}) {
|
|
|
1441
1750
|
}
|
|
1442
1751
|
//#endregion
|
|
1443
1752
|
//#region src/node-http-client-integration.ts
|
|
1444
|
-
const requireBuiltin$
|
|
1753
|
+
const requireBuiltin$2 = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href);
|
|
1445
1754
|
const defaultRandom$1 = () => Math.random();
|
|
1446
1755
|
let cachedHttpModule;
|
|
1447
1756
|
let cachedHttpsModule;
|
|
1448
1757
|
function loadBuiltin(name, fallback) {
|
|
1449
1758
|
try {
|
|
1450
|
-
return requireBuiltin$
|
|
1759
|
+
return requireBuiltin$2(name);
|
|
1451
1760
|
} catch {
|
|
1452
1761
|
try {
|
|
1453
|
-
return requireBuiltin$
|
|
1762
|
+
return requireBuiltin$2(fallback);
|
|
1454
1763
|
} catch {
|
|
1455
1764
|
return null;
|
|
1456
1765
|
}
|
|
@@ -1915,15 +2224,15 @@ const defaultChannels = [
|
|
|
1915
2224
|
"undici:request:trailers",
|
|
1916
2225
|
"undici:request:error"
|
|
1917
2226
|
];
|
|
1918
|
-
const requireBuiltin = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href);
|
|
1919
|
-
let cachedDiagnosticsChannel;
|
|
2227
|
+
const requireBuiltin$1 = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href);
|
|
2228
|
+
let cachedDiagnosticsChannel$1;
|
|
1920
2229
|
function diagnosticsChannelIntegration(options = {}) {
|
|
1921
2230
|
const channels = options.channels ?? defaultChannels;
|
|
1922
2231
|
const captureMessage = options.captureMessage ?? false;
|
|
1923
2232
|
return {
|
|
1924
2233
|
name: "diagnostics-channel",
|
|
1925
2234
|
setup(api) {
|
|
1926
|
-
const diagnosticsChannel = options.diagnosticsChannel === void 0 ? loadDiagnosticsChannel() : options.diagnosticsChannel;
|
|
2235
|
+
const diagnosticsChannel = options.diagnosticsChannel === void 0 ? loadDiagnosticsChannel$1() : options.diagnosticsChannel;
|
|
1927
2236
|
if (!diagnosticsChannel) return;
|
|
1928
2237
|
const disposers = [];
|
|
1929
2238
|
let disposed = false;
|
|
@@ -1950,6 +2259,23 @@ function diagnosticsChannelIntegration(options = {}) {
|
|
|
1950
2259
|
}
|
|
1951
2260
|
};
|
|
1952
2261
|
}
|
|
2262
|
+
function loadDiagnosticsChannel$1() {
|
|
2263
|
+
if (cachedDiagnosticsChannel$1 !== void 0) return cachedDiagnosticsChannel$1;
|
|
2264
|
+
try {
|
|
2265
|
+
cachedDiagnosticsChannel$1 = requireBuiltin$1("node:diagnostics_channel");
|
|
2266
|
+
} catch {
|
|
2267
|
+
try {
|
|
2268
|
+
cachedDiagnosticsChannel$1 = requireBuiltin$1("diagnostics_channel");
|
|
2269
|
+
} catch {
|
|
2270
|
+
cachedDiagnosticsChannel$1 = null;
|
|
2271
|
+
}
|
|
2272
|
+
}
|
|
2273
|
+
return cachedDiagnosticsChannel$1;
|
|
2274
|
+
}
|
|
2275
|
+
//#endregion
|
|
2276
|
+
//#region src/logger-diagnostics.ts
|
|
2277
|
+
const requireBuiltin = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href);
|
|
2278
|
+
let cachedDiagnosticsChannel;
|
|
1953
2279
|
function loadDiagnosticsChannel() {
|
|
1954
2280
|
if (cachedDiagnosticsChannel !== void 0) return cachedDiagnosticsChannel;
|
|
1955
2281
|
try {
|
|
@@ -1963,6 +2289,29 @@ function loadDiagnosticsChannel() {
|
|
|
1963
2289
|
}
|
|
1964
2290
|
return cachedDiagnosticsChannel;
|
|
1965
2291
|
}
|
|
2292
|
+
function installLoggerDiagnosticsChannel(options = {}) {
|
|
2293
|
+
const diagnosticsChannel = options.diagnosticsChannel === void 0 ? loadDiagnosticsChannel() : options.diagnosticsChannel;
|
|
2294
|
+
if (!diagnosticsChannel) return () => {};
|
|
2295
|
+
const prefix = options.prefix ?? "loggerjs";
|
|
2296
|
+
const channels = /* @__PURE__ */ new Map();
|
|
2297
|
+
const channelFor = (stage) => {
|
|
2298
|
+
const name = `${prefix}.${stage}`;
|
|
2299
|
+
let channel = channels.get(name);
|
|
2300
|
+
if (!channel) {
|
|
2301
|
+
channel = diagnosticsChannel.channel(name);
|
|
2302
|
+
channels.set(name, channel);
|
|
2303
|
+
}
|
|
2304
|
+
return channel;
|
|
2305
|
+
};
|
|
2306
|
+
const sink = (event) => {
|
|
2307
|
+
channelFor(event.stage).publish(event);
|
|
2308
|
+
};
|
|
2309
|
+
sink.enabled = (stage) => channelFor(stage).hasSubscribers !== false;
|
|
2310
|
+
const previous = (0, _loggerjs_core.setLoggerDiagnosticSink)(sink);
|
|
2311
|
+
return () => {
|
|
2312
|
+
(0, _loggerjs_core.setLoggerDiagnosticSink)(previous);
|
|
2313
|
+
};
|
|
2314
|
+
}
|
|
1966
2315
|
//#endregion
|
|
1967
2316
|
exports.bullMqIntegration = bullMqIntegration;
|
|
1968
2317
|
exports.captureCliIntegration = captureCliIntegration;
|
|
@@ -1976,6 +2325,7 @@ exports.fileTransport = fileTransport;
|
|
|
1976
2325
|
exports.formatSyslogMessage = formatSyslogMessage;
|
|
1977
2326
|
exports.hapiIntegration = hapiIntegration;
|
|
1978
2327
|
exports.installAsyncLocalStorageContext = installAsyncLocalStorageContext;
|
|
2328
|
+
exports.installLoggerDiagnosticsChannel = installLoggerDiagnosticsChannel;
|
|
1979
2329
|
exports.koaIntegration = koaIntegration;
|
|
1980
2330
|
exports.nestMiddlewareIntegration = nestMiddlewareIntegration;
|
|
1981
2331
|
exports.nodeCompressionPayloadTransform = nodeCompressionPayloadTransform;
|