@spanwise/rum 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.d.ts +51 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +186 -0
- package/dist/client.js.map +1 -0
- package/dist/errors.d.ts +8 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +67 -0
- package/dist/errors.js.map +1 -0
- package/dist/events.d.ts +78 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +11 -0
- package/dist/events.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/instrumentation/fetch.d.ts +16 -0
- package/dist/instrumentation/fetch.d.ts.map +1 -0
- package/dist/instrumentation/fetch.js +109 -0
- package/dist/instrumentation/fetch.js.map +1 -0
- package/dist/instrumentation/xhr.d.ts +16 -0
- package/dist/instrumentation/xhr.d.ts.map +1 -0
- package/dist/instrumentation/xhr.js +129 -0
- package/dist/instrumentation/xhr.js.map +1 -0
- package/dist/otel.d.ts +55 -0
- package/dist/otel.d.ts.map +1 -0
- package/dist/otel.js +91 -0
- package/dist/otel.js.map +1 -0
- package/dist/session.d.ts +11 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +176 -0
- package/dist/session.js.map +1 -0
- package/dist/span-transport.d.ts +18 -0
- package/dist/span-transport.d.ts.map +1 -0
- package/dist/span-transport.js +83 -0
- package/dist/span-transport.js.map +1 -0
- package/dist/spans.d.ts +30 -0
- package/dist/spans.d.ts.map +1 -0
- package/dist/spans.js +21 -0
- package/dist/spans.js.map +1 -0
- package/dist/trace-context.d.ts +37 -0
- package/dist/trace-context.d.ts.map +1 -0
- package/dist/trace-context.js +113 -0
- package/dist/trace-context.js.map +1 -0
- package/dist/transport.d.ts +15 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +101 -0
- package/dist/transport.js.map +1 -0
- package/dist/vitals.d.ts +12 -0
- package/dist/vitals.d.ts.map +1 -0
- package/dist/vitals.js +48 -0
- package/dist/vitals.js.map +1 -0
- package/package.json +38 -0
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { type StorageMode } from "./session.js";
|
|
2
|
+
export type TracingConfig = {
|
|
3
|
+
/** Enable distributed tracing (default: true) */
|
|
4
|
+
enabled?: boolean;
|
|
5
|
+
/** Origins to propagate trace context to (default: same-origin only) */
|
|
6
|
+
propagateToOrigins?: (string | RegExp)[];
|
|
7
|
+
/** Trace fetch requests (default: true) */
|
|
8
|
+
traceFetch?: boolean;
|
|
9
|
+
/** Trace XMLHttpRequest (default: true) */
|
|
10
|
+
traceXHR?: boolean;
|
|
11
|
+
};
|
|
12
|
+
export type BrowserConfig = {
|
|
13
|
+
apiKey: string;
|
|
14
|
+
serviceName?: string;
|
|
15
|
+
baseUrl?: string;
|
|
16
|
+
sampleRate?: number;
|
|
17
|
+
trackClicks?: boolean;
|
|
18
|
+
trackPageViews?: boolean;
|
|
19
|
+
trackVitals?: boolean;
|
|
20
|
+
trackErrors?: boolean;
|
|
21
|
+
/** Track HTTP resources (fetch/XHR) with timing (default: true) */
|
|
22
|
+
trackResources?: boolean;
|
|
23
|
+
/** Distributed tracing configuration */
|
|
24
|
+
tracing?: TracingConfig;
|
|
25
|
+
/**
|
|
26
|
+
* Session storage mode (default: "cookie")
|
|
27
|
+
* - "cookie": Uses cookies with localStorage fallback. Survives OAuth redirects.
|
|
28
|
+
* Requires cookie consent in GDPR regions.
|
|
29
|
+
* - "sessionStorage": Original behavior. Tab-isolated, cleared on tab close.
|
|
30
|
+
* No cookie consent required.
|
|
31
|
+
*/
|
|
32
|
+
sessionStorage?: StorageMode;
|
|
33
|
+
};
|
|
34
|
+
export declare function createSpanwiseBrowser(config: BrowserConfig): {
|
|
35
|
+
trackEvent: () => void;
|
|
36
|
+
trackPageView: () => void;
|
|
37
|
+
trackError: () => void;
|
|
38
|
+
setUser: () => void;
|
|
39
|
+
getSessionId: () => null;
|
|
40
|
+
} | {
|
|
41
|
+
trackEvent: (name: string, properties?: Record<string, unknown>) => void;
|
|
42
|
+
trackPageView: (url?: string) => void;
|
|
43
|
+
trackError: (error: Error, options?: {
|
|
44
|
+
requestId?: string;
|
|
45
|
+
traceId?: string;
|
|
46
|
+
}) => void;
|
|
47
|
+
setUser: (id: string, traits?: Record<string, unknown>) => void;
|
|
48
|
+
getSessionId: () => string;
|
|
49
|
+
};
|
|
50
|
+
export type SpanwiseBrowser = ReturnType<typeof createSpanwiseBrowser>;
|
|
51
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAYA,OAAO,EACN,KAAK,WAAW,EAIhB,MAAM,cAAc,CAAA;AAIrB,MAAM,MAAM,aAAa,GAAG;IAC3B,iDAAiD;IACjD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,wEAAwE;IACxE,kBAAkB,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAA;IACxC,2CAA2C;IAC3C,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC3B,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,mEAAmE;IACnE,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,wCAAwC;IACxC,OAAO,CAAC,EAAE,aAAa,CAAA;IACvB;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,WAAW,CAAA;CAC5B,CAAA;AAmBD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,aAAa;;;;;;;uBA4CnD,MAAM,eACC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAClC,IAAI;0BAhBsB,MAAM,KAAG,IAAI;wBA6BlC,KAAK,YACF;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,KAChD,IAAI;kBAKc,MAAM,WAAW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,IAAI;wBAWtC,MAAM;EAgIpC;AAED,MAAM,MAAM,eAAe,GAAG,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAA"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { captureError, setupErrorTracking } from "./errors.js";
|
|
2
|
+
import { createBaseEvent } from "./events.js";
|
|
3
|
+
import { instrumentFetch, updateFetchConfig } from "./instrumentation/fetch.js";
|
|
4
|
+
import { instrumentXHR, updateXHRConfig } from "./instrumentation/xhr.js";
|
|
5
|
+
import { getOrCreateSession, refreshSession, setStorageMode, } from "./session.js";
|
|
6
|
+
import { createTransport } from "./transport.js";
|
|
7
|
+
import { setupVitalsTracking } from "./vitals.js";
|
|
8
|
+
const DEFAULT_BASE_URL = "https://api.spanwise.dev";
|
|
9
|
+
function getClickTarget(element) {
|
|
10
|
+
if (element.id)
|
|
11
|
+
return `#${element.id}`;
|
|
12
|
+
const tag = element.tagName.toLowerCase();
|
|
13
|
+
const classes = Array.from(element.classList).slice(0, 3).join(".");
|
|
14
|
+
if (classes)
|
|
15
|
+
return `${tag}.${classes}`;
|
|
16
|
+
return tag;
|
|
17
|
+
}
|
|
18
|
+
function getClickText(element) {
|
|
19
|
+
const text = element.textContent?.trim().slice(0, 50);
|
|
20
|
+
return text || undefined;
|
|
21
|
+
}
|
|
22
|
+
export function createSpanwiseBrowser(config) {
|
|
23
|
+
// Apply sampling
|
|
24
|
+
const sampleRate = config.sampleRate ?? 1;
|
|
25
|
+
if (Math.random() > sampleRate) {
|
|
26
|
+
// Return no-op client
|
|
27
|
+
return {
|
|
28
|
+
trackEvent: () => { },
|
|
29
|
+
trackPageView: () => { },
|
|
30
|
+
trackError: () => { },
|
|
31
|
+
setUser: () => { },
|
|
32
|
+
getSessionId: () => null,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
const baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;
|
|
36
|
+
setStorageMode(config.sessionStorage ?? "cookie");
|
|
37
|
+
const { sessionId } = getOrCreateSession();
|
|
38
|
+
let userId;
|
|
39
|
+
const transport = createTransport({
|
|
40
|
+
apiKey: config.apiKey,
|
|
41
|
+
baseUrl,
|
|
42
|
+
serviceName: config.serviceName,
|
|
43
|
+
});
|
|
44
|
+
function enqueueEvent(event) {
|
|
45
|
+
refreshSession();
|
|
46
|
+
transport.enqueue(event);
|
|
47
|
+
}
|
|
48
|
+
function trackPageView(url) {
|
|
49
|
+
const event = {
|
|
50
|
+
...createBaseEvent("page_view", sessionId, userId),
|
|
51
|
+
type: "page_view",
|
|
52
|
+
url: url ?? window.location.href,
|
|
53
|
+
data: {
|
|
54
|
+
referrer: document.referrer || undefined,
|
|
55
|
+
title: document.title,
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
enqueueEvent(event);
|
|
59
|
+
}
|
|
60
|
+
function trackEvent(name, properties) {
|
|
61
|
+
const event = {
|
|
62
|
+
...createBaseEvent("custom", sessionId, userId),
|
|
63
|
+
type: "custom",
|
|
64
|
+
data: {
|
|
65
|
+
name,
|
|
66
|
+
properties,
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
enqueueEvent(event);
|
|
70
|
+
}
|
|
71
|
+
function trackError(error, options) {
|
|
72
|
+
const event = captureError(error, sessionId, userId, options);
|
|
73
|
+
enqueueEvent(event);
|
|
74
|
+
}
|
|
75
|
+
function setUser(id, traits) {
|
|
76
|
+
userId = id;
|
|
77
|
+
// Update instrumentation configs with new userId
|
|
78
|
+
updateFetchConfig(userId);
|
|
79
|
+
updateXHRConfig(userId);
|
|
80
|
+
// Optionally track user identification as custom event
|
|
81
|
+
if (traits) {
|
|
82
|
+
trackEvent("user_identified", { userId: id, ...traits });
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function getSessionIdValue() {
|
|
86
|
+
return sessionId;
|
|
87
|
+
}
|
|
88
|
+
// Auto-tracking setup
|
|
89
|
+
if (config.trackPageViews !== false) {
|
|
90
|
+
// Track initial page view
|
|
91
|
+
trackPageView();
|
|
92
|
+
// Track SPA navigation
|
|
93
|
+
const originalPushState = history.pushState.bind(history);
|
|
94
|
+
const originalReplaceState = history.replaceState.bind(history);
|
|
95
|
+
history.pushState = (...args) => {
|
|
96
|
+
originalPushState(...args);
|
|
97
|
+
trackPageView();
|
|
98
|
+
};
|
|
99
|
+
history.replaceState = (...args) => {
|
|
100
|
+
originalReplaceState(...args);
|
|
101
|
+
trackPageView();
|
|
102
|
+
};
|
|
103
|
+
window.addEventListener("popstate", () => {
|
|
104
|
+
trackPageView();
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
if (config.trackClicks !== false) {
|
|
108
|
+
document.addEventListener("click", (event) => {
|
|
109
|
+
const target = event.target;
|
|
110
|
+
if (!target)
|
|
111
|
+
return;
|
|
112
|
+
// Only track interactive elements
|
|
113
|
+
const interactiveElements = [
|
|
114
|
+
"A",
|
|
115
|
+
"BUTTON",
|
|
116
|
+
"INPUT",
|
|
117
|
+
"SELECT",
|
|
118
|
+
"TEXTAREA",
|
|
119
|
+
];
|
|
120
|
+
const isInteractive = interactiveElements.includes(target.tagName) ||
|
|
121
|
+
target.closest("a, button") !== null ||
|
|
122
|
+
target.getAttribute("role") === "button";
|
|
123
|
+
if (!isInteractive)
|
|
124
|
+
return;
|
|
125
|
+
const clickEvent = {
|
|
126
|
+
...createBaseEvent("click", sessionId, userId),
|
|
127
|
+
type: "click",
|
|
128
|
+
data: {
|
|
129
|
+
target: getClickTarget(target),
|
|
130
|
+
text: getClickText(target),
|
|
131
|
+
x: event.clientX,
|
|
132
|
+
y: event.clientY,
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
enqueueEvent(clickEvent);
|
|
136
|
+
}, { capture: true });
|
|
137
|
+
}
|
|
138
|
+
if (config.trackVitals !== false) {
|
|
139
|
+
setupVitalsTracking(sessionId, userId, (event) => {
|
|
140
|
+
enqueueEvent(event);
|
|
141
|
+
}, () => {
|
|
142
|
+
transport.flushBeacon();
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
if (config.trackErrors !== false) {
|
|
146
|
+
setupErrorTracking(sessionId, userId, (event) => {
|
|
147
|
+
enqueueEvent(event);
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
// Resource tracking: capture HTTP requests with timing and trace correlation
|
|
151
|
+
// - trackResources: store resource events in RUM (default: true)
|
|
152
|
+
// - tracing.enabled: inject traceparent headers for backend correlation (default: true)
|
|
153
|
+
// If either is enabled, we instrument fetch/XHR
|
|
154
|
+
const shouldInstrument = config.trackResources !== false || config.tracing?.enabled !== false;
|
|
155
|
+
const shouldStoreResources = config.trackResources !== false;
|
|
156
|
+
if (shouldInstrument) {
|
|
157
|
+
const ingestUrl = `${baseUrl}/v1/ingest`;
|
|
158
|
+
const instrumentationConfig = {
|
|
159
|
+
propagateToOrigins: config.tracing?.propagateToOrigins,
|
|
160
|
+
sessionId,
|
|
161
|
+
userId,
|
|
162
|
+
ingestUrl,
|
|
163
|
+
};
|
|
164
|
+
const onResource = shouldStoreResources
|
|
165
|
+
? (event) => enqueueEvent(event)
|
|
166
|
+
: () => { }; // traceparent injected but events not stored
|
|
167
|
+
// Capture network errors with URL context (only if error tracking enabled)
|
|
168
|
+
const onNetworkError = config.trackErrors !== false
|
|
169
|
+
? (event) => enqueueEvent(event)
|
|
170
|
+
: undefined;
|
|
171
|
+
if (config.tracing?.traceFetch !== false) {
|
|
172
|
+
instrumentFetch(instrumentationConfig, onResource, onNetworkError);
|
|
173
|
+
}
|
|
174
|
+
if (config.tracing?.traceXHR !== false) {
|
|
175
|
+
instrumentXHR(instrumentationConfig, onResource, onNetworkError);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return {
|
|
179
|
+
trackEvent,
|
|
180
|
+
trackPageView,
|
|
181
|
+
trackError,
|
|
182
|
+
setUser,
|
|
183
|
+
getSessionId: getSessionIdValue,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAS9D,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAC/E,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AACzE,OAAO,EAEN,kBAAkB,EAClB,cAAc,EACd,cAAc,GACd,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAChD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAoCjD,MAAM,gBAAgB,GAAG,0BAA0B,CAAA;AAEnD,SAAS,cAAc,CAAC,OAAgB;IACvC,IAAI,OAAO,CAAC,EAAE;QAAE,OAAO,IAAI,OAAO,CAAC,EAAE,EAAE,CAAA;IAEvC,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,CAAA;IACzC,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACnE,IAAI,OAAO;QAAE,OAAO,GAAG,GAAG,IAAI,OAAO,EAAE,CAAA;IAEvC,OAAO,GAAG,CAAA;AACX,CAAC;AAED,SAAS,YAAY,CAAC,OAAgB;IACrC,MAAM,IAAI,GAAG,OAAO,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IACrD,OAAO,IAAI,IAAI,SAAS,CAAA;AACzB,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,MAAqB;IAC1D,iBAAiB;IACjB,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,CAAC,CAAA;IACzC,IAAI,IAAI,CAAC,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC;QAChC,sBAAsB;QACtB,OAAO;YACN,UAAU,EAAE,GAAG,EAAE,GAAE,CAAC;YACpB,aAAa,EAAE,GAAG,EAAE,GAAE,CAAC;YACvB,UAAU,EAAE,GAAG,EAAE,GAAE,CAAC;YACpB,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC;YACjB,YAAY,EAAE,GAAG,EAAE,CAAC,IAAI;SACxB,CAAA;IACF,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,gBAAgB,CAAA;IAClD,cAAc,CAAC,MAAM,CAAC,cAAc,IAAI,QAAQ,CAAC,CAAA;IACjD,MAAM,EAAE,SAAS,EAAE,GAAG,kBAAkB,EAAE,CAAA;IAC1C,IAAI,MAA0B,CAAA;IAE9B,MAAM,SAAS,GAAG,eAAe,CAAC;QACjC,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,OAAO;QACP,WAAW,EAAE,MAAM,CAAC,WAAW;KAC/B,CAAC,CAAA;IAEF,SAAS,YAAY,CAAC,KAAe;QACpC,cAAc,EAAE,CAAA;QAChB,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IACzB,CAAC;IAED,SAAS,aAAa,CAAC,GAAY;QAClC,MAAM,KAAK,GAAkB;YAC5B,GAAG,eAAe,CAAC,WAAW,EAAE,SAAS,EAAE,MAAM,CAAC;YAClD,IAAI,EAAE,WAAW;YACjB,GAAG,EAAE,GAAG,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI;YAChC,IAAI,EAAE;gBACL,QAAQ,EAAE,QAAQ,CAAC,QAAQ,IAAI,SAAS;gBACxC,KAAK,EAAE,QAAQ,CAAC,KAAK;aACrB;SACD,CAAA;QACD,YAAY,CAAC,KAAK,CAAC,CAAA;IACpB,CAAC;IAED,SAAS,UAAU,CAClB,IAAY,EACZ,UAAoC;QAEpC,MAAM,KAAK,GAAgB;YAC1B,GAAG,eAAe,CAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,CAAC;YAC/C,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE;gBACL,IAAI;gBACJ,UAAU;aACV;SACD,CAAA;QACD,YAAY,CAAC,KAAK,CAAC,CAAA;IACpB,CAAC;IAED,SAAS,UAAU,CAClB,KAAY,EACZ,OAAkD;QAElD,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,CAAA;QAC7D,YAAY,CAAC,KAAK,CAAC,CAAA;IACpB,CAAC;IAED,SAAS,OAAO,CAAC,EAAU,EAAE,MAAgC;QAC5D,MAAM,GAAG,EAAE,CAAA;QACX,iDAAiD;QACjD,iBAAiB,CAAC,MAAM,CAAC,CAAA;QACzB,eAAe,CAAC,MAAM,CAAC,CAAA;QACvB,uDAAuD;QACvD,IAAI,MAAM,EAAE,CAAC;YACZ,UAAU,CAAC,iBAAiB,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,MAAM,EAAE,CAAC,CAAA;QACzD,CAAC;IACF,CAAC;IAED,SAAS,iBAAiB;QACzB,OAAO,SAAS,CAAA;IACjB,CAAC;IAED,sBAAsB;IACtB,IAAI,MAAM,CAAC,cAAc,KAAK,KAAK,EAAE,CAAC;QACrC,0BAA0B;QAC1B,aAAa,EAAE,CAAA;QAEf,uBAAuB;QACvB,MAAM,iBAAiB,GAAG,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QACzD,MAAM,oBAAoB,GAAG,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAE/D,OAAO,CAAC,SAAS,GAAG,CAAC,GAAG,IAAI,EAAE,EAAE;YAC/B,iBAAiB,CAAC,GAAG,IAAI,CAAC,CAAA;YAC1B,aAAa,EAAE,CAAA;QAChB,CAAC,CAAA;QAED,OAAO,CAAC,YAAY,GAAG,CAAC,GAAG,IAAI,EAAE,EAAE;YAClC,oBAAoB,CAAC,GAAG,IAAI,CAAC,CAAA;YAC7B,aAAa,EAAE,CAAA;QAChB,CAAC,CAAA;QAED,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,GAAG,EAAE;YACxC,aAAa,EAAE,CAAA;QAChB,CAAC,CAAC,CAAA;IACH,CAAC;IAED,IAAI,MAAM,CAAC,WAAW,KAAK,KAAK,EAAE,CAAC;QAClC,QAAQ,CAAC,gBAAgB,CACxB,OAAO,EACP,CAAC,KAAK,EAAE,EAAE;YACT,MAAM,MAAM,GAAG,KAAK,CAAC,MAAiB,CAAA;YACtC,IAAI,CAAC,MAAM;gBAAE,OAAM;YAEnB,kCAAkC;YAClC,MAAM,mBAAmB,GAAG;gBAC3B,GAAG;gBACH,QAAQ;gBACR,OAAO;gBACP,QAAQ;gBACR,UAAU;aACV,CAAA;YACD,MAAM,aAAa,GAClB,mBAAmB,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC;gBAC5C,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,IAAI;gBACpC,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,KAAK,QAAQ,CAAA;YAEzC,IAAI,CAAC,aAAa;gBAAE,OAAM;YAE1B,MAAM,UAAU,GAAe;gBAC9B,GAAG,eAAe,CAAC,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC;gBAC9C,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE;oBACL,MAAM,EAAE,cAAc,CAAC,MAAM,CAAC;oBAC9B,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC;oBAC1B,CAAC,EAAE,KAAK,CAAC,OAAO;oBAChB,CAAC,EAAE,KAAK,CAAC,OAAO;iBAChB;aACD,CAAA;YACD,YAAY,CAAC,UAAU,CAAC,CAAA;QACzB,CAAC,EACD,EAAE,OAAO,EAAE,IAAI,EAAE,CACjB,CAAA;IACF,CAAC;IAED,IAAI,MAAM,CAAC,WAAW,KAAK,KAAK,EAAE,CAAC;QAClC,mBAAmB,CAClB,SAAS,EACT,MAAM,EACN,CAAC,KAAK,EAAE,EAAE;YACT,YAAY,CAAC,KAAK,CAAC,CAAA;QACpB,CAAC,EACD,GAAG,EAAE;YACJ,SAAS,CAAC,WAAW,EAAE,CAAA;QACxB,CAAC,CACD,CAAA;IACF,CAAC;IAED,IAAI,MAAM,CAAC,WAAW,KAAK,KAAK,EAAE,CAAC;QAClC,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YAC/C,YAAY,CAAC,KAAK,CAAC,CAAA;QACpB,CAAC,CAAC,CAAA;IACH,CAAC;IAED,6EAA6E;IAC7E,iEAAiE;IACjE,wFAAwF;IACxF,gDAAgD;IAChD,MAAM,gBAAgB,GACrB,MAAM,CAAC,cAAc,KAAK,KAAK,IAAI,MAAM,CAAC,OAAO,EAAE,OAAO,KAAK,KAAK,CAAA;IACrE,MAAM,oBAAoB,GAAG,MAAM,CAAC,cAAc,KAAK,KAAK,CAAA;IAE5D,IAAI,gBAAgB,EAAE,CAAC;QACtB,MAAM,SAAS,GAAG,GAAG,OAAO,YAAY,CAAA;QACxC,MAAM,qBAAqB,GAAG;YAC7B,kBAAkB,EAAE,MAAM,CAAC,OAAO,EAAE,kBAAkB;YACtD,SAAS;YACT,MAAM;YACN,SAAS;SACT,CAAA;QAED,MAAM,UAAU,GAAG,oBAAoB;YACtC,CAAC,CAAC,CAAC,KAAoB,EAAE,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC;YAC/C,CAAC,CAAC,GAAG,EAAE,GAAE,CAAC,CAAA,CAAC,6CAA6C;QAEzD,2EAA2E;QAC3E,MAAM,cAAc,GACnB,MAAM,CAAC,WAAW,KAAK,KAAK;YAC3B,CAAC,CAAC,CAAC,KAAiB,EAAE,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC;YAC5C,CAAC,CAAC,SAAS,CAAA;QAEb,IAAI,MAAM,CAAC,OAAO,EAAE,UAAU,KAAK,KAAK,EAAE,CAAC;YAC1C,eAAe,CAAC,qBAAqB,EAAE,UAAU,EAAE,cAAc,CAAC,CAAA;QACnE,CAAC;QAED,IAAI,MAAM,CAAC,OAAO,EAAE,QAAQ,KAAK,KAAK,EAAE,CAAC;YACxC,aAAa,CAAC,qBAAqB,EAAE,UAAU,EAAE,cAAc,CAAC,CAAA;QACjE,CAAC;IACF,CAAC;IAED,OAAO;QACN,UAAU;QACV,aAAa;QACb,UAAU;QACV,OAAO;QACP,YAAY,EAAE,iBAAiB;KAC/B,CAAA;AACF,CAAC"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ErrorEvent } from "./events.js";
|
|
2
|
+
export type ErrorCallback = (event: ErrorEvent) => void;
|
|
3
|
+
export declare function setupErrorTracking(sessionId: string, userId: string | undefined, onError: ErrorCallback): void;
|
|
4
|
+
export declare function captureError(error: Error, sessionId: string, userId: string | undefined, options?: {
|
|
5
|
+
requestId?: string;
|
|
6
|
+
traceId?: string;
|
|
7
|
+
}): ErrorEvent;
|
|
8
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAG7C,MAAM,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAA;AAkBvD,wBAAgB,kBAAkB,CACjC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,OAAO,EAAE,aAAa,GACpB,IAAI,CAuCN;AAED,wBAAgB,YAAY,CAC3B,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,OAAO,CAAC,EAAE;IACT,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,CAAA;CAChB,GACC,UAAU,CAWZ"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { createBaseEvent } from "./events.js";
|
|
2
|
+
function getSelector(element) {
|
|
3
|
+
if (element.id)
|
|
4
|
+
return `#${element.id}`;
|
|
5
|
+
const tag = element.tagName.toLowerCase();
|
|
6
|
+
const classes = Array.from(element.classList).join(".");
|
|
7
|
+
if (classes)
|
|
8
|
+
return `${tag}.${classes}`;
|
|
9
|
+
return tag;
|
|
10
|
+
}
|
|
11
|
+
function getStackTrace(error) {
|
|
12
|
+
if (!error.stack)
|
|
13
|
+
return undefined;
|
|
14
|
+
// Limit stack trace length
|
|
15
|
+
return error.stack.slice(0, 2000);
|
|
16
|
+
}
|
|
17
|
+
export function setupErrorTracking(sessionId, userId, onError) {
|
|
18
|
+
// Capture unhandled errors
|
|
19
|
+
window.addEventListener("error", (event) => {
|
|
20
|
+
const errorEvent = {
|
|
21
|
+
...createBaseEvent("error", sessionId, userId),
|
|
22
|
+
type: "error",
|
|
23
|
+
data: {
|
|
24
|
+
message: event.message || "Unknown error",
|
|
25
|
+
stack: event.error ? getStackTrace(event.error) : undefined,
|
|
26
|
+
filename: event.filename,
|
|
27
|
+
lineno: event.lineno,
|
|
28
|
+
colno: event.colno,
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
onError(errorEvent);
|
|
32
|
+
});
|
|
33
|
+
// Capture unhandled promise rejections
|
|
34
|
+
window.addEventListener("unhandledrejection", (event) => {
|
|
35
|
+
let message = "Unhandled Promise Rejection";
|
|
36
|
+
let stack;
|
|
37
|
+
if (event.reason instanceof Error) {
|
|
38
|
+
message = event.reason.message;
|
|
39
|
+
stack = getStackTrace(event.reason);
|
|
40
|
+
}
|
|
41
|
+
else if (typeof event.reason === "string") {
|
|
42
|
+
message = event.reason;
|
|
43
|
+
}
|
|
44
|
+
const errorEvent = {
|
|
45
|
+
...createBaseEvent("error", sessionId, userId),
|
|
46
|
+
type: "error",
|
|
47
|
+
data: {
|
|
48
|
+
message,
|
|
49
|
+
stack,
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
onError(errorEvent);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
export function captureError(error, sessionId, userId, options) {
|
|
56
|
+
return {
|
|
57
|
+
...createBaseEvent("error", sessionId, userId),
|
|
58
|
+
type: "error",
|
|
59
|
+
data: {
|
|
60
|
+
message: error.message,
|
|
61
|
+
stack: getStackTrace(error),
|
|
62
|
+
requestId: options?.requestId,
|
|
63
|
+
traceId: options?.traceId,
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAI7C,SAAS,WAAW,CAAC,OAAgB;IACpC,IAAI,OAAO,CAAC,EAAE;QAAE,OAAO,IAAI,OAAO,CAAC,EAAE,EAAE,CAAA;IAEvC,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,CAAA;IACzC,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACvD,IAAI,OAAO;QAAE,OAAO,GAAG,GAAG,IAAI,OAAO,EAAE,CAAA;IAEvC,OAAO,GAAG,CAAA;AACX,CAAC;AAED,SAAS,aAAa,CAAC,KAAY;IAClC,IAAI,CAAC,KAAK,CAAC,KAAK;QAAE,OAAO,SAAS,CAAA;IAClC,2BAA2B;IAC3B,OAAO,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAA;AAClC,CAAC;AAED,MAAM,UAAU,kBAAkB,CACjC,SAAiB,EACjB,MAA0B,EAC1B,OAAsB;IAEtB,2BAA2B;IAC3B,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;QAC1C,MAAM,UAAU,GAAe;YAC9B,GAAG,eAAe,CAAC,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC;YAC9C,IAAI,EAAE,OAAO;YACb,IAAI,EAAE;gBACL,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,eAAe;gBACzC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS;gBAC3D,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,KAAK,EAAE,KAAK,CAAC,KAAK;aAClB;SACD,CAAA;QACD,OAAO,CAAC,UAAU,CAAC,CAAA;IACpB,CAAC,CAAC,CAAA;IAEF,uCAAuC;IACvC,MAAM,CAAC,gBAAgB,CAAC,oBAAoB,EAAE,CAAC,KAAK,EAAE,EAAE;QACvD,IAAI,OAAO,GAAG,6BAA6B,CAAA;QAC3C,IAAI,KAAyB,CAAA;QAE7B,IAAI,KAAK,CAAC,MAAM,YAAY,KAAK,EAAE,CAAC;YACnC,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,OAAO,CAAA;YAC9B,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;QACpC,CAAC;aAAM,IAAI,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC7C,OAAO,GAAG,KAAK,CAAC,MAAM,CAAA;QACvB,CAAC;QAED,MAAM,UAAU,GAAe;YAC9B,GAAG,eAAe,CAAC,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC;YAC9C,IAAI,EAAE,OAAO;YACb,IAAI,EAAE;gBACL,OAAO;gBACP,KAAK;aACL;SACD,CAAA;QACD,OAAO,CAAC,UAAU,CAAC,CAAA;IACpB,CAAC,CAAC,CAAA;AACH,CAAC;AAED,MAAM,UAAU,YAAY,CAC3B,KAAY,EACZ,SAAiB,EACjB,MAA0B,EAC1B,OAGC;IAED,OAAO;QACN,GAAG,eAAe,CAAC,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC;QAC9C,IAAI,EAAE,OAAO;QACb,IAAI,EAAE;YACL,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC;YAC3B,SAAS,EAAE,OAAO,EAAE,SAAS;YAC7B,OAAO,EAAE,OAAO,EAAE,OAAO;SACzB;KACD,CAAA;AACF,CAAC"}
|
package/dist/events.d.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
export type RumEventType = "page_view" | "click" | "vitals" | "error" | "custom" | "resource";
|
|
2
|
+
export type BaseEvent = {
|
|
3
|
+
type: RumEventType;
|
|
4
|
+
sessionId: string;
|
|
5
|
+
userId?: string;
|
|
6
|
+
timestamp: number;
|
|
7
|
+
url: string;
|
|
8
|
+
userAgent: string;
|
|
9
|
+
};
|
|
10
|
+
export type PageViewEvent = BaseEvent & {
|
|
11
|
+
type: "page_view";
|
|
12
|
+
data: {
|
|
13
|
+
referrer?: string;
|
|
14
|
+
title: string;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
export type ClickEvent = BaseEvent & {
|
|
18
|
+
type: "click";
|
|
19
|
+
data: {
|
|
20
|
+
target: string;
|
|
21
|
+
text?: string;
|
|
22
|
+
x: number;
|
|
23
|
+
y: number;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
export type VitalsEvent = BaseEvent & {
|
|
27
|
+
type: "vitals";
|
|
28
|
+
data: {
|
|
29
|
+
lcp?: number;
|
|
30
|
+
fid?: number;
|
|
31
|
+
cls?: number;
|
|
32
|
+
inp?: number;
|
|
33
|
+
ttfb?: number;
|
|
34
|
+
fcp?: number;
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
export type ErrorEvent = BaseEvent & {
|
|
38
|
+
type: "error";
|
|
39
|
+
data: {
|
|
40
|
+
message: string;
|
|
41
|
+
stack?: string;
|
|
42
|
+
filename?: string;
|
|
43
|
+
lineno?: number;
|
|
44
|
+
colno?: number;
|
|
45
|
+
requestId?: string;
|
|
46
|
+
/** Trace ID for correlation with backend traces */
|
|
47
|
+
traceId?: string;
|
|
48
|
+
/** URL that failed (for fetch/network errors) */
|
|
49
|
+
failedUrl?: string;
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
export type CustomEvent = BaseEvent & {
|
|
53
|
+
type: "custom";
|
|
54
|
+
data: {
|
|
55
|
+
name: string;
|
|
56
|
+
properties?: Record<string, unknown>;
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
export type ResourceEvent = BaseEvent & {
|
|
60
|
+
type: "resource";
|
|
61
|
+
data: {
|
|
62
|
+
/** Request URL */
|
|
63
|
+
resourceUrl: string;
|
|
64
|
+
/** HTTP method */
|
|
65
|
+
method: string;
|
|
66
|
+
/** HTTP status code */
|
|
67
|
+
status?: number;
|
|
68
|
+
/** Duration in milliseconds */
|
|
69
|
+
duration: number;
|
|
70
|
+
/** Initiator type */
|
|
71
|
+
initiatorType: "fetch" | "xhr";
|
|
72
|
+
/** Trace ID for correlation with backend traces */
|
|
73
|
+
traceId?: string;
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
export type RumEvent = PageViewEvent | ClickEvent | VitalsEvent | ErrorEvent | CustomEvent | ResourceEvent;
|
|
77
|
+
export declare function createBaseEvent(type: RumEventType, sessionId: string, userId?: string): BaseEvent;
|
|
78
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GACrB,WAAW,GACX,OAAO,GACP,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,UAAU,CAAA;AAEb,MAAM,MAAM,SAAS,GAAG;IACvB,IAAI,EAAE,YAAY,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG;IACvC,IAAI,EAAE,WAAW,CAAA;IACjB,IAAI,EAAE;QACL,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,KAAK,EAAE,MAAM,CAAA;KACb,CAAA;CACD,CAAA;AAED,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG;IACpC,IAAI,EAAE,OAAO,CAAA;IACb,IAAI,EAAE;QACL,MAAM,EAAE,MAAM,CAAA;QACd,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,CAAC,EAAE,MAAM,CAAA;QACT,CAAC,EAAE,MAAM,CAAA;KACT,CAAA;CACD,CAAA;AAED,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG;IACrC,IAAI,EAAE,QAAQ,CAAA;IACd,IAAI,EAAE;QACL,GAAG,CAAC,EAAE,MAAM,CAAA;QACZ,GAAG,CAAC,EAAE,MAAM,CAAA;QACZ,GAAG,CAAC,EAAE,MAAM,CAAA;QACZ,GAAG,CAAC,EAAE,MAAM,CAAA;QACZ,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,GAAG,CAAC,EAAE,MAAM,CAAA;KACZ,CAAA;CACD,CAAA;AAED,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG;IACpC,IAAI,EAAE,OAAO,CAAA;IACb,IAAI,EAAE;QACL,OAAO,EAAE,MAAM,CAAA;QACf,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,SAAS,CAAC,EAAE,MAAM,CAAA;QAClB,mDAAmD;QACnD,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,iDAAiD;QACjD,SAAS,CAAC,EAAE,MAAM,CAAA;KAClB,CAAA;CACD,CAAA;AAED,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG;IACrC,IAAI,EAAE,QAAQ,CAAA;IACd,IAAI,EAAE;QACL,IAAI,EAAE,MAAM,CAAA;QACZ,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KACpC,CAAA;CACD,CAAA;AAED,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG;IACvC,IAAI,EAAE,UAAU,CAAA;IAChB,IAAI,EAAE;QACL,kBAAkB;QAClB,WAAW,EAAE,MAAM,CAAA;QACnB,kBAAkB;QAClB,MAAM,EAAE,MAAM,CAAA;QACd,uBAAuB;QACvB,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,+BAA+B;QAC/B,QAAQ,EAAE,MAAM,CAAA;QAChB,qBAAqB;QACrB,aAAa,EAAE,OAAO,GAAG,KAAK,CAAA;QAC9B,mDAAmD;QACnD,OAAO,CAAC,EAAE,MAAM,CAAA;KAChB,CAAA;CACD,CAAA;AAED,MAAM,MAAM,QAAQ,GACjB,aAAa,GACb,UAAU,GACV,WAAW,GACX,UAAU,GACV,WAAW,GACX,aAAa,CAAA;AAEhB,wBAAgB,eAAe,CAC9B,IAAI,EAAE,YAAY,EAClB,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,GACb,SAAS,CASX"}
|
package/dist/events.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAiGA,MAAM,UAAU,eAAe,CAC9B,IAAkB,EAClB,SAAiB,EACjB,MAAe;IAEf,OAAO;QACN,IAAI;QACJ,SAAS;QACT,MAAM;QACN,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;QACrB,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI;QACzB,SAAS,EAAE,SAAS,CAAC,SAAS;KAC9B,CAAA;AACF,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { createSpanwiseBrowser, type BrowserConfig, type SpanwiseBrowser, type TracingConfig, } from "./client.js";
|
|
2
|
+
export type { RumEvent, RumEventType, PageViewEvent, ClickEvent, VitalsEvent, ErrorEvent, CustomEvent, ResourceEvent, } from "./events.js";
|
|
3
|
+
export { getSessionId, endSession, type StorageMode } from "./session.js";
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,qBAAqB,EACrB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,aAAa,GAClB,MAAM,aAAa,CAAA;AACpB,YAAY,EACX,QAAQ,EACR,YAAY,EACZ,aAAa,EACb,UAAU,EACV,WAAW,EACX,UAAU,EACV,WAAW,EACX,aAAa,GACb,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,qBAAqB,GAIrB,MAAM,aAAa,CAAA;AAWpB,OAAO,EAAE,YAAY,EAAE,UAAU,EAAoB,MAAM,cAAc,CAAA"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fetch instrumentation for browser-side resource tracking.
|
|
3
|
+
* Intercepts fetch calls to inject traceparent headers and capture timing.
|
|
4
|
+
*/
|
|
5
|
+
import type { ErrorEvent, ResourceEvent } from "../events.js";
|
|
6
|
+
export type FetchInstrumentationConfig = {
|
|
7
|
+
propagateToOrigins?: (string | RegExp)[];
|
|
8
|
+
sessionId: string;
|
|
9
|
+
userId?: string;
|
|
10
|
+
ingestUrl?: string;
|
|
11
|
+
};
|
|
12
|
+
export type FetchErrorCallback = (event: ErrorEvent) => void;
|
|
13
|
+
export declare function instrumentFetch(config: FetchInstrumentationConfig, onResource: (event: ResourceEvent) => void, onError?: FetchErrorCallback): void;
|
|
14
|
+
export declare function updateFetchConfig(userId?: string): void;
|
|
15
|
+
export declare function restoreFetch(): void;
|
|
16
|
+
//# sourceMappingURL=fetch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/instrumentation/fetch.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAS7D,MAAM,MAAM,0BAA0B,GAAG;IACxC,kBAAkB,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAA;IACxC,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAA;AAkC5D,wBAAgB,eAAe,CAC9B,MAAM,EAAE,0BAA0B,EAClC,UAAU,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,EAC1C,OAAO,CAAC,EAAE,kBAAkB,GAC1B,IAAI,CAmGN;AAED,wBAAgB,iBAAiB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAIvD;AAED,wBAAgB,YAAY,IAAI,IAAI,CAOnC"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fetch instrumentation for browser-side resource tracking.
|
|
3
|
+
* Intercepts fetch calls to inject traceparent headers and capture timing.
|
|
4
|
+
*/
|
|
5
|
+
import { createBaseEvent } from "../events.js";
|
|
6
|
+
import { createTraceparent, generateSpanId, generateTraceId, shouldPropagate, } from "../trace-context.js";
|
|
7
|
+
// Module state for monkey-patching. Only one instrumentation instance supported.
|
|
8
|
+
let originalFetch = null;
|
|
9
|
+
let currentConfig = null;
|
|
10
|
+
let onFetchError = null;
|
|
11
|
+
function createResourceEvent(config, url, method, traceId, startTime, duration, status) {
|
|
12
|
+
return {
|
|
13
|
+
type: "resource",
|
|
14
|
+
sessionId: config.sessionId,
|
|
15
|
+
userId: config.userId,
|
|
16
|
+
timestamp: startTime,
|
|
17
|
+
url: window.location.href,
|
|
18
|
+
userAgent: navigator.userAgent,
|
|
19
|
+
data: {
|
|
20
|
+
resourceUrl: url,
|
|
21
|
+
method,
|
|
22
|
+
status,
|
|
23
|
+
duration,
|
|
24
|
+
initiatorType: "fetch",
|
|
25
|
+
traceId,
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export function instrumentFetch(config, onResource, onError) {
|
|
30
|
+
if (originalFetch)
|
|
31
|
+
return;
|
|
32
|
+
originalFetch = window.fetch;
|
|
33
|
+
currentConfig = config;
|
|
34
|
+
onFetchError = onError ?? null;
|
|
35
|
+
window.fetch = async function instrumentedFetch(input, init) {
|
|
36
|
+
const url = typeof input === "string"
|
|
37
|
+
? input
|
|
38
|
+
: input instanceof URL
|
|
39
|
+
? input.toString()
|
|
40
|
+
: input.url;
|
|
41
|
+
// Skip internal requests (Next.js RSC, SDK telemetry)
|
|
42
|
+
if (url.includes("_rsc=") ||
|
|
43
|
+
(currentConfig?.ingestUrl && url.startsWith(currentConfig.ingestUrl))) {
|
|
44
|
+
// biome-ignore lint/style/noNonNullAssertion: checked at function entry
|
|
45
|
+
return originalFetch(input, init);
|
|
46
|
+
}
|
|
47
|
+
const method = init?.method ??
|
|
48
|
+
(typeof input !== "string" && !(input instanceof URL)
|
|
49
|
+
? (input.method ?? "GET")
|
|
50
|
+
: "GET");
|
|
51
|
+
// Only inject traceparent for allowed origins
|
|
52
|
+
const shouldInjectTrace = shouldPropagate(url, currentConfig?.propagateToOrigins);
|
|
53
|
+
let traceId;
|
|
54
|
+
let modifiedInit = init;
|
|
55
|
+
if (shouldInjectTrace) {
|
|
56
|
+
traceId = generateTraceId();
|
|
57
|
+
const spanId = generateSpanId();
|
|
58
|
+
const traceparent = createTraceparent(traceId, spanId, true);
|
|
59
|
+
const headers = new Headers(init?.headers);
|
|
60
|
+
headers.set("traceparent", traceparent);
|
|
61
|
+
modifiedInit = { ...init, headers };
|
|
62
|
+
}
|
|
63
|
+
const startTime = Date.now();
|
|
64
|
+
try {
|
|
65
|
+
// biome-ignore lint/style/noNonNullAssertion: checked at function entry
|
|
66
|
+
const response = await originalFetch(input, modifiedInit);
|
|
67
|
+
const duration = Date.now() - startTime;
|
|
68
|
+
// biome-ignore lint/style/noNonNullAssertion: config set at function entry
|
|
69
|
+
const config = currentConfig;
|
|
70
|
+
onResource(createResourceEvent(config, url, method, traceId, startTime, duration, response.status));
|
|
71
|
+
return response;
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
const duration = Date.now() - startTime;
|
|
75
|
+
// biome-ignore lint/style/noNonNullAssertion: config set at function entry
|
|
76
|
+
const config = currentConfig;
|
|
77
|
+
onResource(createResourceEvent(config, url, method, traceId, startTime, duration));
|
|
78
|
+
// Emit error event with the failed URL for better debugging
|
|
79
|
+
if (onFetchError && error instanceof Error) {
|
|
80
|
+
const errorEvent = {
|
|
81
|
+
...createBaseEvent("error", config.sessionId, config.userId),
|
|
82
|
+
type: "error",
|
|
83
|
+
data: {
|
|
84
|
+
message: error.message,
|
|
85
|
+
stack: error.stack?.slice(0, 2000),
|
|
86
|
+
failedUrl: url,
|
|
87
|
+
traceId,
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
onFetchError(errorEvent);
|
|
91
|
+
}
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
export function updateFetchConfig(userId) {
|
|
97
|
+
if (currentConfig) {
|
|
98
|
+
currentConfig.userId = userId;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
export function restoreFetch() {
|
|
102
|
+
if (originalFetch) {
|
|
103
|
+
window.fetch = originalFetch;
|
|
104
|
+
originalFetch = null;
|
|
105
|
+
currentConfig = null;
|
|
106
|
+
onFetchError = null;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=fetch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../src/instrumentation/fetch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* XMLHttpRequest instrumentation for browser-side resource tracking.
|
|
3
|
+
* Intercepts XHR calls to inject traceparent headers and capture timing.
|
|
4
|
+
*/
|
|
5
|
+
import type { ErrorEvent, ResourceEvent } from "../events.js";
|
|
6
|
+
export type XHRInstrumentationConfig = {
|
|
7
|
+
propagateToOrigins?: (string | RegExp)[];
|
|
8
|
+
sessionId: string;
|
|
9
|
+
userId?: string;
|
|
10
|
+
ingestUrl?: string;
|
|
11
|
+
};
|
|
12
|
+
export type XHRErrorCallback = (event: ErrorEvent) => void;
|
|
13
|
+
export declare function instrumentXHR(config: XHRInstrumentationConfig, onResource: (event: ResourceEvent) => void, onError?: XHRErrorCallback): void;
|
|
14
|
+
export declare function updateXHRConfig(userId?: string): void;
|
|
15
|
+
export declare function restoreXHR(): void;
|
|
16
|
+
//# sourceMappingURL=xhr.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"xhr.d.ts","sourceRoot":"","sources":["../../src/instrumentation/xhr.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAS7D,MAAM,MAAM,wBAAwB,GAAG;IACtC,kBAAkB,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAA;IACxC,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAA;AA2C1D,wBAAgB,aAAa,CAC5B,MAAM,EAAE,wBAAwB,EAChC,UAAU,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,EAC1C,OAAO,CAAC,EAAE,gBAAgB,GACxB,IAAI,CA8GN;AAED,wBAAgB,eAAe,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAIrD;AAED,wBAAgB,UAAU,IAAI,IAAI,CAWjC"}
|