@newtalaria/browser
v0.1.4
Published
Talaria browser SDK — error capture and session replay (rrweb)
Maintainers
Readme
@newtalaria/browser
Browser SDK for Talaria — error capture and session replay (rrweb event streams, not video).
Install
npm install @newtalaria/browserFrom this monorepo:
cd new_talaria_js/packages/browser
npm install
npm run buildQuick start
import { Talaria } from '@newtalaria/browser';
Talaria.init({
// Serverpod base URL (no trailing path)
dsn: 'http://localhost:8080',
apiKey: 'tal_live_…', // full raw key from createApiKey
environment: 'development',
release: '1.0.0',
// Continuous session upload (0–1). Default 0 = buffer only until an error.
replaysSessionSampleRate: 0,
// On error, promote the ~60s ring buffer (0–1). Default 1.
replaysOnErrorSampleRate: 1,
// Post-error upload window. Default 15000 (cheap clip). Use 0 to continue
// until the 5-minute max duration (Sentry-like, more expensive).
replaysErrorAfterMs: 15_000,
maskAllInputs: true, // default
});
try {
throw new Error('Something broke');
} catch (error) {
await Talaria.captureException(error);
}
await Talaria.captureMessage('Checkout opened', 'info');
console.log('replay', Talaria.getReplayId());
await Talaria.flush();
await Talaria.close();Talaria.init also installs window.onerror / unhandledrejection handlers unless you pass disableDefaultIntegrations: true.
Recommended sampling (cost)
You pay for uploaded + retained bytes, not for local buffering. Prefer error clips in production; keep full-session sampling low.
| Traffic | replaysSessionSampleRate | replaysOnErrorSampleRate | replaysErrorAfterMs |
| --- | --- | --- | --- |
| High (100k+/day) | 0.01 | 1.0 | 15000 (default clip) |
| Medium (10k–100k/day) | 0.1 | 1.0 | 15000 |
| Low (under 10k/day) | 0.25 | 1.0 | 15000 |
| Marketing / docs site | 0 | 1.0 | 15000 |
| Rich post-error context | 0 | 1.0 | 0 (continue to 5 min cap) |
Defaults (session=0, onError=1, errorAfterMs=15000) are the cheapest useful profile: quiet traffic costs nothing; each sampled error keeps ~60s before + ~15s after.
Replay sampling behavior
| Mode | Behavior |
| --- | --- |
| Session sample hit | replays/start immediately; segments upload every ~5s or ~100KB until unload or 5 min max |
| Session sample miss | Record into a ~60s ring buffer; nothing uploaded until an error sample hits |
| 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 |
| Error sample + replaysErrorAfterMs = 0 | Upload buffer then continue like session mode until 5 min / unload / size caps |
| Server limit (replay segments / total size / duration) | Stop uploading that replay; no retries |
| Oversized single rrweb event | Dropped with a console warning (cannot fit under segment cap) |
| pagehide / close | Flush pending segments with fetch keepalive, then replays/finish; close fully resets so init() works again (React Strict Mode) |
Serverpod URL pattern
Talaria uses Serverpod RPC, not REST resource URLs:
| Call | Method | URL |
| --- | --- | --- |
| Start replay | POST | {baseUrl}/replays/start |
| Upload segment | POST | {baseUrl}/replays/ingestSegment |
| Finish replay | POST | {baseUrl}/replays/finish |
| Ingest event | POST | {baseUrl}/events/ingest |
Local default: http://localhost:8080.
Bodies are JSON with named parameters and __className__ on typed inputs:
{
"input": {
"__className__": "StartReplayInput",
"replayId": "…",
"environment": "development",
"sessionId": "…",
"url": "http://localhost:5173/"
}
}Auth (ingest):
X-API-Key: tal_live_…(preferred)- or
Authorization: Bearer tal_live_…
ByteData (gzipBytes)
Serverpod serializes ByteData as a wrapped base64 string:
decode('<base64>', 'base64')Segment payloads are a gzip-compressed JSON array of rrweb events.
Custom rrweb events:
talaria-console— console level + args (truncated)talaria-network— method, redacted URL, status, duration (no bodies / no auth headers)
Privacy defaults: maskAllInputs: true, password fields masked, [data-talaria-mask] blocked.
Public API
| API | Description |
| --- | --- |
| Talaria.init(options) | Configure + start recording |
| Talaria.captureException(error) | Ingest error (+ replay link when sampled) |
| Talaria.captureMessage(message, level?) | Ingest message |
| Talaria.getReplayId() | Active upload replay id, or null |
| Talaria.flush() | Upload buffered segments |
| Talaria.close() | Stop recording, flush, finish |
Example
See ../../examples/sdk-spa for a minimal page wired to localhost:8080.
Local file: install (marketing / monorepo)
dist/ is gitignored. After editing SDK src/, rebuild before the consumer picks up changes:
cd new_talaria_js/packages/browser
npm run build
# or: npm install in the consumer — `prepare` runs build for file: installsThen restart the Next app with a clean cache:
cd ../new_talaria_marketing # sibling repo
rm -rf .next
npm run devServerpod must be restarted after changing ReplayLimits (compressed cap is 512KiB). A live process still on 256KiB will 400 every near-max segment.
Verify error-clip ingest
- Restart Serverpod (512KiB live).
- Rebuild the browser package; restart marketing with clean
.next. - Browse
/docs/**~30s, throw one test exception. - Expect: a few
ingestSegment200s, onefinish, zero compressed-size 400 spam, dashboard replay plays. - Throw again later: a new bounded clip is allowed (buffer mode reset).
