> ## Documentation Index
> Fetch the complete documentation index at: https://docs.flashduty.com/llms.txt
> Use this file to discover all available pages before exploring further.

# RUM custom dashboards

> Turn an Explorer analytics question into a Flashduty RUM custom dashboard: panel types, panel queries, dashboard variables, saving from the Explorer, table drill-down, version history and the trash.

## Overview

A custom dashboard is an extra tab in the **Insights** tab bar, next to the built-in Overview, Performance, Errors and Resources tabs. Each dashboard holds panels (charts), and a panel's query is the Explorer's analytics question: event type + aggregation + group-by field + DQL filter. That makes a one-off analysis such as "which browsers do the errors come from" or "which page loads slowest" a dashboard you can keep coming back to, without rebuilding the query.

## Entry points and routes

| Where | Address | Notes |
| - | - | - |
| Dashboard tab | `/rum/dashboard/custom/:id` | Opens one dashboard; it shows as a tab of Insights |
| Edit mode | `/rum/dashboard/custom/:id?edit=1` | Opens straight into editing; changes go into a browser draft first |
| New dashboard | `/rum/dashboard/custom/new?edit=1` | From the **+** menu at the right of the tab bar |
| Dashboard management | `/rum/dashboard/manage` | The dashboard list: search, delete, trash |

The **+** menu at the right of the tab bar has two items:

* **New dashboard**: opens an empty dashboard in edit mode. This needs the **Dashboards Manage** permission; without it, the item is not shown.
* **Manage dashboards**: opens the management page; viewing it needs no edit permission.

The tab bar lists every dashboard by title, up to 100; beyond that, reach the rest from the management page.

## Application and time range

* A dashboard follows the **application** and **time range** in the top-right corner of the page. When you open a dashboard whose link carries no time range, the dashboard's own default time range applies; changing the time range on a dashboard also changes the page's time picker.
* Switching tabs carries the page's application and time range over. A dashboard's `env`, `service` and `version` variables and the matching filters of the built-in tabs are translated into each other; other variables are not carried across tabs.

## Panel types

The panel editor's **Visualization** offers four kinds:

| Type | Description |
| - | - |
| **Time series** | The measure over time, drawn as lines or bars |
| **Table** | One row per group, with drill-down (see [Table drill-down](#table-drill-down)) |
| **Stat** | One key number, with optional threshold colors; a stat does not use a group-by |
| **Text** | Markdown text, bound to no query |

## Adding a panel

<Steps>
  <Step title="Enter edit mode">
    Open the dashboard and click **Edit** in the top-right corner, or open a link with `?edit=1`. Edit mode is one browser draft submitted as a whole; a page refresh loses the draft, and leaving warns you first.
  </Step>

  <Step title="Add a chart">
    Click **Add panel** to open the panel editor. A dashboard organizes panels into tabs and sections; a new dashboard starts with one tab.
  </Step>

  <Step title="Configure the query">
    Pick the application (or **Page application**), the event type, the aggregation and measured field, the group-by field and the number of groups to keep, then write a DQL filter if you need one. The preview runs once the query is complete: after a picker change it reruns once the change settles, and a DQL filter runs on Enter or blur. Saving does not require a successful preview.
  </Step>

  <Step title="Pick a chart type and a name">
    A title you leave empty is generated from the query, such as "P75 Time to First Byte · by Browser Name"; an empty description becomes the application name as the panel subtitle, which tells panels querying different applications apart.
  </Step>

  <Step title="Apply and save the dashboard">
    Click **Apply** to put the panel back on the canvas, then **Save** to submit. You can fill in a **version message** (optional); each save produces a new version.
  </Step>
</Steps>

## Panel queries

A panel query has the same parts as the Explorer's analytics view:

| Part | Description |
| - | - |
| **Application** | One application, or **Page application** (`$app`, so the panel follows the page's application) |
| **Event type** | Sessions, Views, Resources, Actions, Errors, Long Tasks, Vitals |
| **Aggregation / measured field** | Count, unique count, average, sum, min, max, P50 / P75 / P90 / P95 / P99; every aggregation except Count needs a field |
| **Group-by field / top** | Split by a field and keep the top `5`, `10`, `20` or `50` groups |
| **DQL filter** | The Explorer's search syntax, see [Data query syntax](../explorer/data-query) |

Group-by fields are limited by field cardinality, exactly as in the Explorer (see [Analytics · Group-by field](../explorer/analytics#group-by-field)): a field that is an event's own ID cannot be grouped by, and any other high-cardinality field takes Count or Sum only, with a time range of at most 7 days.

When the result is estimated from a sample, the panel shows a **Sampled** badge and its explanation.

## Dashboard variables

The variable bar sits at the top of the dashboard. A new dashboard starts with three field variables, `env`, `service` and `version`, all defaulting to **All** (All means no condition).

| Variable kind | Description |
| - | - |
| Built-in `$app` | The page's current application. Choosing **Page application** in a panel query is the same as using `$app`; only an application's `application_id` can reference it |
| Field variable | Candidates are the values of one RUM field; multi-select, All allowed |
| Custom variable | Candidates you type in (one per line, `label=value` or a bare value); single or multi-select |

* Reference a variable in a panel's DQL as `${name}` or `$name`, such as `env:${env}`. A variable with several values expands to `(a OR b)`; with **All** selected, or with no value, the whole condition holding the reference (`env:${env}`, `-env:${env}`, `NOT env:${env}`, and a value list containing it) is dropped rather than queried as an empty value.
* References are replaced in the browser before the query runs, so a panel's DQL has to fill in into a complete statement to return data.
* A new panel's filter starts with the dashboard's field variables that its event type has.
* Renaming a variable rewrites the queries that reference it; a variable still referenced cannot be deleted until those references are cleaned up.
* Variable selections are kept in the link (parameters such as `var-env=...`), so copying the link shares the same selection.

<Note>
  A RUM dashboard has just these two kinds of custom variables: field variables that list the values of a RUM field, and custom variables with candidates you type in. Datasource variables and Prometheus / SQL / logs variable queries do not apply and never appear on a dashboard.
</Note>

## Saving from the Explorer

In the Explorer's analytics chart toolbar, **Save to dashboard** turns the current question into a dashboard panel:

* The chart type can be **Time series / Table / Stat**; pies and distributions are not supported yet and the button says "Pies and distributions cannot be saved to a dashboard yet".
* You can **append to an existing dashboard** (its edit mode opens with this panel appended, and nothing is written before you save), or **create a new dashboard** (a dashboard holding just this panel is created first, then its edit mode opens).
* The panel keeps the current time range and filter and picks up the dashboard's `env` / `service` / `version` variables; its title is generated from the query.

For the procedure and limits, see [Analytics · Saving to a dashboard](../explorer/analytics#saving-to-a-dashboard).

## Table drill-down

Every row of a **Table** panel carries an "Open in Explorer: `field = value`" link. Clicking it opens the Explorer's analytics view with the panel's query and aggregation, its filter narrowed to that row's group value, over the dashboard's current time range.

* A table without a group-by has no drill-down link.
* When a group value contains characters that a DQL condition cannot express exactly, such as quotes or brackets, the link matches by wildcard instead, and its title is marked "(approximate wildcard match)".

## Version history and restore

**Version history** in the dashboard's **⋯** menu opens the version list:

* Each save (deleting and restoring included) produces a new version; the most recent **20** versions are kept and older ones are pruned.
* The table lists the **version** (`v1`, `v2`, …), its **time**, the **actor** and the **message**, and marks the current version as **current**. While the dialog is open, tick two versions and click **Compare** to diff what each one saved.
* Restoring an earlier version saves that version's content as a new version, so the version you restored from stays in the history and you can restore back to it.

## Deleting and the trash

* **Delete** in the dashboard's **⋯** menu moves the dashboard to the trash; the confirmation names the dashboard and says it "will be moved to trash and purged after 30 days."
* **Trash** on the management page lists deleted dashboards with the note "Deleted dashboards are kept for 30 days and can be restored here."; the **restore** icon at the end of a row puts the dashboard back in the list and in the tab bar.
* A dashboard left in the trash for more than 30 days is purged and cannot be restored.

<Note>
  RUM dashboards have no folders: they are not grouped, and the management page has no folder tree or cross-folder move. The list can be searched by title.
</Note>

## Permissions

Creating, editing, deleting and restoring a dashboard needs the **Dashboards Manage** permission. Without it:

* the **+** menu has no **New dashboard**, and the management page has no **New dashboard** button and no delete or restore entry;
* a dashboard has no **Edit**, and its **⋯** menu has no **Clone** or **Delete**;
* you can still view every dashboard, change its variables and time range, and inspect its content with **Export JSON** and **Version history**.

## Limits

| Item | Limit |
| - | - |
| Tabs in a dashboard | 10 |
| Sections per tab | 10 |
| Panels per tab | 30 |
| Panels per dashboard | 100 |
| Queries per tab | 100 |
| Queries per dashboard | 300 |
| Variables | 20 |
| Candidates per variable | 1000 |
| Data links per panel | 5 |
| Queries in a time series panel | 1–26 |
| Queries in a table / stat panel | exactly 1 |
| Markdown size in a text panel | 64 KB |
| Title length | 189 characters |
| Description length | 1024 characters |
| Dashboard definition size | 1 MB |
| Default time ranges | `now-15m`, `now-30m`, `now-1h`, `now-3h`, `now-6h`, `now-12h`, `now-24h`, `now-7d` |
| Auto refresh options | off, `30s`, `1m`, `5m` |

## Next steps

<CardGroup cols={2}>
  <Card title="Web RUM analytics" icon="chart-line" href="./web">
    The four analysis dimensions of the built-in Insights dashboard
  </Card>

  <Card title="Analytics" icon="chart-column" href="../explorer/analytics">
    Aggregations, groups, chart types and drill-down
  </Card>

  <Card title="Data query syntax" icon="magnifying-glass" href="../explorer/data-query">
    The search syntax behind a panel's filter
  </Card>

  <Card title="Explorer overview" icon="compass" href="../explorer/overview">
    The list and analytics view modes
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.