Skip to content

SDK reference

Everything beyond apiKey / endpoint / apiEndpoint / service is optional. Defaults are tuned for a typical SaaS frontend. For a minimal setup, see the quickstart.

FieldWhat it doesNotes
apiKeyPublic ingest token sent on every OTLP request, also used to mint session JWTs for replay uploads.Falls back to OSUITE_INGEST_TOKEN. Public — bundled in your JS. Backend rate-limits per key.
endpointBase URL for OTLP traces and logs. The SDK posts to ${endpoint}/v1/traces and ${endpoint}/v1/logs.Falls back to OSUITE_INGEST_ENDPOINT.
apiEndpointBase URL for the Osuite control plane (replay presign + session JWT). The SDK posts to ${apiEndpoint}/rum/session/init and ${apiEndpoint}/rum/replay-chunk/presign.Falls back to OSUITE_API_ENDPOINT. Different host from endpoint because replay blobs go to object storage, not OTLP.
service.nameIdentifies the frontend in your traces (e.g. frontend-web, admin-app).Required.
service.versionBuild id — git SHA, tag, or semver. Used for source-map matching.Required.
service.environmentproduction, staging, development, etc.Required — backend filters and dashboards key off this.

A session is a continuous user visit. A new one starts after a long idle, after the hard cap, or when you change the user identity.

session: {
inactivityTimeoutMs: 1_800_000,
hardCapMs: 10_800_000,
}
FieldDefaultWhat it does
inactivityTimeoutMs1_800_000 (30 min)Idle time before the session rotates. Activity = clicks, keystrokes, scrolls, fetches, tab focus.
hardCapMs10_800_000 (3 h)Maximum session length regardless of activity. Prevents week-long zombie sessions.

The session id is stored in localStorage and shared across tabs via BroadcastChannel. Calling setUser / clearUser rotates the session immediately so a logged-in session is never conflated with the pre-login one.

Head-based session sampling for traces and logs, with an error-triggered upgrade safety net. See Sampling for the behavior.

sampling: {
sessionSampleRate: 1.0,
upgradeOnError: true,
preSampleBuffer: {
maxItems: 500,
maxAgeMs: 60_000,
},
}
FieldDefaultWhat it does
sessionSampleRate1.0Probability that a session is “sampled” (everything exports immediately). Range [0, 1]. Decided once per session. Set to 0.1 to sample 10% of sessions.
upgradeOnErrortrueWhen true, an unsampled session is upgraded to sampled the first time an error log fires (window.error, unhandledrejection, React error, captureException, captureMessage('fatal')). Buffered spans/logs drain immediately and exporting stays on for the rest of the session.
preSampleBuffer.maxItems500Hard cap on items held for an unsampled session. Older items evicted FIFO.
preSampleBuffer.maxAgeMs60_000Items older than this are dropped on each push.

rrweb session replay. Privacy defaults are strict — all text and inputs are masked unless you opt in per element. See Session replay for masking and privacy classes.

replay: {
mode: 'always',
sampleRate: 0.1,
bufferSeconds: 30,
trailingSeconds: 15,
maxBufferMB: 50,
maskAllText: true,
maskAllInputs: true,
blockClass: 'osuite-block',
ignoreClass: 'osuite-ignore',
unmaskClass: 'osuite-unmask',
uploadOnSessionEnd: false,
}
FieldDefaultWhat it does
mode'always'always: record + upload everything. probabilistic: roll once per session at sampleRate; sampled sessions behave like always, others don’t record. on-error / hybrid currently fall back to always with a warning.
sampleRate0.1Used only by probabilistic. Range [0, 1].
bufferSeconds30Rolling-window length reserved for on-error / hybrid; not active while those fall back to always.
trailingSeconds15How long to keep uploading after a trigger fires; not active while on-error / hybrid fall back to always.
maxBufferMB50Per-session cap on IndexedDB usage. Oldest non-uploaded chunks evicted first.
maskAllTexttrueAll text nodes recorded as ***. Opt back in per element with class="osuite-unmask".
maskAllInputstrueAll <input> / <textarea> / <select> values masked.
blockClass'osuite-block'Elements with this class become a placeholder in replay (e.g. payment forms).
ignoreClass'osuite-ignore'Events on these elements aren’t recorded at all.
unmaskClass'osuite-unmask'Per-element opt-out of maskAllText.
uploadOnSessionEndfalseWhen true, force-flush the rolling buffer when the session rotates.

User-action spans. click is always on; richer detection is opt-in.

interactions: {
level: 'standard',
rageClicks: true,
deadClicks: false,
scrollDepth: { thresholds: [50, 100] },
}
FieldDefaultWhat it does
level'standard''minimal' = clicks only. 'standard' = clicks + form submits + input focus/blur + visibility change.
rageClicksfalseWhen true (or an object), emits user_interaction.rage_click when 3 clicks happen within 1 s in a 20 px radius. Tunable: {clickCount, windowMs, radiusPx}.
deadClicksfalseEmits user_interaction.dead_click when a click triggers no DOM mutation or network within max(mutationWaitMs=100, networkWaitMs=500). Off by default — false-positive prone for legitimate “do nothing” clicks. Tunable: {mutationWaitMs, networkWaitMs}.
scrollDepthfalseEmits user_interaction.scroll_depth when the user crosses configured percentages of page height. Defaults {thresholds: [25, 50, 75, 100]} when set to true.

Input field values are never captured — only field name and type.

Which uncaught error sources to listen on. See Frontend errors for how errors are grouped and reported.

errors: {
captureWindowError: true,
captureUnhandledRejection: true,
captureResourceError: true,
}
FieldDefaultWhat it does
captureWindowErrortrueListen on window.error for runtime errors.
captureUnhandledRejectiontrueListen on unhandledrejection for unhandled Promise rejections.
captureResourceErrortrueListen on window.error for failed <img> / <script> / <link> / <audio> / <video> / <source> loads.

All routed through osuite.captureException internally — same log schema, distinguished by event.name.

Default off. Opt in to capture console.* calls as log records.

console: {
capture: ['error', 'warn'],
}

The default is [] (nothing captured). Each captured call:

  • Still calls the original console.* (your dev tools logs unchanged).
  • Emits event.name='browser.console_<level>'.
  • Serializes args with a circular-and-bigint-safe replacer, capped at 4 KB body.
  • Maps console.log / info to OTel severity INFO; warnWARN; errorERROR; debugDEBUG.

Off by default because console output is high-volume and app code typically expects console to be side-effect-free.

SPA route-change tracking.

navigation: {
enabled: true,
framework: 'auto',
}
FieldDefaultWhat it does
enabledtrueSet false to disable route_change spans.
framework'auto''auto' sniffs __NEXT_DATA__ / __next_f and uses the Next adapter; otherwise falls back to a generic History API adapter.

Both adapters patch pushState / replaceState / popstate, then declare the route settled when the DOM is quiet for 500 ms (or hits a 5 s hard cap). Fetch/XHR spans during that window become children of the route_change span automatically.

Which outgoing requests get the traceparent and baggage headers (carrying session.id + user.id).

propagation: {
allowlist: [/\/api\//, 'api.example.com'],
}
  • Empty allowlist (default) = same-origin only. Same-origin requests (those starting with / or matching window.location.origin) get the headers; everything else does not.
  • Non-empty allowlist replaces same-origin matching. Strings match by substring; regexes match by .test(url).

Same-origin by default avoids leaking trace context to third-party APIs (analytics, ad pixels, vendor SDKs).

debug: true,

Default false. When true, the SDK prints internal diagnostics (init steps, sampling decisions, transport failures) to console.debug. Use during integration; turn off in production.

import { osuite } from '@osuite/rum';
osuite.setUser({ id: 'u_123', plan: 'pro', tenantId: 't_99' });
osuite.clearUser();
osuite.captureException(err, { extra: { feature: 'checkout', cartTotal: 42.5 }, level: 'error' });
osuite.captureMessage('payment retried', 'warn', { extra: { attempt: 2 } });
osuite.addSpanAttributes({ 'cart.total': 42.5, 'cart.items': 3 });
osuite.replay.capture('user-reported-issue');
await osuite.flush();
await osuite.shutdown();
  • setUser / clearUser — set or clear the user identity. Either call rotates the session so a logged-in session is never conflated with the pre-login one.
  • captureException / captureMessage — report handled errors and messages. extra keys become app.<key> log attributes. Levels are 'debug' | 'info' | 'warn' | 'error' | 'fatal'; 'fatal' triggers a sampling upgrade.
  • addSpanAttributes — attach attributes to the active span.
  • replay.capture(label) — no-op while replay mode is always, which already uploads every chunk.
  • flush — force all buffered telemetry out (useful before navigating away).
  • shutdown — stop everything (useful in tests).

The subpath @osuite/rum/react exposes OsuiteErrorBoundary, a React error boundary that reports render crashes and triggers a sampling upgrade. It is kept off the baseline bundle so the core SDK does not pull React in. See Frontend errors for usage.

EntryTarget (gzip)
@osuite/rum baseline< 15 KB
@osuite/rum/react< 1 KB
Replay (rrweb + pako, lazy-loaded)~40 KB

Replay is loaded via dynamic import() so the cost lands only when replay actually starts.

Modern evergreen browsers (Chrome, Edge, Firefox, Safari). ES2020 target. Requires BroadcastChannel for cross-tab session sync (falls back to the storage event), IndexedDB for replay buffering (falls back to in-memory), and localStorage (falls back to in-memory; cross-tab disabled).