@visulima/pail 4.0.0-alpha.1 → 4.0.0-alpha.11
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/CHANGELOG.md +204 -0
- package/LICENSE.md +434 -52
- package/README.md +323 -0
- package/dist/error.d.ts +104 -0
- package/dist/error.js +76 -0
- package/dist/index.browser.d.ts +3 -1
- package/dist/index.browser.js +1490 -3
- package/dist/index.server.d.ts +3 -5
- package/dist/index.server.js +2380 -110
- package/dist/middleware/elysia.d.ts +71 -0
- package/dist/middleware/elysia.js +70 -0
- package/dist/middleware/express.d.ts +86 -0
- package/dist/middleware/express.js +29 -0
- package/dist/middleware/fastify.d.ts +81 -0
- package/dist/middleware/fastify.js +46 -0
- package/dist/middleware/hono.d.ts +85 -0
- package/dist/middleware/hono.js +33 -0
- package/dist/middleware/next/handler.d.ts +36 -0
- package/dist/middleware/next/handler.js +53 -0
- package/dist/middleware/next/middleware.d.ts +59 -0
- package/dist/middleware/next/storage.d.ts +14 -0
- package/dist/middleware/shared/create-middleware-logger.d.ts +82 -0
- package/dist/middleware/shared/headers.d.ts +14 -0
- package/dist/middleware/shared/routes.d.ts +30 -0
- package/dist/middleware/shared/storage.d.ts +29 -0
- package/dist/middleware/sveltekit.d.ts +123 -0
- package/dist/middleware/sveltekit.js +43 -0
- package/dist/object-tree.d.ts +2 -2
- package/dist/object-tree.js +7 -7
- package/dist/packem_shared/{AbstractJsonReporter-BaZ33PlE.js → AbstractJsonReporter-BO8Calb4.js} +112 -32
- package/dist/packem_shared/AbstractJsonReporter-nOj0Ft1F.js +284 -0
- package/dist/packem_shared/{JsonReporter-BRw4skd5.js → JsonReporter-CCmj7oYL.js} +2 -2
- package/dist/packem_shared/{JsonReporter-VzgyLEYz.js → JsonReporter-Ck2PIAEw.js} +2 -2
- package/dist/packem_shared/PrettyReporter-BCvyNzXO.js +2720 -0
- package/dist/packem_shared/{PrettyReporter-DySIXBjQ.js → PrettyReporter-BtTr13Ha.js} +55 -11
- package/dist/packem_shared/abstract-pretty-reporter-CXAKYCb8.js +2635 -0
- package/dist/packem_shared/constants-B1RjD_ps.js +99 -0
- package/dist/packem_shared/createPailError-B_sgL0nF.js +76 -0
- package/dist/packem_shared/headers-BxHWM6KI.js +127 -0
- package/dist/packem_shared/{index-BomQ3E6J.js → index-Bx3-C0j9.js} +29 -21
- package/dist/packem_shared/pailMiddleware-Ci88geIF.js +24 -0
- package/dist/packem_shared/storage-D0vqz8OX.js +36 -0
- package/dist/packem_shared/{InteractiveStreamHook-DiSubbJ1.js → useLogger-D0rU3lcX.js} +13 -1
- package/dist/packem_shared/{write-console-log-based-on-level-DBmRYXpj.js → write-console-log-based-on-level-ree2lDPw.js} +5 -4
- package/dist/packem_shared/{write-stream-BG8fhcs3.js → write-stream-MDqyXmc_.js} +1 -1
- package/dist/pail.browser.d.ts +1 -1
- package/dist/pail.server.d.ts +1 -76
- package/dist/processor/caller/caller-processor.js +1 -1
- package/dist/processor/environment-processor.d.ts +124 -0
- package/dist/processor/environment-processor.js +89 -0
- package/dist/processor/message-formatter-processor.d.ts +2 -3
- package/dist/processor/message-formatter-processor.js +654 -5
- package/dist/processor/opentelemetry-processor.js +4 -4
- package/dist/processor/redact-processor.d.ts +1 -1
- package/dist/processor/redact-processor.js +2 -1
- package/dist/processor/sampling-processor.d.ts +111 -0
- package/dist/processor/sampling-processor.js +59 -0
- package/dist/reporter/file/json-file-reporter.js +1 -1
- package/dist/reporter/http/abstract-http-reporter.js +23 -26
- package/dist/reporter/http/http-reporter.edge-light.js +134 -57
- package/dist/reporter/json/abstract-json-reporter.d.ts +1 -1
- package/dist/reporter/json/index.browser.js +2 -2
- package/dist/reporter/json/index.js +2 -2
- package/dist/reporter/pretty/index.browser.js +1 -1
- package/dist/reporter/pretty/index.js +1 -1
- package/dist/reporter/pretty/pretty-reporter.server.d.ts +1 -1
- package/dist/reporter/raw/raw-reporter.server.d.ts +1 -1
- package/dist/reporter/simple/simple-reporter.server.d.ts +1 -1
- package/dist/reporter/simple/simple-reporter.server.js +8 -12
- package/dist/types.d.ts +4 -4
- package/dist/utils/write-console-log-based-on-level.d.ts +1 -1
- package/dist/wide-event.d.ts +300 -0
- package/dist/wide-event.js +284 -0
- package/package.json +73 -20
- package/dist/interactive/index.d.ts +0 -2
- package/dist/interactive/index.js +0 -2
- package/dist/interactive/interactive-manager.d.ts +0 -108
- package/dist/interactive/interactive-stream-hook.d.ts +0 -68
- package/dist/packem_shared/InteractiveManager-CZ85hGNW.js +0 -172
- package/dist/packem_shared/PrettyReporter-DgZB2eBG.js +0 -222
- package/dist/packem_shared/abstract-pretty-reporter-Di_sdm2r.js +0 -50
- package/dist/packem_shared/format-label-De49vNPd.js +0 -1193
- package/dist/packem_shared/get-longest-label-C9PWeyKq.js +0 -9
- package/dist/packem_shared/index-DqKWykfa.js +0 -1146
- package/dist/packem_shared/interactive-stream-hook-DG4BtN12.js +0 -141
- package/dist/packem_shared/pail.browser-u2CSR_af.js +0 -1427
- package/dist/progress-bar.d.ts +0 -136
- package/dist/progress-bar.js +0 -404
- package/dist/spinner.d.ts +0 -220
- package/dist/spinner.js +0 -2150
- package/dist/utils/ansi-escapes.d.ts +0 -4
|
@@ -9,7 +9,8 @@ class RedactProcessor {
|
|
|
9
9
|
* @param options Additional redaction options
|
|
10
10
|
*/
|
|
11
11
|
constructor(rules, options) {
|
|
12
|
-
|
|
12
|
+
const effectiveRules = rules ?? standardRules;
|
|
13
|
+
this.#redact = (input) => redact(input, effectiveRules, options);
|
|
13
14
|
}
|
|
14
15
|
/**
|
|
15
16
|
* Processes log metadata to redact sensitive information.
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import type { Meta, Processor } from "../types.d.ts";
|
|
2
|
+
/**
|
|
3
|
+
* Head sampling configuration.
|
|
4
|
+
*
|
|
5
|
+
* Controls random sampling rates per log level. Each key is a log level name
|
|
6
|
+
* and the value is the percentage (0-100) of logs at that level to keep.
|
|
7
|
+
* Levels not listed default to 100 (keep all).
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* const headSampling: HeadSamplingConfig = {
|
|
11
|
+
* debug: 0, // Drop all debug logs
|
|
12
|
+
* informational: 10, // Keep 10% of info logs
|
|
13
|
+
* warning: 50, // Keep 50% of warning logs
|
|
14
|
+
* error: 100, // Keep all error logs
|
|
15
|
+
* };
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
type HeadSamplingConfig = Partial<Record<string, number>>;
|
|
19
|
+
/**
|
|
20
|
+
* Tail sampling condition function.
|
|
21
|
+
*
|
|
22
|
+
* A function that receives the log metadata and returns true if the log
|
|
23
|
+
* should be force-kept regardless of head sampling. This allows keeping
|
|
24
|
+
* important logs based on their content (e.g., errors, slow operations).
|
|
25
|
+
* @template L - The log level type
|
|
26
|
+
*/
|
|
27
|
+
type TailSamplingCondition<L extends string = string> = (meta: Readonly<Meta<L>>) => boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Sampling processor configuration options.
|
|
30
|
+
*/
|
|
31
|
+
interface SamplingProcessorOptions<L extends string = string> {
|
|
32
|
+
/**
|
|
33
|
+
* Head sampling rates per log level.
|
|
34
|
+
*
|
|
35
|
+
* A map of log level to sampling percentage (0-100).
|
|
36
|
+
* Levels not specified default to 100 (keep all).
|
|
37
|
+
* Set to 0 to drop all logs at that level.
|
|
38
|
+
*/
|
|
39
|
+
head?: HeadSamplingConfig;
|
|
40
|
+
/**
|
|
41
|
+
* Tail sampling conditions.
|
|
42
|
+
*
|
|
43
|
+
* An array of condition functions that can force-keep a log entry
|
|
44
|
+
* even if it was dropped by head sampling. If any condition returns true,
|
|
45
|
+
* the log is kept.
|
|
46
|
+
*/
|
|
47
|
+
tail?: TailSamplingCondition<L>[];
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Sampling Processor.
|
|
51
|
+
*
|
|
52
|
+
* Inspired by evlog's production sampling strategy, this processor implements
|
|
53
|
+
* both head sampling (random per-level) and tail sampling (force-keep based
|
|
54
|
+
* on conditions) to control log volume in production environments.
|
|
55
|
+
*
|
|
56
|
+
* **Head sampling** randomly drops a percentage of logs per level. This is
|
|
57
|
+
* evaluated first and provides broad volume control.
|
|
58
|
+
*
|
|
59
|
+
* **Tail sampling** can override head sampling to force-keep important logs
|
|
60
|
+
* based on their content. For example, you might drop 90% of info logs but
|
|
61
|
+
* force-keep any that contain error information or relate to slow operations.
|
|
62
|
+
*
|
|
63
|
+
* When a log is dropped by sampling, the processor sets a `__dropped: true`
|
|
64
|
+
* boolean flag on the meta object. Reporters should check for this flag and
|
|
65
|
+
* skip entries where `__dropped` is `true`.
|
|
66
|
+
* @template L - The log level type
|
|
67
|
+
* @example
|
|
68
|
+
* ```typescript
|
|
69
|
+
* import { createPail } from "@visulima/pail";
|
|
70
|
+
* import SamplingProcessor from "@visulima/pail/processor/sampling";
|
|
71
|
+
*
|
|
72
|
+
* const logger = createPail({
|
|
73
|
+
* processors: [
|
|
74
|
+
* new SamplingProcessor({
|
|
75
|
+
* head: {
|
|
76
|
+
* debug: 0, // Drop all debug logs
|
|
77
|
+
* informational: 10, // Keep 10% of info logs
|
|
78
|
+
* warning: 50, // Keep 50% of warnings
|
|
79
|
+
* error: 100, // Keep all errors
|
|
80
|
+
* },
|
|
81
|
+
* tail: [
|
|
82
|
+
* // Force-keep logs with errors regardless of head sampling
|
|
83
|
+
* (meta) => meta.error !== undefined,
|
|
84
|
+
* // Force-keep logs from critical scopes
|
|
85
|
+
* (meta) => meta.scope?.includes("payment") ?? false,
|
|
86
|
+
* ],
|
|
87
|
+
* }),
|
|
88
|
+
* ],
|
|
89
|
+
* });
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
declare class SamplingProcessor<L extends string = string> implements Processor<L> {
|
|
93
|
+
#private;
|
|
94
|
+
/**
|
|
95
|
+
* Creates a new SamplingProcessor instance.
|
|
96
|
+
* @param options Sampling configuration options
|
|
97
|
+
*/
|
|
98
|
+
constructor(options?: SamplingProcessorOptions<L>);
|
|
99
|
+
/**
|
|
100
|
+
* Processes log metadata to apply sampling rules.
|
|
101
|
+
*
|
|
102
|
+
* First evaluates head sampling (random per-level), then checks tail
|
|
103
|
+
* sampling conditions. If a log is dropped, the meta is marked with
|
|
104
|
+
* `__dropped: true` so reporters can skip it.
|
|
105
|
+
* @param meta The log metadata to process
|
|
106
|
+
* @returns The processed metadata, potentially marked as dropped
|
|
107
|
+
*/
|
|
108
|
+
process(meta: Meta<L>): Meta<L>;
|
|
109
|
+
}
|
|
110
|
+
export default SamplingProcessor;
|
|
111
|
+
export type { HeadSamplingConfig, SamplingProcessorOptions, TailSamplingCondition };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
class SamplingProcessor {
|
|
2
|
+
#headRates;
|
|
3
|
+
#tailConditions;
|
|
4
|
+
/**
|
|
5
|
+
* Creates a new SamplingProcessor instance.
|
|
6
|
+
* @param options Sampling configuration options
|
|
7
|
+
*/
|
|
8
|
+
constructor(options = {}) {
|
|
9
|
+
this.#headRates = options.head ?? {};
|
|
10
|
+
this.#tailConditions = options.tail ?? [];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Processes log metadata to apply sampling rules.
|
|
14
|
+
*
|
|
15
|
+
* First evaluates head sampling (random per-level), then checks tail
|
|
16
|
+
* sampling conditions. If a log is dropped, the meta is marked with
|
|
17
|
+
* `__dropped: true` so reporters can skip it.
|
|
18
|
+
* @param meta The log metadata to process
|
|
19
|
+
* @returns The processed metadata, potentially marked as dropped
|
|
20
|
+
*/
|
|
21
|
+
process(meta) {
|
|
22
|
+
const level = meta.type.level;
|
|
23
|
+
if (this.#shouldDrop(level) && !this.#shouldForceKeep(meta)) {
|
|
24
|
+
return { ...meta, dropped: true };
|
|
25
|
+
}
|
|
26
|
+
return meta;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Evaluates head sampling for the given log level.
|
|
30
|
+
* @returns true if the log should be dropped
|
|
31
|
+
*/
|
|
32
|
+
#shouldDrop(level) {
|
|
33
|
+
const rate = this.#headRates[level];
|
|
34
|
+
if (rate === void 0) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
if (rate <= 0) {
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
if (rate >= 100) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
return Math.random() * 100 >= rate;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Evaluates tail sampling conditions.
|
|
47
|
+
* @returns true if any condition forces keeping the log
|
|
48
|
+
*/
|
|
49
|
+
#shouldForceKeep(meta) {
|
|
50
|
+
for (let i = 0; i < this.#tailConditions.length; i += 1) {
|
|
51
|
+
if (this.#tailConditions[i](meta)) {
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export { SamplingProcessor as default };
|
|
@@ -20,7 +20,7 @@ const __cjs_getBuiltinModule = (module) => {
|
|
|
20
20
|
const {
|
|
21
21
|
Buffer
|
|
22
22
|
} = __cjs_getBuiltinModule("node:buffer");
|
|
23
|
-
import { AbstractJsonReporter } from '../../packem_shared/AbstractJsonReporter-
|
|
23
|
+
import { AbstractJsonReporter } from '../../packem_shared/AbstractJsonReporter-nOj0Ft1F.js';
|
|
24
24
|
const {
|
|
25
25
|
gzipSync
|
|
26
26
|
} = __cjs_getBuiltinModule("node:zlib");
|
|
@@ -33,24 +33,25 @@ const compressData = async (data) => {
|
|
|
33
33
|
const reader = stream.readable.getReader();
|
|
34
34
|
const encoder = new TextEncoder();
|
|
35
35
|
const chunks = [];
|
|
36
|
-
writer.write(encoder.encode(data));
|
|
37
|
-
writer.close();
|
|
36
|
+
await writer.write(encoder.encode(data));
|
|
37
|
+
await writer.close();
|
|
38
38
|
let done = false;
|
|
39
39
|
while (!done) {
|
|
40
|
-
const
|
|
41
|
-
done =
|
|
42
|
-
if (
|
|
43
|
-
chunks.push(
|
|
40
|
+
const result = await reader.read();
|
|
41
|
+
done = result.done;
|
|
42
|
+
if (result.value) {
|
|
43
|
+
chunks.push(result.value);
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
const totalLength = chunks.reduce((accumulator, chunk) => accumulator + chunk.length, 0);
|
|
47
|
-
const
|
|
47
|
+
const resultBuffer = new Uint8Array(totalLength);
|
|
48
48
|
let offset = 0;
|
|
49
|
-
for (
|
|
50
|
-
|
|
49
|
+
for (let i = 0; i < chunks.length; i += 1) {
|
|
50
|
+
const chunk = chunks[i];
|
|
51
|
+
resultBuffer.set(chunk, offset);
|
|
51
52
|
offset += chunk.length;
|
|
52
53
|
}
|
|
53
|
-
return
|
|
54
|
+
return resultBuffer;
|
|
54
55
|
}
|
|
55
56
|
return gzipSync(data);
|
|
56
57
|
};
|
|
@@ -125,7 +126,7 @@ const processResponse = async (response, url, method, headers, body, onDebugRequ
|
|
|
125
126
|
return false;
|
|
126
127
|
}
|
|
127
128
|
if (response.status < 500 && response.status !== 429) {
|
|
128
|
-
const error = new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
129
|
+
const error = new Error(`HTTP ${String(response.status)}: ${response.statusText}`);
|
|
129
130
|
if (onError) {
|
|
130
131
|
onError(error);
|
|
131
132
|
}
|
|
@@ -185,7 +186,7 @@ const sendWithRetry = async (url, method, headers, body, maxRetries, retryDelay,
|
|
|
185
186
|
continue;
|
|
186
187
|
}
|
|
187
188
|
if (!response.ok) {
|
|
188
|
-
const error = new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
189
|
+
const error = new Error(`HTTP ${String(response.status)}: ${response.statusText}`);
|
|
189
190
|
if (onError) {
|
|
190
191
|
onError(error);
|
|
191
192
|
}
|
|
@@ -298,7 +299,7 @@ class AbstractHttpReporter extends AbstractJsonReporter {
|
|
|
298
299
|
const logEntrySize = this.edgeCompat || typeof TextEncoder === "undefined" ? Buffer.byteLength(payload, "utf8") : new TextEncoder().encode(payload).length;
|
|
299
300
|
if (logEntrySize > this.maxLogSize) {
|
|
300
301
|
const error = new LogSizeError(
|
|
301
|
-
`Log entry exceeds maximum size of ${this.maxLogSize} bytes. Size: ${logEntrySize} bytes`,
|
|
302
|
+
`Log entry exceeds maximum size of ${String(this.maxLogSize)} bytes. Size: ${String(logEntrySize)} bytes`,
|
|
302
303
|
{ data: payloadTemplate.data, logLevel: logLevelString, message: messageString },
|
|
303
304
|
logEntrySize,
|
|
304
305
|
this.maxLogSize
|
|
@@ -330,17 +331,15 @@ class AbstractHttpReporter extends AbstractJsonReporter {
|
|
|
330
331
|
const payloadSizeWithEntry = this.currentBatchSize + logEntrySize + this.batchSendDelimiter.length;
|
|
331
332
|
const payloadSizeThreshold = this.maxPayloadSize * 0.9;
|
|
332
333
|
if (payloadSizeWithEntry > payloadSizeThreshold && this.batchQueue.length > 0) {
|
|
333
|
-
this.processBatch();
|
|
334
|
+
void this.processBatch();
|
|
334
335
|
}
|
|
335
336
|
this.batchQueue.push(payload);
|
|
336
337
|
this.currentBatchSize += logEntrySize + this.batchSendDelimiter.length;
|
|
337
|
-
|
|
338
|
-
this.
|
|
339
|
-
|
|
340
|
-
}, this.batchSendTimeout);
|
|
341
|
-
}
|
|
338
|
+
this.batchTimeout ??= setTimeout(() => {
|
|
339
|
+
void this.processBatch();
|
|
340
|
+
}, this.batchSendTimeout);
|
|
342
341
|
if (this.batchQueue.length >= this.batchSize) {
|
|
343
|
-
this.processBatch();
|
|
342
|
+
void this.processBatch();
|
|
344
343
|
}
|
|
345
344
|
}
|
|
346
345
|
/**
|
|
@@ -371,7 +370,7 @@ class AbstractHttpReporter extends AbstractJsonReporter {
|
|
|
371
370
|
} finally {
|
|
372
371
|
this.isProcessingBatch = false;
|
|
373
372
|
if (this.batchQueue.length > 0) {
|
|
374
|
-
this.processBatch();
|
|
373
|
+
void this.processBatch();
|
|
375
374
|
}
|
|
376
375
|
}
|
|
377
376
|
}
|
|
@@ -404,9 +403,7 @@ class AbstractHttpReporter extends AbstractJsonReporter {
|
|
|
404
403
|
*/
|
|
405
404
|
async sendPayload(payload, contentType) {
|
|
406
405
|
const headers = typeof this.headers === "function" ? this.headers() : { ...this.headers };
|
|
407
|
-
|
|
408
|
-
headers["content-type"] = contentType ?? this.contentType;
|
|
409
|
-
}
|
|
406
|
+
headers["content-type"] ??= contentType ?? this.contentType;
|
|
410
407
|
let finalPayload = payload;
|
|
411
408
|
if (this.compression && !this.edgeCompat) {
|
|
412
409
|
try {
|
|
@@ -414,7 +411,7 @@ class AbstractHttpReporter extends AbstractJsonReporter {
|
|
|
414
411
|
headers["content-encoding"] = "gzip";
|
|
415
412
|
} catch (error) {
|
|
416
413
|
if (this.onError) {
|
|
417
|
-
this.onError(new Error(`Compression failed: ${error}`));
|
|
414
|
+
this.onError(new Error(`Compression failed: ${String(error)}`));
|
|
418
415
|
}
|
|
419
416
|
}
|
|
420
417
|
}
|
|
@@ -36,7 +36,7 @@ const ErrorProto = Object.create(
|
|
|
36
36
|
{},
|
|
37
37
|
{
|
|
38
38
|
cause: {
|
|
39
|
-
enumerable:
|
|
39
|
+
enumerable: false,
|
|
40
40
|
value: void 0,
|
|
41
41
|
writable: true
|
|
42
42
|
},
|
|
@@ -46,62 +46,89 @@ const ErrorProto = Object.create(
|
|
|
46
46
|
writable: true
|
|
47
47
|
},
|
|
48
48
|
errors: {
|
|
49
|
-
enumerable:
|
|
49
|
+
enumerable: false,
|
|
50
50
|
value: void 0,
|
|
51
51
|
writable: true
|
|
52
52
|
},
|
|
53
53
|
message: {
|
|
54
|
-
enumerable:
|
|
54
|
+
enumerable: false,
|
|
55
55
|
value: void 0,
|
|
56
56
|
writable: true
|
|
57
57
|
},
|
|
58
58
|
name: {
|
|
59
|
-
enumerable:
|
|
59
|
+
enumerable: false,
|
|
60
60
|
value: void 0,
|
|
61
61
|
writable: true
|
|
62
62
|
},
|
|
63
63
|
stack: {
|
|
64
|
-
enumerable:
|
|
64
|
+
enumerable: false,
|
|
65
65
|
value: void 0,
|
|
66
66
|
writable: true
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
69
|
);
|
|
70
70
|
const toJsonWasCalled = /* @__PURE__ */ new WeakSet();
|
|
71
|
+
const makePropertiesEnumerable = (object) => {
|
|
72
|
+
const props = Object.getOwnPropertyNames(object);
|
|
73
|
+
for (const prop of props) {
|
|
74
|
+
const descriptor = Object.getOwnPropertyDescriptor(object, prop);
|
|
75
|
+
if (descriptor) {
|
|
76
|
+
if (!descriptor.enumerable) {
|
|
77
|
+
Object.defineProperty(object, prop, {
|
|
78
|
+
...descriptor,
|
|
79
|
+
enumerable: true
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
if (descriptor.value && typeof descriptor.value === "object" && !Array.isArray(descriptor.value) && (Object.getPrototypeOf(descriptor.value) === Object.prototype || Object.getPrototypeOf(descriptor.value) === null)) {
|
|
83
|
+
makePropertiesEnumerable(descriptor.value);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
};
|
|
71
88
|
const toJSON = (from) => {
|
|
72
89
|
toJsonWasCalled.add(from);
|
|
73
90
|
const json = from.toJSON();
|
|
74
91
|
toJsonWasCalled.delete(from);
|
|
92
|
+
if (
|
|
93
|
+
// Only make properties enumerable if the object is extensible
|
|
94
|
+
// Non-extensible objects (like when toJSON returns 'this') should preserve original enumerability
|
|
95
|
+
Object.isExtensible(json)
|
|
96
|
+
) {
|
|
97
|
+
makePropertiesEnumerable(json);
|
|
98
|
+
}
|
|
75
99
|
return json;
|
|
76
100
|
};
|
|
77
101
|
const serializeValue = (value, seen, depth, options) => {
|
|
78
102
|
if (value && value instanceof Uint8Array && value.constructor.name === "Buffer") {
|
|
79
103
|
return "[object Buffer]";
|
|
80
104
|
}
|
|
81
|
-
if (value !== null && typeof value === "object" && typeof value.pipe === "function") {
|
|
105
|
+
if (value !== null && typeof value === "object" && "pipe" in value && typeof value.pipe === "function") {
|
|
82
106
|
return "[object Stream]";
|
|
83
107
|
}
|
|
84
108
|
if (value instanceof Error) {
|
|
85
|
-
if (seen.
|
|
109
|
+
if (seen.has(value)) {
|
|
86
110
|
return "[Circular]";
|
|
87
111
|
}
|
|
88
112
|
depth += 1;
|
|
89
113
|
return _serialize(value, options, seen, depth);
|
|
90
114
|
}
|
|
91
|
-
if (options.useToJSON && typeof value.toJSON === "function") {
|
|
115
|
+
if (options.useToJSON && value !== null && typeof value === "object" && "toJSON" in value && typeof value.toJSON === "function") {
|
|
92
116
|
return value.toJSON();
|
|
93
117
|
}
|
|
94
|
-
if (
|
|
118
|
+
if (value instanceof Date) {
|
|
95
119
|
return value.toISOString();
|
|
96
120
|
}
|
|
97
121
|
if (typeof value === "function") {
|
|
98
122
|
return `[Function: ${value.name || "anonymous"}]`;
|
|
99
123
|
}
|
|
124
|
+
if (typeof value === "bigint") {
|
|
125
|
+
return `${String(value)}n`;
|
|
126
|
+
}
|
|
100
127
|
if (isPlainObject(value)) {
|
|
101
|
-
depth
|
|
102
|
-
if (options.maxDepth && depth >= options.maxDepth) {
|
|
128
|
+
if (options.maxDepth !== void 0 && options.maxDepth !== Number.POSITIVE_INFINITY && depth + 1 >= options.maxDepth) {
|
|
103
129
|
return {};
|
|
104
130
|
}
|
|
131
|
+
depth += 1;
|
|
105
132
|
const plainObject = {};
|
|
106
133
|
for (const key in value) {
|
|
107
134
|
plainObject[key] = serializeValue(value[key], seen, depth, options);
|
|
@@ -115,7 +142,7 @@ const serializeValue = (value, seen, depth, options) => {
|
|
|
115
142
|
}
|
|
116
143
|
};
|
|
117
144
|
const _serialize = (error, options, seen, depth) => {
|
|
118
|
-
seen.
|
|
145
|
+
seen.add(error);
|
|
119
146
|
if (options.maxDepth === 0) {
|
|
120
147
|
return {};
|
|
121
148
|
}
|
|
@@ -123,31 +150,88 @@ const _serialize = (error, options, seen, depth) => {
|
|
|
123
150
|
return toJSON(error);
|
|
124
151
|
}
|
|
125
152
|
const protoError = Object.create(ErrorProto);
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
153
|
+
Object.defineProperty(protoError, "name", {
|
|
154
|
+
configurable: true,
|
|
155
|
+
enumerable: true,
|
|
156
|
+
value: Object.prototype.toString.call(error.constructor) === "[object Function]" ? error.constructor.name : error.name,
|
|
157
|
+
writable: true
|
|
158
|
+
});
|
|
159
|
+
Object.defineProperty(protoError, "message", {
|
|
160
|
+
configurable: true,
|
|
161
|
+
enumerable: true,
|
|
162
|
+
value: error.message,
|
|
163
|
+
writable: true
|
|
164
|
+
});
|
|
165
|
+
Object.defineProperty(protoError, "stack", {
|
|
166
|
+
configurable: true,
|
|
167
|
+
enumerable: true,
|
|
168
|
+
value: error.stack,
|
|
169
|
+
writable: true
|
|
170
|
+
});
|
|
129
171
|
if (Array.isArray(error.errors)) {
|
|
130
172
|
const aggregateErrors = [];
|
|
131
173
|
for (const aggregateError of error.errors) {
|
|
132
174
|
if (!(aggregateError instanceof Error)) {
|
|
133
175
|
throw new TypeError("All errors in the 'errors' property must be instances of Error");
|
|
134
176
|
}
|
|
135
|
-
if (seen.
|
|
136
|
-
protoError
|
|
177
|
+
if (seen.has(aggregateError)) {
|
|
178
|
+
Object.defineProperty(protoError, "errors", {
|
|
179
|
+
configurable: true,
|
|
180
|
+
enumerable: true,
|
|
181
|
+
value: [],
|
|
182
|
+
writable: true
|
|
183
|
+
});
|
|
137
184
|
return protoError;
|
|
138
185
|
}
|
|
139
186
|
aggregateErrors.push(_serialize(aggregateError, options, seen, depth));
|
|
140
187
|
}
|
|
141
|
-
protoError
|
|
188
|
+
Object.defineProperty(protoError, "errors", {
|
|
189
|
+
configurable: true,
|
|
190
|
+
enumerable: true,
|
|
191
|
+
value: aggregateErrors,
|
|
192
|
+
writable: true
|
|
193
|
+
});
|
|
142
194
|
}
|
|
143
|
-
|
|
144
|
-
|
|
195
|
+
const causeValue = error.cause;
|
|
196
|
+
if (causeValue !== void 0 && causeValue !== null) {
|
|
197
|
+
if (causeValue instanceof Error) {
|
|
198
|
+
if (seen.has(causeValue)) {
|
|
199
|
+
Object.defineProperty(protoError, "cause", {
|
|
200
|
+
configurable: true,
|
|
201
|
+
enumerable: true,
|
|
202
|
+
value: "[Circular]",
|
|
203
|
+
writable: true
|
|
204
|
+
});
|
|
205
|
+
} else {
|
|
206
|
+
Object.defineProperty(protoError, "cause", {
|
|
207
|
+
configurable: true,
|
|
208
|
+
enumerable: true,
|
|
209
|
+
value: _serialize(causeValue, options, seen, depth),
|
|
210
|
+
writable: true
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
} else {
|
|
214
|
+
const serializedCause = serializeValue(causeValue, seen, depth, options);
|
|
215
|
+
Object.defineProperty(protoError, "cause", {
|
|
216
|
+
configurable: true,
|
|
217
|
+
enumerable: true,
|
|
218
|
+
value: serializedCause,
|
|
219
|
+
writable: true
|
|
220
|
+
});
|
|
221
|
+
}
|
|
145
222
|
}
|
|
146
223
|
for (const key in error) {
|
|
147
|
-
if (
|
|
148
|
-
|
|
149
|
-
protoError[key] = serializeValue(value, seen, depth, options);
|
|
224
|
+
if (key === "name" || key === "message" || key === "stack" || key === "cause" || key === "errors") {
|
|
225
|
+
continue;
|
|
150
226
|
}
|
|
227
|
+
const value = error[key];
|
|
228
|
+
const serializedValue = serializeValue(value, seen, depth, options);
|
|
229
|
+
Object.defineProperty(protoError, key, {
|
|
230
|
+
configurable: true,
|
|
231
|
+
enumerable: true,
|
|
232
|
+
value: serializedValue,
|
|
233
|
+
writable: true
|
|
234
|
+
});
|
|
151
235
|
}
|
|
152
236
|
if (Array.isArray(options.exclude) && options.exclude.length > 0) {
|
|
153
237
|
for (const key of options.exclude) {
|
|
@@ -166,7 +250,7 @@ const serialize = (error, options = {}) => _serialize(
|
|
|
166
250
|
maxDepth: options.maxDepth ?? Number.POSITIVE_INFINITY,
|
|
167
251
|
useToJSON: options.useToJSON ?? false
|
|
168
252
|
},
|
|
169
|
-
|
|
253
|
+
/* @__PURE__ */ new Set(),
|
|
170
254
|
0
|
|
171
255
|
);
|
|
172
256
|
|
|
@@ -188,7 +272,6 @@ class AbstractJsonReporter {
|
|
|
188
272
|
* Sets a custom stringify function for object serialization.
|
|
189
273
|
* @param function_ The stringify function to use for serialization
|
|
190
274
|
*/
|
|
191
|
-
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
|
|
192
275
|
setStringify(function_) {
|
|
193
276
|
this.stringify = function_;
|
|
194
277
|
}
|
|
@@ -199,19 +282,16 @@ class AbstractJsonReporter {
|
|
|
199
282
|
rest.label = rest.label.trim();
|
|
200
283
|
}
|
|
201
284
|
if (file) {
|
|
202
|
-
rest.file = `${file.name}:${file.line}${file.column ? `:${file.column}` : ""}`;
|
|
203
|
-
}
|
|
204
|
-
if (message === EMPTY_SYMBOL) {
|
|
205
|
-
rest.message = void 0;
|
|
206
|
-
} else {
|
|
207
|
-
rest.message = message;
|
|
285
|
+
rest.file = `${file.name ?? ""}:${String(file.line)}${file.column ? `:${String(file.column)}` : ""}`;
|
|
208
286
|
}
|
|
287
|
+
rest.message = message === EMPTY_SYMBOL ? void 0 : message;
|
|
209
288
|
if (error) {
|
|
210
289
|
rest.error = serialize(error, this.errorOptions);
|
|
211
290
|
}
|
|
212
291
|
if (context) {
|
|
213
292
|
const newContext = [];
|
|
214
|
-
for (
|
|
293
|
+
for (let i = 0; i < context.length; i += 1) {
|
|
294
|
+
const item = context[i];
|
|
215
295
|
if (item === EMPTY_SYMBOL) {
|
|
216
296
|
continue;
|
|
217
297
|
}
|
|
@@ -235,24 +315,25 @@ const compressData = async (data) => {
|
|
|
235
315
|
const reader = stream.readable.getReader();
|
|
236
316
|
const encoder = new TextEncoder();
|
|
237
317
|
const chunks = [];
|
|
238
|
-
writer.write(encoder.encode(data));
|
|
239
|
-
writer.close();
|
|
318
|
+
await writer.write(encoder.encode(data));
|
|
319
|
+
await writer.close();
|
|
240
320
|
let done = false;
|
|
241
321
|
while (!done) {
|
|
242
|
-
const
|
|
243
|
-
done =
|
|
244
|
-
if (
|
|
245
|
-
chunks.push(
|
|
322
|
+
const result = await reader.read();
|
|
323
|
+
done = result.done;
|
|
324
|
+
if (result.value) {
|
|
325
|
+
chunks.push(result.value);
|
|
246
326
|
}
|
|
247
327
|
}
|
|
248
328
|
const totalLength = chunks.reduce((accumulator, chunk) => accumulator + chunk.length, 0);
|
|
249
|
-
const
|
|
329
|
+
const resultBuffer = new Uint8Array(totalLength);
|
|
250
330
|
let offset = 0;
|
|
251
|
-
for (
|
|
252
|
-
|
|
331
|
+
for (let i = 0; i < chunks.length; i += 1) {
|
|
332
|
+
const chunk = chunks[i];
|
|
333
|
+
resultBuffer.set(chunk, offset);
|
|
253
334
|
offset += chunk.length;
|
|
254
335
|
}
|
|
255
|
-
return
|
|
336
|
+
return resultBuffer;
|
|
256
337
|
}
|
|
257
338
|
return gzipSync(data);
|
|
258
339
|
};
|
|
@@ -327,7 +408,7 @@ const processResponse = async (response, url, method, headers, body, onDebugRequ
|
|
|
327
408
|
return false;
|
|
328
409
|
}
|
|
329
410
|
if (response.status < 500 && response.status !== 429) {
|
|
330
|
-
const error = new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
411
|
+
const error = new Error(`HTTP ${String(response.status)}: ${response.statusText}`);
|
|
331
412
|
if (onError) {
|
|
332
413
|
onError(error);
|
|
333
414
|
}
|
|
@@ -387,7 +468,7 @@ const sendWithRetry = async (url, method, headers, body, maxRetries, retryDelay,
|
|
|
387
468
|
continue;
|
|
388
469
|
}
|
|
389
470
|
if (!response.ok) {
|
|
390
|
-
const error = new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
471
|
+
const error = new Error(`HTTP ${String(response.status)}: ${response.statusText}`);
|
|
391
472
|
if (onError) {
|
|
392
473
|
onError(error);
|
|
393
474
|
}
|
|
@@ -500,7 +581,7 @@ class AbstractHttpReporter extends AbstractJsonReporter {
|
|
|
500
581
|
const logEntrySize = this.edgeCompat || typeof TextEncoder === "undefined" ? Buffer.byteLength(payload, "utf8") : new TextEncoder().encode(payload).length;
|
|
501
582
|
if (logEntrySize > this.maxLogSize) {
|
|
502
583
|
const error = new LogSizeError(
|
|
503
|
-
`Log entry exceeds maximum size of ${this.maxLogSize} bytes. Size: ${logEntrySize} bytes`,
|
|
584
|
+
`Log entry exceeds maximum size of ${String(this.maxLogSize)} bytes. Size: ${String(logEntrySize)} bytes`,
|
|
504
585
|
{ data: payloadTemplate.data, logLevel: logLevelString, message: messageString },
|
|
505
586
|
logEntrySize,
|
|
506
587
|
this.maxLogSize
|
|
@@ -532,17 +613,15 @@ class AbstractHttpReporter extends AbstractJsonReporter {
|
|
|
532
613
|
const payloadSizeWithEntry = this.currentBatchSize + logEntrySize + this.batchSendDelimiter.length;
|
|
533
614
|
const payloadSizeThreshold = this.maxPayloadSize * 0.9;
|
|
534
615
|
if (payloadSizeWithEntry > payloadSizeThreshold && this.batchQueue.length > 0) {
|
|
535
|
-
this.processBatch();
|
|
616
|
+
void this.processBatch();
|
|
536
617
|
}
|
|
537
618
|
this.batchQueue.push(payload);
|
|
538
619
|
this.currentBatchSize += logEntrySize + this.batchSendDelimiter.length;
|
|
539
|
-
|
|
540
|
-
this.
|
|
541
|
-
|
|
542
|
-
}, this.batchSendTimeout);
|
|
543
|
-
}
|
|
620
|
+
this.batchTimeout ??= setTimeout(() => {
|
|
621
|
+
void this.processBatch();
|
|
622
|
+
}, this.batchSendTimeout);
|
|
544
623
|
if (this.batchQueue.length >= this.batchSize) {
|
|
545
|
-
this.processBatch();
|
|
624
|
+
void this.processBatch();
|
|
546
625
|
}
|
|
547
626
|
}
|
|
548
627
|
/**
|
|
@@ -573,7 +652,7 @@ class AbstractHttpReporter extends AbstractJsonReporter {
|
|
|
573
652
|
} finally {
|
|
574
653
|
this.isProcessingBatch = false;
|
|
575
654
|
if (this.batchQueue.length > 0) {
|
|
576
|
-
this.processBatch();
|
|
655
|
+
void this.processBatch();
|
|
577
656
|
}
|
|
578
657
|
}
|
|
579
658
|
}
|
|
@@ -606,9 +685,7 @@ class AbstractHttpReporter extends AbstractJsonReporter {
|
|
|
606
685
|
*/
|
|
607
686
|
async sendPayload(payload, contentType) {
|
|
608
687
|
const headers = typeof this.headers === "function" ? this.headers() : { ...this.headers };
|
|
609
|
-
|
|
610
|
-
headers["content-type"] = contentType ?? this.contentType;
|
|
611
|
-
}
|
|
688
|
+
headers["content-type"] ??= contentType ?? this.contentType;
|
|
612
689
|
let finalPayload = payload;
|
|
613
690
|
if (this.compression && !this.edgeCompat) {
|
|
614
691
|
try {
|
|
@@ -616,7 +693,7 @@ class AbstractHttpReporter extends AbstractJsonReporter {
|
|
|
616
693
|
headers["content-encoding"] = "gzip";
|
|
617
694
|
} catch (error) {
|
|
618
695
|
if (this.onError) {
|
|
619
|
-
this.onError(new Error(`Compression failed: ${error}`));
|
|
696
|
+
this.onError(new Error(`Compression failed: ${String(error)}`));
|
|
620
697
|
}
|
|
621
698
|
}
|
|
622
699
|
}
|