@diegotsi/flint-core 1.7.0 → 1.9.0
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/{chunk-HVSD45YR.js → chunk-SO6WYKFF.js} +15 -2
- package/dist/{chunk-HVSD45YR.js.map → chunk-SO6WYKFF.js.map} +1 -1
- package/dist/datadog-FLEAFTUB.js +11 -0
- package/dist/index.cjs +257 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +78 -1
- package/dist/index.d.ts +78 -1
- package/dist/index.js +244 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/datadog-I3QKI6Q3.js +0 -9
- /package/dist/{datadog-I3QKI6Q3.js.map → datadog-FLEAFTUB.js.map} +0 -0
|
@@ -21,9 +21,22 @@ function createDatadogReplayProvider(site) {
|
|
|
21
21
|
return void 0;
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
|
+
function trackDatadogBugReported(meta) {
|
|
25
|
+
try {
|
|
26
|
+
const ddRum = window.DD_RUM;
|
|
27
|
+
ddRum?.addAction?.("flint.bug_reported", {
|
|
28
|
+
bug_id: meta.bugId,
|
|
29
|
+
severity: meta.severity,
|
|
30
|
+
url: meta.url,
|
|
31
|
+
title: meta.title
|
|
32
|
+
});
|
|
33
|
+
} catch {
|
|
34
|
+
}
|
|
35
|
+
}
|
|
24
36
|
|
|
25
37
|
export {
|
|
26
38
|
DATADOG_BLOCKED_HOSTS,
|
|
27
|
-
createDatadogReplayProvider
|
|
39
|
+
createDatadogReplayProvider,
|
|
40
|
+
trackDatadogBugReported
|
|
28
41
|
};
|
|
29
|
-
//# sourceMappingURL=chunk-
|
|
42
|
+
//# sourceMappingURL=chunk-SO6WYKFF.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/integrations/datadog.ts"],"sourcesContent":["/**\n * Datadog RUM integration — opt-in helper.\n *\n * Usage:\n * import { Flint } from \"@diegotsi/flint-core\";\n * import { createDatadogReplayProvider, DATADOG_BLOCKED_HOSTS } from \"@diegotsi/flint-core\";\n *\n * Flint.init({\n * projectKey: \"...\",\n * serverUrl: \"...\",\n * externalReplayProvider: createDatadogReplayProvider(\"app.datadoghq.com\"),\n * blockedHosts: DATADOG_BLOCKED_HOSTS,\n * });\n */\n\n/** Datadog intake hosts to exclude from network capture. */\nexport const DATADOG_BLOCKED_HOSTS = [\n \"browser-intake-datadoghq.com\",\n \"rum.browser-intake-datadoghq.com\",\n \"logs.browser-intake-datadoghq.com\",\n \"session-replay.browser-intake-datadoghq.com\",\n];\n\n/**\n * Creates an `externalReplayProvider` that reads the current Datadog RUM\n * session and returns a deep link to the Session Replay viewer.\n */\nexport function createDatadogReplayProvider(site: string): () => string | undefined {\n return () => {\n try {\n const ddRum = (window as unknown as Record<string, unknown>).DD_RUM as\n | { getInternalContext?: () => { session_id?: string } | undefined }\n | undefined;\n const ctx = ddRum?.getInternalContext?.();\n if (ctx?.session_id) {\n const ts = Date.now();\n const fromTs = ts - 30_000;\n const toTs = ts + 5_000;\n return `https://${site}/rum/replay/sessions/${ctx.session_id}?from_ts=${fromTs}&to_ts=${toTs}&tab=replay&live=false`;\n }\n } catch {\n // DD_RUM not available — silently skip\n }\n return undefined;\n };\n}\n"],"mappings":";AAgBO,IAAM,wBAAwB;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAMO,SAAS,4BAA4B,MAAwC;AAClF,SAAO,MAAM;AACX,QAAI;AACF,YAAM,QAAS,OAA8C;AAG7D,YAAM,MAAM,OAAO,qBAAqB;AACxC,UAAI,KAAK,YAAY;AACnB,cAAM,KAAK,KAAK,IAAI;AACpB,cAAM,SAAS,KAAK;AACpB,cAAM,OAAO,KAAK;AAClB,eAAO,WAAW,IAAI,wBAAwB,IAAI,UAAU,YAAY,MAAM,UAAU,IAAI;AAAA,MAC9F;AAAA,IACF,QAAQ;AAAA,IAER;AACA,WAAO;AAAA,EACT;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/integrations/datadog.ts"],"sourcesContent":["/**\n * Datadog RUM integration — opt-in helper.\n *\n * Usage:\n * import { Flint } from \"@diegotsi/flint-core\";\n * import { createDatadogReplayProvider, DATADOG_BLOCKED_HOSTS } from \"@diegotsi/flint-core\";\n *\n * Flint.init({\n * projectKey: \"...\",\n * serverUrl: \"...\",\n * externalReplayProvider: createDatadogReplayProvider(\"app.datadoghq.com\"),\n * blockedHosts: DATADOG_BLOCKED_HOSTS,\n * });\n */\n\n/** Datadog intake hosts to exclude from network capture. */\nexport const DATADOG_BLOCKED_HOSTS = [\n \"browser-intake-datadoghq.com\",\n \"rum.browser-intake-datadoghq.com\",\n \"logs.browser-intake-datadoghq.com\",\n \"session-replay.browser-intake-datadoghq.com\",\n];\n\n/**\n * Creates an `externalReplayProvider` that reads the current Datadog RUM\n * session and returns a deep link to the Session Replay viewer.\n */\nexport function createDatadogReplayProvider(site: string): () => string | undefined {\n return () => {\n try {\n const ddRum = (window as unknown as Record<string, unknown>).DD_RUM as\n | { getInternalContext?: () => { session_id?: string } | undefined }\n | undefined;\n const ctx = ddRum?.getInternalContext?.();\n if (ctx?.session_id) {\n const ts = Date.now();\n const fromTs = ts - 30_000;\n const toTs = ts + 5_000;\n return `https://${site}/rum/replay/sessions/${ctx.session_id}?from_ts=${fromTs}&to_ts=${toTs}&tab=replay&live=false`;\n }\n } catch {\n // DD_RUM not available — silently skip\n }\n return undefined;\n };\n}\n\n/**\n * Emits a custom Datadog RUM action at the moment a bug is reported, so it\n * shows up as a clickable marker on the Session Replay timeline — making the\n * report moment easy to find in long sessions.\n *\n * No-op when Datadog RUM (`window.DD_RUM`) is not present on the page.\n */\nexport function trackDatadogBugReported(meta: {\n bugId: string;\n severity?: string;\n url?: string;\n title?: string;\n}): void {\n try {\n const ddRum = (window as unknown as Record<string, unknown>).DD_RUM as\n | { addAction?: (name: string, context?: Record<string, unknown>) => void }\n | undefined;\n ddRum?.addAction?.(\"flint.bug_reported\", {\n bug_id: meta.bugId,\n severity: meta.severity,\n url: meta.url,\n title: meta.title,\n });\n } catch {\n // DD_RUM not available — silently skip\n }\n}\n"],"mappings":";AAgBO,IAAM,wBAAwB;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAMO,SAAS,4BAA4B,MAAwC;AAClF,SAAO,MAAM;AACX,QAAI;AACF,YAAM,QAAS,OAA8C;AAG7D,YAAM,MAAM,OAAO,qBAAqB;AACxC,UAAI,KAAK,YAAY;AACnB,cAAM,KAAK,KAAK,IAAI;AACpB,cAAM,SAAS,KAAK;AACpB,cAAM,OAAO,KAAK;AAClB,eAAO,WAAW,IAAI,wBAAwB,IAAI,UAAU,YAAY,MAAM,UAAU,IAAI;AAAA,MAC9F;AAAA,IACF,QAAQ;AAAA,IAER;AACA,WAAO;AAAA,EACT;AACF;AASO,SAAS,wBAAwB,MAK/B;AACP,MAAI;AACF,UAAM,QAAS,OAA8C;AAG7D,WAAO,YAAY,sBAAsB;AAAA,MACvC,QAAQ,KAAK;AAAA,MACb,UAAU,KAAK;AAAA,MACf,KAAK,KAAK;AAAA,MACV,OAAO,KAAK;AAAA,IACd,CAAC;AAAA,EACH,QAAQ;AAAA,EAER;AACF;","names":[]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DATADOG_BLOCKED_HOSTS,
|
|
3
|
+
createDatadogReplayProvider,
|
|
4
|
+
trackDatadogBugReported
|
|
5
|
+
} from "./chunk-SO6WYKFF.js";
|
|
6
|
+
export {
|
|
7
|
+
DATADOG_BLOCKED_HOSTS,
|
|
8
|
+
createDatadogReplayProvider,
|
|
9
|
+
trackDatadogBugReported
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=datadog-FLEAFTUB.js.map
|
package/dist/index.cjs
CHANGED
|
@@ -24,7 +24,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
24
24
|
var datadog_exports = {};
|
|
25
25
|
__export(datadog_exports, {
|
|
26
26
|
DATADOG_BLOCKED_HOSTS: () => DATADOG_BLOCKED_HOSTS,
|
|
27
|
-
createDatadogReplayProvider: () => createDatadogReplayProvider
|
|
27
|
+
createDatadogReplayProvider: () => createDatadogReplayProvider,
|
|
28
|
+
trackDatadogBugReported: () => trackDatadogBugReported
|
|
28
29
|
});
|
|
29
30
|
function createDatadogReplayProvider(site) {
|
|
30
31
|
return () => {
|
|
@@ -42,6 +43,18 @@ function createDatadogReplayProvider(site) {
|
|
|
42
43
|
return void 0;
|
|
43
44
|
};
|
|
44
45
|
}
|
|
46
|
+
function trackDatadogBugReported(meta) {
|
|
47
|
+
try {
|
|
48
|
+
const ddRum = window.DD_RUM;
|
|
49
|
+
ddRum?.addAction?.("flint.bug_reported", {
|
|
50
|
+
bug_id: meta.bugId,
|
|
51
|
+
severity: meta.severity,
|
|
52
|
+
url: meta.url,
|
|
53
|
+
title: meta.title
|
|
54
|
+
});
|
|
55
|
+
} catch {
|
|
56
|
+
}
|
|
57
|
+
}
|
|
45
58
|
var DATADOG_BLOCKED_HOSTS;
|
|
46
59
|
var init_datadog = __esm({
|
|
47
60
|
"src/integrations/datadog.ts"() {
|
|
@@ -64,6 +77,7 @@ __export(index_exports, {
|
|
|
64
77
|
collectEnvironment: () => collectEnvironment,
|
|
65
78
|
createConsoleCollector: () => createConsoleCollector,
|
|
66
79
|
createDatadogReplayProvider: () => createDatadogReplayProvider,
|
|
80
|
+
createErrorCaptureCollector: () => createErrorCaptureCollector,
|
|
67
81
|
createFormErrorCollector: () => createFormErrorCollector,
|
|
68
82
|
createFrustrationCollector: () => createFrustrationCollector,
|
|
69
83
|
createNetworkCollector: () => createNetworkCollector,
|
|
@@ -71,7 +85,8 @@ __export(index_exports, {
|
|
|
71
85
|
resolveTheme: () => resolveTheme,
|
|
72
86
|
submitReplay: () => submitReplay,
|
|
73
87
|
submitReport: () => submitReport,
|
|
74
|
-
subscribe: () => subscribe
|
|
88
|
+
subscribe: () => subscribe,
|
|
89
|
+
trackDatadogBugReported: () => trackDatadogBugReported
|
|
75
90
|
});
|
|
76
91
|
module.exports = __toCommonJS(index_exports);
|
|
77
92
|
|
|
@@ -141,8 +156,7 @@ async function submitReplay(serverUrl, projectKey, reportId, events) {
|
|
|
141
156
|
});
|
|
142
157
|
}
|
|
143
158
|
|
|
144
|
-
// src/
|
|
145
|
-
var MAX_ENTRIES = 50;
|
|
159
|
+
// src/sanitize.ts
|
|
146
160
|
var SENSITIVE_PATTERNS = [
|
|
147
161
|
/(?:password|passwd|pwd|secret|token|api[_-]?key|access[_-]?key|authorization|bearer)\s*[:=]\s*["']?[^\s"',]{4,}/gi,
|
|
148
162
|
/\b(sk-[a-zA-Z0-9_-]{20,})\b/g,
|
|
@@ -161,6 +175,9 @@ function sanitize(str) {
|
|
|
161
175
|
}
|
|
162
176
|
return result;
|
|
163
177
|
}
|
|
178
|
+
|
|
179
|
+
// src/collectors/console.ts
|
|
180
|
+
var MAX_ENTRIES = 50;
|
|
164
181
|
function createConsoleCollector() {
|
|
165
182
|
const entries = [];
|
|
166
183
|
let active = false;
|
|
@@ -280,6 +297,216 @@ function collectEnvironment() {
|
|
|
280
297
|
};
|
|
281
298
|
}
|
|
282
299
|
|
|
300
|
+
// src/collectors/errorCapture.ts
|
|
301
|
+
var MAX_MESSAGE = 1e3;
|
|
302
|
+
var MAX_STACK = 8e3;
|
|
303
|
+
var MAX_BATCH = 20;
|
|
304
|
+
var MAX_PAYLOAD_BYTES = 6e4;
|
|
305
|
+
var PER_KEY_PER_MINUTE = 10;
|
|
306
|
+
var GLOBAL_PAGE_CAP = 100;
|
|
307
|
+
var FLUSH_INTERVAL_MS = 5e3;
|
|
308
|
+
var THROTTLE_WINDOW_MS = 6e4;
|
|
309
|
+
var BREADCRUMB_CONSOLE = 10;
|
|
310
|
+
var BREADCRUMB_NETWORK = 10;
|
|
311
|
+
var DEFAULT_IGNORE = [/ResizeObserver loop/i, /^Script error\.?$/];
|
|
312
|
+
var EXTENSION_URL = /(chrome|moz|safari|safari-web)-extension:\/\//;
|
|
313
|
+
function normalizeForKey(message) {
|
|
314
|
+
return message.toLowerCase().replace(/\d+/g, "#").replace(/\s+/g, " ").trim().slice(0, 200);
|
|
315
|
+
}
|
|
316
|
+
function topFrame(stack) {
|
|
317
|
+
if (!stack) return "";
|
|
318
|
+
const lines = stack.split("\n").map((l) => l.trim());
|
|
319
|
+
return lines.find((l) => l.startsWith("at ") || /@/.test(l)) ?? "";
|
|
320
|
+
}
|
|
321
|
+
function createErrorCaptureCollector(options) {
|
|
322
|
+
const sampleRate = options.sampleRate ?? 1;
|
|
323
|
+
const ignoreList = [...DEFAULT_IGNORE, ...options.ignoreErrors ?? []];
|
|
324
|
+
const sessionId = `s_${Date.now().toString(36)}${Math.random().toString(36).slice(2, 10)}`;
|
|
325
|
+
let active = false;
|
|
326
|
+
let queue = [];
|
|
327
|
+
let interval = null;
|
|
328
|
+
let sentCount = 0;
|
|
329
|
+
let environment;
|
|
330
|
+
const keyTimestamps = /* @__PURE__ */ new Map();
|
|
331
|
+
function debugLog2(...args) {
|
|
332
|
+
if (options.debug) console.log("[Flint]", ...args);
|
|
333
|
+
}
|
|
334
|
+
function isIgnored(message, stack, frameUrl) {
|
|
335
|
+
for (const entry of ignoreList) {
|
|
336
|
+
if (typeof entry === "string") {
|
|
337
|
+
if (message.includes(entry)) return true;
|
|
338
|
+
} else if (entry.test(message)) {
|
|
339
|
+
return true;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
if (EXTENSION_URL.test(frameUrl ?? "") || EXTENSION_URL.test(stack ?? "")) return true;
|
|
343
|
+
return false;
|
|
344
|
+
}
|
|
345
|
+
function isThrottled(localKey) {
|
|
346
|
+
const now = Date.now();
|
|
347
|
+
const stamps = (keyTimestamps.get(localKey) ?? []).filter((t) => now - t < THROTTLE_WINDOW_MS);
|
|
348
|
+
if (stamps.length >= PER_KEY_PER_MINUTE) {
|
|
349
|
+
keyTimestamps.set(localKey, stamps);
|
|
350
|
+
return true;
|
|
351
|
+
}
|
|
352
|
+
stamps.push(now);
|
|
353
|
+
keyTimestamps.set(localKey, stamps);
|
|
354
|
+
return false;
|
|
355
|
+
}
|
|
356
|
+
function capture(input) {
|
|
357
|
+
try {
|
|
358
|
+
if (sentCount + queue.length >= GLOBAL_PAGE_CAP) return;
|
|
359
|
+
let message = input.message.slice(0, MAX_MESSAGE);
|
|
360
|
+
if (isIgnored(message, input.stack, input.frameUrl)) return;
|
|
361
|
+
if (sampleRate < 1 && Math.random() >= sampleRate) return;
|
|
362
|
+
const localKey = `${input.type}|${normalizeForKey(message)}|${topFrame(input.stack)}`;
|
|
363
|
+
if (isThrottled(localKey)) return;
|
|
364
|
+
const pending = queue.find((e) => e._localKey === localKey);
|
|
365
|
+
if (pending) {
|
|
366
|
+
pending.count += 1;
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
message = sanitize(message);
|
|
370
|
+
const stack = input.stack ? sanitize(input.stack.slice(0, MAX_STACK)) : void 0;
|
|
371
|
+
if (!environment && options.getEnvironment) {
|
|
372
|
+
try {
|
|
373
|
+
environment = options.getEnvironment();
|
|
374
|
+
} catch {
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
const user = options.getUser?.();
|
|
378
|
+
let event = {
|
|
379
|
+
type: input.type,
|
|
380
|
+
message,
|
|
381
|
+
errorClass: input.errorClass,
|
|
382
|
+
stack,
|
|
383
|
+
url: typeof location !== "undefined" ? location.href : "",
|
|
384
|
+
timestamp: Date.now(),
|
|
385
|
+
release: options.release,
|
|
386
|
+
appVersion: options.appVersion,
|
|
387
|
+
userId: user?.id,
|
|
388
|
+
sessionId,
|
|
389
|
+
browser: environment?.browser,
|
|
390
|
+
os: environment?.os,
|
|
391
|
+
count: 1,
|
|
392
|
+
breadcrumbs: options.getBreadcrumbs ? {
|
|
393
|
+
consoleLogs: options.getBreadcrumbs().consoleLogs.slice(-BREADCRUMB_CONSOLE),
|
|
394
|
+
networkErrors: options.getBreadcrumbs().networkErrors.slice(-BREADCRUMB_NETWORK)
|
|
395
|
+
} : void 0,
|
|
396
|
+
_localKey: localKey
|
|
397
|
+
};
|
|
398
|
+
if (options.beforeSend) {
|
|
399
|
+
try {
|
|
400
|
+
const result = options.beforeSend(event);
|
|
401
|
+
if (!result) return;
|
|
402
|
+
event = { ...result, _localKey: localKey };
|
|
403
|
+
} catch {
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
queue.push(event);
|
|
407
|
+
debugLog2("Error captured", input.errorClass, message);
|
|
408
|
+
if (queue.length >= MAX_BATCH) flush(false);
|
|
409
|
+
} catch {
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
function serialize(events) {
|
|
413
|
+
const wire = events.map(({ _localKey, ...e }) => e);
|
|
414
|
+
let body = JSON.stringify(wire);
|
|
415
|
+
if (body.length > MAX_PAYLOAD_BYTES) {
|
|
416
|
+
body = JSON.stringify(wire.map((e) => ({ ...e, breadcrumbs: void 0 })));
|
|
417
|
+
if (body.length > MAX_PAYLOAD_BYTES) {
|
|
418
|
+
body = JSON.stringify(wire.map((e) => ({ ...e, breadcrumbs: void 0, stack: e.stack?.slice(0, 2e3) })));
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
return body;
|
|
422
|
+
}
|
|
423
|
+
function flush(unloading) {
|
|
424
|
+
if (queue.length === 0) return;
|
|
425
|
+
const events = queue;
|
|
426
|
+
queue = [];
|
|
427
|
+
sentCount += events.length;
|
|
428
|
+
const base = options.serverUrl.replace(/\/$/, "");
|
|
429
|
+
const url = `${base}/api/v1/error-events?project_key=${encodeURIComponent(options.projectKey)}`;
|
|
430
|
+
const body = serialize(events);
|
|
431
|
+
if (unloading && typeof navigator !== "undefined" && typeof navigator.sendBeacon === "function") {
|
|
432
|
+
const ok = navigator.sendBeacon(url, body);
|
|
433
|
+
debugLog2("Flushed via beacon", events.length, ok);
|
|
434
|
+
if (ok) return;
|
|
435
|
+
}
|
|
436
|
+
fetch(url, {
|
|
437
|
+
method: "POST",
|
|
438
|
+
headers: { "Content-Type": "text/plain;charset=UTF-8" },
|
|
439
|
+
body,
|
|
440
|
+
keepalive: unloading
|
|
441
|
+
}).catch(() => {
|
|
442
|
+
});
|
|
443
|
+
debugLog2("Flushed via fetch", events.length);
|
|
444
|
+
}
|
|
445
|
+
function onError(event) {
|
|
446
|
+
const e = event;
|
|
447
|
+
if (typeof e.message !== "string" && !(e.error instanceof Error)) return;
|
|
448
|
+
const err = e.error instanceof Error ? e.error : void 0;
|
|
449
|
+
capture({
|
|
450
|
+
type: "error",
|
|
451
|
+
message: err?.message ?? (e.message || "Unknown error"),
|
|
452
|
+
errorClass: err?.name ?? "Error",
|
|
453
|
+
stack: err?.stack,
|
|
454
|
+
frameUrl: e.filename
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
function onRejection(event) {
|
|
458
|
+
const reason = event.reason;
|
|
459
|
+
const err = reason instanceof Error ? reason : void 0;
|
|
460
|
+
let message;
|
|
461
|
+
if (err) {
|
|
462
|
+
message = err.message;
|
|
463
|
+
} else {
|
|
464
|
+
try {
|
|
465
|
+
message = typeof reason === "string" ? reason : JSON.stringify(reason);
|
|
466
|
+
} catch {
|
|
467
|
+
message = String(reason);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
capture({
|
|
471
|
+
type: "unhandledrejection",
|
|
472
|
+
message: message || "Unhandled promise rejection",
|
|
473
|
+
errorClass: err?.name ?? "UnhandledRejection",
|
|
474
|
+
stack: err?.stack
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
function onPageHide() {
|
|
478
|
+
flush(true);
|
|
479
|
+
}
|
|
480
|
+
function onVisibilityChange() {
|
|
481
|
+
if (document.visibilityState === "hidden") flush(true);
|
|
482
|
+
}
|
|
483
|
+
return {
|
|
484
|
+
start() {
|
|
485
|
+
if (active) return;
|
|
486
|
+
active = true;
|
|
487
|
+
window.addEventListener("error", onError, { capture: true });
|
|
488
|
+
window.addEventListener("unhandledrejection", onRejection, { capture: true });
|
|
489
|
+
window.addEventListener("pagehide", onPageHide);
|
|
490
|
+
document.addEventListener("visibilitychange", onVisibilityChange);
|
|
491
|
+
interval = setInterval(() => flush(false), FLUSH_INTERVAL_MS);
|
|
492
|
+
},
|
|
493
|
+
stop() {
|
|
494
|
+
if (!active) return;
|
|
495
|
+
active = false;
|
|
496
|
+
window.removeEventListener("error", onError, { capture: true });
|
|
497
|
+
window.removeEventListener("unhandledrejection", onRejection, { capture: true });
|
|
498
|
+
window.removeEventListener("pagehide", onPageHide);
|
|
499
|
+
document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
500
|
+
if (interval) clearInterval(interval);
|
|
501
|
+
interval = null;
|
|
502
|
+
flush(false);
|
|
503
|
+
},
|
|
504
|
+
flush() {
|
|
505
|
+
flush(false);
|
|
506
|
+
}
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
|
|
283
510
|
// src/collectors/formErrors.ts
|
|
284
511
|
var MAX_ENTRIES2 = 30;
|
|
285
512
|
var POST_SUBMIT_CHECK_MS = 300;
|
|
@@ -977,6 +1204,8 @@ function init(config) {
|
|
|
977
1204
|
enableFormErrors = true,
|
|
978
1205
|
enableFrustration = false,
|
|
979
1206
|
autoReportFrustration = false,
|
|
1207
|
+
enableErrorMonitoring = true,
|
|
1208
|
+
errorMonitoring: errorMonitoringOpts,
|
|
980
1209
|
enableReplay = false,
|
|
981
1210
|
replayBufferMs = DEFAULT_REPLAY_BUFFER_MS,
|
|
982
1211
|
blockedHosts = [],
|
|
@@ -1012,6 +1241,23 @@ function init(config) {
|
|
|
1012
1241
|
}
|
|
1013
1242
|
const frustrationCol = enableFrustration ? createFrustrationCollector(frustrationOpts) : null;
|
|
1014
1243
|
frustrationCol?.start();
|
|
1244
|
+
const errorCaptureCol = enableErrorMonitoring ? createErrorCaptureCollector({
|
|
1245
|
+
serverUrl: config.serverUrl,
|
|
1246
|
+
projectKey: config.projectKey,
|
|
1247
|
+
release: config.release,
|
|
1248
|
+
appVersion: config.appVersion,
|
|
1249
|
+
debug: config.debug,
|
|
1250
|
+
sampleRate: errorMonitoringOpts?.sampleRate,
|
|
1251
|
+
ignoreErrors: errorMonitoringOpts?.ignoreErrors,
|
|
1252
|
+
beforeSend: errorMonitoringOpts?.beforeSend,
|
|
1253
|
+
getUser: () => getSnapshot().user ?? config.user,
|
|
1254
|
+
getBreadcrumbs: () => ({
|
|
1255
|
+
consoleLogs: consoleCol?.getEntries() ?? [],
|
|
1256
|
+
networkErrors: networkCol?.getEntries() ?? []
|
|
1257
|
+
}),
|
|
1258
|
+
getEnvironment: _collectors?.environment ?? collectEnvironment
|
|
1259
|
+
}) : null;
|
|
1260
|
+
errorCaptureCol?.start();
|
|
1015
1261
|
if (config.user) {
|
|
1016
1262
|
flint.setUser(config.user);
|
|
1017
1263
|
}
|
|
@@ -1021,7 +1267,8 @@ function init(config) {
|
|
|
1021
1267
|
console: !!consoleCol,
|
|
1022
1268
|
network: !!networkCol,
|
|
1023
1269
|
formErrors: !!formErrorsCol,
|
|
1024
|
-
frustration: !!frustrationCol
|
|
1270
|
+
frustration: !!frustrationCol,
|
|
1271
|
+
errorCapture: !!errorCaptureCol
|
|
1025
1272
|
});
|
|
1026
1273
|
instance = {
|
|
1027
1274
|
config,
|
|
@@ -1029,6 +1276,7 @@ function init(config) {
|
|
|
1029
1276
|
network: networkCol,
|
|
1030
1277
|
formErrors: formErrorsCol,
|
|
1031
1278
|
frustration: frustrationCol,
|
|
1279
|
+
errorCapture: errorCaptureCol,
|
|
1032
1280
|
replayEvents,
|
|
1033
1281
|
stopReplay: null
|
|
1034
1282
|
};
|
|
@@ -1109,6 +1357,7 @@ function shutdown() {
|
|
|
1109
1357
|
instance.formErrors?.stop();
|
|
1110
1358
|
_setFormErrorCollector(null);
|
|
1111
1359
|
instance.frustration?.stop();
|
|
1360
|
+
instance.errorCapture?.stop();
|
|
1112
1361
|
instance.stopReplay?.();
|
|
1113
1362
|
instance = null;
|
|
1114
1363
|
}
|
|
@@ -1200,6 +1449,7 @@ function resolveTheme(theme) {
|
|
|
1200
1449
|
collectEnvironment,
|
|
1201
1450
|
createConsoleCollector,
|
|
1202
1451
|
createDatadogReplayProvider,
|
|
1452
|
+
createErrorCaptureCollector,
|
|
1203
1453
|
createFormErrorCollector,
|
|
1204
1454
|
createFrustrationCollector,
|
|
1205
1455
|
createNetworkCollector,
|
|
@@ -1207,6 +1457,7 @@ function resolveTheme(theme) {
|
|
|
1207
1457
|
resolveTheme,
|
|
1208
1458
|
submitReplay,
|
|
1209
1459
|
submitReport,
|
|
1210
|
-
subscribe
|
|
1460
|
+
subscribe,
|
|
1461
|
+
trackDatadogBugReported
|
|
1211
1462
|
});
|
|
1212
1463
|
//# sourceMappingURL=index.cjs.map
|