Skip to main content
Version: NG 3.0 (Beta)

Browser RUM

Introduction

Browser RUM (Real User Monitoring) delivers full visibility into the user experience across every digital transaction in web applications. It captures real user performance data directly from the browser, offering deep insights into page load times, user interactions, and frontend issues to optimize performance in real time.

Getting Started

Compatibility

Browser RUM is supported for the following browsers/runtime:

  • Google Chrome (Version 131.0.6778.85 and above)

Data Collection Method





GSH Overview



Browser RUM collects real user monitoring data using VuNet’s JavaScript RUM Agent.

The recommended approach is to deploy a proxy server in the DMZ to receive telemetry from users' browsers running the web application. This proxy serves as a secure intermediary between the end-user browsers (where the RUM JavaScript agent executes) and the RUM data collector of the observability platform hosted within the internal network.



Prerequisites
Inputs for Configuring Data Source
To configure this data source, you will require the following parameters:



Key
Help Text


Application Name
Name of the monitored application.


SSL

Select Yes
if you want to require TLS (SSL) for secure communication. Select
No
if TLS is not required.



Traces Sampling Percentage
Specify the sampling percentage for trace data collected by browser RUM agent. A percentage number between 0 and 100 is to be provided. If 0% is used, RUM agent will not collect any traces. If 100% is used, RUM agent will collect and send all traces. When a number between 0 and 100 is used, the RUM agent will send the specified percentage of traces using a random sampling policy.


Session Replay Sampling Percentage

Specify the sampling percentage for session replay data collected by the browser RUM agent. A value between 0 and 100 must be provided.



- If set to 0%, the RUM agent will not collect any session replay data.

- If set to 100%, session replay data will be captured and sent for all user sessions.

- For values between 0 and 100, the RUM agent uses a normalized percentage function to decide whether a session is selected for replay. The decision is based on the following logic:

percentage(base + replayPercentage * RandomJitter) < replayPercentage


base: A numeric value generated by hashing the session ID (originally a string).
RandomJitter: A randomness factor that can vary by ±25% to ensure better distribution across sessions.
percentage: A function that normalizes the result to always fall within the range of 0 to 100.

- Values above 100 (e.g., 105) are capped at 100.

- Values below 0 (e.g., -5) are raised to 0.


If the normalized value is less than the configured replayPercentage, the session is selected for replay. This mechanism helps control the volume of session replay data while maintaining fair and balanced sampling across sessions.




NOTE:

To disable trace collection, set Traces Sampling Percentage to 0.
To disable session replay collection, set Session Replay Sampling Percentage to 0.
To disable both trace and session replay data, set both values to 0.


Certificate:

Browser-to-Proxy SSL Certificate: Used to establish secure connections between the JavaScript running in the browser and the proxy server.


OTEL Collector Certificate: Required for secure communication between the proxy server and the OpenTelemetry (OTEL) collector.



CORS

To ensure successful communication between the application and the proxy server, the following CORS-related requirements must be met:



Restrict Origins: Only trusted application domains should be allowed to send data. The proxy server must be configured to whitelist specific origins using the following headers:

Access-Control-Allow-Origin: https://<appname.com>

Replace https://<appname.com> with the actual domain(s) of your frontend application.


Security Mechanism Compatibility: If the application uses security mechanisms such as CSP (Content Security Policy) or firewalls, they must be configured to allow communication with the proxy.
CSP headers must permit connect-src access to the proxy domain:

Content-Security-Policy: script-src 'self'; connect-src 'self' https://<proxy_address>;

Ensure the proxy's hostname (e.g., https://otelproxy.com) is included in the connect-src directive.


Preflight Request Support: The proxy must correctly handle preflight OPTIONS requests. These requests are automatically issued by browsers before a POST request to verify CORS permissions.
Ensure your NGINX or proxy server returns the appropriate CORS headers for OPTIONS requests.




The Role of the Proxy Server in Browser RUM
The proxy server is a critical component in a Real User Monitoring (RUM) deployment. It acts as a secure intermediary between end-user browsers (where the RUM JavaScript agent runs) and the backend RUM data collector. Integrating a proxy server provides the following technical benefits:

SSL/TLS Termination: The proxy server terminates HTTPS connections, ensuring encrypted and trusted transmission of RUM data from browsers.
CORS Enforcement: It manages Cross-Origin Resource Sharing (CORS) headers, allowing only requests from approved frontend domains to be processed, which protects against cross-site data leaks.
API Key and Authorization Validation: Incoming requests are checked for valid API keys or authorization tokens. Unauthorized requests are rejected, ensuring only trusted clients can send monitoring data.
Request Routing and Load Balancing: The proxy server forwards accepted telemetry data to the correct backend RUM collector endpoint and can distribute load across multiple backend instances for high availability.
Network Security: Only the proxy is exposed to the internet. The backend RUM collector stays protected within a private network, and firewall rules only need to allow access to the proxy.
Client IP Forwarding: To enable accurate user attribution, the proxy passes the original client IP address to the backend using headers such as X-Forwarded-For.
Preflight and OPTIONS Handling: The proxy handles browser CORS preflight (OPTIONS) requests, which is essential for seamless communication from modern browsers.
Security Headers Management: Additional security headers (like Strict-Transport-Security and X-Frame-Options) can be injected to enhance security.





Prerequisites

Inputs for Configuring Data Source

  • Application: Enter the name of the application you want to monitor

  • SSL Required: Enable TLS communication for Browser RUM ingestion. Once enabled, browser RUM data sent from the application to the vuSmartMaps ingestion endpoint will be securely encrypted. After enabling this feature, follow the additional instrumentation configuration steps provided in the 'TLS Configuration' section of the instrumentation guide.

  • Traces Sampling Percentage: Specify the sampling percentage for trace data collected by browser RUM agent. A percentage number between 0 and 100 is to be provided. If 0% is used, RUM agent will not collect any traces. If 100% is used, RUM agent will collect and send all traces. When a number between 0 and 100 is used, the RUM agent will send the specified percentage of traces using a random sampling policy.

  • Session Replay Sampling Percentage: Specify the sampling percentage for session replay data collected by the browser RUM agent. A value between 0 and 100 must be provided.

  • If set to 0% , the RUM agent will not collect any session replay data.

  • If set to 100% , session replay data will be captured and sent for all user sessions.

  • For values between 0 and 100, the RUM agent uses a normalized percentage function to decide whether a session is selected for replay. The decision is based on the following logic: percentage(base + replayPercentage * RandomJitter) < replayPercentage

base : A numeric value generated by hashing the session ID (originally a string). RandomJitter : A randomness factor that can vary by ±25% to ensure better distribution across sessions. percentage : A function that normalizes the result to always fall within the range of 0 to 100.

  • Values above 100 (e.g., 105) are capped at 100.
  • Values below 0 (e.g., -5) are raised to 0. If the normalized value is less than the configured replayPercentage , the session is selected for replay. This mechanism helps control the volume of session replay data while maintaining fair and balanced sampling across sessions.
  • Allowed Origins: Allowed Origins: Comma-separated list of origins permitted to access the OpentTelemetry Collector. Example: "http://example.com,https://app.example.com,http://localhost:3000" If not specified, defaults to "*" (allow all origins)
  • Allowed Headers: Allowed Headers: Comma-separated list of HTTP headers permitted in CORS requests Example: "Content-Type,Authorization,X-Requested-With" If not specified, defaults to "*" (allow all headers)

Firewall Requirement

To collect data from this O11ySource, ensure the following ports are opened:

Source IPDestination IPDestination PortProtocolDirection
BrowserProxy Server443TCPInbound
Proxy ServervuSmartMaps Web Services443TCPOutbound
Proxy ServervuSmartMaps OTEL Collector4319*TCPOutbound

*Before providing the firewall requirements, please update the port based on the customer environment.

Configuring the Target

Modify the application's front end code to include Vunet's JavaScript RUM Agent using CDN or NPM based on your environment. The complete instructions for instrumentation can be downloaded as a package from the Browser RUM O11ySource.

Configuration Steps





GSH Overview





- *``
Enable
``**
the Browser RUM O11ySource.


Select the sources tab and press the
- *``
+
``**
button to add a new application that has to be monitored.


Provide the required configurations:



Application Name


SSL


Trace Sampling %


Session Replay %



Afterwards, select
- *``
Save and Continue
``**
to proceed with downloading the java script instrumentation package


Then click
- *``
Finish
``**
to close the data source window.


Client Side Browser RUM Instrumentation
Instrumenting JavaScript Applications
This section guides you through tracing JavaScript applications using Browser RUM.
Before you begin, ensure the following:


Configure your web server as a reverse proxy to serve the RUM script and forward trace data, or use a dedicated proxy server for receiving RUM traces.


The RUM script should send data to the proxy at the following endpoint:

https://<proxy_address>/rum/v1/traces,

which forwards it to the OpenTelemetry Collector:

https://<RUM-collector-host>:4319/v1/traces


The instrumentation would require the JavaScript to be added to html pages by editing/updating the html pages and adding the <script> tag.


The method of editing/updating HTML files depends on the technology used for the web application:


JavaScript-based applications (JS, Angular, React):

For Single Page Applications (SPA): edit the main HTML file (typically index.html) to include the <script> tag.
For Multi Page Applications: update all main HTML pages to include the <script> tag.



Server-side rendered applications (PHP, JSP, ASP.NET): the HTML files are generated dynamically by the server. Insert the <script> tag via server-side code (e.g., in header.php, _Layout.cshtml, etc.).




Ensure that the application and environment allow externally loaded or inline scripts to be executed, since the RUM SDK is loaded as a script.


Host / Virtual Machine (VM)
Copy the RUM Script: Add /public/js/vunet-rum.js (absolute path) to your application’s codebase, preferably in the js folder.
Add the RUM Script to the Page Header: Insert the following code snippet in your HTML file's <head> section:

<script>

(function (w, s, d, r, e, n) {

(w[s] = w[s] || {

readyListeners: [],

onReady: function (e) {

w[s].readyListeners.push(e);

},

}),

((e = d.createElement('script')).async = 1),

(e.src = r),(n = d.getElementsByTagName('script')[0]).parentNode.insertBefore(e, n);

})( window, 'vunetRum', document, '/public/js/rum.vunet.js');

window.vunetRum.onReady(function () {

window.vunetRum.initialize({

collectionSourceUrl: "<VUNET_TELEMETRY_RECEIVER_URL>", //mention the urlwhere the otel collector is running

serviceName: '<SERVICE_NAME>',// mention the service name of the application

applicationName: '<APPLICATION_NAME>', // mention the name of the application

decideApiEndpoint: "/vuSmartMaps/api/rum/",

collectErrors: true,

dropShortTracesMs: 100,//drop traces shorter than 100 milliseconds

authorizationToken: "ef7ae8b1fa097092a66a56882fd8366cfbdb1b6848ae0d529a21a68a94e245020"

});

});

</script>


Update the Variables

VUNET_TELEMETRY_RECEIVER_URL: URL of the reverse proxy
Example: http://10.1.1.1/rum/v1/traces
SERVICE_NAME: Service name for the application
Example: 'vubank-frontend'
APPLICATION_NAME: Name of the application
Example: 'IBMB'
authorizationToken:

Generate a token and include it in the RUM script on the application side.
The same token must also be configured on the proxy server to validate incoming requests.
On a Linux host, you can use the following command to generate the token:

openssl rand -hex 32



dropShortTracesMs:

Filters out short, low-value traces based on total trace duration.
If the total duration of a trace (from its root span’s start to its end) is less than the specified value, the entire trace is discarded.
All spans within such short traces will also be excluded.
This helps eliminate fast, low-impact user interactions.
Value is specified in milliseconds (e.g., 100).



Rebuild and deploy the updated application to your hosting environment to apply changes.
Cloud Machine Setup (Using CDN)
For cloud environments, use the CDN-hosted script below:

<script>

(function (w, s, d, r, e, n) {

(w[s] = w[s] || {

readyListeners: [],

onReady: function (e) {

w[s].readyListeners.push(e);

},

}),

((e = d.createElement('script')).async = 1),

(e.src = r),(n = d.getElementsByTagName('script')[0]).parentNode.insertBefore(e, n);

})( window, 'vunetRum', document, 'https://cdn.vunet.ai/rum/vunet-rum.js');

window.vunetRum.onReady(function () {

window.vunetRum.initialize({

collectionSourceUrl: "<VUNET_TELEMETRY_RECEIVER_URL>", //mention the urlwhere the otel collector is running

serviceName: '<SERVICE_NAME>',// mention the service name of the application

applicationName: '<APPLICATION_NAME>', // mention the name of the application

decideApiEndpoint: "/vuSmartMaps/api/rum/",

collectErrors: true,

dropShortTracesMs: 100,//drop traces shorter than 100 milliseconds

authorizationToken: "ef7ae8b1fa097092a66a56882fd8366cfbdb1b6848ae0d529a21a68a94e245020"

});

});

</script>


NOTE: Ensure that the CSP is configured to allow loading files from our CDN https://cdn.vunet.ai/rum/vunet-rum.js.
If the JS file is loaded correctly, then it should function as expected. If there are difficulties in receiving data, verify that the JS file is properly loaded and that the collectionSourceUrl is correct and accessible.
Update the Variables

VUNET_TELEMETRY_RECEIVER_URL: URL of the reverse proxy
Example: http://10.1.1.1/rum/v1/traces
SERVICE_NAME: Service name for the application
Example: 'vubank-frontend'
APPLICATION_NAME: Name of the application
Example: 'IBMB'
Container
For containerized environments, follow these steps:

Add the RUM script to your page header as shown above.
Rebuild the Docker container with the updated codebase.

Kubernetes
For Kubernetes environments, follow these steps:

Add the RUM script to your page header as shown above.
Rebuild and redeploy the Docker container in your Kubernetes environment.





Metrics Collected

NameDescriptionData Type
timestampThe timestamp when the span or event occurred.DateTime64(6)
traceIdUnique identifier for a distributed trace that includes multiple spans.String
spanIdIdentifier for a specific span within a trace.String
span_parentSpanIdIdentifier linking this span to its parent span, indicating the hierarchical relationship.String
span_nameName or label for the span, typically indicating the operation or activity being traced.LowCardinality(String)
span_kindIndicates client/server/internal span categorization.LowCardinality(String)
span_start_timeTimestamp marking the start time of the span.DateTime64(6)
span_end_timeTimestamp marking the end time of the span.DateTime64(6)
span_durationNanoDuration of the span in nanoseconds.UInt64
status_codeStatus code indicating the result of the span (e.g., success, error).UInt8
is_root_spanBoolean indicating if the span is the root of the trace.Bool
resource_attributes_applicationApplication from which the span originated.LowCardinality(String)
resource_attributes_service_nameService name from which the span originated.LowCardinality(String)
span_attributes_browser_nameBrowser name of the end user.LowCardinality(String)
span_attributes_os_nameOperating system name of the end user.LowCardinality(String)
span_attributes_componentComponent associated with the span.String
span_attributes_http_urlFull HTTP URL involved in the span.String
span_attributes_instrumentation_library_nameName of the instrumentation library used.String
span_attributes_location_hrefLocation (href) of the span source.String
span_attributes_rum_session_idBrowser RUM session identifier.String
span_attributes_dns_lookup_timeTime spent on DNS lookup (ns).UInt64
span_attributes_tcp_connect_timeTCP connection time (ns).UInt64
span_attributes_secure_connect_timeTLS handshake time (ns).UInt64
span_attributes_request_timeRequest time (ns).UInt64
span_attributes_response_timeResponse time (ns).UInt64
span_attributes_server_timeTime spent on server processing (ns).UInt64
span_attributes_network_timeTotal network time (ns).UInt64
span_attributes_frontend_timeFrontend processing time (ns).UInt64
span_attributes_load_timeTotal page load time (ns).UInt64
span_attributes_processing_timeApplication processing time (ns).UInt64
span_attributes_http_action_typeHTTP action performed (e.g., GET, POST).String
span_attributes_longtask_nameName of the long task.String
span_attributes_longtask_durationDuration of the long task (ns).UInt64
span_attributes_root_span_http_urlRoot span's HTTP URL.String
span_attributes_root_span_operationOperation type of the root span.String
span_attributes_event_typeType of event (e.g., navigation, click).String
span_attributes_http_longtasks_sumSum duration of long tasks in the span (ns).UInt64
span_attributes_new_location_hrefUpdated URL after navigation.String
span_attributes_target_elementTarget HTML element interacted with.String
span_attributes_http_hostHost part of the HTTP URL.String
span_attributes_http_methodHTTP method used in the request.String
span_attributes_http_status_codeHTTP response status code.UInt32
span_attributes_http_time_in_xhr_callsTime spent in XHR calls (ns).UInt64
span_attributes_http_time_to_first_xhrTime until first XHR (ns).UInt64
span_attributes_http_time_to_last_xhrTime until last XHR (ns).UInt64
span_attributes_http_time_to_xhr_processing_endTime until end of XHR processing (ns).UInt64
span_attributes_clsCumulative Layout Shift score.UInt64
span_attributes_fpFirst Paint timing (ns).UInt64
span_attributes_fcpFirst Contentful Paint timing (ns).UInt64
span_attributes_ttfbTime to First Byte (ns).UInt64
span_attributes_fidFirst Input Delay (ns).UInt64
span_attributes_lcpLargest Contentful Paint timing (ns).UInt64
span_attributes_http_client_ipIP address of the client making the HTTP request.String
country_nameCountry of the client.String
region_nameRegion of the client.String
city_nameCity of the client.String
timezoneTimezone of the client.String
latitudeLatitude of the client’s location.Float64
longitudeLongitude of the client’s location.Float64
logs_attributes_error_messageA descriptive message of the error that occurred, typically from the client-side JavaScript runtime. This field contains the human-readable explanation of what went wrong.String
logs_attributes_error_nameRepresents the type or name of the error encountered on the client, such as TypeError, ReferenceError, SyntaxError, etc.String
logs_attributes_error_stackContains the full stack trace associated with the error message, including function names, line numbers, and file locations.String
messageGeneral message field from logs, which may overlap with logs_attributes_error_message but could also contain other structured log messages.String