@diegotsi/flint-core 1.6.1 → 1.8.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/index.cjs +243 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +71 -1
- package/dist/index.d.ts +71 -1
- package/dist/index.js +242 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -75,6 +75,32 @@ interface FormErrorEntry {
|
|
|
75
75
|
url: string;
|
|
76
76
|
timestamp: number;
|
|
77
77
|
}
|
|
78
|
+
interface ErrorBreadcrumbs {
|
|
79
|
+
consoleLogs: ConsoleEntry[];
|
|
80
|
+
networkErrors: NetworkEntry[];
|
|
81
|
+
}
|
|
82
|
+
interface ErrorEventPayload {
|
|
83
|
+
type: "error" | "unhandledrejection";
|
|
84
|
+
message: string;
|
|
85
|
+
errorClass: string;
|
|
86
|
+
stack?: string;
|
|
87
|
+
/** Page URL where the error occurred */
|
|
88
|
+
url: string;
|
|
89
|
+
/** Client time — orders breadcrumbs only; the server buckets by receive time */
|
|
90
|
+
timestamp: number;
|
|
91
|
+
release?: string;
|
|
92
|
+
appVersion?: string;
|
|
93
|
+
userId?: string;
|
|
94
|
+
/** Anonymous per-page-load session hash when no user is set */
|
|
95
|
+
sessionId?: string;
|
|
96
|
+
browser?: string;
|
|
97
|
+
os?: string;
|
|
98
|
+
/** In-batch dedup count — identical errors merged client-side before flush */
|
|
99
|
+
count: number;
|
|
100
|
+
breadcrumbs?: ErrorBreadcrumbs;
|
|
101
|
+
/** @internal client-side throttle/dedup key — stripped before sending */
|
|
102
|
+
_localKey?: string;
|
|
103
|
+
}
|
|
78
104
|
type Locale = "pt-BR" | "en-US";
|
|
79
105
|
type Theme = "light" | "dark" | ThemeOverride;
|
|
80
106
|
interface ThemeOverride {
|
|
@@ -128,6 +154,20 @@ interface FlintConfig {
|
|
|
128
154
|
enableDeadClicks?: boolean;
|
|
129
155
|
};
|
|
130
156
|
onFrustration?: (event: FrustrationEvent) => void;
|
|
157
|
+
/** Capture uncaught errors & unhandled rejections automatically. Default: true */
|
|
158
|
+
enableErrorMonitoring?: boolean;
|
|
159
|
+
errorMonitoring?: {
|
|
160
|
+
/** Fraction of captured errors to report, 0..1. Default: 1.0 */
|
|
161
|
+
sampleRate?: number;
|
|
162
|
+
/** Errors whose message matches any entry are dropped (string = substring match) */
|
|
163
|
+
ignoreErrors?: (string | RegExp)[];
|
|
164
|
+
/** Mutate or drop (return null) an event before it is sent */
|
|
165
|
+
beforeSend?: (event: ErrorEventPayload) => ErrorEventPayload | null;
|
|
166
|
+
};
|
|
167
|
+
/** Application version string, e.g. "2.1.0" */
|
|
168
|
+
appVersion?: string;
|
|
169
|
+
/** Release/deploy identifier, e.g. "v2.1.0-rc1" or a commit SHA */
|
|
170
|
+
release?: string;
|
|
131
171
|
/** Returns an external session replay URL at report time (Datadog, FullStory, LogRocket, etc.) */
|
|
132
172
|
externalReplayProvider?: () => string | undefined;
|
|
133
173
|
/** @internal Inject platform-specific collectors (e.g. React Native) */
|
|
@@ -164,6 +204,8 @@ interface ReportPayload {
|
|
|
164
204
|
label?: string;
|
|
165
205
|
source?: "widget" | "auto_capture" | "text_issue" | "feature_request";
|
|
166
206
|
type?: "BUG" | "FEATURE_REQUEST";
|
|
207
|
+
appVersion?: string;
|
|
208
|
+
release?: string;
|
|
167
209
|
}
|
|
168
210
|
interface ReportResult {
|
|
169
211
|
id: string;
|
|
@@ -179,6 +221,33 @@ declare function submitReplay(serverUrl: string, projectKey: string, reportId: s
|
|
|
179
221
|
|
|
180
222
|
declare function collectEnvironment(): EnvironmentInfo;
|
|
181
223
|
|
|
224
|
+
interface ErrorCaptureCollector {
|
|
225
|
+
start(): void;
|
|
226
|
+
stop(): void;
|
|
227
|
+
/** Flush pending events immediately (also called on pagehide/interval). */
|
|
228
|
+
flush(): void;
|
|
229
|
+
}
|
|
230
|
+
interface ErrorCaptureOptions {
|
|
231
|
+
serverUrl: string;
|
|
232
|
+
projectKey: string;
|
|
233
|
+
release?: string;
|
|
234
|
+
appVersion?: string;
|
|
235
|
+
/** Fraction of captured errors to report, 0..1. Default 1.0 */
|
|
236
|
+
sampleRate?: number;
|
|
237
|
+
/** Errors whose message matches any entry are dropped (string = substring match) */
|
|
238
|
+
ignoreErrors?: (string | RegExp)[];
|
|
239
|
+
/** Mutate or drop (return null) an event before it is queued for sending */
|
|
240
|
+
beforeSend?: (event: ErrorEventPayload) => ErrorEventPayload | null;
|
|
241
|
+
getUser?: () => FlintUser | undefined;
|
|
242
|
+
getBreadcrumbs?: () => {
|
|
243
|
+
consoleLogs: ConsoleEntry[];
|
|
244
|
+
networkErrors: NetworkEntry[];
|
|
245
|
+
};
|
|
246
|
+
getEnvironment?: () => EnvironmentInfo;
|
|
247
|
+
debug?: boolean;
|
|
248
|
+
}
|
|
249
|
+
declare function createErrorCaptureCollector(options: ErrorCaptureOptions): ErrorCaptureCollector;
|
|
250
|
+
|
|
182
251
|
interface FormErrorCollector {
|
|
183
252
|
start(): void;
|
|
184
253
|
stop(): void;
|
|
@@ -227,6 +296,7 @@ interface FlintInstance {
|
|
|
227
296
|
network: NetworkCollector | null;
|
|
228
297
|
formErrors: FormErrorCollector | null;
|
|
229
298
|
frustration: FrustrationCollector | null;
|
|
299
|
+
errorCapture: ErrorCaptureCollector | null;
|
|
230
300
|
replayEvents: unknown[];
|
|
231
301
|
stopReplay: (() => void) | null;
|
|
232
302
|
}
|
|
@@ -276,4 +346,4 @@ interface ResolvedTheme {
|
|
|
276
346
|
}
|
|
277
347
|
declare function resolveTheme(theme: Theme): ResolvedTheme;
|
|
278
348
|
|
|
279
|
-
export { type CollectedMeta, type ConsoleCollector, type ConsoleEntry, DATADOG_BLOCKED_HOSTS, type EnvironmentInfo, Flint, type FlintConfig, type FlintState, type FlintUser, type FlintWidgetProps, type FormErrorCollector, type FormErrorEntry, type FrustrationCollector, type FrustrationEvent, type Locale, type NetworkCollector, type NetworkEntry, type ReportPayload, type ReportResult, type ResolvedTheme, type Severity, type Theme, type ThemeOverride, _setFormErrorCollector, collectEnvironment, createConsoleCollector, createDatadogReplayProvider, createFormErrorCollector, createFrustrationCollector, createNetworkCollector, getSnapshot, resolveTheme, submitReplay, submitReport, subscribe };
|
|
349
|
+
export { type CollectedMeta, type ConsoleCollector, type ConsoleEntry, DATADOG_BLOCKED_HOSTS, type EnvironmentInfo, type ErrorBreadcrumbs, type ErrorCaptureCollector, type ErrorCaptureOptions, type ErrorEventPayload, Flint, type FlintConfig, type FlintState, type FlintUser, type FlintWidgetProps, type FormErrorCollector, type FormErrorEntry, type FrustrationCollector, type FrustrationEvent, type Locale, type NetworkCollector, type NetworkEntry, type ReportPayload, type ReportResult, type ResolvedTheme, type Severity, type Theme, type ThemeOverride, _setFormErrorCollector, collectEnvironment, createConsoleCollector, createDatadogReplayProvider, createErrorCaptureCollector, createFormErrorCollector, createFrustrationCollector, createNetworkCollector, getSnapshot, resolveTheme, submitReplay, submitReport, subscribe };
|
package/dist/index.js
CHANGED
|
@@ -39,6 +39,8 @@ async function submitReport(serverUrl, projectKey, payload, screenshot) {
|
|
|
39
39
|
form.append("severity", payload.severity);
|
|
40
40
|
if (payload.url) form.append("url", payload.url);
|
|
41
41
|
if (payload.meta) form.append("meta", JSON.stringify(payload.meta));
|
|
42
|
+
if (payload.appVersion) form.append("appVersion", payload.appVersion);
|
|
43
|
+
if (payload.release) form.append("release", payload.release);
|
|
42
44
|
form.append("screenshot", screenshot);
|
|
43
45
|
body = form;
|
|
44
46
|
} else {
|
|
@@ -67,8 +69,7 @@ async function submitReplay(serverUrl, projectKey, reportId, events) {
|
|
|
67
69
|
});
|
|
68
70
|
}
|
|
69
71
|
|
|
70
|
-
// src/
|
|
71
|
-
var MAX_ENTRIES = 50;
|
|
72
|
+
// src/sanitize.ts
|
|
72
73
|
var SENSITIVE_PATTERNS = [
|
|
73
74
|
/(?:password|passwd|pwd|secret|token|api[_-]?key|access[_-]?key|authorization|bearer)\s*[:=]\s*["']?[^\s"',]{4,}/gi,
|
|
74
75
|
/\b(sk-[a-zA-Z0-9_-]{20,})\b/g,
|
|
@@ -87,6 +88,9 @@ function sanitize(str) {
|
|
|
87
88
|
}
|
|
88
89
|
return result;
|
|
89
90
|
}
|
|
91
|
+
|
|
92
|
+
// src/collectors/console.ts
|
|
93
|
+
var MAX_ENTRIES = 50;
|
|
90
94
|
function createConsoleCollector() {
|
|
91
95
|
const entries = [];
|
|
92
96
|
let active = false;
|
|
@@ -206,6 +210,216 @@ function collectEnvironment() {
|
|
|
206
210
|
};
|
|
207
211
|
}
|
|
208
212
|
|
|
213
|
+
// src/collectors/errorCapture.ts
|
|
214
|
+
var MAX_MESSAGE = 1e3;
|
|
215
|
+
var MAX_STACK = 8e3;
|
|
216
|
+
var MAX_BATCH = 20;
|
|
217
|
+
var MAX_PAYLOAD_BYTES = 6e4;
|
|
218
|
+
var PER_KEY_PER_MINUTE = 10;
|
|
219
|
+
var GLOBAL_PAGE_CAP = 100;
|
|
220
|
+
var FLUSH_INTERVAL_MS = 5e3;
|
|
221
|
+
var THROTTLE_WINDOW_MS = 6e4;
|
|
222
|
+
var BREADCRUMB_CONSOLE = 10;
|
|
223
|
+
var BREADCRUMB_NETWORK = 10;
|
|
224
|
+
var DEFAULT_IGNORE = [/ResizeObserver loop/i, /^Script error\.?$/];
|
|
225
|
+
var EXTENSION_URL = /(chrome|moz|safari|safari-web)-extension:\/\//;
|
|
226
|
+
function normalizeForKey(message) {
|
|
227
|
+
return message.toLowerCase().replace(/\d+/g, "#").replace(/\s+/g, " ").trim().slice(0, 200);
|
|
228
|
+
}
|
|
229
|
+
function topFrame(stack) {
|
|
230
|
+
if (!stack) return "";
|
|
231
|
+
const lines = stack.split("\n").map((l) => l.trim());
|
|
232
|
+
return lines.find((l) => l.startsWith("at ") || /@/.test(l)) ?? "";
|
|
233
|
+
}
|
|
234
|
+
function createErrorCaptureCollector(options) {
|
|
235
|
+
const sampleRate = options.sampleRate ?? 1;
|
|
236
|
+
const ignoreList = [...DEFAULT_IGNORE, ...options.ignoreErrors ?? []];
|
|
237
|
+
const sessionId = `s_${Date.now().toString(36)}${Math.random().toString(36).slice(2, 10)}`;
|
|
238
|
+
let active = false;
|
|
239
|
+
let queue = [];
|
|
240
|
+
let interval = null;
|
|
241
|
+
let sentCount = 0;
|
|
242
|
+
let environment;
|
|
243
|
+
const keyTimestamps = /* @__PURE__ */ new Map();
|
|
244
|
+
function debugLog2(...args) {
|
|
245
|
+
if (options.debug) console.log("[Flint]", ...args);
|
|
246
|
+
}
|
|
247
|
+
function isIgnored(message, stack, frameUrl) {
|
|
248
|
+
for (const entry of ignoreList) {
|
|
249
|
+
if (typeof entry === "string") {
|
|
250
|
+
if (message.includes(entry)) return true;
|
|
251
|
+
} else if (entry.test(message)) {
|
|
252
|
+
return true;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
if (EXTENSION_URL.test(frameUrl ?? "") || EXTENSION_URL.test(stack ?? "")) return true;
|
|
256
|
+
return false;
|
|
257
|
+
}
|
|
258
|
+
function isThrottled(localKey) {
|
|
259
|
+
const now = Date.now();
|
|
260
|
+
const stamps = (keyTimestamps.get(localKey) ?? []).filter((t) => now - t < THROTTLE_WINDOW_MS);
|
|
261
|
+
if (stamps.length >= PER_KEY_PER_MINUTE) {
|
|
262
|
+
keyTimestamps.set(localKey, stamps);
|
|
263
|
+
return true;
|
|
264
|
+
}
|
|
265
|
+
stamps.push(now);
|
|
266
|
+
keyTimestamps.set(localKey, stamps);
|
|
267
|
+
return false;
|
|
268
|
+
}
|
|
269
|
+
function capture(input) {
|
|
270
|
+
try {
|
|
271
|
+
if (sentCount + queue.length >= GLOBAL_PAGE_CAP) return;
|
|
272
|
+
let message = input.message.slice(0, MAX_MESSAGE);
|
|
273
|
+
if (isIgnored(message, input.stack, input.frameUrl)) return;
|
|
274
|
+
if (sampleRate < 1 && Math.random() >= sampleRate) return;
|
|
275
|
+
const localKey = `${input.type}|${normalizeForKey(message)}|${topFrame(input.stack)}`;
|
|
276
|
+
if (isThrottled(localKey)) return;
|
|
277
|
+
const pending = queue.find((e) => e._localKey === localKey);
|
|
278
|
+
if (pending) {
|
|
279
|
+
pending.count += 1;
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
message = sanitize(message);
|
|
283
|
+
const stack = input.stack ? sanitize(input.stack.slice(0, MAX_STACK)) : void 0;
|
|
284
|
+
if (!environment && options.getEnvironment) {
|
|
285
|
+
try {
|
|
286
|
+
environment = options.getEnvironment();
|
|
287
|
+
} catch {
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
const user = options.getUser?.();
|
|
291
|
+
let event = {
|
|
292
|
+
type: input.type,
|
|
293
|
+
message,
|
|
294
|
+
errorClass: input.errorClass,
|
|
295
|
+
stack,
|
|
296
|
+
url: typeof location !== "undefined" ? location.href : "",
|
|
297
|
+
timestamp: Date.now(),
|
|
298
|
+
release: options.release,
|
|
299
|
+
appVersion: options.appVersion,
|
|
300
|
+
userId: user?.id,
|
|
301
|
+
sessionId,
|
|
302
|
+
browser: environment?.browser,
|
|
303
|
+
os: environment?.os,
|
|
304
|
+
count: 1,
|
|
305
|
+
breadcrumbs: options.getBreadcrumbs ? {
|
|
306
|
+
consoleLogs: options.getBreadcrumbs().consoleLogs.slice(-BREADCRUMB_CONSOLE),
|
|
307
|
+
networkErrors: options.getBreadcrumbs().networkErrors.slice(-BREADCRUMB_NETWORK)
|
|
308
|
+
} : void 0,
|
|
309
|
+
_localKey: localKey
|
|
310
|
+
};
|
|
311
|
+
if (options.beforeSend) {
|
|
312
|
+
try {
|
|
313
|
+
const result = options.beforeSend(event);
|
|
314
|
+
if (!result) return;
|
|
315
|
+
event = { ...result, _localKey: localKey };
|
|
316
|
+
} catch {
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
queue.push(event);
|
|
320
|
+
debugLog2("Error captured", input.errorClass, message);
|
|
321
|
+
if (queue.length >= MAX_BATCH) flush(false);
|
|
322
|
+
} catch {
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
function serialize(events) {
|
|
326
|
+
const wire = events.map(({ _localKey, ...e }) => e);
|
|
327
|
+
let body = JSON.stringify(wire);
|
|
328
|
+
if (body.length > MAX_PAYLOAD_BYTES) {
|
|
329
|
+
body = JSON.stringify(wire.map((e) => ({ ...e, breadcrumbs: void 0 })));
|
|
330
|
+
if (body.length > MAX_PAYLOAD_BYTES) {
|
|
331
|
+
body = JSON.stringify(wire.map((e) => ({ ...e, breadcrumbs: void 0, stack: e.stack?.slice(0, 2e3) })));
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
return body;
|
|
335
|
+
}
|
|
336
|
+
function flush(unloading) {
|
|
337
|
+
if (queue.length === 0) return;
|
|
338
|
+
const events = queue;
|
|
339
|
+
queue = [];
|
|
340
|
+
sentCount += events.length;
|
|
341
|
+
const base = options.serverUrl.replace(/\/$/, "");
|
|
342
|
+
const url = `${base}/api/v1/error-events?project_key=${encodeURIComponent(options.projectKey)}`;
|
|
343
|
+
const body = serialize(events);
|
|
344
|
+
if (unloading && typeof navigator !== "undefined" && typeof navigator.sendBeacon === "function") {
|
|
345
|
+
const ok = navigator.sendBeacon(url, body);
|
|
346
|
+
debugLog2("Flushed via beacon", events.length, ok);
|
|
347
|
+
if (ok) return;
|
|
348
|
+
}
|
|
349
|
+
fetch(url, {
|
|
350
|
+
method: "POST",
|
|
351
|
+
headers: { "Content-Type": "text/plain;charset=UTF-8" },
|
|
352
|
+
body,
|
|
353
|
+
keepalive: unloading
|
|
354
|
+
}).catch(() => {
|
|
355
|
+
});
|
|
356
|
+
debugLog2("Flushed via fetch", events.length);
|
|
357
|
+
}
|
|
358
|
+
function onError(event) {
|
|
359
|
+
const e = event;
|
|
360
|
+
if (typeof e.message !== "string" && !(e.error instanceof Error)) return;
|
|
361
|
+
const err = e.error instanceof Error ? e.error : void 0;
|
|
362
|
+
capture({
|
|
363
|
+
type: "error",
|
|
364
|
+
message: err?.message ?? (e.message || "Unknown error"),
|
|
365
|
+
errorClass: err?.name ?? "Error",
|
|
366
|
+
stack: err?.stack,
|
|
367
|
+
frameUrl: e.filename
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
function onRejection(event) {
|
|
371
|
+
const reason = event.reason;
|
|
372
|
+
const err = reason instanceof Error ? reason : void 0;
|
|
373
|
+
let message;
|
|
374
|
+
if (err) {
|
|
375
|
+
message = err.message;
|
|
376
|
+
} else {
|
|
377
|
+
try {
|
|
378
|
+
message = typeof reason === "string" ? reason : JSON.stringify(reason);
|
|
379
|
+
} catch {
|
|
380
|
+
message = String(reason);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
capture({
|
|
384
|
+
type: "unhandledrejection",
|
|
385
|
+
message: message || "Unhandled promise rejection",
|
|
386
|
+
errorClass: err?.name ?? "UnhandledRejection",
|
|
387
|
+
stack: err?.stack
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
function onPageHide() {
|
|
391
|
+
flush(true);
|
|
392
|
+
}
|
|
393
|
+
function onVisibilityChange() {
|
|
394
|
+
if (document.visibilityState === "hidden") flush(true);
|
|
395
|
+
}
|
|
396
|
+
return {
|
|
397
|
+
start() {
|
|
398
|
+
if (active) return;
|
|
399
|
+
active = true;
|
|
400
|
+
window.addEventListener("error", onError, { capture: true });
|
|
401
|
+
window.addEventListener("unhandledrejection", onRejection, { capture: true });
|
|
402
|
+
window.addEventListener("pagehide", onPageHide);
|
|
403
|
+
document.addEventListener("visibilitychange", onVisibilityChange);
|
|
404
|
+
interval = setInterval(() => flush(false), FLUSH_INTERVAL_MS);
|
|
405
|
+
},
|
|
406
|
+
stop() {
|
|
407
|
+
if (!active) return;
|
|
408
|
+
active = false;
|
|
409
|
+
window.removeEventListener("error", onError, { capture: true });
|
|
410
|
+
window.removeEventListener("unhandledrejection", onRejection, { capture: true });
|
|
411
|
+
window.removeEventListener("pagehide", onPageHide);
|
|
412
|
+
document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
413
|
+
if (interval) clearInterval(interval);
|
|
414
|
+
interval = null;
|
|
415
|
+
flush(false);
|
|
416
|
+
},
|
|
417
|
+
flush() {
|
|
418
|
+
flush(false);
|
|
419
|
+
}
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
|
|
209
423
|
// src/collectors/formErrors.ts
|
|
210
424
|
var MAX_ENTRIES2 = 30;
|
|
211
425
|
var POST_SUBMIT_CHECK_MS = 300;
|
|
@@ -900,6 +1114,8 @@ function init(config) {
|
|
|
900
1114
|
enableFormErrors = true,
|
|
901
1115
|
enableFrustration = false,
|
|
902
1116
|
autoReportFrustration = false,
|
|
1117
|
+
enableErrorMonitoring = true,
|
|
1118
|
+
errorMonitoring: errorMonitoringOpts,
|
|
903
1119
|
enableReplay = false,
|
|
904
1120
|
replayBufferMs = DEFAULT_REPLAY_BUFFER_MS,
|
|
905
1121
|
blockedHosts = [],
|
|
@@ -935,6 +1151,23 @@ function init(config) {
|
|
|
935
1151
|
}
|
|
936
1152
|
const frustrationCol = enableFrustration ? createFrustrationCollector(frustrationOpts) : null;
|
|
937
1153
|
frustrationCol?.start();
|
|
1154
|
+
const errorCaptureCol = enableErrorMonitoring ? createErrorCaptureCollector({
|
|
1155
|
+
serverUrl: config.serverUrl,
|
|
1156
|
+
projectKey: config.projectKey,
|
|
1157
|
+
release: config.release,
|
|
1158
|
+
appVersion: config.appVersion,
|
|
1159
|
+
debug: config.debug,
|
|
1160
|
+
sampleRate: errorMonitoringOpts?.sampleRate,
|
|
1161
|
+
ignoreErrors: errorMonitoringOpts?.ignoreErrors,
|
|
1162
|
+
beforeSend: errorMonitoringOpts?.beforeSend,
|
|
1163
|
+
getUser: () => getSnapshot().user ?? config.user,
|
|
1164
|
+
getBreadcrumbs: () => ({
|
|
1165
|
+
consoleLogs: consoleCol?.getEntries() ?? [],
|
|
1166
|
+
networkErrors: networkCol?.getEntries() ?? []
|
|
1167
|
+
}),
|
|
1168
|
+
getEnvironment: _collectors?.environment ?? collectEnvironment
|
|
1169
|
+
}) : null;
|
|
1170
|
+
errorCaptureCol?.start();
|
|
938
1171
|
if (config.user) {
|
|
939
1172
|
flint.setUser(config.user);
|
|
940
1173
|
}
|
|
@@ -944,7 +1177,8 @@ function init(config) {
|
|
|
944
1177
|
console: !!consoleCol,
|
|
945
1178
|
network: !!networkCol,
|
|
946
1179
|
formErrors: !!formErrorsCol,
|
|
947
|
-
frustration: !!frustrationCol
|
|
1180
|
+
frustration: !!frustrationCol,
|
|
1181
|
+
errorCapture: !!errorCaptureCol
|
|
948
1182
|
});
|
|
949
1183
|
instance = {
|
|
950
1184
|
config,
|
|
@@ -952,6 +1186,7 @@ function init(config) {
|
|
|
952
1186
|
network: networkCol,
|
|
953
1187
|
formErrors: formErrorsCol,
|
|
954
1188
|
frustration: frustrationCol,
|
|
1189
|
+
errorCapture: errorCaptureCol,
|
|
955
1190
|
replayEvents,
|
|
956
1191
|
stopReplay: null
|
|
957
1192
|
};
|
|
@@ -981,6 +1216,8 @@ function init(config) {
|
|
|
981
1216
|
severity: event.type === "error_loop" ? "P1" : event.type === "rage_click" ? "P2" : "P3",
|
|
982
1217
|
url: event.url,
|
|
983
1218
|
source: "auto_capture",
|
|
1219
|
+
appVersion: config.appVersion,
|
|
1220
|
+
release: config.release,
|
|
984
1221
|
meta: {
|
|
985
1222
|
...config.meta,
|
|
986
1223
|
environment: getEnvironment(),
|
|
@@ -1030,6 +1267,7 @@ function shutdown() {
|
|
|
1030
1267
|
instance.formErrors?.stop();
|
|
1031
1268
|
_setFormErrorCollector(null);
|
|
1032
1269
|
instance.frustration?.stop();
|
|
1270
|
+
instance.errorCapture?.stop();
|
|
1033
1271
|
instance.stopReplay?.();
|
|
1034
1272
|
instance = null;
|
|
1035
1273
|
}
|
|
@@ -1120,6 +1358,7 @@ export {
|
|
|
1120
1358
|
collectEnvironment,
|
|
1121
1359
|
createConsoleCollector,
|
|
1122
1360
|
createDatadogReplayProvider,
|
|
1361
|
+
createErrorCaptureCollector,
|
|
1123
1362
|
createFormErrorCollector,
|
|
1124
1363
|
createFrustrationCollector,
|
|
1125
1364
|
createNetworkCollector,
|