vedatrace 0.2.1 → 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 +53 -7
- package/dist/index-BcBZY8as.mjs +231 -0
- package/dist/index-osD28Hs0.cjs +239 -0
- package/dist/index.cjs +122 -119
- package/dist/index.d.cts +80 -35
- package/dist/index.d.mts +80 -35
- package/dist/index.mjs +122 -120
- package/dist/integrations/express.cjs +3 -4
- package/dist/integrations/express.d.cts +1 -1
- package/dist/integrations/express.d.mts +1 -1
- package/dist/integrations/express.mjs +3 -4
- package/dist/integrations/nextjs.cjs +31 -5
- package/dist/integrations/nextjs.d.cts +7 -15
- package/dist/integrations/nextjs.d.mts +7 -15
- package/dist/integrations/nextjs.mjs +31 -6
- package/dist/integrations/react.cjs +1 -1
- package/dist/integrations/react.d.cts +1 -1
- package/dist/integrations/react.d.mts +1 -1
- package/dist/integrations/react.mjs +1 -1
- package/dist/transports/index.cjs +5 -153
- package/dist/transports/index.d.cts +16 -6
- package/dist/transports/index.d.mts +16 -6
- package/dist/transports/index.mjs +1 -153
- package/dist/{types-BU0UESs9.d.cts → types-CSBzeGyK.d.cts} +8 -0
- package/dist/{types-BU0UESs9.d.mts → types-CSBzeGyK.d.mts} +8 -0
- package/package.json +150 -141
package/dist/index.cjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var transports_index = require('./
|
|
5
|
+
var transports_index = require('./index-osD28Hs0.cjs');
|
|
6
6
|
|
|
7
7
|
class VedaTraceBatcher {
|
|
8
8
|
constructor(transports, config, immediateFlush = false) {
|
|
@@ -10,55 +10,53 @@ class VedaTraceBatcher {
|
|
|
10
10
|
this.config = config;
|
|
11
11
|
this.immediateFlush = immediateFlush;
|
|
12
12
|
this.context = config.executionContext;
|
|
13
|
+
this.waitUntilFn = config.waitUntil;
|
|
13
14
|
}
|
|
14
15
|
queue = [];
|
|
15
16
|
flushTimer = null;
|
|
16
|
-
|
|
17
|
+
flushQueued = false;
|
|
17
18
|
isFlushing = false;
|
|
18
19
|
pendingFlush = null;
|
|
19
20
|
context;
|
|
20
|
-
|
|
21
|
+
waitUntilFn;
|
|
22
|
+
/**
|
|
23
|
+
* Set when the ingestion endpoint rejects our credentials. Every subsequent
|
|
24
|
+
* batch would fail identically, so we stop rather than spend a request (and a
|
|
25
|
+
* retry storm) per flush for the life of the process. start() clears it.
|
|
26
|
+
*/
|
|
27
|
+
halted = false;
|
|
21
28
|
setContext(ctx) {
|
|
22
29
|
this.context = ctx;
|
|
23
30
|
}
|
|
24
|
-
/** Get current context */
|
|
25
31
|
getContext() {
|
|
26
32
|
return this.context;
|
|
27
33
|
}
|
|
28
|
-
/** Add log to queue with context-aware flush */
|
|
29
34
|
add(log) {
|
|
35
|
+
if (this.halted) return;
|
|
30
36
|
this.queue.push(log);
|
|
31
|
-
if (
|
|
37
|
+
if (this.context || this.waitUntilFn) {
|
|
38
|
+
this.debouncedFlush();
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (this.immediateFlush) {
|
|
42
|
+
this.flush();
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (!this.flushTimer) {
|
|
32
46
|
this.startFlushTimer();
|
|
33
47
|
}
|
|
34
|
-
if (this.
|
|
35
|
-
this.debouncedFlush();
|
|
36
|
-
} else if (this.queue.length >= this.config.batchSize) {
|
|
48
|
+
if (this.queue.length >= this.config.batchSize) {
|
|
37
49
|
this.flush();
|
|
38
50
|
}
|
|
39
51
|
}
|
|
40
|
-
/** Debounced flush - prevents rapid-fire flushes */
|
|
41
52
|
debouncedFlush() {
|
|
42
|
-
if (this.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
this.
|
|
47
|
-
|
|
48
|
-
if (this.config.onError) {
|
|
49
|
-
this.config.onError(
|
|
50
|
-
error instanceof Error ? error : new Error(String(error))
|
|
51
|
-
);
|
|
52
|
-
} else {
|
|
53
|
-
console.error(
|
|
54
|
-
"[VedaTrace] Debounced flush error:",
|
|
55
|
-
error instanceof Error ? error.message : String(error)
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
}, 100);
|
|
53
|
+
if (this.flushQueued) return;
|
|
54
|
+
this.flushQueued = true;
|
|
55
|
+
queueMicrotask(() => {
|
|
56
|
+
this.flushQueued = false;
|
|
57
|
+
this.flush().catch((error) => this.reportError(error));
|
|
58
|
+
});
|
|
60
59
|
}
|
|
61
|
-
/** Flush logs to all transports with waitUntil protection */
|
|
62
60
|
async flush() {
|
|
63
61
|
if (this.isFlushing) {
|
|
64
62
|
return this.pendingFlush ?? Promise.resolve();
|
|
@@ -72,10 +70,16 @@ class VedaTraceBatcher {
|
|
|
72
70
|
const flushPromise = this.sendWithRetry(logsToSend).finally(() => {
|
|
73
71
|
this.isFlushing = false;
|
|
74
72
|
this.pendingFlush = null;
|
|
73
|
+
}).then(() => {
|
|
74
|
+
if (this.queue.length > 0 && !this.halted) {
|
|
75
|
+
return this.flush();
|
|
76
|
+
}
|
|
75
77
|
});
|
|
76
78
|
this.pendingFlush = flushPromise;
|
|
77
|
-
if (this.context) {
|
|
79
|
+
if (this.context && typeof this.context.waitUntil === "function") {
|
|
78
80
|
this.context.waitUntil(flushPromise);
|
|
81
|
+
} else if (typeof this.waitUntilFn === "function") {
|
|
82
|
+
this.waitUntilFn(flushPromise);
|
|
79
83
|
}
|
|
80
84
|
return flushPromise;
|
|
81
85
|
}
|
|
@@ -85,26 +89,47 @@ class VedaTraceBatcher {
|
|
|
85
89
|
try {
|
|
86
90
|
await transport.send(logs);
|
|
87
91
|
} catch (error) {
|
|
88
|
-
errors.push(error
|
|
92
|
+
errors.push(error);
|
|
89
93
|
}
|
|
90
94
|
}
|
|
91
|
-
if (errors.length
|
|
92
|
-
|
|
93
|
-
await this.delay(this.config.retryDelay * (attempt + 1));
|
|
94
|
-
return this.sendWithRetry(logs, attempt + 1);
|
|
95
|
-
}
|
|
96
|
-
const combinedError = new Error(
|
|
97
|
-
`Failed to send logs after ${this.config.maxRetries} retries: ${errors.map((e) => e.message).join(", ")}`
|
|
98
|
-
);
|
|
99
|
-
if (this.config.onError) {
|
|
100
|
-
this.config.onError(combinedError);
|
|
101
|
-
} else {
|
|
102
|
-
console.error("[VedaTrace]", combinedError.message);
|
|
103
|
-
}
|
|
95
|
+
if (errors.length === 0 || errors.length < this.transports.length) {
|
|
96
|
+
this.config.onSuccess?.();
|
|
104
97
|
return;
|
|
105
98
|
}
|
|
106
|
-
|
|
107
|
-
|
|
99
|
+
const fatalError = errors.find(transports_index.isFatal);
|
|
100
|
+
if (fatalError) {
|
|
101
|
+
this.halt(fatalError);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (errors.some(transports_index.isRetryable) && attempt < this.config.maxRetries) {
|
|
105
|
+
const backoff = this.config.retryDelay * (attempt + 1);
|
|
106
|
+
await this.delay(transports_index.retryAfterMs(errors) ?? backoff);
|
|
107
|
+
return this.sendWithRetry(logs, attempt + 1);
|
|
108
|
+
}
|
|
109
|
+
const detail = errors.map(describeError).join(", ");
|
|
110
|
+
this.reportError(
|
|
111
|
+
new Error(
|
|
112
|
+
errors.some(transports_index.isRetryable) ? `Failed to send ${logs.length} logs after ${this.config.maxRetries} retries: ${detail}` : `Failed to send ${logs.length} logs: ${detail}`
|
|
113
|
+
)
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
/** Stop accepting logs after an unrecoverable authentication failure. */
|
|
117
|
+
halt(error) {
|
|
118
|
+
this.halted = true;
|
|
119
|
+
this.queue = [];
|
|
120
|
+
this.stop();
|
|
121
|
+
this.reportError(
|
|
122
|
+
new Error(
|
|
123
|
+
`VedaTrace disabled: ${describeError(error)}. Check your API key and the key's allowed origins, then call logger.start() to resume.`
|
|
124
|
+
)
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
reportError(error) {
|
|
128
|
+
const normalized = error instanceof Error ? error : new Error(String(error));
|
|
129
|
+
if (this.config.onError) {
|
|
130
|
+
this.config.onError(normalized);
|
|
131
|
+
} else {
|
|
132
|
+
console.error("[VedaTrace]", normalized.message);
|
|
108
133
|
}
|
|
109
134
|
}
|
|
110
135
|
startFlushTimer() {
|
|
@@ -113,22 +138,11 @@ class VedaTraceBatcher {
|
|
|
113
138
|
}
|
|
114
139
|
this.flushTimer = setInterval(() => {
|
|
115
140
|
if (this.queue.length > 0) {
|
|
116
|
-
this.flush().catch((error) =>
|
|
117
|
-
if (this.config.onError) {
|
|
118
|
-
this.config.onError(
|
|
119
|
-
error instanceof Error ? error : new Error(String(error))
|
|
120
|
-
);
|
|
121
|
-
} else {
|
|
122
|
-
console.error(
|
|
123
|
-
"[VedaTrace] Flush error:",
|
|
124
|
-
error instanceof Error ? error.message : String(error)
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
});
|
|
141
|
+
this.flush().catch((error) => this.reportError(error));
|
|
128
142
|
}
|
|
129
143
|
}, this.config.flushInterval);
|
|
130
144
|
if (this.config.unrefTimer === true) {
|
|
131
|
-
this.flushTimer.unref();
|
|
145
|
+
this.flushTimer.unref?.();
|
|
132
146
|
}
|
|
133
147
|
}
|
|
134
148
|
stop() {
|
|
@@ -136,12 +150,10 @@ class VedaTraceBatcher {
|
|
|
136
150
|
clearInterval(this.flushTimer);
|
|
137
151
|
this.flushTimer = null;
|
|
138
152
|
}
|
|
139
|
-
|
|
140
|
-
clearTimeout(this.flushDebounceTimer);
|
|
141
|
-
this.flushDebounceTimer = null;
|
|
142
|
-
}
|
|
153
|
+
this.flushQueued = false;
|
|
143
154
|
}
|
|
144
155
|
start() {
|
|
156
|
+
this.halted = false;
|
|
145
157
|
if (!this.flushTimer && !this.immediateFlush) {
|
|
146
158
|
this.startFlushTimer();
|
|
147
159
|
}
|
|
@@ -152,10 +164,17 @@ class VedaTraceBatcher {
|
|
|
152
164
|
getQueueSize() {
|
|
153
165
|
return this.queue.length;
|
|
154
166
|
}
|
|
167
|
+
/** True once an auth failure has shut the batcher down. */
|
|
168
|
+
isHalted() {
|
|
169
|
+
return this.halted;
|
|
170
|
+
}
|
|
155
171
|
setExecutionContext(ctx) {
|
|
156
172
|
this.context = ctx;
|
|
157
173
|
}
|
|
158
174
|
}
|
|
175
|
+
function describeError(error) {
|
|
176
|
+
return error instanceof Error ? error.message : String(error);
|
|
177
|
+
}
|
|
159
178
|
|
|
160
179
|
function detectRuntime() {
|
|
161
180
|
if (typeof navigator !== "undefined" && navigator.userAgent === "Cloudflare-Workers") {
|
|
@@ -198,7 +217,8 @@ function isBrowser() {
|
|
|
198
217
|
return detectRuntime() === "browser";
|
|
199
218
|
}
|
|
200
219
|
|
|
201
|
-
const SDK_VERSION =
|
|
220
|
+
const SDK_VERSION = "0.3.1";
|
|
221
|
+
|
|
202
222
|
class VedaTraceLogger {
|
|
203
223
|
batcher = null;
|
|
204
224
|
runtime;
|
|
@@ -351,24 +371,17 @@ class BrowserLifecycle {
|
|
|
351
371
|
this.config = config;
|
|
352
372
|
this.boundVisibilityHandler = this.handleVisibilityChange.bind(this);
|
|
353
373
|
this.boundPageHideHandler = this.handlePageHide.bind(this);
|
|
354
|
-
this.boundBeforeUnloadHandler = this.handleBeforeUnload.bind(this);
|
|
355
|
-
this.boundUnloadHandler = this.handleUnload.bind(this);
|
|
356
374
|
}
|
|
357
375
|
boundVisibilityHandler;
|
|
358
376
|
boundPageHideHandler;
|
|
359
|
-
boundBeforeUnloadHandler;
|
|
360
|
-
boundUnloadHandler;
|
|
361
377
|
isAttached = false;
|
|
362
378
|
pendingFlush = null;
|
|
363
379
|
/** Start listening for browser lifecycle events */
|
|
364
380
|
attach() {
|
|
365
381
|
if (this.isAttached) return;
|
|
366
|
-
if (typeof document
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
window.addEventListener("beforeunload", this.boundBeforeUnloadHandler);
|
|
370
|
-
window.addEventListener("unload", this.boundUnloadHandler);
|
|
371
|
-
}
|
|
382
|
+
if (typeof document === "undefined" || typeof window === "undefined") return;
|
|
383
|
+
document.addEventListener("visibilitychange", this.boundVisibilityHandler);
|
|
384
|
+
window.addEventListener("pagehide", this.boundPageHideHandler);
|
|
372
385
|
this.isAttached = true;
|
|
373
386
|
if (this.config.debug) {
|
|
374
387
|
console.log("[VedaTrace] Browser lifecycle handlers attached");
|
|
@@ -377,21 +390,25 @@ class BrowserLifecycle {
|
|
|
377
390
|
/** Stop listening for browser lifecycle events */
|
|
378
391
|
detach() {
|
|
379
392
|
if (!this.isAttached) return;
|
|
380
|
-
if (typeof document !== "undefined") {
|
|
393
|
+
if (typeof document !== "undefined" && typeof window !== "undefined") {
|
|
381
394
|
document.removeEventListener(
|
|
382
395
|
"visibilitychange",
|
|
383
396
|
this.boundVisibilityHandler
|
|
384
397
|
);
|
|
385
398
|
window.removeEventListener("pagehide", this.boundPageHideHandler);
|
|
386
|
-
window.removeEventListener("beforeunload", this.boundBeforeUnloadHandler);
|
|
387
|
-
window.removeEventListener("unload", this.boundUnloadHandler);
|
|
388
399
|
}
|
|
389
400
|
this.isAttached = false;
|
|
390
401
|
if (this.config.debug) {
|
|
391
402
|
console.log("[VedaTrace] Browser lifecycle handlers detached");
|
|
392
403
|
}
|
|
393
404
|
}
|
|
394
|
-
/**
|
|
405
|
+
/**
|
|
406
|
+
* Flush when the page becomes hidden.
|
|
407
|
+
*
|
|
408
|
+
* This is the one that actually matters: on mobile, a backgrounded tab is
|
|
409
|
+
* often discarded without ever firing pagehide, so "hidden" is the last
|
|
410
|
+
* reliable moment to ship what we have.
|
|
411
|
+
*/
|
|
395
412
|
handleVisibilityChange() {
|
|
396
413
|
if (document.visibilityState === "hidden") {
|
|
397
414
|
if (this.config.debug) {
|
|
@@ -400,7 +417,7 @@ class BrowserLifecycle {
|
|
|
400
417
|
this.scheduleFlush();
|
|
401
418
|
}
|
|
402
419
|
}
|
|
403
|
-
/**
|
|
420
|
+
/** Final flush as the page is torn down or frozen into the bfcache. */
|
|
404
421
|
handlePageHide(event) {
|
|
405
422
|
if (this.config.debug) {
|
|
406
423
|
console.log(
|
|
@@ -408,46 +425,16 @@ class BrowserLifecycle {
|
|
|
408
425
|
event.persisted ? "(cached)" : "(navigation)"
|
|
409
426
|
);
|
|
410
427
|
}
|
|
411
|
-
|
|
412
|
-
this.scheduleFlush();
|
|
413
|
-
} else {
|
|
414
|
-
this.finalFlush();
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
/** Handle beforeunload - backup flush mechanism */
|
|
418
|
-
handleBeforeUnload(event) {
|
|
419
|
-
if (this.config.debug) {
|
|
420
|
-
console.log("[VedaTrace] Before unload event");
|
|
421
|
-
}
|
|
422
|
-
this.finalFlush();
|
|
423
|
-
}
|
|
424
|
-
/** Handle unload - fallback for older browsers */
|
|
425
|
-
handleUnload() {
|
|
426
|
-
if (this.config.debug) {
|
|
427
|
-
console.log("[VedaTrace] Unload event");
|
|
428
|
-
}
|
|
429
|
-
this.finalFlush();
|
|
428
|
+
this.scheduleFlush();
|
|
430
429
|
}
|
|
431
|
-
/**
|
|
430
|
+
/** Flush at most once at a time; keepalive carries it past the document. */
|
|
432
431
|
scheduleFlush() {
|
|
433
432
|
if (this.pendingFlush) return;
|
|
434
|
-
this.pendingFlush = this.config.flush().
|
|
433
|
+
this.pendingFlush = this.config.flush().catch(() => {
|
|
434
|
+
}).finally(() => {
|
|
435
435
|
this.pendingFlush = null;
|
|
436
436
|
});
|
|
437
437
|
}
|
|
438
|
-
/**
|
|
439
|
-
* Final flush using keepalive fetch
|
|
440
|
-
* For sending logs after the page context is destroyed
|
|
441
|
-
*/
|
|
442
|
-
finalFlush() {
|
|
443
|
-
for (const transport of this.config.transports) {
|
|
444
|
-
if (transport.name === "http" && "flush" in transport) {
|
|
445
|
-
transport.flush?.();
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
this.config.flush().catch(() => {
|
|
449
|
-
});
|
|
450
|
-
}
|
|
451
438
|
/** Check if handlers are attached */
|
|
452
439
|
isActive() {
|
|
453
440
|
return this.isAttached;
|
|
@@ -528,6 +515,16 @@ function redactPii(value, mask) {
|
|
|
528
515
|
return result;
|
|
529
516
|
}
|
|
530
517
|
|
|
518
|
+
function resolveApiKey(config) {
|
|
519
|
+
if (config.apiKey) return config.apiKey;
|
|
520
|
+
try {
|
|
521
|
+
if (typeof process !== "undefined" && process.env) {
|
|
522
|
+
return process.env.VEDATRACE_API_KEY || void 0;
|
|
523
|
+
}
|
|
524
|
+
} catch {
|
|
525
|
+
}
|
|
526
|
+
return void 0;
|
|
527
|
+
}
|
|
531
528
|
const RUNTIME_FLUSH_INTERVALS = {
|
|
532
529
|
node: 3e3,
|
|
533
530
|
bun: 3e3,
|
|
@@ -538,15 +535,16 @@ const RUNTIME_FLUSH_INTERVALS = {
|
|
|
538
535
|
};
|
|
539
536
|
function vedatrace(config = {}) {
|
|
540
537
|
const runtime = detectRuntime();
|
|
541
|
-
const
|
|
542
|
-
|
|
538
|
+
const apiKey = resolveApiKey(config);
|
|
539
|
+
const logger = new VedaTraceLogger(apiKey ? { ...config, apiKey } : config);
|
|
540
|
+
if (apiKey && (!config.transports || config.transports.length === 0)) {
|
|
543
541
|
const isBrowserEnv = isBrowser();
|
|
544
542
|
const isServerlessEnv = isServerless();
|
|
545
543
|
const isLongRunningEnv = isLongRunning();
|
|
546
544
|
const HttpTransport = isBrowserEnv ? transports_index.VedaTraceHttpTransportBrowser : transports_index.VedaTraceHttpTransport;
|
|
547
545
|
const httpConfig = {
|
|
548
|
-
apiKey
|
|
549
|
-
keepalive: isBrowserEnv
|
|
546
|
+
apiKey,
|
|
547
|
+
keepalive: isBrowserEnv || isServerlessEnv
|
|
550
548
|
};
|
|
551
549
|
if (config.endpoint) httpConfig.endpoint = config.endpoint;
|
|
552
550
|
const httpTransport = new HttpTransport(httpConfig);
|
|
@@ -571,12 +569,15 @@ function vedatrace(config = {}) {
|
|
|
571
569
|
unrefTimer: config.unrefTimer ?? shouldUnrefTimer,
|
|
572
570
|
executionContext: config.executionContext,
|
|
573
571
|
onError: config.onError,
|
|
574
|
-
onSuccess: config.onSuccess
|
|
572
|
+
onSuccess: config.onSuccess,
|
|
573
|
+
debug: config.debug,
|
|
574
|
+
waitUntil: config.waitUntil
|
|
575
575
|
},
|
|
576
576
|
immediateFlush
|
|
577
577
|
);
|
|
578
578
|
logger.setBatcher(batcher);
|
|
579
|
-
|
|
579
|
+
const isNodeRuntime = typeof process !== "undefined" && process.versions?.node;
|
|
580
|
+
if (typeof process !== "undefined" && (isLongRunningEnv || isNodeRuntime)) {
|
|
580
581
|
const flushLogs = async () => {
|
|
581
582
|
await batcher.flush();
|
|
582
583
|
};
|
|
@@ -612,7 +613,9 @@ function devVedatrace(config = {}) {
|
|
|
612
613
|
exports.VedaTraceConsoleTransport = transports_index.VedaTraceConsoleTransport;
|
|
613
614
|
exports.VedaTraceHttpTransport = transports_index.VedaTraceHttpTransport;
|
|
614
615
|
exports.VedaTraceHttpTransportBrowser = transports_index.VedaTraceHttpTransportBrowser;
|
|
616
|
+
exports.VedaTraceTransportError = transports_index.VedaTraceTransportError;
|
|
615
617
|
exports.BrowserLifecycle = BrowserLifecycle;
|
|
618
|
+
exports.SDK_VERSION = SDK_VERSION;
|
|
616
619
|
exports.VedaTraceBatcher = VedaTraceBatcher;
|
|
617
620
|
exports.VedaTraceLogger = VedaTraceLogger;
|
|
618
621
|
exports.default = vedatrace;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,17 +1,14 @@
|
|
|
1
|
-
import { b as VedaTraceTransport, B as BatcherConfig, c as VedaTraceEdgeContext, I as InternalLogEntry, V as VedaTraceLoggerInterface, R as RuntimeType$1, a as VedaTraceConfig, L as LogMetadata, d as RedactionConfig } from './types-
|
|
2
|
-
export { e as VedaTraceLevel, f as VedaTraceLog } from './types-
|
|
1
|
+
import { b as VedaTraceTransport, B as BatcherConfig, c as VedaTraceEdgeContext, I as InternalLogEntry, V as VedaTraceLoggerInterface, R as RuntimeType$1, a as VedaTraceConfig, L as LogMetadata, d as RedactionConfig } from './types-CSBzeGyK.cjs';
|
|
2
|
+
export { e as VedaTraceLevel, f as VedaTraceLog } from './types-CSBzeGyK.cjs';
|
|
3
3
|
export { ConsoleFormat, ConsoleTransportConfig, HttpTransportConfig, VedaTraceConsoleTransport, VedaTraceHttpTransport, VedaTraceHttpTransportBrowser } from './transports/index.cjs';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* VedaTrace Batcher - Context-Aware for Cloudflare Workers
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
* 1.
|
|
10
|
-
* 2.
|
|
11
|
-
* 3.
|
|
12
|
-
* 4. Debounced flush to avoid excessive network calls
|
|
13
|
-
* 5. Automatic flush on each log entry when context is present
|
|
14
|
-
* 6. All callbacks moved into BatcherConfig for cleaner API
|
|
8
|
+
* Three flush modes:
|
|
9
|
+
* 1. Reliable mode (context or waitUntilFn): debounced flush + waitUntil for guaranteed delivery
|
|
10
|
+
* 2. Immediate mode: flush() called directly from add() during handler execution
|
|
11
|
+
* 3. Batch mode: periodic/batch-size flush for long-running environments
|
|
15
12
|
*/
|
|
16
13
|
|
|
17
14
|
declare class VedaTraceBatcher {
|
|
@@ -20,30 +17,63 @@ declare class VedaTraceBatcher {
|
|
|
20
17
|
private immediateFlush;
|
|
21
18
|
private queue;
|
|
22
19
|
private flushTimer;
|
|
23
|
-
private
|
|
20
|
+
private flushQueued;
|
|
24
21
|
private isFlushing;
|
|
25
22
|
private pendingFlush;
|
|
26
23
|
private context;
|
|
24
|
+
private waitUntilFn;
|
|
25
|
+
/**
|
|
26
|
+
* Set when the ingestion endpoint rejects our credentials. Every subsequent
|
|
27
|
+
* batch would fail identically, so we stop rather than spend a request (and a
|
|
28
|
+
* retry storm) per flush for the life of the process. start() clears it.
|
|
29
|
+
*/
|
|
30
|
+
private halted;
|
|
27
31
|
constructor(transports: VedaTraceTransport[], config: BatcherConfig, immediateFlush?: boolean);
|
|
28
|
-
/** Attach execution context after initialization */
|
|
29
32
|
setContext(ctx: VedaTraceEdgeContext): void;
|
|
30
|
-
/** Get current context */
|
|
31
33
|
getContext(): VedaTraceEdgeContext | undefined;
|
|
32
|
-
/** Add log to queue with context-aware flush */
|
|
33
34
|
add(log: InternalLogEntry): void;
|
|
34
|
-
/** Debounced flush - prevents rapid-fire flushes */
|
|
35
35
|
private debouncedFlush;
|
|
36
|
-
/** Flush logs to all transports with waitUntil protection */
|
|
37
36
|
flush(): Promise<void>;
|
|
38
37
|
private sendWithRetry;
|
|
38
|
+
/** Stop accepting logs after an unrecoverable authentication failure. */
|
|
39
|
+
private halt;
|
|
40
|
+
private reportError;
|
|
39
41
|
private startFlushTimer;
|
|
40
42
|
stop(): void;
|
|
41
43
|
start(): void;
|
|
42
44
|
private delay;
|
|
43
45
|
getQueueSize(): number;
|
|
46
|
+
/** True once an auth failure has shut the batcher down. */
|
|
47
|
+
isHalted(): boolean;
|
|
44
48
|
setExecutionContext(ctx: VedaTraceEdgeContext): void;
|
|
45
49
|
}
|
|
46
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Transport error types
|
|
53
|
+
*
|
|
54
|
+
* The batcher needs to tell three cases apart:
|
|
55
|
+
* - retryable (network blip, timeout, 429, 5xx) — back off and try again
|
|
56
|
+
* - permanent (400 malformed batch) — retrying wastes the caller's time
|
|
57
|
+
* - fatal (401/403 bad key or blocked origin) — every future batch will
|
|
58
|
+
* fail the same way, so stop instead of burning a request per flush
|
|
59
|
+
*/
|
|
60
|
+
declare class VedaTraceTransportError extends Error {
|
|
61
|
+
readonly name = "VedaTraceTransportError";
|
|
62
|
+
readonly status: number | undefined;
|
|
63
|
+
readonly retryable: boolean;
|
|
64
|
+
readonly fatal: boolean;
|
|
65
|
+
/** Server-requested backoff from a `Retry-After` header, in milliseconds. */
|
|
66
|
+
readonly retryAfterMs: number | undefined;
|
|
67
|
+
constructor(message: string, options?: {
|
|
68
|
+
status?: number;
|
|
69
|
+
retryable?: boolean;
|
|
70
|
+
fatal?: boolean;
|
|
71
|
+
retryAfterMs?: number;
|
|
72
|
+
});
|
|
73
|
+
/** Build an error from an HTTP response status. */
|
|
74
|
+
static fromStatus(status: number, body: string, retryAfterMs?: number): VedaTraceTransportError;
|
|
75
|
+
}
|
|
76
|
+
|
|
47
77
|
/**
|
|
48
78
|
* Core VedaTrace Logger implementation
|
|
49
79
|
* Supports Cloudflare Workers / Pages via withContext() integration
|
|
@@ -80,12 +110,17 @@ declare class VedaTraceLogger implements VedaTraceLoggerInterface {
|
|
|
80
110
|
* Browser lifecycle management for VedaTrace
|
|
81
111
|
*
|
|
82
112
|
* Handles:
|
|
83
|
-
* - visibilitychange: flush when page becomes hidden
|
|
84
|
-
* - pagehide: final flush when
|
|
85
|
-
* - beforeunload: backup flush before page unload
|
|
113
|
+
* - visibilitychange: flush when the page becomes hidden
|
|
114
|
+
* - pagehide: final flush when the page goes away
|
|
86
115
|
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
116
|
+
* `beforeunload` and `unload` are deliberately not used. Registering either one
|
|
117
|
+
* makes Chrome and Safari ineligible for the back/forward cache, so a logging
|
|
118
|
+
* SDK that listens for them measurably slows down every back-navigation in the
|
|
119
|
+
* host app. `visibilitychange` + `pagehide` covers every case they did,
|
|
120
|
+
* including Safari, and is the pair the browsers themselves recommend.
|
|
121
|
+
*
|
|
122
|
+
* The final flush goes out through the batcher's normal HTTP transport, which
|
|
123
|
+
* sets `keepalive: true` in the browser so the request outlives the document.
|
|
89
124
|
*/
|
|
90
125
|
|
|
91
126
|
interface BrowserLifecycleConfig {
|
|
@@ -101,8 +136,6 @@ declare class BrowserLifecycle {
|
|
|
101
136
|
private config;
|
|
102
137
|
private boundVisibilityHandler;
|
|
103
138
|
private boundPageHideHandler;
|
|
104
|
-
private boundBeforeUnloadHandler;
|
|
105
|
-
private boundUnloadHandler;
|
|
106
139
|
private isAttached;
|
|
107
140
|
private pendingFlush;
|
|
108
141
|
constructor(config: BrowserLifecycleConfig);
|
|
@@ -110,21 +143,18 @@ declare class BrowserLifecycle {
|
|
|
110
143
|
attach(): void;
|
|
111
144
|
/** Stop listening for browser lifecycle events */
|
|
112
145
|
detach(): void;
|
|
113
|
-
/**
|
|
146
|
+
/**
|
|
147
|
+
* Flush when the page becomes hidden.
|
|
148
|
+
*
|
|
149
|
+
* This is the one that actually matters: on mobile, a backgrounded tab is
|
|
150
|
+
* often discarded without ever firing pagehide, so "hidden" is the last
|
|
151
|
+
* reliable moment to ship what we have.
|
|
152
|
+
*/
|
|
114
153
|
private handleVisibilityChange;
|
|
115
|
-
/**
|
|
154
|
+
/** Final flush as the page is torn down or frozen into the bfcache. */
|
|
116
155
|
private handlePageHide;
|
|
117
|
-
/**
|
|
118
|
-
private handleBeforeUnload;
|
|
119
|
-
/** Handle unload - fallback for older browsers */
|
|
120
|
-
private handleUnload;
|
|
121
|
-
/** Schedule a debounced flush (for visibility change) */
|
|
156
|
+
/** Flush at most once at a time; keepalive carries it past the document. */
|
|
122
157
|
private scheduleFlush;
|
|
123
|
-
/**
|
|
124
|
-
* Final flush using keepalive fetch
|
|
125
|
-
* For sending logs after the page context is destroyed
|
|
126
|
-
*/
|
|
127
|
-
private finalFlush;
|
|
128
158
|
/** Check if handlers are attached */
|
|
129
159
|
isActive(): boolean;
|
|
130
160
|
}
|
|
@@ -149,6 +179,21 @@ declare function isServerless(): boolean;
|
|
|
149
179
|
declare function isLongRunning(): boolean;
|
|
150
180
|
declare function isBrowser(): boolean;
|
|
151
181
|
|
|
182
|
+
/**
|
|
183
|
+
* SDK version, inlined at build time.
|
|
184
|
+
*
|
|
185
|
+
* This file is generated by `scripts/sync-version.mjs` from package.json and is
|
|
186
|
+
* checked in so type-checking and tests work without a build step. Do not edit
|
|
187
|
+
* it by hand — `bun run build` and `changeset version` both regenerate it, and
|
|
188
|
+
* a test asserts it matches package.json.
|
|
189
|
+
*
|
|
190
|
+
* It exists because the previous `process.env.npm_package_version` read was
|
|
191
|
+
* wrong twice over: npm only sets that variable for its own lifecycle scripts,
|
|
192
|
+
* so it was always undefined for consumers, and the bare `process` reference
|
|
193
|
+
* survived bundling and threw a ReferenceError in browsers.
|
|
194
|
+
*/
|
|
195
|
+
declare const SDK_VERSION = "0.3.1";
|
|
196
|
+
|
|
152
197
|
/**
|
|
153
198
|
* VedaTrace SDK - Universal JavaScript logging
|
|
154
199
|
*
|
|
@@ -189,4 +234,4 @@ declare function vedatrace(config?: VedaTraceConfig): VedaTraceLoggerInterface;
|
|
|
189
234
|
*/
|
|
190
235
|
declare function devVedatrace(config?: Omit<VedaTraceConfig, "apiKey" | "transports">): VedaTraceLoggerInterface;
|
|
191
236
|
|
|
192
|
-
export { BatcherConfig, BrowserLifecycle, InternalLogEntry, LogMetadata, RedactionConfig, RuntimeType$1 as RuntimeType, VedaTraceBatcher, VedaTraceConfig, VedaTraceEdgeContext, VedaTraceLogger, VedaTraceLoggerInterface, VedaTraceTransport, vedatrace as default, detectRuntime, devVedatrace, isBrowser, isEdgeRuntime, isLongRunning, isServerless, redact, vedatrace };
|
|
237
|
+
export { BatcherConfig, BrowserLifecycle, InternalLogEntry, LogMetadata, RedactionConfig, RuntimeType$1 as RuntimeType, SDK_VERSION, VedaTraceBatcher, VedaTraceConfig, VedaTraceEdgeContext, VedaTraceLogger, VedaTraceLoggerInterface, VedaTraceTransport, VedaTraceTransportError, vedatrace as default, detectRuntime, devVedatrace, isBrowser, isEdgeRuntime, isLongRunning, isServerless, redact, vedatrace };
|