@newtalaria/browser 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/dist/client.d.ts +10 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +91 -7
- package/dist/index.js.map +2 -2
- package/dist/replay/segment_buffer.d.ts +2 -0
- package/dist/replay/segment_buffer.d.ts.map +1 -1
- package/dist/types.d.ts +6 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -29,7 +29,7 @@ Talaria.init({
|
|
|
29
29
|
release: '1.0.0',
|
|
30
30
|
// Continuous session upload (0–1). Default 0 = buffer only until an error.
|
|
31
31
|
replaysSessionSampleRate: 0,
|
|
32
|
-
// On error,
|
|
32
|
+
// On error, upload ~60s before + ~15s after (0–1). Default 1.
|
|
33
33
|
replaysOnErrorSampleRate: 1,
|
|
34
34
|
maskAllInputs: true, // default
|
|
35
35
|
});
|
|
@@ -95,9 +95,10 @@ Segment payloads are a **gzip-compressed JSON array** of rrweb events.
|
|
|
95
95
|
|
|
96
96
|
| Mode | Behavior |
|
|
97
97
|
| --- | --- |
|
|
98
|
-
| Session sample hit | `replays/start` immediately; segments upload every ~5s or ~100KB |
|
|
98
|
+
| Session sample hit | `replays/start` immediately; segments upload every ~5s or ~100KB until unload |
|
|
99
99
|
| Session sample miss | Record into a ~60s ring buffer; nothing uploaded until an error sample hits |
|
|
100
|
-
| Error sample hit |
|
|
100
|
+
| Error sample hit | Upload the ring buffer + ~15s after the error, attach `replayId`, then `finish` and return to buffer-only mode |
|
|
101
|
+
| Server limit (segments / size / duration) | Stop uploading that replay; no retries |
|
|
101
102
|
| `pagehide` / `close` | Flush pending segments with `fetch` `keepalive`, then `replays/finish` |
|
|
102
103
|
|
|
103
104
|
Custom rrweb events:
|
package/dist/client.d.ts
CHANGED
|
@@ -6,11 +6,14 @@ export declare class TalariaClient {
|
|
|
6
6
|
private sessionId;
|
|
7
7
|
private recorder;
|
|
8
8
|
private buffer;
|
|
9
|
+
/** Continuous upload for the whole page session (session sample hit). */
|
|
10
|
+
private sessionSampled;
|
|
9
11
|
private uploadEnabled;
|
|
10
12
|
private startedOnServer;
|
|
11
13
|
private finishedOnServer;
|
|
12
14
|
private segmentIndex;
|
|
13
15
|
private flushTimer;
|
|
16
|
+
private errorClipTimer;
|
|
14
17
|
private uploadChain;
|
|
15
18
|
private closed;
|
|
16
19
|
private teardowns;
|
|
@@ -26,6 +29,13 @@ export declare class TalariaClient {
|
|
|
26
29
|
close(): Promise<void>;
|
|
27
30
|
private onRrwebEvent;
|
|
28
31
|
private capture;
|
|
32
|
+
private scheduleErrorClipEnd;
|
|
33
|
+
private clearErrorClipTimer;
|
|
34
|
+
/** Flush trailing post-error window, finish replay, return to ring buffer. */
|
|
35
|
+
private endErrorClip;
|
|
36
|
+
/** After an error clip (or terminal limit), buffer locally until the next error. */
|
|
37
|
+
private resetToBufferMode;
|
|
38
|
+
private stopUploadingAfterLimit;
|
|
29
39
|
private installGlobalHandlers;
|
|
30
40
|
private enqueueUpload;
|
|
31
41
|
private ensureStarted;
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EAEd,aAAa,EACb,kBAAkB,EACnB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EAEd,aAAa,EACb,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAyEpB,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAAgC;IAC/C,OAAO,CAAC,SAAS,CAAmC;IACpD,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,QAAQ,CAA+B;IAC/C,OAAO,CAAC,MAAM,CAAuB;IACrC,yEAAyE;IACzE,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,UAAU,CAA+C;IACjE,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,WAAW,CAAoC;IACvD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAkB;IAEnC,IAAI,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI;IA0DvC,WAAW,IAAI,MAAM,GAAG,IAAI;IAItB,gBAAgB,CACpB,KAAK,EAAE,OAAO,EACd,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,IAAI,CAAC;IAcV,cAAc,CAClB,OAAO,EAAE,MAAM,EACf,KAAK,GAAE,aAAsB,EAC7B,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,IAAI,CAAC;IASV,KAAK,CAAC,IAAI,CAAC,EAAE;QACjB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,MAAM,CAAC,EAAE,OAAO,CAAC;KAClB,GAAG,OAAO,CAAC,IAAI,CAAC;IA8BX,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA0B5B,OAAO,CAAC,YAAY;YAcN,OAAO;IAkErB,OAAO,CAAC,oBAAoB;IAS5B,OAAO,CAAC,mBAAmB;IAO3B,8EAA8E;YAChE,YAAY;IAoB1B,oFAAoF;IACpF,OAAO,CAAC,iBAAiB;IAUzB,OAAO,CAAC,uBAAuB;IAc/B,OAAO,CAAC,qBAAqB;IA6B7B,OAAO,CAAC,aAAa;YAKP,aAAa;YAiBb,qBAAqB;YAkDrB,cAAc;CAkB7B"}
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ import type { CaptureContext, SeverityLevel, TalariaInitOptions } from './types.
|
|
|
9
9
|
* dsn: 'http://localhost:8080',
|
|
10
10
|
* apiKey: 'tal_live_…',
|
|
11
11
|
* environment: 'development',
|
|
12
|
+
* // Error clip: ~60s before + ~15s after (not full-session upload).
|
|
12
13
|
* replaysOnErrorSampleRate: 1,
|
|
13
14
|
* });
|
|
14
15
|
*
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EACb,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAIpB
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EACb,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAIpB;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,OAAO;kBACJ,kBAAkB,GAAG,IAAI;4BAIf,OAAO,YAAY,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;4BAK9D,MAAM,UACP,aAAa,YACX,cAAc,GACvB,OAAO,CAAC,IAAI,CAAC;mBAID,MAAM,GAAG,IAAI;aAInB,OAAO,CAAC,IAAI,CAAC;aAIb,OAAO,CAAC,IAAI,CAAC;CAGvB,CAAC;AAEF,YAAY,EACV,cAAc,EACd,WAAW,EACX,aAAa,EACb,kBAAkB,GACnB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,eAAe,OAAO,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -164,6 +164,7 @@ function estimateJsonBytes(value) {
|
|
|
164
164
|
var SEGMENT_SIZE_BYTES = 1e5;
|
|
165
165
|
var SEGMENT_FLUSH_MS = 5e3;
|
|
166
166
|
var RING_BUFFER_MS = 6e4;
|
|
167
|
+
var ERROR_REPLAY_AFTER_MS = 15e3;
|
|
167
168
|
var SegmentBuffer = class {
|
|
168
169
|
constructor() {
|
|
169
170
|
this.events = [];
|
|
@@ -13145,6 +13146,10 @@ function levelToEventType(level) {
|
|
|
13145
13146
|
if (level === "debug") return "debug";
|
|
13146
13147
|
return "info";
|
|
13147
13148
|
}
|
|
13149
|
+
function isTerminalReplayLimitError(error) {
|
|
13150
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
13151
|
+
return msg.includes("replay exceeds max segment count") || msg.includes("replay exceeds max total size") || msg.includes("replay exceeds max duration") || msg.includes("Replay has expired");
|
|
13152
|
+
}
|
|
13148
13153
|
var TalariaClient = class {
|
|
13149
13154
|
constructor() {
|
|
13150
13155
|
this.options = null;
|
|
@@ -13153,11 +13158,14 @@ var TalariaClient = class {
|
|
|
13153
13158
|
this.sessionId = null;
|
|
13154
13159
|
this.recorder = null;
|
|
13155
13160
|
this.buffer = new SegmentBuffer();
|
|
13161
|
+
/** Continuous upload for the whole page session (session sample hit). */
|
|
13162
|
+
this.sessionSampled = false;
|
|
13156
13163
|
this.uploadEnabled = false;
|
|
13157
13164
|
this.startedOnServer = false;
|
|
13158
13165
|
this.finishedOnServer = false;
|
|
13159
13166
|
this.segmentIndex = 0;
|
|
13160
13167
|
this.flushTimer = null;
|
|
13168
|
+
this.errorClipTimer = null;
|
|
13161
13169
|
this.uploadChain = Promise.resolve();
|
|
13162
13170
|
this.closed = false;
|
|
13163
13171
|
this.teardowns = [];
|
|
@@ -13179,8 +13187,8 @@ var TalariaClient = class {
|
|
|
13179
13187
|
this.startedOnServer = false;
|
|
13180
13188
|
this.segmentIndex = 0;
|
|
13181
13189
|
this.buffer = new SegmentBuffer();
|
|
13182
|
-
|
|
13183
|
-
this.uploadEnabled = sessionSampled;
|
|
13190
|
+
this.sessionSampled = Math.random() < this.options.replaysSessionSampleRate;
|
|
13191
|
+
this.uploadEnabled = this.sessionSampled;
|
|
13184
13192
|
this.recorder = startRecorder({
|
|
13185
13193
|
maskAllInputs: this.options.maskAllInputs,
|
|
13186
13194
|
blockSelector: this.options.blockSelector,
|
|
@@ -13239,16 +13247,26 @@ var TalariaClient = class {
|
|
|
13239
13247
|
return;
|
|
13240
13248
|
}
|
|
13241
13249
|
await this.enqueueUpload(async () => {
|
|
13250
|
+
if (!this.uploadEnabled || this.closed) return;
|
|
13242
13251
|
await this.ensureStarted({ keepalive });
|
|
13243
13252
|
await this.uploadPendingSegments({ keepalive });
|
|
13244
|
-
if (opts?.finish) {
|
|
13245
|
-
await this.finishOnServer({
|
|
13253
|
+
if (opts?.finish && this.uploadEnabled) {
|
|
13254
|
+
await this.finishOnServer({
|
|
13255
|
+
keepalive,
|
|
13256
|
+
reason: opts.reason ?? "pagehide"
|
|
13257
|
+
});
|
|
13258
|
+
if (!this.sessionSampled) {
|
|
13259
|
+
this.resetToBufferMode();
|
|
13260
|
+
} else {
|
|
13261
|
+
this.uploadEnabled = false;
|
|
13262
|
+
}
|
|
13246
13263
|
}
|
|
13247
13264
|
});
|
|
13248
13265
|
}
|
|
13249
13266
|
async close() {
|
|
13250
13267
|
if (this.closed) return;
|
|
13251
13268
|
this.closed = true;
|
|
13269
|
+
this.clearErrorClipTimer();
|
|
13252
13270
|
if (this.flushTimer) {
|
|
13253
13271
|
clearInterval(this.flushTimer);
|
|
13254
13272
|
this.flushTimer = null;
|
|
@@ -13281,9 +13299,14 @@ var TalariaClient = class {
|
|
|
13281
13299
|
throw new Error("@newtalaria/browser: call Talaria.init() first");
|
|
13282
13300
|
}
|
|
13283
13301
|
const isErrorLike = args.level === "error" || args.level === "fatal";
|
|
13284
|
-
if (isErrorLike && !this.
|
|
13285
|
-
if (
|
|
13286
|
-
this.
|
|
13302
|
+
if (isErrorLike && !this.sessionSampled) {
|
|
13303
|
+
if (!this.uploadEnabled) {
|
|
13304
|
+
if (Math.random() < this.options.replaysOnErrorSampleRate) {
|
|
13305
|
+
this.uploadEnabled = true;
|
|
13306
|
+
this.scheduleErrorClipEnd();
|
|
13307
|
+
}
|
|
13308
|
+
} else {
|
|
13309
|
+
this.scheduleErrorClipEnd();
|
|
13287
13310
|
}
|
|
13288
13311
|
}
|
|
13289
13312
|
const attachReplay = this.uploadEnabled;
|
|
@@ -13321,6 +13344,55 @@ var TalariaClient = class {
|
|
|
13321
13344
|
throw error;
|
|
13322
13345
|
}
|
|
13323
13346
|
}
|
|
13347
|
+
scheduleErrorClipEnd() {
|
|
13348
|
+
if (this.sessionSampled || this.closed) return;
|
|
13349
|
+
this.clearErrorClipTimer();
|
|
13350
|
+
this.errorClipTimer = setTimeout(() => {
|
|
13351
|
+
this.errorClipTimer = null;
|
|
13352
|
+
void this.endErrorClip();
|
|
13353
|
+
}, ERROR_REPLAY_AFTER_MS);
|
|
13354
|
+
}
|
|
13355
|
+
clearErrorClipTimer() {
|
|
13356
|
+
if (this.errorClipTimer) {
|
|
13357
|
+
clearTimeout(this.errorClipTimer);
|
|
13358
|
+
this.errorClipTimer = null;
|
|
13359
|
+
}
|
|
13360
|
+
}
|
|
13361
|
+
/** Flush trailing post-error window, finish replay, return to ring buffer. */
|
|
13362
|
+
async endErrorClip() {
|
|
13363
|
+
if (this.closed || this.sessionSampled || !this.uploadEnabled || !this.options || !this.transport) {
|
|
13364
|
+
return;
|
|
13365
|
+
}
|
|
13366
|
+
await this.enqueueUpload(async () => {
|
|
13367
|
+
if (!this.uploadEnabled || this.sessionSampled) return;
|
|
13368
|
+
await this.ensureStarted({ keepalive: false });
|
|
13369
|
+
await this.uploadPendingSegments({ keepalive: false });
|
|
13370
|
+
await this.finishOnServer({ keepalive: false, reason: "error_clip" });
|
|
13371
|
+
this.resetToBufferMode();
|
|
13372
|
+
});
|
|
13373
|
+
}
|
|
13374
|
+
/** After an error clip (or terminal limit), buffer locally until the next error. */
|
|
13375
|
+
resetToBufferMode() {
|
|
13376
|
+
this.clearErrorClipTimer();
|
|
13377
|
+
this.uploadEnabled = false;
|
|
13378
|
+
this.startedOnServer = false;
|
|
13379
|
+
this.finishedOnServer = false;
|
|
13380
|
+
this.segmentIndex = 0;
|
|
13381
|
+
this.replayId = createId();
|
|
13382
|
+
this.buffer.trimRing();
|
|
13383
|
+
}
|
|
13384
|
+
stopUploadingAfterLimit() {
|
|
13385
|
+
this.clearErrorClipTimer();
|
|
13386
|
+
this.uploadEnabled = false;
|
|
13387
|
+
if (this.sessionSampled) {
|
|
13388
|
+
if (this.flushTimer) {
|
|
13389
|
+
clearInterval(this.flushTimer);
|
|
13390
|
+
this.flushTimer = null;
|
|
13391
|
+
}
|
|
13392
|
+
} else {
|
|
13393
|
+
this.resetToBufferMode();
|
|
13394
|
+
}
|
|
13395
|
+
}
|
|
13324
13396
|
installGlobalHandlers() {
|
|
13325
13397
|
if (typeof window === "undefined") return;
|
|
13326
13398
|
const onError = (event) => {
|
|
@@ -13382,6 +13454,18 @@ var TalariaClient = class {
|
|
|
13382
13454
|
});
|
|
13383
13455
|
this.segmentIndex = index2 + 1;
|
|
13384
13456
|
} catch (error) {
|
|
13457
|
+
if (isTerminalReplayLimitError(error)) {
|
|
13458
|
+
console.warn(
|
|
13459
|
+
"@newtalaria/browser: replay upload stopped (server limit)",
|
|
13460
|
+
error
|
|
13461
|
+
);
|
|
13462
|
+
await this.finishOnServer({
|
|
13463
|
+
keepalive: opts.keepalive,
|
|
13464
|
+
reason: "limit"
|
|
13465
|
+
});
|
|
13466
|
+
this.stopUploadingAfterLimit();
|
|
13467
|
+
break;
|
|
13468
|
+
}
|
|
13385
13469
|
this.buffer.prepend(events);
|
|
13386
13470
|
console.warn("@newtalaria/browser: replays/ingestSegment failed", error);
|
|
13387
13471
|
break;
|