Observability·6 min read·

Real User Monitoring (RUM) with Grafana Faro and OpenTelemetry

Capture real-world user performance, Core Web Vitals, and JavaScript exceptions using the Grafana Faro Web SDK connected to an OTel Collector.

NB

Netbay Infrastructure Team

Netbay Engineering

On this page

Synthetic API probes and server-side metrics only reveal half the truth of application performance. A backend API might respond in 20 milliseconds, but if an unoptimized JavaScript bundle freezes the client's browser for two seconds, or if third-party font loading blocks rendering on mobile devices, users experience severe slowness.

Real User Monitoring (RUM) tracks actual end-user experiences in the browser. Grafana Faro is an open-source Web SDK that captures Core Web Vitals (LCP, FID, CLS), unhandled JavaScript exceptions, network timing, and client-side telemetry. By streaming Faro beacons directly to an OpenTelemetry Collector on your Linux VPS, you correlate frontend errors with backend distributed trace spans without recurring SaaS fees.

Faro Architecture and Data Flow

  1. **Browser Client**: Integrates the lightweight @grafana/faro-web-sdk package into modern web apps.
  2. **Beacons**: Telemetry is batched into compact JSON beacons transmitted via navigator.sendBeacon so data transfer never delays navigation.
  3. **OTel Ingress**: An OpenTelemetry Collector receiver accepts Faro payloads on an internal or public endpoint.
  4. **Grafana Dashboards**: Visualizes Core Web Vitals alongside backend traces in Tempo and application logs in Loki.

This unified tracing model links browser frontend click events directly to backend database queries.

Integrating the Grafana Faro Web SDK

Add the Faro SDK and tracing instrumentation to your web frontend:

bash
npm install @grafana/faro-web-sdk @grafana/faro-web-tracing

Initialize Faro in your application entrypoint:

typescript
// rum-telemetry.ts
import { initializeFaro, LogLevel } from "@grafana/faro-web-sdk";
import { TracingInstrumentation } from "@grafana/faro-web-tracing";

export const faro = initializeFaro({
  url: "https://telemetry.example.com/collect",
  app: {
    name: "storefront-frontend",
    version: "2.4.1",
    environment: "production",
  },
  instrumentations: [
    // Automatically capture fetch and XHR timing
    new TracingInstrumentation(),
  ],
  // Redact customer emails and sensitive input values
  beforeSend: (item) => {
    if (item.meta?.user?.email) {
      item.meta.user.email = "[REDACTED]";
    }
    return item;
  },
});

console.log("Grafana Faro RUM initialized.");

Faro automatically hooks into the browser PerformanceObserver API, calculating:

  • **LCP (Largest Contentful Paint)**: Render time of the largest visible content element.
  • **CLS (Cumulative Layout Shift)**: Unexpected visual page movement.
  • **INP (Interaction to Next Paint)**: Browser responsiveness to user clicks and taps.
Expand
Grafana Faro RUM
Grafana Faro Real User Monitoring and Core Web Vitals

Propagating W3C Trace Context Across Client and Server

To trace a transaction from a button click in the browser all the way to a database query on your Linux VPS, propagate W3C traceparent headers:

typescript
// api-client.ts
import { faro } from "./rum-telemetry";

export async function fetchCatalog(category: string) {
  const span = faro.api.getOTEL()?.trace.getTracer("storefront").startSpan("fetchCatalog");

  try {
    const response = await fetch("/api/v1/products?category=" + encodeURIComponent(category), {
      headers: {
        // Faro automatically injects traceparent header
        Accept: "application/json",
      },
    });
    return await response.json();
  } catch (error) {
    faro.api.pushError(error as Error, { context: { category } });
    throw error;
  } finally {
    span?.end();
  }
}

When the backend receives traceparent, it attaches its server-side spans to the same Trace ID, providing complete end-to-end visualization in Grafana Tempo.

End-to-End Real User Monitoring (RUM) Flow User Browser - Core Web Vitals (LCP/CLS) - JS Error stack traces - W3C traceparent header - PII redacted on client navigator.sendBeacon OTel Collector Gateway - Ingests Faro beacons - Correlates client trace - Batch buffer memory - High-Speed SSD caching Lucknow DC01 VPS Grafana Dashboards - Real user latency charts - Tempo: unified trace view - Loki: browser console logs - Zero third-party fees Intel Xeon Platinum Faro connects frontend client latency directly with backend server spans
Grafana Dashboards, OpenTelemetry Tracing, and RUM Monitoring
YouTube

Inspecting Beacons and Verifying Traces

Verify that incoming client beacons reach your collector:

bash
# Inspect real-time collector log output
sudo journalctl -u otelcol-contrib -f | grep "storefront-frontend"

Grafana Faro delivers deep frontend visibility without compromising user privacy or paying proprietary monitoring subscriptions.

Deploy your telemetry pipelines on Netbay Linux VPS in under 60 seconds with High-Speed SSD in Lucknow DC01 — netbayhosts.in.

Keep reading

Follow along on a real VPS

Deploy Linux in under 60 seconds

These guides are written against Ubuntu, Debian, and RHEL-family images — the same ones on NetBay.

Deploy an instance