@newtalaria/browser 0.1.0 → 0.1.4

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 CHANGED
@@ -29,8 +29,11 @@ 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, flush buffer + attach replayId (0–1). Default 1.
32
+ // On error, promote the ~60s ring buffer (0–1). Default 1.
33
33
  replaysOnErrorSampleRate: 1,
34
+ // Post-error upload window. Default 15000 (cheap clip). Use 0 to continue
35
+ // until the 5-minute max duration (Sentry-like, more expensive).
36
+ replaysErrorAfterMs: 15_000,
34
37
  maskAllInputs: true, // default
35
38
  });
36
39
 
@@ -49,6 +52,32 @@ await Talaria.close();
49
52
 
50
53
  `Talaria.init` also installs `window.onerror` / `unhandledrejection` handlers unless you pass `disableDefaultIntegrations: true`.
51
54
 
55
+ ## Recommended sampling (cost)
56
+
57
+ You pay for **uploaded + retained** bytes, not for local buffering. Prefer error clips in production; keep full-session sampling low.
58
+
59
+ | Traffic | `replaysSessionSampleRate` | `replaysOnErrorSampleRate` | `replaysErrorAfterMs` |
60
+ | --- | --- | --- | --- |
61
+ | High (100k+/day) | `0.01` | `1.0` | `15000` (default clip) |
62
+ | Medium (10k–100k/day) | `0.1` | `1.0` | `15000` |
63
+ | Low (under 10k/day) | `0.25` | `1.0` | `15000` |
64
+ | Marketing / docs site | `0` | `1.0` | `15000` |
65
+ | Rich post-error context | `0` | `1.0` | `0` (continue to 5 min cap) |
66
+
67
+ **Defaults (`session=0`, `onError=1`, `errorAfterMs=15000`)** are the cheapest useful profile: quiet traffic costs nothing; each sampled error keeps ~60s before + ~15s after.
68
+
69
+ ## Replay sampling behavior
70
+
71
+ | Mode | Behavior |
72
+ | --- | --- |
73
+ | Session sample hit | `replays/start` immediately; segments upload every ~5s or ~100KB until unload or **5 min** max |
74
+ | Session sample miss | Record into a ~60s ring buffer; nothing uploaded until an error sample hits |
75
+ | Error sample + `replaysErrorAfterMs > 0` | Upload buffer (≤480KiB gzip pack target / 512KiB server cap) + trailing window, hard caps **12 segments** or **2MiB** compressed, attach `replayId` only if segments landed, `finish`, return to buffer mode |
76
+ | Error sample + `replaysErrorAfterMs = 0` | Upload buffer then continue like session mode until **5 min** / unload / size caps |
77
+ | Server limit (replay segments / total size / duration) | Stop uploading that replay; no retries |
78
+ | Oversized single rrweb event | Dropped with a console warning (cannot fit under segment cap) |
79
+ | `pagehide` / `close` | Flush pending segments with `fetch` `keepalive`, then `replays/finish`; `close` fully resets so `init()` works again (React Strict Mode) |
80
+
52
81
  ## Serverpod URL pattern
53
82
 
54
83
  Talaria uses **Serverpod RPC**, not REST resource URLs:
@@ -91,15 +120,6 @@ decode('<base64>', 'base64')
91
120
 
92
121
  Segment payloads are a **gzip-compressed JSON array** of rrweb events.
93
122
 
94
- ## Replay sampling
95
-
96
- | Mode | Behavior |
97
- | --- | --- |
98
- | Session sample hit | `replays/start` immediately; segments upload every ~5s or ~100KB |
99
- | Session sample miss | Record into a ~60s ring buffer; nothing uploaded until an error sample hits |
100
- | Error sample hit | Enable upload, flush buffer, send event with `replayId` |
101
- | `pagehide` / `close` | Flush pending segments with `fetch` `keepalive`, then `replays/finish` |
102
-
103
123
  Custom rrweb events:
104
124
 
105
125
  - `talaria-console` — console level + args (truncated)
@@ -121,3 +141,31 @@ Privacy defaults: `maskAllInputs: true`, password fields masked, `[data-talaria-
121
141
  ## Example
122
142
 
123
143
  See [`../../examples/sdk-spa`](../../examples/sdk-spa) for a minimal page wired to `localhost:8080`.
144
+
145
+ ## Local `file:` install (marketing / monorepo)
146
+
147
+ `dist/` is gitignored. After editing SDK `src/`, rebuild before the consumer picks up changes:
148
+
149
+ ```bash
150
+ cd new_talaria_js/packages/browser
151
+ npm run build
152
+ # or: npm install in the consumer — `prepare` runs build for file: installs
153
+ ```
154
+
155
+ Then restart the Next app with a clean cache:
156
+
157
+ ```bash
158
+ cd ../new_talaria_marketing # sibling repo
159
+ rm -rf .next
160
+ npm run dev
161
+ ```
162
+
163
+ **Serverpod must be restarted** after changing `ReplayLimits` (compressed cap is 512KiB). A live process still on 256KiB will 400 every near-max segment.
164
+
165
+ ### Verify error-clip ingest
166
+
167
+ 1. Restart Serverpod (512KiB live).
168
+ 2. Rebuild the browser package; restart marketing with clean `.next`.
169
+ 3. Browse `/docs/**` ~30s, throw one test exception.
170
+ 4. Expect: a few `ingestSegment` 200s, one `finish`, **zero** compressed-size 400 spam, dashboard replay plays.
171
+ 5. Throw again later: a new bounded clip is allowed (buffer mode reset).
package/dist/client.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  import type { CaptureContext, SeverityLevel, TalariaInitOptions } from './types.js';
2
+ export { computeErrorClipDeadlineMs, fitCompressedPrefix, isErrorClipBudgetExhausted, planOversizedRetry, } from './replay/fit_segment.js';
3
+ export { MAX_SEGMENTS_ERROR_CLIP, MAX_ERROR_CLIP_COMPRESSED_BYTES, TARGET_COMPRESSED_SEGMENT_BYTES, MAX_COMPRESSED_SEGMENT_BYTES, } from './replay/segment_buffer.js';
2
4
  export declare class TalariaClient {
3
5
  private options;
4
6
  private transport;
@@ -6,14 +8,28 @@ export declare class TalariaClient {
6
8
  private sessionId;
7
9
  private recorder;
8
10
  private buffer;
11
+ /** Continuous upload for the whole page session (session sample hit). */
12
+ private sessionSampled;
9
13
  private uploadEnabled;
10
14
  private startedOnServer;
11
15
  private finishedOnServer;
12
16
  private segmentIndex;
17
+ private uploadedCompressedBytes;
18
+ /** Wall clock when continuous upload began (session or error promote). */
19
+ private uploadStartedAtMs;
20
+ /** Absolute deadline for error-clip mode (not extended by later errors). */
21
+ private errorClipDeadlineMs;
13
22
  private flushTimer;
23
+ private errorClipTimer;
24
+ private maxDurationTimer;
14
25
  private uploadChain;
15
26
  private closed;
16
27
  private teardowns;
28
+ /**
29
+ * Replay id that just finished with segments — kept briefly so capture can
30
+ * attach it to the error event after budget/timer finish resets buffer mode.
31
+ */
32
+ private linkableReplayId;
17
33
  init(options: TalariaInitOptions): void;
18
34
  getReplayId(): string | null;
19
35
  captureException(error: unknown, context?: CaptureContext): Promise<void>;
@@ -23,13 +39,49 @@ export declare class TalariaClient {
23
39
  keepalive?: boolean;
24
40
  finish?: boolean;
25
41
  }): Promise<void>;
42
+ /**
43
+ * Stop recording, flush while still open, then fully reset so `init()` can
44
+ * run again (React Strict Mode remount).
45
+ */
26
46
  close(): Promise<void>;
27
47
  private onRrwebEvent;
28
48
  private capture;
49
+ private markUploadStarted;
50
+ private isPastMaxDuration;
51
+ private isPastErrorClipDeadline;
52
+ private isErrorClipMode;
53
+ private scheduleMaxDurationStop;
54
+ private clearMaxDurationTimer;
55
+ private runStopForMaxDuration;
56
+ /**
57
+ * Schedule end of the cheap error clip against a fixed absolute deadline.
58
+ * Subsequent errors re-arm the timer but never push the wall later.
59
+ */
60
+ private scheduleErrorClipEnd;
61
+ private clearErrorClipTimer;
62
+ /** Flush trailing post-error window, finish replay, return to ring buffer. */
63
+ private endErrorClip;
64
+ private runEndErrorClip;
65
+ /** After an error clip (or terminal limit), buffer locally until the next error. */
66
+ private resetToBufferMode;
67
+ /** Emit a checkout FullSnapshot into the ring buffer (sync via rrweb emit). */
68
+ private checkoutFullSnapshot;
69
+ /**
70
+ * Ensure segment 0 begins at Meta+FullSnapshot. Orphan increments alone
71
+ * produce a blank rrweb player.
72
+ */
73
+ private prepareBufferForNewReplay;
74
+ private stopUploadingAfterLimit;
29
75
  private installGlobalHandlers;
30
76
  private enqueueUpload;
31
77
  private ensureStarted;
32
78
  private uploadPendingSegments;
79
+ private maxSegmentsAllowed;
80
+ /**
81
+ * Pull the largest event prefix that gzips under the target compressed size.
82
+ * Drops a single event that can never fit.
83
+ */
84
+ private takeFittedSegment;
33
85
  private finishOnServer;
34
86
  }
35
87
  //# sourceMappingURL=client.d.ts.map
@@ -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;AA6DpB,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,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,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;IAmBX,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAyB5B,OAAO,CAAC,YAAY;YAcN,OAAO;IA4DrB,OAAO,CAAC,qBAAqB;IA6B7B,OAAO,CAAC,aAAa;YAKP,aAAa;YAiBb,qBAAqB;YAqCrB,cAAc;CAkB7B"}
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;AAoCpB,OAAO,EACL,0BAA0B,EAC1B,mBAAmB,EACnB,0BAA0B,EAC1B,kBAAkB,GACnB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,uBAAuB,EACvB,+BAA+B,EAC/B,+BAA+B,EAC/B,4BAA4B,GAC7B,MAAM,4BAA4B,CAAC;AAuEpC,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,uBAAuB,CAAK;IACpC,0EAA0E;IAC1E,OAAO,CAAC,iBAAiB,CAAuB;IAChD,4EAA4E;IAC5E,OAAO,CAAC,mBAAmB,CAAuB;IAClD,OAAO,CAAC,UAAU,CAA+C;IACjE,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,gBAAgB,CAA8C;IACtE,OAAO,CAAC,WAAW,CAAoC;IACvD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAkB;IACnC;;;OAGG;IACH,OAAO,CAAC,gBAAgB,CAAuB;IAE/C,IAAI,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI;IAgEvC,WAAW,IAAI,MAAM,GAAG,IAAI;IAKtB,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;IA0CjB;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAmD5B,OAAO,CAAC,YAAY;YAwBN,OAAO;IA4ErB,OAAO,CAAC,iBAAiB;IAkBzB,OAAO,CAAC,iBAAiB;IAKzB,OAAO,CAAC,uBAAuB;IAK/B,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,uBAAuB;IAiB/B,OAAO,CAAC,qBAAqB;YAOf,qBAAqB;IAsBnC;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAmB5B,OAAO,CAAC,mBAAmB;IAO3B,8EAA8E;YAChE,YAAY;YAgBZ,eAAe;IAW7B,oFAAoF;IACpF,OAAO,CAAC,iBAAiB;IAiBzB,+EAA+E;IAC/E,OAAO,CAAC,oBAAoB;IAI5B;;;OAGG;IACH,OAAO,CAAC,yBAAyB;IAYjC,OAAO,CAAC,uBAAuB;IAc/B,OAAO,CAAC,qBAAqB;IA6B7B,OAAO,CAAC,aAAa;YAKP,aAAa;YAkBb,qBAAqB;IA8HnC,OAAO,CAAC,kBAAkB;IAQ1B;;;OAGG;YACW,iBAAiB;YA2BjB,cAAc;CAuB7B"}
package/dist/index.d.ts CHANGED
@@ -10,6 +10,8 @@ import type { CaptureContext, SeverityLevel, TalariaInitOptions } from './types.
10
10
  * apiKey: 'tal_live_…',
11
11
  * environment: 'development',
12
12
  * replaysOnErrorSampleRate: 1,
13
+ * // Default 15s post-error clip; set 0 to continue until 5 min cap.
14
+ * replaysErrorAfterMs: 15_000,
13
15
  * });
14
16
  *
15
17
  * try {
@@ -27,7 +29,9 @@ export declare const Talaria: {
27
29
  flush(): Promise<void>;
28
30
  close(): Promise<void>;
29
31
  };
30
- export type { CaptureContext, Environment, SeverityLevel, TalariaInitOptions, } from './types.js';
31
32
  export { TalariaClient } from './client.js';
33
+ export { computeErrorClipDeadlineMs, fitCompressedPrefix, isErrorClipBudgetExhausted, planOversizedRetry, } from './replay/fit_segment.js';
34
+ export { MAX_SEGMENTS_ERROR_CLIP, MAX_ERROR_CLIP_COMPRESSED_BYTES, TARGET_COMPRESSED_SEGMENT_BYTES, MAX_COMPRESSED_SEGMENT_BYTES, } from './replay/segment_buffer.js';
35
+ export type { CaptureContext, Environment, SeverityLevel, TalariaInitOptions, } from './types.js';
32
36
  export default Talaria;
33
37
  //# sourceMappingURL=index.d.ts.map
@@ -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;;;;;;;;;;;;;;;;;;;GAmBG;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"}
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;;;;;;;;;;;;;;;;;;;;;GAqBG;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,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EACL,0BAA0B,EAC1B,mBAAmB,EACnB,0BAA0B,EAC1B,kBAAkB,GACnB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,uBAAuB,EACvB,+BAA+B,EAC/B,+BAA+B,EAC/B,4BAA4B,GAC7B,MAAM,4BAA4B,CAAC;AAEpC,YAAY,EACV,cAAc,EACd,WAAW,EACX,aAAa,EACb,kBAAkB,GACnB,MAAM,YAAY,CAAC;AAEpB,eAAe,OAAO,CAAC"}