|
| 1 | +--- |
| 2 | +title: "UI Telemetry" |
| 3 | +llm_description: "Explains what anonymous frontend telemetry data Dappnode collects, how it flows through a proxy to Grafana Cloud, and how to enable or disable it." |
| 4 | +--- |
| 5 | + |
| 6 | +# UI Telemetry |
| 7 | + |
| 8 | +Dappnode collects **optional, anonymous frontend telemetry** from the Dappnode UI to help improve the product. This telemetry is powered by the [Grafana Faro Web SDK](https://github.com/grafana/faro-web-sdk/), an open-source frontend observability library. |
| 9 | + |
| 10 | +:::caution |
| 11 | +UI Telemetry is **disabled by default**. No data is sent until you explicitly enable it in the Dappnode settings. You are always in control. |
| 12 | +::: |
| 13 | + |
| 14 | +## Why We Collect Telemetry |
| 15 | + |
| 16 | +This telemetry data helps the Dappnode team: |
| 17 | + |
| 18 | +- **Improve product performance** — identify slow pages, rendering bottlenecks, and resource loading issues in real-world conditions |
| 19 | +- **Help users in support** — inspect error logs and traces to diagnose issues faster when users report problems |
| 20 | +- **Identify and fix UI bugs** — detect unhandled exceptions and crashes that users may not report |
| 21 | +- **Prioritize development efforts** — understand which pages and features are most used so we can focus on what matters most |
| 22 | + |
| 23 | +## Architecture Overview |
| 24 | + |
| 25 | +Every Dappnode user who has telemetry enabled sends metrics from their browser to a **proxy server** operated by Dappnode. The proxy applies filtering and security checks before forwarding the data to **Grafana Cloud** for visualization and processing. |
| 26 | + |
| 27 | +``` |
| 28 | +┌──────────────────┐ ┌──────────────────────────────────┐ ┌───────────────┐ |
| 29 | +│ Dappnode UI │──────▶│ Proxy │──────▶│ Grafana Cloud │ |
| 30 | +│ (your browser) │ HTTPS │ grafana-cloud-proxy.dappnode.net│ │ (storage & │ |
| 31 | +│ │ │ filtering & security layer │ │ dashboards) │ |
| 32 | +└──────────────────┘ └──────────────────────────────────┘ └───────────────┘ |
| 33 | +``` |
| 34 | + |
| 35 | +:::info |
| 36 | +The proxy acts as a security and filtering layer between your browser and Grafana Cloud. Your Dappnode UI never communicates directly with Grafana Cloud — all telemetry goes through the Dappnode-operated proxy first. |
| 37 | +::: |
| 38 | + |
| 39 | +## What Data Is Collected |
| 40 | + |
| 41 | +The following sections describe each category of data collected by the Faro SDK with the current Dappnode configuration. |
| 42 | + |
| 43 | +### Errors & Exceptions |
| 44 | + |
| 45 | +Unhandled JavaScript errors and rejected promises are automatically captured. This includes: |
| 46 | + |
| 47 | +- **Error message** and **error type** |
| 48 | +- **Stack trace** (file name, line number, column number) |
| 49 | +- The browser's `window.onerror` and `onunhandledrejection` events |
| 50 | + |
| 51 | +This helps the team detect crashes and bugs that occur in production, even when users don't report them. |
| 52 | + |
| 53 | +### Console Logs |
| 54 | + |
| 55 | +The SDK captures browser console messages at the `console.error` and `console.warn` levels. These provide context around errors and help diagnose issues. |
| 56 | + |
| 57 | +:::note |
| 58 | +Lower-level console methods (`console.log`, `console.debug`, `console.trace`) are **not captured** by default. |
| 59 | +::: |
| 60 | + |
| 61 | +### Web Vitals (Performance Metrics) |
| 62 | + |
| 63 | +[Web Vitals](https://web.dev/vitals/) are industry-standard metrics that measure real-user experience. The following are collected: |
| 64 | + |
| 65 | +| Metric | What it measures | |
| 66 | +| ----------------------------------- | ------------------------------------------------------------------- | |
| 67 | +| **TTFB** (Time to First Byte) | How long until the browser receives the first byte from the server | |
| 68 | +| **FCP** (First Contentful Paint) | How long until the first text or image appears on screen | |
| 69 | +| **LCP** (Largest Contentful Paint) | How long until the largest visible element finishes rendering | |
| 70 | +| **FID** (First Input Delay) | Delay between a user's first interaction and the browser's response | |
| 71 | +| **INP** (Interaction to Next Paint) | Responsiveness across all interactions during the session | |
| 72 | +| **CLS** (Cumulative Layout Shift) | How much unexpected layout movement occurs on the page | |
| 73 | + |
| 74 | +### Navigation & Resource Performance |
| 75 | + |
| 76 | +The SDK automatically tracks page load and resource fetch performance, including: |
| 77 | + |
| 78 | +- **Page load timing** — total load time, DOM parsing time, DOM processing time, time to first byte |
| 79 | +- **Resource timing** — load duration of JavaScript, CSS, images and other assets (DNS lookup, TCP handshake, TLS negotiation, request/response time) |
| 80 | + |
| 81 | +This data helps identify slow-loading pages and bottleneck resources. |
| 82 | + |
| 83 | +### Session Tracking |
| 84 | + |
| 85 | +An **anonymous session ID** is generated and stored in your browser's `localStorage` to group related events together. This allows the team to understand sequences of errors or performance issues within a single session. |
| 86 | + |
| 87 | +- Sessions have a **maximum lifetime of 4 hours** |
| 88 | +- Sessions expire after **15 minutes of inactivity** |
| 89 | +- Session lifecycle events are tracked: `session_start`, `session_resume`, `session_extend` |
| 90 | +- **No user identity** is attached to sessions — they are completely anonymous |
| 91 | + |
| 92 | +### Page & Route Tracking |
| 93 | + |
| 94 | +The URL path of each page you visit within the Dappnode UI is recorded. This uses React Router v6 integration to track single-page application (SPA) view changes. |
| 95 | + |
| 96 | +- Only the **route path** is tracked (e.g., `/stakers/ethereum`) |
| 97 | +- This helps understand which sections of the UI are most used and where errors occur |
| 98 | + |
| 99 | +### Distributed Traces |
| 100 | + |
| 101 | +HTTP requests made by the Dappnode UI (via `fetch` and `XMLHttpRequest`) are traced using [OpenTelemetry](https://opentelemetry.io/). For each request, the following timing data is captured: |
| 102 | + |
| 103 | +- Request duration, DNS lookup time, TCP handshake time, TLS negotiation time |
| 104 | +- Request and response time, redirect time |
| 105 | +- Response status and resource size |
| 106 | + |
| 107 | +:::note |
| 108 | +Requests to the telemetry proxy itself are excluded from tracing to avoid recursive data collection. |
| 109 | +::: |
| 110 | + |
| 111 | +## What We Do NOT Collect |
| 112 | + |
| 113 | +:::tip |
| 114 | +Dappnode takes your privacy seriously. The following data is **never** collected: |
| 115 | + |
| 116 | +- **Personal information** — no names, emails, or account identifiers |
| 117 | +- **Form inputs or credentials** — no passwords, seed phrases, or private keys |
| 118 | +- **Wallet addresses** — no blockchain addresses of any kind |
| 119 | +- **Screenshots or session recordings** — no visual capture of your screen |
| 120 | +- **Keystrokes** — no keyboard input is recorded |
| 121 | + ::: |
| 122 | + |
| 123 | +## How to Enable or Disable Telemetry |
| 124 | + |
| 125 | +You can enable or disable UI Telemetry at any time from the Dappnode settings: |
| 126 | + |
| 127 | +1. Navigate to [http://my.dappnode/system/advanced](http://my.dappnode/system/advanced) |
| 128 | +2. Scroll to the **"UI Telemetry"** section |
| 129 | +3. Toggle the switch to **enable** or **disable** telemetry |
| 130 | +4. The change takes effect immediately — no restart required |
| 131 | + |
| 132 | +When disabled, the Faro SDK is paused and **no data is sent** to the proxy or Grafana Cloud. |
0 commit comments