grafanafarorum
Reactive icon

GrafanaFaroRUM

Stable version 1.0.0 (Compatible with OutSystems 11)
Uploaded
 on 7 Oct (8 hours ago)
 by 
0.0
 (0 ratings)
grafanafarorum

GrafanaFaroRUM

Documentation
1.0.0

Grafana Faro RUM

Sends Real User Monitoring data from OutSystems 11 Reactive Web apps to Grafana (Grafana Cloud Frontend Observability or Grafana Alloy), using the Grafana Faro Web SDK 2.12.1.

Records page loads, web vitals, JS errors, OutSystems exceptions you report, view changes, custom events and logs, user id, and optional fetch/XHR traces.

No CDN at runtime: the Faro scripts ship inside the module. No proxy: the browser posts straight to Grafana. Fails silent: if disabled, misconfigured or the collector is down, the app runs as if the component were not there.


Requirements

  • OutSystems 11, Reactive Web app
  • Grafana Cloud (free tier is enough) or Grafana Alloy with faro.receiver
  • Browser can reach the collector over HTTPS


1. Create the Grafana app

  1. Grafana Cloud: Observability > Frontend > Frontend Apps > Create new.
  2. App name: the name you want to see in Grafana.
  3. CORS Allowed Origins: your OutSystems app origin, scheme and host only, for example https://myenv.outsystemscloud.com. One * wildcard is allowed. Changes take about 2 minutes.
  4. Save, open the app's Web SDK Configuration tab, copy the URL. It looks like https://faro-collector-prod-<region>.grafana.net/collect/<app key>.

The URL is visible in the browser. It is an ingest address, not a secret. Protect it with CORS.


2. Install

  • Install the component from the Forge.
  • In your app: Manage Dependencies (Ctrl+Q), select GrafanaFaroRUM, tick the FaroRUM block and the Faro_* actions you use.
  • Service Center > Factory > Modules > GrafanaFaroRUM > Site Properties. Set:

            Enabled = True

            CollectorUrl = the URL you copied

            Environment = dev, qa or prod (optional)

  • Drop the FaroRUM block into your Layout, once. It renders nothing.
  • Publish your app


Site property values are per environment and are not moved by deployments. Set them in each environment. No republish is needed to change them.

After you update the component, republish every app that uses it. A Reactive app serves the component's scripts from its own published copy.


3. Check it works

In the browser console:

OSFaro.getStatus()

Expect initialized: true and a sessionId. OSFaro is not defined means Faro did not start.

In the Network tab, filter on collect: POSTs to your collector should return 202.


4. Site properties

Module GrafanaFaroRUM. Take effect on the next page load.

  • Enabled (False): master switch. False means nothing loads, nothing is sent.
  • CollectorUrl (empty): must start with https://. http://localhost is allowed for development. Anything else keeps Faro off and writes one line to the module's General log.
  • ApiKey (empty): optional ingest key. Visible in the browser. Grafana Cloud URLs already contain the app key.
  • AppName (empty): name shown in Grafana. Empty uses the consuming module's name.
  • AppVersion (empty): free text.
  • Environment (empty): sent as the app environment.
  • SessionSampleRate (1.0): 0.0 to 1.0, clamped. Applies to new sessions only. A session keeps its decision.
  • TracingEnabled (False): loads the tracing script and records fetch/XHR spans.
  • TracePropagationUrls (empty): comma-separated regexes that may receive a traceparent header. Empty means same-origin only.
  • CaptureConsole (False): send console.warn and console.error.
  • IgnoreUrls (empty): comma-separated regexes. Matching requests are not reported. The collector URL is always ignored.
  • IgnoreErrors (empty): comma-separated regexes matched against error messages.
  • StripQueryString (True): remove ?query and #fragment from page, request and stack-trace URLs before sending.
  • SendUserIdentity (False): when False, Faro_SetUser sends the user id only.
  • AutoSetUser (False): sends the logged-in user's id (never name or email) when Faro starts.
  • StartPaused (False): Faro starts paused and sends nothing until Faro_Resume.
  • GlobalAttributesJson (empty): flat JSON object added as session attributes to every event, for example {"tenant":"acme","region":"sg"}. Invalid JSON is ignored.


5. Client actions

All are public, never raise, and do nothing when Faro is not running. *Json inputs take a flat JSON object. Invalid JSON is ignored. Values are sent as text.

  • Faro_Initialize(AppNameOverride): loads and starts Faro. The block calls it. Safe on every screen.
  • Faro_SetUser(UserId, Username, Email, AttributesJson): username and email are sent only if SendUserIdentity is True.
  • Faro_ResetUser: clears the user. Call on logout.
  • Faro_PushEvent(Name, AttributesJson): custom event.
  • Faro_PushLog(Message, Level, ContextJson): Level is debug, info (default), warn or error.
  • Faro_PushError(Message, ContextJson): report an error.
  • Faro_ReportException(ExceptionMessage, ContextJson): for OnException handlers. Adds screen and source=OnException.
  • Faro_SetView(ViewName): set the view name. Navigation is already tracked.
  • Faro_Pause: stops sending. Events raised while paused are dropped, not queued.
  • Faro_Resume: sends again.
  • Faro_GetStatus: outputs IsInitialized, IsPaused, SessionId, WrapperVersion.
  • FaroRUM block inputs (both optional): AppNameOverride, ViewName (forces the view name; default comes from the URL).


6. Common patterns

Report handled exceptions. Exceptions caught in an OnException handler never reach the browser's error handler. In the handler, call Faro_ReportException with ExceptionMessage = AllExceptions.ExceptionMessage.

Identify the user. Call Faro_SetUser(UserId) after login and Faro_ResetUser on logout. Faro keeps the session across page reloads but not the user, so set it again after each full page load. Or set AutoSetUser to True.

Consent. Set StartPaused to True. Call Faro_Resume when the user agrees and Faro_Pause if they withdraw.

Support. Show the SessionId from Faro_GetStatus on error screens so support can find the session in Grafana.

Business dimensions. Put tenant, region or release in GlobalAttributesJson.


7. Behaviour to know

  • Navigation is tracked automatically. A bare module URL (/Module/) is reported as (default screen). Other screens use the last URL segment.
  • The user is not kept across page reloads. The session is.
  • Session sampling and session attributes are fixed when the session starts. Changing the site property only affects new sessions.
  • Pausing drops events. Wait about 2 seconds after an event before pausing, so it has been sent.
  • Dead or unreachable collector: Faro retries a few times, then drops the data. The app is unaffected.
  • Request URLs in resource timings include the OutSystems platform's own calls (for example moduleversioninfo). Use IgnoreUrls to hide ones you don't want.


8. Find your data

Frontend Apps > your app: overview (page loads, errors, web vitals) and the Sessions tab, which shows one session's events, logs and errors in order.

Explore > your stack's logs data source (Loki). The app name is the service_name label:

{service_name="YourAppName"} |= "demo_click"

{service_name="YourAppName"} | logfmt | user_id != ""

Fields such as event_name, user_id and session_id are inside the log line, not labels.

Traces (tracing on): the traces data source (Tempo), search by app name.

Data can take a minute or two. Check the time range first.


9. CSP

No script-src change: the scripts are served from your own app. Add the collector host to connect-src:

connect-src 'self' https://faro-collector-prod-ap-southeast-1.grafana.net


10. Privacy

Sent by default: page URL without query string or fragment, browser, OS and viewport details, page and resource timings, web vitals, JS errors with stack traces, view changes, a random session id.

Not sent unless you turn on SendUserIdentity and pass them: names and emails.

Watch for:

  • Error messages are sent as written. Do not put personal data in exception messages, or filter them with IgnoreErrors.
  • Custom events, logs and attributes contain whatever you put in them.
  • If you need consent first, use StartPaused and Faro_Resume.


11. Tracing

With TracingEnabled True, fetch and XHR calls become spans. traceparent is added to same-origin requests only. To allow another host, list it in TracePropagationUrls, for example ^https://api\.example\.com/. It is never added to third parties by default.

The browser spans always appear. Linking them to back-end traces needs a back end that honours traceparent. OutSystems server-side continuation is not guaranteed.


12. Demo app

GrafanaFaroRUM_Demo has a layout with the FaroRUM block, a Home screen and a Second screen. Home has a status panel and buttons for: JS error, OutSystems exception, custom event, log, set and reset user, pause and resume, a server call, and navigation to Second. Set Enabled and CollectorUrl, click through, and watch Grafana.


13. Troubleshooting

  • Nothing in Grafana: check Enabled, CollectorUrl, the selected app and the time range. OSFaro.getStatus() should show initialized: true.
  • Faro does not start: Service Center > Monitoring > Logs > General, module GrafanaFaroRUM. A line "Faro disabled: CollectorUrl must start with https://..." means the URL was rejected.
  • CORS error: the origin in the Grafana app's CORS list must match exactly. Allow 2 minutes.
  • Requests blocked: add the collector host to CSP connect-src.
  • Some visitors send nothing: SessionSampleRate is below 1.
  • User missing after reload: call Faro_SetUser on every load, or use AutoSetUser.
  • Consent test events missing: events while paused are dropped.
  • Updated component has no effect: republish the consuming app, hard-refresh, check OSFaro.version.