Real User Monitoring

See exactly what your users see. Every click, every error, every slow request — stitched into the same trace as your backend, so you stop guessing where the problem actually is.

Osuite RUM session of a shopper on the checkout page: the session replay shows the Place order click, and the error panel shows ApiError: POST /api/orders failed: 504 Gateway Timeout, linked to a backend trace through web, gateway and orders
The Place order click
Opens the failing backend trace
  1. The Place order click
  2. Opens the failing backend trace

Frontend observability that speaks the same language as the rest of your stack.

One trace, frontend to database

Every browser fetch carries W3C traceparent and baggage, so a user's click stitches into the same trace as your backend services

Replay every session

rrweb-powered session replay with strict masking by default, lazy-loaded so the baseline SDK stays under 15KB gzip

Privacy-first, by default

Text and inputs are masked unless you opt in per element. Trace headers stay same-origin so you never leak context to third parties

Click to query

From one click to the query that failed

A replay from the demo incident. A shopper presses Place order and waits while the request runs through gateway and orders, until a Postgres call gives up waiting for a connection and the shopper sees an error. Pause or scrub the replay at any step.

shop.example.com/checkoutDemo · sample data

Replay: on /checkout a shopper presses Place order. The button reads Placing order… for 8.35s, then the page shows “We couldn’t place your order. Please try again.”

2×

Backend trace

504 · 8.35s

webgatewayorders

HTTP POSTweb8.35s
POST /api/ordersgateway8.07s
POST /ordersorders4.74s
SELECT ordersorders4.32s

SELECT orders · timeout exceeded when trying to connect

Session events

  1. Route change · /checkouthttps://shop.example.com/checkout0:00.0
  2. Click “Place order”button#place-order0:02.4
  3. POST /api/orders504 · 8.35s0:02.4
  4. ApiErrorPOST /api/orders failed: 504 Gateway Timeout0:10.8

End-to-End Trace Correlation

  • Every browser fetch and XHR carries W3C traceparent and baggage headers, so the same request shows up in your backend's traces — not in a separate frontend silo
  • Jump from a user's click to the slow database query that backed it in a single waterfall, with frontend and backend spans living in the same view
  • session.id and user.id propagate to backend logs and traces, so any backend error is one click away from the exact session that produced it
Osuite RUM session zoomed on the checkout replay and its error panel: the shopper's Place order click in the replay, and beside it the ApiError: POST /api/orders failed: 504 Gateway Timeout with its backend trace through web, gateway and orders and a View backend trace button
Its backend trace, one click away
  1. Its backend trace, one click away

Session Replay With Privacy By Default

  • rrweb-powered replay captures the DOM, every interaction, scroll, and route change so you can watch what the user actually did, not just what they reported
  • Strict masking is on out of the box — text and inputs are redacted unless you explicitly unmask them per element, and whole regions can be blocked from replay entirely
  • The replay engine is lazy-loaded via dynamic import, so the baseline SDK stays under 15KB gzip and the cost only lands when replay actually starts
Osuite session replay of the shopfront checkout page: masked card inputs, the Place order button, and the toast We couldn't place your order. Please try again, above a player timeline marked with errors, network failures, navigations and clicks

Frontend Errors and Crashes

  • Capture every uncaught error, unhandled promise rejection, failed resource load, and React render crash with full stack traces and component context
  • Error-triggered sampling upgrade: even sessions you chose not to sample get exported the moment something breaks, with the surrounding context intact
  • Group errors by frequency, browser, route, and user impact — and from any error, jump straight into the session replay or the matching backend trace
Osuite RUM sessions filtered by error.type:ApiError: facets for errors, replay, browser, OS and device beside a chart of sessions with errors climbing late in the hour, and the list of affected sessions with their users, devices, top URL and replay links
Every session that hit this ApiError
  1. Every session that hit this ApiError

Real User Performance, Not Synthetic Averages

  • Capture real page-load timing on every session — documentLoad, documentFetch, and resourceFetch spans backed by the Navigation Timing API, plus an HTTP span for every fetch and XHR call
  • SPA route-change spans automatically adopt the fetch and XHR calls that fire during navigation, so you see the true settling time of every page transition
  • Surface UX friction with optional rage-click, dead-click, and scroll-depth detection — so you find the moments users get stuck without waiting for a support ticket

Page load /checkout

example
  1. documentLoad 1.24s
  2. documentFetch /checkout 182ms
  3. resourceFetch /assets/index.css 122ms
  4. resourceFetch /assets/index.js 376ms
  5. resourceFetch /images/pour-over.webp 328ms

Recorded on every session by the RUM SDK, from the Navigation Timing API

Frequently Asked Questions

How is Osuite RUM different from standalone session-replay or frontend monitoring tools?
Osuite RUM is OpenTelemetry-native end to end. Frontend traces, errors, and replay all share the same session and trace context as your backend services, so a slow click links directly to the slow database query that caused it — in one waterfall, not two tools. You also get session replay, error monitoring, and frontend tracing in a single SDK instead of stitching three vendors together.
How is user data protected? What is the default privacy posture?
Replay masking is on by default — every text node renders as ***, every input is masked, and you opt back in per element with an osuite-unmask class. Whole regions like payment forms can be replaced with a placeholder using osuite-block, or excluded entirely with osuite-ignore. Trace headers (which carry session.id and user.id) are restricted to same-origin requests by default so they never leak to third-party APIs, analytics, or ad pixels. The session JWT used for replay uploads is held in memory only — never persisted to localStorage.
Will it slow down my app or bloat my bundle?
The baseline SDK is under 15KB gzipped. The rrweb replay engine and pako compressor are loaded via dynamic import — about 40KB gzipped — only when replay actually starts, so users on unsampled sessions never download them. Spans, logs, and replay chunks are all batched and sent off the critical path.
What does the SDK capture out of the box?
One init() call gives you page loads, fetch and XHR spans, SPA route changes (Next.js and any History API framework), click spans, uncaught errors, unhandled promise rejections, resource load failures, React render errors via the optional error boundary, and full session replay. Identity is opt-in via setUser, and richer interaction signals like rage clicks, dead clicks, and scroll depth are one config flag away.
Can I sample sessions to control cost without losing the broken ones?
Yes. Head-based session sampling decides once per session whether to export. Unsampled sessions still buffer recent activity, and the moment an error fires, the session is upgraded to sampled and the buffered context is flushed. So you keep the spend predictable without losing the sessions that actually matter.
Which browsers and frameworks are supported?
Modern evergreen browsers — Chrome, Edge, Firefox, Safari — on an ES2020 target. Route-change tracking auto-detects Next.js and falls back to a generic History API adapter that works with React Router, Vue Router, SvelteKit, and anything else built on the History API. A subpath import provides an OsuiteErrorBoundary for React apps that want a render-error boundary.

See what Osuite can do for your team

Get a personalized walkthrough of the platform and a cost comparison against your current observability stack.

No commitment. No sales pressure. Just a real look at the platform.