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.d.mts
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.mjs';
|
|
2
|
+
export { e as VedaTraceLevel, f as VedaTraceLog } from './types-CSBzeGyK.mjs';
|
|
3
3
|
export { ConsoleFormat, ConsoleTransportConfig, HttpTransportConfig, VedaTraceConsoleTransport, VedaTraceHttpTransport, VedaTraceHttpTransportBrowser } from './transports/index.mjs';
|
|
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 };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { VedaTraceHttpTransportBrowser, VedaTraceHttpTransport, VedaTraceConsoleTransport } from './
|
|
1
|
+
import { i as isFatal, a as isRetryable, r as retryAfterMs, V as VedaTraceHttpTransportBrowser, b as VedaTraceHttpTransport, c as VedaTraceConsoleTransport } from './index-BcBZY8as.mjs';
|
|
2
|
+
export { d as VedaTraceTransportError } from './index-BcBZY8as.mjs';
|
|
2
3
|
|
|
3
4
|
class VedaTraceBatcher {
|
|
4
5
|
constructor(transports, config, immediateFlush = false) {
|
|
@@ -6,55 +7,53 @@ class VedaTraceBatcher {
|
|
|
6
7
|
this.config = config;
|
|
7
8
|
this.immediateFlush = immediateFlush;
|
|
8
9
|
this.context = config.executionContext;
|
|
10
|
+
this.waitUntilFn = config.waitUntil;
|
|
9
11
|
}
|
|
10
12
|
queue = [];
|
|
11
13
|
flushTimer = null;
|
|
12
|
-
|
|
14
|
+
flushQueued = false;
|
|
13
15
|
isFlushing = false;
|
|
14
16
|
pendingFlush = null;
|
|
15
17
|
context;
|
|
16
|
-
|
|
18
|
+
waitUntilFn;
|
|
19
|
+
/**
|
|
20
|
+
* Set when the ingestion endpoint rejects our credentials. Every subsequent
|
|
21
|
+
* batch would fail identically, so we stop rather than spend a request (and a
|
|
22
|
+
* retry storm) per flush for the life of the process. start() clears it.
|
|
23
|
+
*/
|
|
24
|
+
halted = false;
|
|
17
25
|
setContext(ctx) {
|
|
18
26
|
this.context = ctx;
|
|
19
27
|
}
|
|
20
|
-
/** Get current context */
|
|
21
28
|
getContext() {
|
|
22
29
|
return this.context;
|
|
23
30
|
}
|
|
24
|
-
/** Add log to queue with context-aware flush */
|
|
25
31
|
add(log) {
|
|
32
|
+
if (this.halted) return;
|
|
26
33
|
this.queue.push(log);
|
|
27
|
-
if (
|
|
34
|
+
if (this.context || this.waitUntilFn) {
|
|
35
|
+
this.debouncedFlush();
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (this.immediateFlush) {
|
|
39
|
+
this.flush();
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (!this.flushTimer) {
|
|
28
43
|
this.startFlushTimer();
|
|
29
44
|
}
|
|
30
|
-
if (this.
|
|
31
|
-
this.debouncedFlush();
|
|
32
|
-
} else if (this.queue.length >= this.config.batchSize) {
|
|
45
|
+
if (this.queue.length >= this.config.batchSize) {
|
|
33
46
|
this.flush();
|
|
34
47
|
}
|
|
35
48
|
}
|
|
36
|
-
/** Debounced flush - prevents rapid-fire flushes */
|
|
37
49
|
debouncedFlush() {
|
|
38
|
-
if (this.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
this.
|
|
43
|
-
|
|
44
|
-
if (this.config.onError) {
|
|
45
|
-
this.config.onError(
|
|
46
|
-
error instanceof Error ? error : new Error(String(error))
|
|
47
|
-
);
|
|
48
|
-
} else {
|
|
49
|
-
console.error(
|
|
50
|
-
"[VedaTrace] Debounced flush error:",
|
|
51
|
-
error instanceof Error ? error.message : String(error)
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
}, 100);
|
|
50
|
+
if (this.flushQueued) return;
|
|
51
|
+
this.flushQueued = true;
|
|
52
|
+
queueMicrotask(() => {
|
|
53
|
+
this.flushQueued = false;
|
|
54
|
+
this.flush().catch((error) => this.reportError(error));
|
|
55
|
+
});
|
|
56
56
|
}
|
|
57
|
-
/** Flush logs to all transports with waitUntil protection */
|
|
58
57
|
async flush() {
|
|
59
58
|
if (this.isFlushing) {
|
|
60
59
|
return this.pendingFlush ?? Promise.resolve();
|
|
@@ -68,10 +67,16 @@ class VedaTraceBatcher {
|
|
|
68
67
|
const flushPromise = this.sendWithRetry(logsToSend).finally(() => {
|
|
69
68
|
this.isFlushing = false;
|
|
70
69
|
this.pendingFlush = null;
|
|
70
|
+
}).then(() => {
|
|
71
|
+
if (this.queue.length > 0 && !this.halted) {
|
|
72
|
+
return this.flush();
|
|
73
|
+
}
|
|
71
74
|
});
|
|
72
75
|
this.pendingFlush = flushPromise;
|
|
73
|
-
if (this.context) {
|
|
76
|
+
if (this.context && typeof this.context.waitUntil === "function") {
|
|
74
77
|
this.context.waitUntil(flushPromise);
|
|
78
|
+
} else if (typeof this.waitUntilFn === "function") {
|
|
79
|
+
this.waitUntilFn(flushPromise);
|
|
75
80
|
}
|
|
76
81
|
return flushPromise;
|
|
77
82
|
}
|
|
@@ -81,26 +86,47 @@ class VedaTraceBatcher {
|
|
|
81
86
|
try {
|
|
82
87
|
await transport.send(logs);
|
|
83
88
|
} catch (error) {
|
|
84
|
-
errors.push(error
|
|
89
|
+
errors.push(error);
|
|
85
90
|
}
|
|
86
91
|
}
|
|
87
|
-
if (errors.length
|
|
88
|
-
|
|
89
|
-
await this.delay(this.config.retryDelay * (attempt + 1));
|
|
90
|
-
return this.sendWithRetry(logs, attempt + 1);
|
|
91
|
-
}
|
|
92
|
-
const combinedError = new Error(
|
|
93
|
-
`Failed to send logs after ${this.config.maxRetries} retries: ${errors.map((e) => e.message).join(", ")}`
|
|
94
|
-
);
|
|
95
|
-
if (this.config.onError) {
|
|
96
|
-
this.config.onError(combinedError);
|
|
97
|
-
} else {
|
|
98
|
-
console.error("[VedaTrace]", combinedError.message);
|
|
99
|
-
}
|
|
92
|
+
if (errors.length === 0 || errors.length < this.transports.length) {
|
|
93
|
+
this.config.onSuccess?.();
|
|
100
94
|
return;
|
|
101
95
|
}
|
|
102
|
-
|
|
103
|
-
|
|
96
|
+
const fatalError = errors.find(isFatal);
|
|
97
|
+
if (fatalError) {
|
|
98
|
+
this.halt(fatalError);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
if (errors.some(isRetryable) && attempt < this.config.maxRetries) {
|
|
102
|
+
const backoff = this.config.retryDelay * (attempt + 1);
|
|
103
|
+
await this.delay(retryAfterMs(errors) ?? backoff);
|
|
104
|
+
return this.sendWithRetry(logs, attempt + 1);
|
|
105
|
+
}
|
|
106
|
+
const detail = errors.map(describeError).join(", ");
|
|
107
|
+
this.reportError(
|
|
108
|
+
new Error(
|
|
109
|
+
errors.some(isRetryable) ? `Failed to send ${logs.length} logs after ${this.config.maxRetries} retries: ${detail}` : `Failed to send ${logs.length} logs: ${detail}`
|
|
110
|
+
)
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
/** Stop accepting logs after an unrecoverable authentication failure. */
|
|
114
|
+
halt(error) {
|
|
115
|
+
this.halted = true;
|
|
116
|
+
this.queue = [];
|
|
117
|
+
this.stop();
|
|
118
|
+
this.reportError(
|
|
119
|
+
new Error(
|
|
120
|
+
`VedaTrace disabled: ${describeError(error)}. Check your API key and the key's allowed origins, then call logger.start() to resume.`
|
|
121
|
+
)
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
reportError(error) {
|
|
125
|
+
const normalized = error instanceof Error ? error : new Error(String(error));
|
|
126
|
+
if (this.config.onError) {
|
|
127
|
+
this.config.onError(normalized);
|
|
128
|
+
} else {
|
|
129
|
+
console.error("[VedaTrace]", normalized.message);
|
|
104
130
|
}
|
|
105
131
|
}
|
|
106
132
|
startFlushTimer() {
|
|
@@ -109,22 +135,11 @@ class VedaTraceBatcher {
|
|
|
109
135
|
}
|
|
110
136
|
this.flushTimer = setInterval(() => {
|
|
111
137
|
if (this.queue.length > 0) {
|
|
112
|
-
this.flush().catch((error) =>
|
|
113
|
-
if (this.config.onError) {
|
|
114
|
-
this.config.onError(
|
|
115
|
-
error instanceof Error ? error : new Error(String(error))
|
|
116
|
-
);
|
|
117
|
-
} else {
|
|
118
|
-
console.error(
|
|
119
|
-
"[VedaTrace] Flush error:",
|
|
120
|
-
error instanceof Error ? error.message : String(error)
|
|
121
|
-
);
|
|
122
|
-
}
|
|
123
|
-
});
|
|
138
|
+
this.flush().catch((error) => this.reportError(error));
|
|
124
139
|
}
|
|
125
140
|
}, this.config.flushInterval);
|
|
126
141
|
if (this.config.unrefTimer === true) {
|
|
127
|
-
this.flushTimer.unref();
|
|
142
|
+
this.flushTimer.unref?.();
|
|
128
143
|
}
|
|
129
144
|
}
|
|
130
145
|
stop() {
|
|
@@ -132,12 +147,10 @@ class VedaTraceBatcher {
|
|
|
132
147
|
clearInterval(this.flushTimer);
|
|
133
148
|
this.flushTimer = null;
|
|
134
149
|
}
|
|
135
|
-
|
|
136
|
-
clearTimeout(this.flushDebounceTimer);
|
|
137
|
-
this.flushDebounceTimer = null;
|
|
138
|
-
}
|
|
150
|
+
this.flushQueued = false;
|
|
139
151
|
}
|
|
140
152
|
start() {
|
|
153
|
+
this.halted = false;
|
|
141
154
|
if (!this.flushTimer && !this.immediateFlush) {
|
|
142
155
|
this.startFlushTimer();
|
|
143
156
|
}
|
|
@@ -148,10 +161,17 @@ class VedaTraceBatcher {
|
|
|
148
161
|
getQueueSize() {
|
|
149
162
|
return this.queue.length;
|
|
150
163
|
}
|
|
164
|
+
/** True once an auth failure has shut the batcher down. */
|
|
165
|
+
isHalted() {
|
|
166
|
+
return this.halted;
|
|
167
|
+
}
|
|
151
168
|
setExecutionContext(ctx) {
|
|
152
169
|
this.context = ctx;
|
|
153
170
|
}
|
|
154
171
|
}
|
|
172
|
+
function describeError(error) {
|
|
173
|
+
return error instanceof Error ? error.message : String(error);
|
|
174
|
+
}
|
|
155
175
|
|
|
156
176
|
function detectRuntime() {
|
|
157
177
|
if (typeof navigator !== "undefined" && navigator.userAgent === "Cloudflare-Workers") {
|
|
@@ -194,7 +214,8 @@ function isBrowser() {
|
|
|
194
214
|
return detectRuntime() === "browser";
|
|
195
215
|
}
|
|
196
216
|
|
|
197
|
-
const SDK_VERSION =
|
|
217
|
+
const SDK_VERSION = "0.3.1";
|
|
218
|
+
|
|
198
219
|
class VedaTraceLogger {
|
|
199
220
|
batcher = null;
|
|
200
221
|
runtime;
|
|
@@ -347,24 +368,17 @@ class BrowserLifecycle {
|
|
|
347
368
|
this.config = config;
|
|
348
369
|
this.boundVisibilityHandler = this.handleVisibilityChange.bind(this);
|
|
349
370
|
this.boundPageHideHandler = this.handlePageHide.bind(this);
|
|
350
|
-
this.boundBeforeUnloadHandler = this.handleBeforeUnload.bind(this);
|
|
351
|
-
this.boundUnloadHandler = this.handleUnload.bind(this);
|
|
352
371
|
}
|
|
353
372
|
boundVisibilityHandler;
|
|
354
373
|
boundPageHideHandler;
|
|
355
|
-
boundBeforeUnloadHandler;
|
|
356
|
-
boundUnloadHandler;
|
|
357
374
|
isAttached = false;
|
|
358
375
|
pendingFlush = null;
|
|
359
376
|
/** Start listening for browser lifecycle events */
|
|
360
377
|
attach() {
|
|
361
378
|
if (this.isAttached) return;
|
|
362
|
-
if (typeof document
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
window.addEventListener("beforeunload", this.boundBeforeUnloadHandler);
|
|
366
|
-
window.addEventListener("unload", this.boundUnloadHandler);
|
|
367
|
-
}
|
|
379
|
+
if (typeof document === "undefined" || typeof window === "undefined") return;
|
|
380
|
+
document.addEventListener("visibilitychange", this.boundVisibilityHandler);
|
|
381
|
+
window.addEventListener("pagehide", this.boundPageHideHandler);
|
|
368
382
|
this.isAttached = true;
|
|
369
383
|
if (this.config.debug) {
|
|
370
384
|
console.log("[VedaTrace] Browser lifecycle handlers attached");
|
|
@@ -373,21 +387,25 @@ class BrowserLifecycle {
|
|
|
373
387
|
/** Stop listening for browser lifecycle events */
|
|
374
388
|
detach() {
|
|
375
389
|
if (!this.isAttached) return;
|
|
376
|
-
if (typeof document !== "undefined") {
|
|
390
|
+
if (typeof document !== "undefined" && typeof window !== "undefined") {
|
|
377
391
|
document.removeEventListener(
|
|
378
392
|
"visibilitychange",
|
|
379
393
|
this.boundVisibilityHandler
|
|
380
394
|
);
|
|
381
395
|
window.removeEventListener("pagehide", this.boundPageHideHandler);
|
|
382
|
-
window.removeEventListener("beforeunload", this.boundBeforeUnloadHandler);
|
|
383
|
-
window.removeEventListener("unload", this.boundUnloadHandler);
|
|
384
396
|
}
|
|
385
397
|
this.isAttached = false;
|
|
386
398
|
if (this.config.debug) {
|
|
387
399
|
console.log("[VedaTrace] Browser lifecycle handlers detached");
|
|
388
400
|
}
|
|
389
401
|
}
|
|
390
|
-
/**
|
|
402
|
+
/**
|
|
403
|
+
* Flush when the page becomes hidden.
|
|
404
|
+
*
|
|
405
|
+
* This is the one that actually matters: on mobile, a backgrounded tab is
|
|
406
|
+
* often discarded without ever firing pagehide, so "hidden" is the last
|
|
407
|
+
* reliable moment to ship what we have.
|
|
408
|
+
*/
|
|
391
409
|
handleVisibilityChange() {
|
|
392
410
|
if (document.visibilityState === "hidden") {
|
|
393
411
|
if (this.config.debug) {
|
|
@@ -396,7 +414,7 @@ class BrowserLifecycle {
|
|
|
396
414
|
this.scheduleFlush();
|
|
397
415
|
}
|
|
398
416
|
}
|
|
399
|
-
/**
|
|
417
|
+
/** Final flush as the page is torn down or frozen into the bfcache. */
|
|
400
418
|
handlePageHide(event) {
|
|
401
419
|
if (this.config.debug) {
|
|
402
420
|
console.log(
|
|
@@ -404,46 +422,16 @@ class BrowserLifecycle {
|
|
|
404
422
|
event.persisted ? "(cached)" : "(navigation)"
|
|
405
423
|
);
|
|
406
424
|
}
|
|
407
|
-
|
|
408
|
-
this.scheduleFlush();
|
|
409
|
-
} else {
|
|
410
|
-
this.finalFlush();
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
/** Handle beforeunload - backup flush mechanism */
|
|
414
|
-
handleBeforeUnload(event) {
|
|
415
|
-
if (this.config.debug) {
|
|
416
|
-
console.log("[VedaTrace] Before unload event");
|
|
417
|
-
}
|
|
418
|
-
this.finalFlush();
|
|
419
|
-
}
|
|
420
|
-
/** Handle unload - fallback for older browsers */
|
|
421
|
-
handleUnload() {
|
|
422
|
-
if (this.config.debug) {
|
|
423
|
-
console.log("[VedaTrace] Unload event");
|
|
424
|
-
}
|
|
425
|
-
this.finalFlush();
|
|
425
|
+
this.scheduleFlush();
|
|
426
426
|
}
|
|
427
|
-
/**
|
|
427
|
+
/** Flush at most once at a time; keepalive carries it past the document. */
|
|
428
428
|
scheduleFlush() {
|
|
429
429
|
if (this.pendingFlush) return;
|
|
430
|
-
this.pendingFlush = this.config.flush().
|
|
430
|
+
this.pendingFlush = this.config.flush().catch(() => {
|
|
431
|
+
}).finally(() => {
|
|
431
432
|
this.pendingFlush = null;
|
|
432
433
|
});
|
|
433
434
|
}
|
|
434
|
-
/**
|
|
435
|
-
* Final flush using keepalive fetch
|
|
436
|
-
* For sending logs after the page context is destroyed
|
|
437
|
-
*/
|
|
438
|
-
finalFlush() {
|
|
439
|
-
for (const transport of this.config.transports) {
|
|
440
|
-
if (transport.name === "http" && "flush" in transport) {
|
|
441
|
-
transport.flush?.();
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
this.config.flush().catch(() => {
|
|
445
|
-
});
|
|
446
|
-
}
|
|
447
435
|
/** Check if handlers are attached */
|
|
448
436
|
isActive() {
|
|
449
437
|
return this.isAttached;
|
|
@@ -524,6 +512,16 @@ function redactPii(value, mask) {
|
|
|
524
512
|
return result;
|
|
525
513
|
}
|
|
526
514
|
|
|
515
|
+
function resolveApiKey(config) {
|
|
516
|
+
if (config.apiKey) return config.apiKey;
|
|
517
|
+
try {
|
|
518
|
+
if (typeof process !== "undefined" && process.env) {
|
|
519
|
+
return process.env.VEDATRACE_API_KEY || void 0;
|
|
520
|
+
}
|
|
521
|
+
} catch {
|
|
522
|
+
}
|
|
523
|
+
return void 0;
|
|
524
|
+
}
|
|
527
525
|
const RUNTIME_FLUSH_INTERVALS = {
|
|
528
526
|
node: 3e3,
|
|
529
527
|
bun: 3e3,
|
|
@@ -534,15 +532,16 @@ const RUNTIME_FLUSH_INTERVALS = {
|
|
|
534
532
|
};
|
|
535
533
|
function vedatrace(config = {}) {
|
|
536
534
|
const runtime = detectRuntime();
|
|
537
|
-
const
|
|
538
|
-
|
|
535
|
+
const apiKey = resolveApiKey(config);
|
|
536
|
+
const logger = new VedaTraceLogger(apiKey ? { ...config, apiKey } : config);
|
|
537
|
+
if (apiKey && (!config.transports || config.transports.length === 0)) {
|
|
539
538
|
const isBrowserEnv = isBrowser();
|
|
540
539
|
const isServerlessEnv = isServerless();
|
|
541
540
|
const isLongRunningEnv = isLongRunning();
|
|
542
541
|
const HttpTransport = isBrowserEnv ? VedaTraceHttpTransportBrowser : VedaTraceHttpTransport;
|
|
543
542
|
const httpConfig = {
|
|
544
|
-
apiKey
|
|
545
|
-
keepalive: isBrowserEnv
|
|
543
|
+
apiKey,
|
|
544
|
+
keepalive: isBrowserEnv || isServerlessEnv
|
|
546
545
|
};
|
|
547
546
|
if (config.endpoint) httpConfig.endpoint = config.endpoint;
|
|
548
547
|
const httpTransport = new HttpTransport(httpConfig);
|
|
@@ -567,12 +566,15 @@ function vedatrace(config = {}) {
|
|
|
567
566
|
unrefTimer: config.unrefTimer ?? shouldUnrefTimer,
|
|
568
567
|
executionContext: config.executionContext,
|
|
569
568
|
onError: config.onError,
|
|
570
|
-
onSuccess: config.onSuccess
|
|
569
|
+
onSuccess: config.onSuccess,
|
|
570
|
+
debug: config.debug,
|
|
571
|
+
waitUntil: config.waitUntil
|
|
571
572
|
},
|
|
572
573
|
immediateFlush
|
|
573
574
|
);
|
|
574
575
|
logger.setBatcher(batcher);
|
|
575
|
-
|
|
576
|
+
const isNodeRuntime = typeof process !== "undefined" && process.versions?.node;
|
|
577
|
+
if (typeof process !== "undefined" && (isLongRunningEnv || isNodeRuntime)) {
|
|
576
578
|
const flushLogs = async () => {
|
|
577
579
|
await batcher.flush();
|
|
578
580
|
};
|
|
@@ -605,4 +607,4 @@ function devVedatrace(config = {}) {
|
|
|
605
607
|
});
|
|
606
608
|
}
|
|
607
609
|
|
|
608
|
-
export { BrowserLifecycle, VedaTraceBatcher, VedaTraceConsoleTransport, VedaTraceHttpTransport, VedaTraceHttpTransportBrowser, VedaTraceLogger, vedatrace as default, detectRuntime, devVedatrace, isBrowser, isEdgeRuntime, isLongRunning, isServerless, redact, vedatrace };
|
|
610
|
+
export { BrowserLifecycle, SDK_VERSION, VedaTraceBatcher, VedaTraceConsoleTransport, VedaTraceHttpTransport, VedaTraceHttpTransportBrowser, VedaTraceLogger, vedatrace as default, detectRuntime, devVedatrace, isBrowser, isEdgeRuntime, isLongRunning, isServerless, redact, vedatrace };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var index = require('../index.cjs');
|
|
4
|
-
require('../
|
|
4
|
+
require('../index-osD28Hs0.cjs');
|
|
5
5
|
|
|
6
6
|
function vedaTraceMiddleware(config = {}) {
|
|
7
7
|
const {
|
|
@@ -11,10 +11,11 @@ function vedaTraceMiddleware(config = {}) {
|
|
|
11
11
|
logBody = false,
|
|
12
12
|
...vedaConfig
|
|
13
13
|
} = config;
|
|
14
|
+
const baseLogger = index.default(vedaConfig);
|
|
14
15
|
return (req, res, next) => {
|
|
15
16
|
const requestId = generateRequestId(req);
|
|
16
17
|
req.requestId = requestId;
|
|
17
|
-
const logger =
|
|
18
|
+
const logger = baseLogger.child({
|
|
18
19
|
requestId,
|
|
19
20
|
...requestMetadata(req)
|
|
20
21
|
});
|
|
@@ -38,8 +39,6 @@ function vedaTraceMiddleware(config = {}) {
|
|
|
38
39
|
statusCode: res.statusCode,
|
|
39
40
|
durationMs: duration
|
|
40
41
|
});
|
|
41
|
-
logger.flush().catch(() => {
|
|
42
|
-
});
|
|
43
42
|
});
|
|
44
43
|
}
|
|
45
44
|
next();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Request, Response, NextFunction } from 'express';
|
|
2
|
-
import { V as VedaTraceLoggerInterface, a as VedaTraceConfig, L as LogMetadata } from '../types-
|
|
2
|
+
import { V as VedaTraceLoggerInterface, a as VedaTraceConfig, L as LogMetadata } from '../types-CSBzeGyK.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Express.js middleware integration for VedaTrace
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Request, Response, NextFunction } from 'express';
|
|
2
|
-
import { V as VedaTraceLoggerInterface, a as VedaTraceConfig, L as LogMetadata } from '../types-
|
|
2
|
+
import { V as VedaTraceLoggerInterface, a as VedaTraceConfig, L as LogMetadata } from '../types-CSBzeGyK.mjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Express.js middleware integration for VedaTrace
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import vedatrace from '../index.mjs';
|
|
2
|
-
import '../
|
|
2
|
+
import '../index-BcBZY8as.mjs';
|
|
3
3
|
|
|
4
4
|
function vedaTraceMiddleware(config = {}) {
|
|
5
5
|
const {
|
|
@@ -9,10 +9,11 @@ function vedaTraceMiddleware(config = {}) {
|
|
|
9
9
|
logBody = false,
|
|
10
10
|
...vedaConfig
|
|
11
11
|
} = config;
|
|
12
|
+
const baseLogger = vedatrace(vedaConfig);
|
|
12
13
|
return (req, res, next) => {
|
|
13
14
|
const requestId = generateRequestId(req);
|
|
14
15
|
req.requestId = requestId;
|
|
15
|
-
const logger =
|
|
16
|
+
const logger = baseLogger.child({
|
|
16
17
|
requestId,
|
|
17
18
|
...requestMetadata(req)
|
|
18
19
|
});
|
|
@@ -36,8 +37,6 @@ function vedaTraceMiddleware(config = {}) {
|
|
|
36
37
|
statusCode: res.statusCode,
|
|
37
38
|
durationMs: duration
|
|
38
39
|
});
|
|
39
|
-
logger.flush().catch(() => {
|
|
40
|
-
});
|
|
41
40
|
});
|
|
42
41
|
}
|
|
43
42
|
next();
|