Real User Monitoring
Real User Monitoring (RUM) records what real users experience in their browser or
on their phone: how fast your pages load, how quickly they react to a click, which
errors and crashes they hit, and which backend request each page or screen made. It
lives under Frontend in the sidebar (/frontend/applications).
The rest of FuseScope sees requests from the server inward. RUM adds the other end: the time spent in the browser or the app, and the errors your servers never see.
Platforms
Section titled “Platforms”| Platform | SDK | Status | Set up |
|---|---|---|---|
| Web | @fusescope/browser (npm) |
Beta | Set up a web application |
| Android | io.fuseone.fusescope:android (Maven Central), Java and Kotlin |
Beta | Set up an Android application |
| iOS | Planned |
An application has one platform, chosen when you create it. The screens are the same for both; the differences are noted where they matter. On Android, a view is a screen (an Activity, a Fragment or a Compose destination), errors include crashes and ANRs (the app not responding), and stack traces are retraced with R8 mappings instead of source maps. Native (NDK) crashes are not captured yet; they are planned.
Use RUM when users say “the site is slow” and the backend looks healthy, when you want to know whether a release made pages slower, or when you need the backend trace behind one user’s failing click.
What you get
Section titled “What you get”- Sessions. A session is one user’s visit, from the first page until 15 minutes
without a click, key press, scroll or touch, or 4 hours at most. All tabs of one
browser share it. On Android, a session ends after 15 minutes in the background, or at
4 hours. Every span and event carries its
session.id, and a session that follows an expired one carries its id assession.previous_id. See Sessions. - Views. A view is one page or screen the user saw, named by its route
template, such as
/product/:id, so/product/1234and/product/99count as one route. The view the page was loaded on is a page load; every later view of a single-page app is a route change. Each view records how long the user stayed on it, the time on view. See Views. - Web Vitals. Google’s standard measures of page experience, explained below.
- Errors. Uncaught JavaScript errors and unhandled promise rejections on the web; crashes and ANRs on Android; and errors you report yourself. Each has its type, message, stack trace and the route it happened on, grouped so one bug is one row. With your source maps or R8 mappings uploaded, stack traces show your original code. See Errors.
- App start (Android). Cold, warm and hot start times, rated with Android vitals’ thresholds, shown as p75 on the overview.
- Clicks. Each click records which element was clicked, as a short selector such as
button#checkout, never its text. - Requests linked to backend traces. Each
fetchorXMLHttpRequestcall in the browser, and each OkHttp request on Android, is a span. The SDK adds the W3Ctraceparentheader to requests to your backend, so the backend’s trace becomes a child of the browser’s request. From a session, a route or an error, one click opens the backend trace in Trace details.
RUM data is stored as ordinary traces and logs, so the
Traces explorer, the
Logs explorer, dashboards and
alert rules work on it. Filter by
fusescope.rum.application.id to see one application.
Web Vitals in plain words
Section titled “Web Vitals in plain words”Web Vitals are measured on each page load. FuseScope shows the 75th percentile (p75): three loads in four were at least this good. Each value is rated good, needs improvement or poor with Google’s thresholds:
| Vital | What it measures | Good | Needs improvement | Poor |
|---|---|---|---|---|
| LCP, Largest Contentful Paint | How long until the largest image or block of text is on screen: when the page looks loaded. | ≤ 2.5 s | ≤ 4 s | > 4 s |
| INP, Interaction to Next Paint | How long the page takes to show a reaction after a click, tap or key press. The slowest interactions of the visit count. | ≤ 200 ms | ≤ 500 ms | > 500 ms |
| CLS, Cumulative Layout Shift | How much the content jumps around while it loads, such as a button moving as an image appears. It has no unit. | ≤ 0.1 | ≤ 0.25 | > 0.25 |
The SDK also records FCP (First Contentful Paint, the first text or image) and TTFB (Time to First Byte, how long the server took to start answering). Each route’s detail shows their p75.
Privacy by default
Section titled “Privacy by default”RUM is designed so that no personal data is collected unless you decide otherwise.
- Query strings and fragments are dropped from URLs, span names and error
messages:
/search?q=boots#topbecomes/search. Keep named parameters, such aspage, with an allowlist. The SDK does this in the browser, and the FuseScope gateway does it again on the server for URL attributes and span names, so a client that skips it is still covered. - No form input or typed text is ever captured. Clicks record the element’s tag and a CSS selector, not its text.
- The client IP is not stored. The gateway uses it in memory for the rate limit only.
- Consent hook. With Wait for consent on, the SDK records nothing until your
consent banner calls
setConsent(true). - Users are anonymous unless you call
setUser(). The id you pass is then sent inuser.idas its SHA-256 hash, unless you turn hashing off. You can find a user’s sessions by hashing their id the same way, without FuseScope storing who they are.
The application’s settings say which of these the server enforces and which the SDK applies; see Set up a web application. The Android SDK applies the same defaults and sends no persistent device identifier; see Privacy defaults.
Homologated, not mandatory
Section titled “Homologated, not mandatory”FuseScope publishes a browser SDK, @fusescope/browser,
a thin distribution of OpenTelemetry JS, and an Android SDK,
io.fuseone.fusescope:android, a thin
distribution of OpenTelemetry Android. Both add sessions, views, privacy scrubbing and
the attributes the RUM screens read. It is the tested and recommended path, but it is
not required. FuseScope accepts any OpenTelemetry client that sends OTLP to the RUM
endpoints with an application key, and never checks which SDK sent the data.
A client configured by hand only needs a few attributes for the screens to fill:
session.id, fusescope.rum.view.route, spans named view, and exception and
browser.web_vital events with an event.name attribute; an Android client also needs
app.package.name. See
Use another OpenTelemetry client.