rusty-replay 1.0.7 → 1.0.8
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 +82 -54
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -6
- package/dist/index.d.ts +2 -6
- package/dist/index.js +81 -52
- package/dist/index.js.map +1 -1
- package/package.json +4 -2
package/dist/index.cjs
CHANGED
@@ -51,33 +51,6 @@ var init_cjs_shims = __esm({
|
|
51
51
|
}
|
52
52
|
});
|
53
53
|
|
54
|
-
// src/recorder.ts
|
55
|
-
function startRecording() {
|
56
|
-
events = [];
|
57
|
-
(0, import_rrweb.record)({
|
58
|
-
emit(event) {
|
59
|
-
events.push(event);
|
60
|
-
if (events.length > MAX_EVENTS) {
|
61
|
-
events = events.slice(-MAX_EVENTS);
|
62
|
-
}
|
63
|
-
}
|
64
|
-
});
|
65
|
-
}
|
66
|
-
function getRecordedEvents(beforeErrorSec = 30) {
|
67
|
-
const now = Date.now();
|
68
|
-
return events.filter((e) => now - e.timestamp < beforeErrorSec * 1e3);
|
69
|
-
}
|
70
|
-
var import_rrweb, events, MAX_EVENTS;
|
71
|
-
var init_recorder = __esm({
|
72
|
-
"src/recorder.ts"() {
|
73
|
-
"use strict";
|
74
|
-
init_cjs_shims();
|
75
|
-
import_rrweb = require("rrweb");
|
76
|
-
events = [];
|
77
|
-
MAX_EVENTS = 1e3;
|
78
|
-
}
|
79
|
-
});
|
80
|
-
|
81
54
|
// src/environment.ts
|
82
55
|
function getBrowserInfo() {
|
83
56
|
const ua = navigator.userAgent;
|
@@ -150,6 +123,11 @@ var init_error_batcher = __esm({
|
|
150
123
|
this.opts.endpoint,
|
151
124
|
{ events: batch },
|
152
125
|
{
|
126
|
+
maxBodyLength: 1e3 * 1024 * 1024,
|
127
|
+
// 10MB
|
128
|
+
maxContentLength: 1e3 * 1024 * 1024,
|
129
|
+
// 10MB
|
130
|
+
timeout: 3e4,
|
153
131
|
headers: {
|
154
132
|
"Content-Type": "application/json",
|
155
133
|
Authorization: `Bearer ${this.opts.apiKey}`
|
@@ -181,6 +159,58 @@ var init_error_batcher = __esm({
|
|
181
159
|
}
|
182
160
|
});
|
183
161
|
|
162
|
+
// src/recorder.ts
|
163
|
+
function startRecording() {
|
164
|
+
events = [];
|
165
|
+
stopFn == null ? void 0 : stopFn();
|
166
|
+
stopFn = (0, import_rrweb.record)({
|
167
|
+
emit(event) {
|
168
|
+
if (event.type === 2) console.log("[rrweb] FullSnapshot \uAE30\uB85D\uB428:", event);
|
169
|
+
events.push(event);
|
170
|
+
if (events.length > MAX_EVENTS) {
|
171
|
+
events = events.slice(-MAX_EVENTS);
|
172
|
+
}
|
173
|
+
},
|
174
|
+
// checkoutEveryNms: 1000, // 1초마다 체크아웃
|
175
|
+
checkoutEveryNms: 15e3,
|
176
|
+
// 15초마다 한 번
|
177
|
+
checkoutEveryNth: 100
|
178
|
+
// 100개 이벤트마다 한 번
|
179
|
+
// packFn: pack,
|
180
|
+
});
|
181
|
+
}
|
182
|
+
function getRecordedEvents(beforeErrorSec = 10, errorTime = Date.now(), source = events) {
|
183
|
+
const sliced = source.filter(
|
184
|
+
(e) => errorTime - e.timestamp < beforeErrorSec * 1e3
|
185
|
+
);
|
186
|
+
const snapshotCandidates = source.filter((e) => e.type === 2);
|
187
|
+
const lastSnapshot = [...snapshotCandidates].reverse().find((e) => e.timestamp <= errorTime);
|
188
|
+
if (lastSnapshot && !sliced.includes(lastSnapshot)) {
|
189
|
+
return [lastSnapshot, ...sliced];
|
190
|
+
}
|
191
|
+
if (!sliced.some((e) => e.type === 2)) {
|
192
|
+
console.warn("\u26A0\uFE0F Snapshot \uC5C6\uC774 \uC798\uB9B0 replay\uC785\uB2C8\uB2E4. \uBCF5\uC6D0 \uBD88\uAC00\uB2A5\uD560 \uC218 \uC788\uC74C.");
|
193
|
+
}
|
194
|
+
return sliced;
|
195
|
+
}
|
196
|
+
function clearEvents() {
|
197
|
+
events = [];
|
198
|
+
}
|
199
|
+
function getCurrentEvents() {
|
200
|
+
return events.slice();
|
201
|
+
}
|
202
|
+
var import_rrweb, events, MAX_EVENTS, stopFn;
|
203
|
+
var init_recorder = __esm({
|
204
|
+
"src/recorder.ts"() {
|
205
|
+
"use strict";
|
206
|
+
init_cjs_shims();
|
207
|
+
import_rrweb = require("rrweb");
|
208
|
+
events = [];
|
209
|
+
MAX_EVENTS = 1e3;
|
210
|
+
stopFn = void 0;
|
211
|
+
}
|
212
|
+
});
|
213
|
+
|
184
214
|
// src/handler.ts
|
185
215
|
var handler_exports = {};
|
186
216
|
__export(handler_exports, {
|
@@ -215,20 +245,38 @@ var init_handler = __esm({
|
|
215
245
|
// src/reporter.ts
|
216
246
|
function init(options) {
|
217
247
|
var _a;
|
218
|
-
|
219
|
-
globalOpts.beforeErrorSec = (_a = options.beforeErrorSec) != null ? _a : 30;
|
248
|
+
globalOpts.beforeErrorSec = (_a = options.beforeErrorSec) != null ? _a : 10;
|
220
249
|
batcher = new ErrorBatcher({
|
221
250
|
endpoint: options.endpoint,
|
222
251
|
apiKey: options.apiKey,
|
223
252
|
flushIntervalMs: options.flushIntervalMs,
|
224
253
|
maxBufferSize: options.maxBufferSize
|
225
254
|
});
|
226
|
-
|
255
|
+
if (typeof window !== "undefined") {
|
256
|
+
const start = () => {
|
257
|
+
startRecording();
|
258
|
+
Promise.resolve().then(() => (init_handler(), handler_exports)).then((mod) => mod.setupGlobalErrorHandler());
|
259
|
+
};
|
260
|
+
if (document.readyState === "complete") {
|
261
|
+
requestAnimationFrame(() => startRecording());
|
262
|
+
} else {
|
263
|
+
window.addEventListener("load", () => {
|
264
|
+
requestAnimationFrame(() => startRecording());
|
265
|
+
});
|
266
|
+
}
|
267
|
+
}
|
227
268
|
}
|
228
269
|
function captureException(error, additionalInfo, userId) {
|
229
270
|
var _a, _b;
|
271
|
+
const errorTime = Date.now();
|
272
|
+
const eventsSnapshot = getCurrentEvents();
|
273
|
+
const replay = getRecordedEvents(
|
274
|
+
globalOpts.beforeErrorSec,
|
275
|
+
errorTime,
|
276
|
+
eventsSnapshot
|
277
|
+
);
|
278
|
+
clearEvents();
|
230
279
|
const { browser, os, userAgent } = getBrowserInfo();
|
231
|
-
const replay = getRecordedEvents(globalOpts.beforeErrorSec);
|
232
280
|
return batcher.capture({
|
233
281
|
message: (_a = error.message) != null ? _a : "",
|
234
282
|
stacktrace: (_b = error.stack) != null ? _b : "",
|
@@ -243,32 +291,14 @@ function captureException(error, additionalInfo, userId) {
|
|
243
291
|
apiKey: batcher.getApiKey()
|
244
292
|
});
|
245
293
|
}
|
246
|
-
function wrap(fn, info) {
|
247
|
-
return (...args) => {
|
248
|
-
try {
|
249
|
-
return fn(...args);
|
250
|
-
} catch (err) {
|
251
|
-
if (err instanceof Error) {
|
252
|
-
captureException(err, info == null ? void 0 : info.additionalInfo, info == null ? void 0 : info.userId);
|
253
|
-
} else {
|
254
|
-
captureException(
|
255
|
-
new Error(String(err)),
|
256
|
-
info == null ? void 0 : info.additionalInfo,
|
257
|
-
info == null ? void 0 : info.userId
|
258
|
-
);
|
259
|
-
}
|
260
|
-
throw err;
|
261
|
-
}
|
262
|
-
};
|
263
|
-
}
|
264
294
|
var batcher, globalOpts;
|
265
295
|
var init_reporter = __esm({
|
266
296
|
"src/reporter.ts"() {
|
267
297
|
"use strict";
|
268
298
|
init_cjs_shims();
|
269
|
-
init_recorder();
|
270
299
|
init_environment();
|
271
300
|
init_error_batcher();
|
301
|
+
init_recorder();
|
272
302
|
globalOpts = { beforeErrorSec: 30 };
|
273
303
|
}
|
274
304
|
});
|
@@ -283,8 +313,7 @@ __export(index_exports, {
|
|
283
313
|
getRecordedEvents: () => getRecordedEvents,
|
284
314
|
init: () => init,
|
285
315
|
setupGlobalErrorHandler: () => setupGlobalErrorHandler,
|
286
|
-
startRecording: () => startRecording
|
287
|
-
wrap: () => wrap
|
316
|
+
startRecording: () => startRecording
|
288
317
|
});
|
289
318
|
module.exports = __toCommonJS(index_exports);
|
290
319
|
init_cjs_shims();
|
@@ -302,7 +331,6 @@ init_error_batcher();
|
|
302
331
|
getRecordedEvents,
|
303
332
|
init,
|
304
333
|
setupGlobalErrorHandler,
|
305
|
-
startRecording
|
306
|
-
wrap
|
334
|
+
startRecording
|
307
335
|
});
|
308
336
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../../node_modules/.pnpm/tsup@8.4.0_jiti@2.4.2_postcss@8.5.3_typescript@5.8.3/node_modules/tsup/assets/cjs_shims.js","../src/recorder.ts","../src/environment.ts","../src/error-batcher.ts","../src/handler.ts","../src/reporter.ts","../src/index.ts"],"sourcesContent":["// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () =>\n typeof document === 'undefined'\n ? new URL(`file:${__filename}`).href\n : (document.currentScript && document.currentScript.src) ||\n new URL('main.js', document.baseURI).href\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","import type { eventWithTime } from '@rrweb/types';\nimport { record } from 'rrweb';\n\nlet events: eventWithTime[] = [];\nconst MAX_EVENTS = 1000;\n\nexport function startRecording() {\n events = [];\n record({\n emit(event) {\n events.push(event);\n if (events.length > MAX_EVENTS) {\n events = events.slice(-MAX_EVENTS);\n }\n },\n });\n}\n\nexport function getRecordedEvents(beforeErrorSec = 30): eventWithTime[] {\n const now = Date.now();\n return events.filter((e) => now - e.timestamp < beforeErrorSec * 1000);\n}\n","export function getBrowserInfo() {\n const ua = navigator.userAgent;\n let browser = 'unknown',\n os = 'unknown';\n\n if (ua.includes('Firefox')) browser = 'Firefox';\n else if (ua.includes('SamsungBrowser')) browser = 'Samsung Browser';\n else if (ua.includes('Opera') || ua.includes('OPR')) browser = 'Opera';\n else if (ua.includes('Trident')) browser = 'IE';\n else if (ua.includes('Edge')) browser = 'Edge (Legacy)';\n else if (ua.includes('Edg')) browser = 'Edge';\n else if (ua.includes('Chrome')) browser = 'Chrome';\n else if (ua.includes('Safari')) browser = 'Safari';\n\n if (ua.includes('Windows')) os = 'Windows';\n else if (ua.includes('Mac')) os = 'macOS';\n else if (ua.includes('Linux')) os = 'Linux';\n else if (ua.includes('Android')) os = 'Android';\n else if (ua.includes('like Mac')) os = 'iOS';\n\n return { browser, os, userAgent: ua };\n}\n\nexport function getEnvironment(): 'development' | 'staging' | 'production' {\n if (process.env.NODE_ENV === 'development') return 'development';\n if (process.env.NEXT_PUBLIC_VERCEL_ENV === 'preview') return 'staging';\n return 'production';\n}\n","import axios from 'axios';\nimport type { BatcherOptions, BatchedEvent } from './reporter';\n\nexport class ErrorBatcher {\n private queue: BatchedEvent[] = [];\n private isFlushing = false;\n private flushTimer: number;\n private readonly apiKey: string;\n\n constructor(private opts: BatcherOptions) {\n this.apiKey = opts.apiKey;\n const interval = opts.flushIntervalMs ?? 3000;\n this.flushTimer = window.setInterval(() => this.flush(), interval);\n window.addEventListener('beforeunload', () => this.flushOnUnload());\n }\n\n public getApiKey(): string {\n return this.apiKey;\n }\n\n public capture(evt: Omit<BatchedEvent, 'id' | 'timestamp'>): string {\n const id = this.makeId();\n const timestamp = new Date().toISOString();\n const record: BatchedEvent = { id, timestamp, ...evt };\n\n if (this.queue.length >= (this.opts.maxBufferSize ?? 64)) {\n this.queue.shift();\n }\n this.queue.push(record);\n return id;\n }\n\n private async flush() {\n if (this.isFlushing || this.queue.length === 0) return;\n this.isFlushing = true;\n\n const batch = this.queue.splice(0, this.queue.length);\n try {\n await axios.post(\n this.opts.endpoint,\n { events: batch },\n {\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.opts.apiKey}`,\n },\n }\n );\n } catch {\n this.queue.unshift(...batch);\n } finally {\n this.isFlushing = false;\n }\n }\n\n private flushOnUnload() {\n if (!navigator.sendBeacon || this.queue.length === 0) return;\n const payload = JSON.stringify({ events: this.queue });\n navigator.sendBeacon(this.opts.endpoint, payload);\n }\n\n private makeId() {\n return 'xxxx-xxxx-4xxx-yxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n\n public destroy() {\n clearInterval(this.flushTimer);\n }\n}\n","import { captureException } from './reporter';\n\nexport function setupGlobalErrorHandler() {\n if ((window as any).__errorHandlerSetup) return;\n\n const origOnError = window.onerror;\n window.onerror = function thisWindowOnError(\n this: Window & WindowEventHandlers,\n message: string | Event,\n source?: string,\n lineno?: number,\n colno?: number,\n error?: Error\n ): boolean {\n origOnError?.call(this, message, source, lineno, colno, error);\n captureException(\n error ??\n new Error(typeof message === 'string' ? message : 'Unknown error')\n );\n return false;\n };\n\n const origOnUnhandledRejection = window.onunhandledrejection;\n window.onunhandledrejection = function thisWindowOnRejection(\n this: Window & WindowEventHandlers,\n event: PromiseRejectionEvent\n ): any {\n origOnUnhandledRejection?.call(this, event);\n const err =\n event.reason instanceof Error\n ? event.reason\n : new Error(JSON.stringify(event.reason));\n captureException(err);\n } as typeof window.onunhandledrejection;\n\n (window as any).__errorHandlerSetup = true;\n}\n","import { startRecording, getRecordedEvents } from './recorder';\nimport { getBrowserInfo, getEnvironment } from './environment';\nimport { ErrorBatcher } from './error-batcher';\n\nexport interface BatchedEvent {\n id: string;\n timestamp: string;\n message: string;\n stacktrace: string;\n replay: any[];\n environment: string;\n browser: string;\n os: string;\n userAgent: string;\n userId?: number;\n additionalInfo?: Record<string, any>;\n appVersion: string;\n apiKey: string;\n}\n\nexport interface BatcherOptions {\n endpoint: string;\n apiKey: string;\n flushIntervalMs?: number;\n maxBufferSize?: number;\n}\n\nexport interface InitOptions {\n endpoint: string;\n apiKey: string;\n flushIntervalMs?: number;\n maxBufferSize?: number;\n beforeErrorSec?: number;\n}\n\nlet batcher: ErrorBatcher;\nlet globalOpts: { beforeErrorSec: number } = { beforeErrorSec: 30 };\n\nexport function init(options: InitOptions) {\n startRecording();\n globalOpts.beforeErrorSec = options.beforeErrorSec ?? 30;\n batcher = new ErrorBatcher({\n endpoint: options.endpoint,\n apiKey: options.apiKey,\n flushIntervalMs: options.flushIntervalMs,\n maxBufferSize: options.maxBufferSize,\n });\n import('./handler.js').then((mod) => mod.setupGlobalErrorHandler());\n}\n\nexport function captureException(\n error: Error,\n additionalInfo?: Record<string, any>,\n userId?: number\n): string {\n const { browser, os, userAgent } = getBrowserInfo();\n const replay = getRecordedEvents(globalOpts.beforeErrorSec);\n return batcher.capture({\n message: error.message ?? '',\n stacktrace: error.stack ?? '',\n replay,\n environment: getEnvironment(),\n browser,\n os,\n userAgent,\n userId,\n additionalInfo,\n appVersion: '1.0.0',\n apiKey: batcher.getApiKey(),\n });\n}\n\nexport function wrap<T extends (...args: any[]) => any>(\n fn: T,\n info?: { additionalInfo?: Record<string, any>; userId?: number }\n): (...args: Parameters<T>) => ReturnType<T> {\n return (...args) => {\n try {\n return fn(...args);\n } catch (err) {\n if (err instanceof Error) {\n captureException(err, info?.additionalInfo, info?.userId);\n } else {\n captureException(\n new Error(String(err)),\n info?.additionalInfo,\n info?.userId\n );\n }\n throw err;\n }\n };\n}\n","export * from './reporter';\nexport { setupGlobalErrorHandler } from './handler';\nexport { startRecording, getRecordedEvents } from './recorder';\nexport { getBrowserInfo, getEnvironment } from './environment';\nexport { ErrorBatcher } from './error-batcher';\nexport type { BatchedEvent, InitOptions } from './reporter';\n"],"mappings":"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","names":["record","axios"]}
|
1
|
+
{"version":3,"sources":["../../../node_modules/.pnpm/tsup@8.4.0_jiti@2.4.2_postcss@8.5.3_typescript@5.8.3/node_modules/tsup/assets/cjs_shims.js","../src/environment.ts","../src/error-batcher.ts","../src/recorder.ts","../src/handler.ts","../src/reporter.ts","../src/index.ts"],"sourcesContent":["// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () =>\n typeof document === 'undefined'\n ? new URL(`file:${__filename}`).href\n : (document.currentScript && document.currentScript.src) ||\n new URL('main.js', document.baseURI).href\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","export function getBrowserInfo() {\n const ua = navigator.userAgent;\n let browser = 'unknown',\n os = 'unknown';\n\n if (ua.includes('Firefox')) browser = 'Firefox';\n else if (ua.includes('SamsungBrowser')) browser = 'Samsung Browser';\n else if (ua.includes('Opera') || ua.includes('OPR')) browser = 'Opera';\n else if (ua.includes('Trident')) browser = 'IE';\n else if (ua.includes('Edge')) browser = 'Edge (Legacy)';\n else if (ua.includes('Edg')) browser = 'Edge';\n else if (ua.includes('Chrome')) browser = 'Chrome';\n else if (ua.includes('Safari')) browser = 'Safari';\n\n if (ua.includes('Windows')) os = 'Windows';\n else if (ua.includes('Mac')) os = 'macOS';\n else if (ua.includes('Linux')) os = 'Linux';\n else if (ua.includes('Android')) os = 'Android';\n else if (ua.includes('like Mac')) os = 'iOS';\n\n return { browser, os, userAgent: ua };\n}\n\nexport function getEnvironment(): 'development' | 'staging' | 'production' {\n if (process.env.NODE_ENV === 'development') return 'development';\n if (process.env.NEXT_PUBLIC_VERCEL_ENV === 'preview') return 'staging';\n return 'production';\n}\n","import axios from 'axios';\nimport type { BatcherOptions, BatchedEvent } from './reporter';\n\nexport class ErrorBatcher {\n private queue: BatchedEvent[] = [];\n private isFlushing = false;\n private flushTimer: number;\n private readonly apiKey: string;\n\n constructor(private opts: BatcherOptions) {\n this.apiKey = opts.apiKey;\n const interval = opts.flushIntervalMs ?? 3000;\n this.flushTimer = window.setInterval(() => this.flush(), interval);\n window.addEventListener('beforeunload', () => this.flushOnUnload());\n }\n\n public getApiKey(): string {\n return this.apiKey;\n }\n\n public capture(evt: Omit<BatchedEvent, 'id' | 'timestamp'>): string {\n const id = this.makeId();\n const timestamp = new Date().toISOString();\n const record: BatchedEvent = { id, timestamp, ...evt };\n\n if (this.queue.length >= (this.opts.maxBufferSize ?? 64)) {\n this.queue.shift();\n }\n this.queue.push(record);\n return id;\n }\n\n private async flush() {\n if (this.isFlushing || this.queue.length === 0) return;\n this.isFlushing = true;\n\n const batch = this.queue.splice(0, this.queue.length);\n try {\n await axios.post(\n this.opts.endpoint,\n { events: batch },\n {\n maxBodyLength: 1000 * 1024 * 1024, // 10MB\n maxContentLength: 1000 * 1024 * 1024, // 10MB\n timeout: 30000,\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.opts.apiKey}`,\n },\n }\n );\n } catch {\n this.queue.unshift(...batch);\n } finally {\n this.isFlushing = false;\n }\n }\n\n private flushOnUnload() {\n if (!navigator.sendBeacon || this.queue.length === 0) return;\n const payload = JSON.stringify({ events: this.queue });\n navigator.sendBeacon(this.opts.endpoint, payload);\n }\n\n private makeId() {\n return 'xxxx-xxxx-4xxx-yxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n\n public destroy() {\n clearInterval(this.flushTimer);\n }\n}\n","import type { eventWithTime, listenerHandler } from '@rrweb/types';\nimport { record } from 'rrweb';\nimport { pack } from '@rrweb/packer';\n\nlet events: eventWithTime[] = [];\nconst MAX_EVENTS = 1000;\nlet stopFn: listenerHandler | undefined = undefined;\n\nexport function startRecording() {\n events = [];\n stopFn?.();\n stopFn = record({\n emit(event) {\n if (event.type === 2) console.log('[rrweb] FullSnapshot 기록됨:', event);\n\n events.push(event);\n if (events.length > MAX_EVENTS) {\n events = events.slice(-MAX_EVENTS);\n }\n },\n // checkoutEveryNms: 1000, // 1초마다 체크아웃\n checkoutEveryNms: 15000, // 15초마다 한 번\n checkoutEveryNth: 100, // 100개 이벤트마다 한 번\n // packFn: pack,\n });\n}\n\nexport function getRecordedEvents(\n beforeErrorSec = 10,\n errorTime = Date.now(),\n source = events\n): eventWithTime[] {\n const sliced = source.filter(\n (e) => errorTime - e.timestamp < beforeErrorSec * 1000\n );\n\n const snapshotCandidates = source.filter((e) => e.type === 2);\n const lastSnapshot = [...snapshotCandidates]\n .reverse()\n .find((e) => e.timestamp <= errorTime);\n\n if (lastSnapshot && !sliced.includes(lastSnapshot)) {\n return [lastSnapshot, ...sliced];\n }\n\n if (!sliced.some((e) => e.type === 2)) {\n console.warn('⚠️ Snapshot 없이 잘린 replay입니다. 복원 불가능할 수 있음.');\n }\n\n return sliced;\n}\n\n// export function getRecordedEvents(\n// beforeErrorSec = 10,\n// errorTime = Date.now(),\n// source = events\n// ): eventWithTime[] {\n// const sliced = source.filter(\n// (e) => errorTime - e.timestamp < beforeErrorSec * 1000\n// );\n\n// const fullSnapshots = source.filter((e) => e.type === 2);\n// const lastSnapshot = fullSnapshots.reverse().find(\n// (e) => e.timestamp <= sliced[0]?.timestamp\n// );\n// // const lastSnapshot = fullSnapshots\n// // .reverse()\n// // .find((e) => e.timestamp <= (sliced[0]?.timestamp ?? errorTime));\n\n// if (lastSnapshot && !sliced.includes(lastSnapshot)) {\n// return [lastSnapshot, ...sliced];\n// }\n\n// if (!sliced.some((e) => e.type === 2)) {\n// console.warn('⚠️ Snapshot 없이 잘린 replay입니다. 복원 불가능할 수 있음.');\n// }\n\n// return sliced;\n// }\n\nexport function clearEvents() {\n events = [];\n}\n\nexport function getCurrentEvents(): eventWithTime[] {\n return events.slice();\n}\n","import { captureException } from './reporter';\n\nexport function setupGlobalErrorHandler() {\n if ((window as any).__errorHandlerSetup) return;\n\n const origOnError = window.onerror;\n window.onerror = function thisWindowOnError(\n this: Window & WindowEventHandlers,\n message: string | Event,\n source?: string,\n lineno?: number,\n colno?: number,\n error?: Error\n ): boolean {\n origOnError?.call(this, message, source, lineno, colno, error);\n captureException(\n error ??\n new Error(typeof message === 'string' ? message : 'Unknown error')\n );\n return false;\n };\n\n const origOnUnhandledRejection = window.onunhandledrejection;\n window.onunhandledrejection = function thisWindowOnRejection(\n this: Window & WindowEventHandlers,\n event: PromiseRejectionEvent\n ): any {\n origOnUnhandledRejection?.call(this, event);\n const err =\n event.reason instanceof Error\n ? event.reason\n : new Error(JSON.stringify(event.reason));\n captureException(err);\n } as typeof window.onunhandledrejection;\n\n (window as any).__errorHandlerSetup = true;\n}\n","import { getBrowserInfo, getEnvironment } from './environment';\nimport { ErrorBatcher } from './error-batcher';\nimport {\n startRecording,\n getRecordedEvents,\n getCurrentEvents,\n clearEvents,\n} from './recorder';\n\nexport interface BatchedEvent {\n id: string;\n timestamp: string;\n message: string;\n stacktrace: string;\n replay: any[];\n environment: string;\n browser: string;\n os: string;\n userAgent: string;\n userId?: number;\n additionalInfo?: Record<string, any>;\n appVersion: string;\n apiKey: string;\n}\n\nexport interface BatcherOptions {\n endpoint: string;\n apiKey: string;\n flushIntervalMs?: number;\n maxBufferSize?: number;\n}\n\nexport interface InitOptions {\n endpoint: string;\n apiKey: string;\n flushIntervalMs?: number;\n maxBufferSize?: number;\n beforeErrorSec?: number;\n}\n\nlet batcher: ErrorBatcher;\nlet globalOpts: { beforeErrorSec: number } = { beforeErrorSec: 30 };\n\nexport function init(options: InitOptions) {\n globalOpts.beforeErrorSec = options.beforeErrorSec ?? 10;\n\n batcher = new ErrorBatcher({\n endpoint: options.endpoint,\n apiKey: options.apiKey,\n flushIntervalMs: options.flushIntervalMs,\n maxBufferSize: options.maxBufferSize,\n });\n\n if (typeof window !== 'undefined') {\n const start = () => {\n startRecording(); // DOM 렌더링 후에 시작되도록 지연 실행\n import('./handler.js').then((mod) => mod.setupGlobalErrorHandler());\n };\n\n if (document.readyState === 'complete') {\n requestAnimationFrame(() => startRecording());\n } else {\n window.addEventListener('load', () => {\n requestAnimationFrame(() => startRecording());\n });\n }\n\n // if ('requestIdleCallback' in window) {\n // window.requestIdleCallback(start);\n // } else {\n // setTimeout(start, 100);\n // }\n }\n}\n\nexport function captureException(\n error: Error,\n additionalInfo?: Record<string, any>,\n userId?: number\n): string {\n const errorTime = Date.now();\n const eventsSnapshot = getCurrentEvents();\n const replay = getRecordedEvents(\n globalOpts.beforeErrorSec,\n errorTime,\n eventsSnapshot\n );\n\n clearEvents(); // 다음 에러 기록을 위해 초기화\n\n const { browser, os, userAgent } = getBrowserInfo();\n\n return batcher.capture({\n message: error.message ?? '',\n stacktrace: error.stack ?? '',\n replay,\n environment: getEnvironment(),\n browser,\n os,\n userAgent,\n userId,\n additionalInfo,\n appVersion: '1.0.0',\n apiKey: batcher.getApiKey(),\n });\n}\n","export * from './reporter';\nexport { setupGlobalErrorHandler } from './handler';\nexport { startRecording, getRecordedEvents } from './recorder';\nexport { getBrowserInfo, getEnvironment } from './environment';\nexport { ErrorBatcher } from './error-batcher';\nexport type { BatchedEvent, InitOptions } from './reporter';\n"],"mappings":"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","names":["record","axios"]}
|
package/dist/index.d.cts
CHANGED
@@ -30,15 +30,11 @@ interface InitOptions {
|
|
30
30
|
}
|
31
31
|
declare function init(options: InitOptions): void;
|
32
32
|
declare function captureException(error: Error, additionalInfo?: Record<string, any>, userId?: number): string;
|
33
|
-
declare function wrap<T extends (...args: any[]) => any>(fn: T, info?: {
|
34
|
-
additionalInfo?: Record<string, any>;
|
35
|
-
userId?: number;
|
36
|
-
}): (...args: Parameters<T>) => ReturnType<T>;
|
37
33
|
|
38
34
|
declare function setupGlobalErrorHandler(): void;
|
39
35
|
|
40
36
|
declare function startRecording(): void;
|
41
|
-
declare function getRecordedEvents(beforeErrorSec?: number): eventWithTime[];
|
37
|
+
declare function getRecordedEvents(beforeErrorSec?: number, errorTime?: number, source?: eventWithTime[]): eventWithTime[];
|
42
38
|
|
43
39
|
declare function getBrowserInfo(): {
|
44
40
|
browser: string;
|
@@ -62,4 +58,4 @@ declare class ErrorBatcher {
|
|
62
58
|
destroy(): void;
|
63
59
|
}
|
64
60
|
|
65
|
-
export { type BatchedEvent, type BatcherOptions, ErrorBatcher, type InitOptions, captureException, getBrowserInfo, getEnvironment, getRecordedEvents, init, setupGlobalErrorHandler, startRecording
|
61
|
+
export { type BatchedEvent, type BatcherOptions, ErrorBatcher, type InitOptions, captureException, getBrowserInfo, getEnvironment, getRecordedEvents, init, setupGlobalErrorHandler, startRecording };
|
package/dist/index.d.ts
CHANGED
@@ -30,15 +30,11 @@ interface InitOptions {
|
|
30
30
|
}
|
31
31
|
declare function init(options: InitOptions): void;
|
32
32
|
declare function captureException(error: Error, additionalInfo?: Record<string, any>, userId?: number): string;
|
33
|
-
declare function wrap<T extends (...args: any[]) => any>(fn: T, info?: {
|
34
|
-
additionalInfo?: Record<string, any>;
|
35
|
-
userId?: number;
|
36
|
-
}): (...args: Parameters<T>) => ReturnType<T>;
|
37
33
|
|
38
34
|
declare function setupGlobalErrorHandler(): void;
|
39
35
|
|
40
36
|
declare function startRecording(): void;
|
41
|
-
declare function getRecordedEvents(beforeErrorSec?: number): eventWithTime[];
|
37
|
+
declare function getRecordedEvents(beforeErrorSec?: number, errorTime?: number, source?: eventWithTime[]): eventWithTime[];
|
42
38
|
|
43
39
|
declare function getBrowserInfo(): {
|
44
40
|
browser: string;
|
@@ -62,4 +58,4 @@ declare class ErrorBatcher {
|
|
62
58
|
destroy(): void;
|
63
59
|
}
|
64
60
|
|
65
|
-
export { type BatchedEvent, type BatcherOptions, ErrorBatcher, type InitOptions, captureException, getBrowserInfo, getEnvironment, getRecordedEvents, init, setupGlobalErrorHandler, startRecording
|
61
|
+
export { type BatchedEvent, type BatcherOptions, ErrorBatcher, type InitOptions, captureException, getBrowserInfo, getEnvironment, getRecordedEvents, init, setupGlobalErrorHandler, startRecording };
|
package/dist/index.js
CHANGED
@@ -30,33 +30,6 @@ var init_esm_shims = __esm({
|
|
30
30
|
}
|
31
31
|
});
|
32
32
|
|
33
|
-
// src/recorder.ts
|
34
|
-
import { record } from "rrweb";
|
35
|
-
function startRecording() {
|
36
|
-
events = [];
|
37
|
-
record({
|
38
|
-
emit(event) {
|
39
|
-
events.push(event);
|
40
|
-
if (events.length > MAX_EVENTS) {
|
41
|
-
events = events.slice(-MAX_EVENTS);
|
42
|
-
}
|
43
|
-
}
|
44
|
-
});
|
45
|
-
}
|
46
|
-
function getRecordedEvents(beforeErrorSec = 30) {
|
47
|
-
const now = Date.now();
|
48
|
-
return events.filter((e) => now - e.timestamp < beforeErrorSec * 1e3);
|
49
|
-
}
|
50
|
-
var events, MAX_EVENTS;
|
51
|
-
var init_recorder = __esm({
|
52
|
-
"src/recorder.ts"() {
|
53
|
-
"use strict";
|
54
|
-
init_esm_shims();
|
55
|
-
events = [];
|
56
|
-
MAX_EVENTS = 1e3;
|
57
|
-
}
|
58
|
-
});
|
59
|
-
|
60
33
|
// src/environment.ts
|
61
34
|
function getBrowserInfo() {
|
62
35
|
const ua = navigator.userAgent;
|
@@ -129,6 +102,11 @@ var init_error_batcher = __esm({
|
|
129
102
|
this.opts.endpoint,
|
130
103
|
{ events: batch },
|
131
104
|
{
|
105
|
+
maxBodyLength: 1e3 * 1024 * 1024,
|
106
|
+
// 10MB
|
107
|
+
maxContentLength: 1e3 * 1024 * 1024,
|
108
|
+
// 10MB
|
109
|
+
timeout: 3e4,
|
132
110
|
headers: {
|
133
111
|
"Content-Type": "application/json",
|
134
112
|
Authorization: `Bearer ${this.opts.apiKey}`
|
@@ -160,6 +138,58 @@ var init_error_batcher = __esm({
|
|
160
138
|
}
|
161
139
|
});
|
162
140
|
|
141
|
+
// src/recorder.ts
|
142
|
+
import { record } from "rrweb";
|
143
|
+
function startRecording() {
|
144
|
+
events = [];
|
145
|
+
stopFn == null ? void 0 : stopFn();
|
146
|
+
stopFn = record({
|
147
|
+
emit(event) {
|
148
|
+
if (event.type === 2) console.log("[rrweb] FullSnapshot \uAE30\uB85D\uB428:", event);
|
149
|
+
events.push(event);
|
150
|
+
if (events.length > MAX_EVENTS) {
|
151
|
+
events = events.slice(-MAX_EVENTS);
|
152
|
+
}
|
153
|
+
},
|
154
|
+
// checkoutEveryNms: 1000, // 1초마다 체크아웃
|
155
|
+
checkoutEveryNms: 15e3,
|
156
|
+
// 15초마다 한 번
|
157
|
+
checkoutEveryNth: 100
|
158
|
+
// 100개 이벤트마다 한 번
|
159
|
+
// packFn: pack,
|
160
|
+
});
|
161
|
+
}
|
162
|
+
function getRecordedEvents(beforeErrorSec = 10, errorTime = Date.now(), source = events) {
|
163
|
+
const sliced = source.filter(
|
164
|
+
(e) => errorTime - e.timestamp < beforeErrorSec * 1e3
|
165
|
+
);
|
166
|
+
const snapshotCandidates = source.filter((e) => e.type === 2);
|
167
|
+
const lastSnapshot = [...snapshotCandidates].reverse().find((e) => e.timestamp <= errorTime);
|
168
|
+
if (lastSnapshot && !sliced.includes(lastSnapshot)) {
|
169
|
+
return [lastSnapshot, ...sliced];
|
170
|
+
}
|
171
|
+
if (!sliced.some((e) => e.type === 2)) {
|
172
|
+
console.warn("\u26A0\uFE0F Snapshot \uC5C6\uC774 \uC798\uB9B0 replay\uC785\uB2C8\uB2E4. \uBCF5\uC6D0 \uBD88\uAC00\uB2A5\uD560 \uC218 \uC788\uC74C.");
|
173
|
+
}
|
174
|
+
return sliced;
|
175
|
+
}
|
176
|
+
function clearEvents() {
|
177
|
+
events = [];
|
178
|
+
}
|
179
|
+
function getCurrentEvents() {
|
180
|
+
return events.slice();
|
181
|
+
}
|
182
|
+
var events, MAX_EVENTS, stopFn;
|
183
|
+
var init_recorder = __esm({
|
184
|
+
"src/recorder.ts"() {
|
185
|
+
"use strict";
|
186
|
+
init_esm_shims();
|
187
|
+
events = [];
|
188
|
+
MAX_EVENTS = 1e3;
|
189
|
+
stopFn = void 0;
|
190
|
+
}
|
191
|
+
});
|
192
|
+
|
163
193
|
// src/handler.ts
|
164
194
|
var handler_exports = {};
|
165
195
|
__export(handler_exports, {
|
@@ -194,20 +224,38 @@ var init_handler = __esm({
|
|
194
224
|
// src/reporter.ts
|
195
225
|
function init(options) {
|
196
226
|
var _a;
|
197
|
-
|
198
|
-
globalOpts.beforeErrorSec = (_a = options.beforeErrorSec) != null ? _a : 30;
|
227
|
+
globalOpts.beforeErrorSec = (_a = options.beforeErrorSec) != null ? _a : 10;
|
199
228
|
batcher = new ErrorBatcher({
|
200
229
|
endpoint: options.endpoint,
|
201
230
|
apiKey: options.apiKey,
|
202
231
|
flushIntervalMs: options.flushIntervalMs,
|
203
232
|
maxBufferSize: options.maxBufferSize
|
204
233
|
});
|
205
|
-
|
234
|
+
if (typeof window !== "undefined") {
|
235
|
+
const start = () => {
|
236
|
+
startRecording();
|
237
|
+
Promise.resolve().then(() => (init_handler(), handler_exports)).then((mod) => mod.setupGlobalErrorHandler());
|
238
|
+
};
|
239
|
+
if (document.readyState === "complete") {
|
240
|
+
requestAnimationFrame(() => startRecording());
|
241
|
+
} else {
|
242
|
+
window.addEventListener("load", () => {
|
243
|
+
requestAnimationFrame(() => startRecording());
|
244
|
+
});
|
245
|
+
}
|
246
|
+
}
|
206
247
|
}
|
207
248
|
function captureException(error, additionalInfo, userId) {
|
208
249
|
var _a, _b;
|
250
|
+
const errorTime = Date.now();
|
251
|
+
const eventsSnapshot = getCurrentEvents();
|
252
|
+
const replay = getRecordedEvents(
|
253
|
+
globalOpts.beforeErrorSec,
|
254
|
+
errorTime,
|
255
|
+
eventsSnapshot
|
256
|
+
);
|
257
|
+
clearEvents();
|
209
258
|
const { browser, os, userAgent } = getBrowserInfo();
|
210
|
-
const replay = getRecordedEvents(globalOpts.beforeErrorSec);
|
211
259
|
return batcher.capture({
|
212
260
|
message: (_a = error.message) != null ? _a : "",
|
213
261
|
stacktrace: (_b = error.stack) != null ? _b : "",
|
@@ -222,32 +270,14 @@ function captureException(error, additionalInfo, userId) {
|
|
222
270
|
apiKey: batcher.getApiKey()
|
223
271
|
});
|
224
272
|
}
|
225
|
-
function wrap(fn, info) {
|
226
|
-
return (...args) => {
|
227
|
-
try {
|
228
|
-
return fn(...args);
|
229
|
-
} catch (err) {
|
230
|
-
if (err instanceof Error) {
|
231
|
-
captureException(err, info == null ? void 0 : info.additionalInfo, info == null ? void 0 : info.userId);
|
232
|
-
} else {
|
233
|
-
captureException(
|
234
|
-
new Error(String(err)),
|
235
|
-
info == null ? void 0 : info.additionalInfo,
|
236
|
-
info == null ? void 0 : info.userId
|
237
|
-
);
|
238
|
-
}
|
239
|
-
throw err;
|
240
|
-
}
|
241
|
-
};
|
242
|
-
}
|
243
273
|
var batcher, globalOpts;
|
244
274
|
var init_reporter = __esm({
|
245
275
|
"src/reporter.ts"() {
|
246
276
|
"use strict";
|
247
277
|
init_esm_shims();
|
248
|
-
init_recorder();
|
249
278
|
init_environment();
|
250
279
|
init_error_batcher();
|
280
|
+
init_recorder();
|
251
281
|
globalOpts = { beforeErrorSec: 30 };
|
252
282
|
}
|
253
283
|
});
|
@@ -267,7 +297,6 @@ export {
|
|
267
297
|
getRecordedEvents,
|
268
298
|
init,
|
269
299
|
setupGlobalErrorHandler,
|
270
|
-
startRecording
|
271
|
-
wrap
|
300
|
+
startRecording
|
272
301
|
};
|
273
302
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../../node_modules/.pnpm/tsup@8.4.0_jiti@2.4.2_postcss@8.5.3_typescript@5.8.3/node_modules/tsup/assets/esm_shims.js","../src/recorder.ts","../src/environment.ts","../src/error-batcher.ts","../src/handler.ts","../src/reporter.ts","../src/index.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport { fileURLToPath } from 'url'\nimport path from 'path'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","import type { eventWithTime } from '@rrweb/types';\nimport { record } from 'rrweb';\n\nlet events: eventWithTime[] = [];\nconst MAX_EVENTS = 1000;\n\nexport function startRecording() {\n events = [];\n record({\n emit(event) {\n events.push(event);\n if (events.length > MAX_EVENTS) {\n events = events.slice(-MAX_EVENTS);\n }\n },\n });\n}\n\nexport function getRecordedEvents(beforeErrorSec = 30): eventWithTime[] {\n const now = Date.now();\n return events.filter((e) => now - e.timestamp < beforeErrorSec * 1000);\n}\n","export function getBrowserInfo() {\n const ua = navigator.userAgent;\n let browser = 'unknown',\n os = 'unknown';\n\n if (ua.includes('Firefox')) browser = 'Firefox';\n else if (ua.includes('SamsungBrowser')) browser = 'Samsung Browser';\n else if (ua.includes('Opera') || ua.includes('OPR')) browser = 'Opera';\n else if (ua.includes('Trident')) browser = 'IE';\n else if (ua.includes('Edge')) browser = 'Edge (Legacy)';\n else if (ua.includes('Edg')) browser = 'Edge';\n else if (ua.includes('Chrome')) browser = 'Chrome';\n else if (ua.includes('Safari')) browser = 'Safari';\n\n if (ua.includes('Windows')) os = 'Windows';\n else if (ua.includes('Mac')) os = 'macOS';\n else if (ua.includes('Linux')) os = 'Linux';\n else if (ua.includes('Android')) os = 'Android';\n else if (ua.includes('like Mac')) os = 'iOS';\n\n return { browser, os, userAgent: ua };\n}\n\nexport function getEnvironment(): 'development' | 'staging' | 'production' {\n if (process.env.NODE_ENV === 'development') return 'development';\n if (process.env.NEXT_PUBLIC_VERCEL_ENV === 'preview') return 'staging';\n return 'production';\n}\n","import axios from 'axios';\nimport type { BatcherOptions, BatchedEvent } from './reporter';\n\nexport class ErrorBatcher {\n private queue: BatchedEvent[] = [];\n private isFlushing = false;\n private flushTimer: number;\n private readonly apiKey: string;\n\n constructor(private opts: BatcherOptions) {\n this.apiKey = opts.apiKey;\n const interval = opts.flushIntervalMs ?? 3000;\n this.flushTimer = window.setInterval(() => this.flush(), interval);\n window.addEventListener('beforeunload', () => this.flushOnUnload());\n }\n\n public getApiKey(): string {\n return this.apiKey;\n }\n\n public capture(evt: Omit<BatchedEvent, 'id' | 'timestamp'>): string {\n const id = this.makeId();\n const timestamp = new Date().toISOString();\n const record: BatchedEvent = { id, timestamp, ...evt };\n\n if (this.queue.length >= (this.opts.maxBufferSize ?? 64)) {\n this.queue.shift();\n }\n this.queue.push(record);\n return id;\n }\n\n private async flush() {\n if (this.isFlushing || this.queue.length === 0) return;\n this.isFlushing = true;\n\n const batch = this.queue.splice(0, this.queue.length);\n try {\n await axios.post(\n this.opts.endpoint,\n { events: batch },\n {\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.opts.apiKey}`,\n },\n }\n );\n } catch {\n this.queue.unshift(...batch);\n } finally {\n this.isFlushing = false;\n }\n }\n\n private flushOnUnload() {\n if (!navigator.sendBeacon || this.queue.length === 0) return;\n const payload = JSON.stringify({ events: this.queue });\n navigator.sendBeacon(this.opts.endpoint, payload);\n }\n\n private makeId() {\n return 'xxxx-xxxx-4xxx-yxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n\n public destroy() {\n clearInterval(this.flushTimer);\n }\n}\n","import { captureException } from './reporter';\n\nexport function setupGlobalErrorHandler() {\n if ((window as any).__errorHandlerSetup) return;\n\n const origOnError = window.onerror;\n window.onerror = function thisWindowOnError(\n this: Window & WindowEventHandlers,\n message: string | Event,\n source?: string,\n lineno?: number,\n colno?: number,\n error?: Error\n ): boolean {\n origOnError?.call(this, message, source, lineno, colno, error);\n captureException(\n error ??\n new Error(typeof message === 'string' ? message : 'Unknown error')\n );\n return false;\n };\n\n const origOnUnhandledRejection = window.onunhandledrejection;\n window.onunhandledrejection = function thisWindowOnRejection(\n this: Window & WindowEventHandlers,\n event: PromiseRejectionEvent\n ): any {\n origOnUnhandledRejection?.call(this, event);\n const err =\n event.reason instanceof Error\n ? event.reason\n : new Error(JSON.stringify(event.reason));\n captureException(err);\n } as typeof window.onunhandledrejection;\n\n (window as any).__errorHandlerSetup = true;\n}\n","import { startRecording, getRecordedEvents } from './recorder';\nimport { getBrowserInfo, getEnvironment } from './environment';\nimport { ErrorBatcher } from './error-batcher';\n\nexport interface BatchedEvent {\n id: string;\n timestamp: string;\n message: string;\n stacktrace: string;\n replay: any[];\n environment: string;\n browser: string;\n os: string;\n userAgent: string;\n userId?: number;\n additionalInfo?: Record<string, any>;\n appVersion: string;\n apiKey: string;\n}\n\nexport interface BatcherOptions {\n endpoint: string;\n apiKey: string;\n flushIntervalMs?: number;\n maxBufferSize?: number;\n}\n\nexport interface InitOptions {\n endpoint: string;\n apiKey: string;\n flushIntervalMs?: number;\n maxBufferSize?: number;\n beforeErrorSec?: number;\n}\n\nlet batcher: ErrorBatcher;\nlet globalOpts: { beforeErrorSec: number } = { beforeErrorSec: 30 };\n\nexport function init(options: InitOptions) {\n startRecording();\n globalOpts.beforeErrorSec = options.beforeErrorSec ?? 30;\n batcher = new ErrorBatcher({\n endpoint: options.endpoint,\n apiKey: options.apiKey,\n flushIntervalMs: options.flushIntervalMs,\n maxBufferSize: options.maxBufferSize,\n });\n import('./handler.js').then((mod) => mod.setupGlobalErrorHandler());\n}\n\nexport function captureException(\n error: Error,\n additionalInfo?: Record<string, any>,\n userId?: number\n): string {\n const { browser, os, userAgent } = getBrowserInfo();\n const replay = getRecordedEvents(globalOpts.beforeErrorSec);\n return batcher.capture({\n message: error.message ?? '',\n stacktrace: error.stack ?? '',\n replay,\n environment: getEnvironment(),\n browser,\n os,\n userAgent,\n userId,\n additionalInfo,\n appVersion: '1.0.0',\n apiKey: batcher.getApiKey(),\n });\n}\n\nexport function wrap<T extends (...args: any[]) => any>(\n fn: T,\n info?: { additionalInfo?: Record<string, any>; userId?: number }\n): (...args: Parameters<T>) => ReturnType<T> {\n return (...args) => {\n try {\n return fn(...args);\n } catch (err) {\n if (err instanceof Error) {\n captureException(err, info?.additionalInfo, info?.userId);\n } else {\n captureException(\n new Error(String(err)),\n info?.additionalInfo,\n info?.userId\n );\n }\n throw err;\n }\n };\n}\n","export * from './reporter';\nexport { setupGlobalErrorHandler } from './handler';\nexport { startRecording, getRecordedEvents } from './recorder';\nexport { getBrowserInfo, getEnvironment } from './environment';\nexport { ErrorBatcher } from './error-batcher';\nexport type { BatchedEvent, InitOptions } from './reporter';\n"],"mappings":"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","names":["record"]}
|
1
|
+
{"version":3,"sources":["../../../node_modules/.pnpm/tsup@8.4.0_jiti@2.4.2_postcss@8.5.3_typescript@5.8.3/node_modules/tsup/assets/esm_shims.js","../src/environment.ts","../src/error-batcher.ts","../src/recorder.ts","../src/handler.ts","../src/reporter.ts","../src/index.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport { fileURLToPath } from 'url'\nimport path from 'path'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","export function getBrowserInfo() {\n const ua = navigator.userAgent;\n let browser = 'unknown',\n os = 'unknown';\n\n if (ua.includes('Firefox')) browser = 'Firefox';\n else if (ua.includes('SamsungBrowser')) browser = 'Samsung Browser';\n else if (ua.includes('Opera') || ua.includes('OPR')) browser = 'Opera';\n else if (ua.includes('Trident')) browser = 'IE';\n else if (ua.includes('Edge')) browser = 'Edge (Legacy)';\n else if (ua.includes('Edg')) browser = 'Edge';\n else if (ua.includes('Chrome')) browser = 'Chrome';\n else if (ua.includes('Safari')) browser = 'Safari';\n\n if (ua.includes('Windows')) os = 'Windows';\n else if (ua.includes('Mac')) os = 'macOS';\n else if (ua.includes('Linux')) os = 'Linux';\n else if (ua.includes('Android')) os = 'Android';\n else if (ua.includes('like Mac')) os = 'iOS';\n\n return { browser, os, userAgent: ua };\n}\n\nexport function getEnvironment(): 'development' | 'staging' | 'production' {\n if (process.env.NODE_ENV === 'development') return 'development';\n if (process.env.NEXT_PUBLIC_VERCEL_ENV === 'preview') return 'staging';\n return 'production';\n}\n","import axios from 'axios';\nimport type { BatcherOptions, BatchedEvent } from './reporter';\n\nexport class ErrorBatcher {\n private queue: BatchedEvent[] = [];\n private isFlushing = false;\n private flushTimer: number;\n private readonly apiKey: string;\n\n constructor(private opts: BatcherOptions) {\n this.apiKey = opts.apiKey;\n const interval = opts.flushIntervalMs ?? 3000;\n this.flushTimer = window.setInterval(() => this.flush(), interval);\n window.addEventListener('beforeunload', () => this.flushOnUnload());\n }\n\n public getApiKey(): string {\n return this.apiKey;\n }\n\n public capture(evt: Omit<BatchedEvent, 'id' | 'timestamp'>): string {\n const id = this.makeId();\n const timestamp = new Date().toISOString();\n const record: BatchedEvent = { id, timestamp, ...evt };\n\n if (this.queue.length >= (this.opts.maxBufferSize ?? 64)) {\n this.queue.shift();\n }\n this.queue.push(record);\n return id;\n }\n\n private async flush() {\n if (this.isFlushing || this.queue.length === 0) return;\n this.isFlushing = true;\n\n const batch = this.queue.splice(0, this.queue.length);\n try {\n await axios.post(\n this.opts.endpoint,\n { events: batch },\n {\n maxBodyLength: 1000 * 1024 * 1024, // 10MB\n maxContentLength: 1000 * 1024 * 1024, // 10MB\n timeout: 30000,\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.opts.apiKey}`,\n },\n }\n );\n } catch {\n this.queue.unshift(...batch);\n } finally {\n this.isFlushing = false;\n }\n }\n\n private flushOnUnload() {\n if (!navigator.sendBeacon || this.queue.length === 0) return;\n const payload = JSON.stringify({ events: this.queue });\n navigator.sendBeacon(this.opts.endpoint, payload);\n }\n\n private makeId() {\n return 'xxxx-xxxx-4xxx-yxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n\n public destroy() {\n clearInterval(this.flushTimer);\n }\n}\n","import type { eventWithTime, listenerHandler } from '@rrweb/types';\nimport { record } from 'rrweb';\nimport { pack } from '@rrweb/packer';\n\nlet events: eventWithTime[] = [];\nconst MAX_EVENTS = 1000;\nlet stopFn: listenerHandler | undefined = undefined;\n\nexport function startRecording() {\n events = [];\n stopFn?.();\n stopFn = record({\n emit(event) {\n if (event.type === 2) console.log('[rrweb] FullSnapshot 기록됨:', event);\n\n events.push(event);\n if (events.length > MAX_EVENTS) {\n events = events.slice(-MAX_EVENTS);\n }\n },\n // checkoutEveryNms: 1000, // 1초마다 체크아웃\n checkoutEveryNms: 15000, // 15초마다 한 번\n checkoutEveryNth: 100, // 100개 이벤트마다 한 번\n // packFn: pack,\n });\n}\n\nexport function getRecordedEvents(\n beforeErrorSec = 10,\n errorTime = Date.now(),\n source = events\n): eventWithTime[] {\n const sliced = source.filter(\n (e) => errorTime - e.timestamp < beforeErrorSec * 1000\n );\n\n const snapshotCandidates = source.filter((e) => e.type === 2);\n const lastSnapshot = [...snapshotCandidates]\n .reverse()\n .find((e) => e.timestamp <= errorTime);\n\n if (lastSnapshot && !sliced.includes(lastSnapshot)) {\n return [lastSnapshot, ...sliced];\n }\n\n if (!sliced.some((e) => e.type === 2)) {\n console.warn('⚠️ Snapshot 없이 잘린 replay입니다. 복원 불가능할 수 있음.');\n }\n\n return sliced;\n}\n\n// export function getRecordedEvents(\n// beforeErrorSec = 10,\n// errorTime = Date.now(),\n// source = events\n// ): eventWithTime[] {\n// const sliced = source.filter(\n// (e) => errorTime - e.timestamp < beforeErrorSec * 1000\n// );\n\n// const fullSnapshots = source.filter((e) => e.type === 2);\n// const lastSnapshot = fullSnapshots.reverse().find(\n// (e) => e.timestamp <= sliced[0]?.timestamp\n// );\n// // const lastSnapshot = fullSnapshots\n// // .reverse()\n// // .find((e) => e.timestamp <= (sliced[0]?.timestamp ?? errorTime));\n\n// if (lastSnapshot && !sliced.includes(lastSnapshot)) {\n// return [lastSnapshot, ...sliced];\n// }\n\n// if (!sliced.some((e) => e.type === 2)) {\n// console.warn('⚠️ Snapshot 없이 잘린 replay입니다. 복원 불가능할 수 있음.');\n// }\n\n// return sliced;\n// }\n\nexport function clearEvents() {\n events = [];\n}\n\nexport function getCurrentEvents(): eventWithTime[] {\n return events.slice();\n}\n","import { captureException } from './reporter';\n\nexport function setupGlobalErrorHandler() {\n if ((window as any).__errorHandlerSetup) return;\n\n const origOnError = window.onerror;\n window.onerror = function thisWindowOnError(\n this: Window & WindowEventHandlers,\n message: string | Event,\n source?: string,\n lineno?: number,\n colno?: number,\n error?: Error\n ): boolean {\n origOnError?.call(this, message, source, lineno, colno, error);\n captureException(\n error ??\n new Error(typeof message === 'string' ? message : 'Unknown error')\n );\n return false;\n };\n\n const origOnUnhandledRejection = window.onunhandledrejection;\n window.onunhandledrejection = function thisWindowOnRejection(\n this: Window & WindowEventHandlers,\n event: PromiseRejectionEvent\n ): any {\n origOnUnhandledRejection?.call(this, event);\n const err =\n event.reason instanceof Error\n ? event.reason\n : new Error(JSON.stringify(event.reason));\n captureException(err);\n } as typeof window.onunhandledrejection;\n\n (window as any).__errorHandlerSetup = true;\n}\n","import { getBrowserInfo, getEnvironment } from './environment';\nimport { ErrorBatcher } from './error-batcher';\nimport {\n startRecording,\n getRecordedEvents,\n getCurrentEvents,\n clearEvents,\n} from './recorder';\n\nexport interface BatchedEvent {\n id: string;\n timestamp: string;\n message: string;\n stacktrace: string;\n replay: any[];\n environment: string;\n browser: string;\n os: string;\n userAgent: string;\n userId?: number;\n additionalInfo?: Record<string, any>;\n appVersion: string;\n apiKey: string;\n}\n\nexport interface BatcherOptions {\n endpoint: string;\n apiKey: string;\n flushIntervalMs?: number;\n maxBufferSize?: number;\n}\n\nexport interface InitOptions {\n endpoint: string;\n apiKey: string;\n flushIntervalMs?: number;\n maxBufferSize?: number;\n beforeErrorSec?: number;\n}\n\nlet batcher: ErrorBatcher;\nlet globalOpts: { beforeErrorSec: number } = { beforeErrorSec: 30 };\n\nexport function init(options: InitOptions) {\n globalOpts.beforeErrorSec = options.beforeErrorSec ?? 10;\n\n batcher = new ErrorBatcher({\n endpoint: options.endpoint,\n apiKey: options.apiKey,\n flushIntervalMs: options.flushIntervalMs,\n maxBufferSize: options.maxBufferSize,\n });\n\n if (typeof window !== 'undefined') {\n const start = () => {\n startRecording(); // DOM 렌더링 후에 시작되도록 지연 실행\n import('./handler.js').then((mod) => mod.setupGlobalErrorHandler());\n };\n\n if (document.readyState === 'complete') {\n requestAnimationFrame(() => startRecording());\n } else {\n window.addEventListener('load', () => {\n requestAnimationFrame(() => startRecording());\n });\n }\n\n // if ('requestIdleCallback' in window) {\n // window.requestIdleCallback(start);\n // } else {\n // setTimeout(start, 100);\n // }\n }\n}\n\nexport function captureException(\n error: Error,\n additionalInfo?: Record<string, any>,\n userId?: number\n): string {\n const errorTime = Date.now();\n const eventsSnapshot = getCurrentEvents();\n const replay = getRecordedEvents(\n globalOpts.beforeErrorSec,\n errorTime,\n eventsSnapshot\n );\n\n clearEvents(); // 다음 에러 기록을 위해 초기화\n\n const { browser, os, userAgent } = getBrowserInfo();\n\n return batcher.capture({\n message: error.message ?? '',\n stacktrace: error.stack ?? '',\n replay,\n environment: getEnvironment(),\n browser,\n os,\n userAgent,\n userId,\n additionalInfo,\n appVersion: '1.0.0',\n apiKey: batcher.getApiKey(),\n });\n}\n","export * from './reporter';\nexport { setupGlobalErrorHandler } from './handler';\nexport { startRecording, getRecordedEvents } from './recorder';\nexport { getBrowserInfo, getEnvironment } from './environment';\nexport { ErrorBatcher } from './error-batcher';\nexport type { BatchedEvent, InitOptions } from './reporter';\n"],"mappings":"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","names":["record"]}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "rusty-replay",
|
3
|
-
"version": "1.0.
|
3
|
+
"version": "1.0.8",
|
4
4
|
"description": "",
|
5
5
|
"main": "dist/index.cjs",
|
6
6
|
"module": "dist/index.js",
|
@@ -20,7 +20,9 @@
|
|
20
20
|
"rrweb-player": "^1.0.0-alpha.4"
|
21
21
|
},
|
22
22
|
"dependencies": {
|
23
|
-
"
|
23
|
+
"@rrweb/packer": "2.0.0-alpha.18",
|
24
|
+
"axios": "^1.8.4",
|
25
|
+
"rrweb-snapshot": "2.0.0-alpha.4"
|
24
26
|
},
|
25
27
|
"devDependencies": {
|
26
28
|
"@types/node": "^20",
|