Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions docs/docs/developers/build/custom-apis/adhoc-measures.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
---
title: Adhoc Measures in APIs
description: Define measures at query time with an arithmetic expression over existing measures
sidebar_label: Adhoc Measures
sidebar_position: 35
---

An adhoc measure is a measure you define in the query itself, by combining the metrics view's existing measures with an arithmetic expression such as `revenue - cost`. It is the API counterpart of the [adhoc measures](/guide/dashboards/explore/adhoc-measures) that users create in Explore dashboards. Use one when a client needs a derived value that isn't worth adding to the [metrics view](/developers/build/metrics-view).

An adhoc measure uses the `expression` compute:

| Field | Description |
|-------|-------------|
| `expression` | Required. An arithmetic expression over the metrics view's measure names. See the [expression reference](/guide/dashboards/explore/adhoc-measures#expression-reference). |
| `display_name` | Optional. The label used in exports and result metadata. |

The measure's `name` is the column name in the result. It must not match a dimension or measure in the metrics view.

## In a custom API

A custom API defined with a `metrics` query can include adhoc measures next to regular ones. This API returns revenue and profit margin by region:

```yaml
# apis/margin_by_region.yaml
type: api
metrics:
metrics_view: sales_metrics
dimensions:
- name: region
measures:
- name: revenue
- name: margin_pct
compute:
expression:
expression: round((revenue - cost) / revenue * 100, 1)
display_name: Margin %
sort:
- name: margin_pct
desc: true
```

```json
[
{"region": "US", "revenue": 100, "margin_pct": 40},
{"region": "DK", "revenue": 50, "margin_pct": 10}
]
```

You can sort on an adhoc measure by its `name`, like any other measure. See [Calling APIs](/developers/build/custom-apis/calling) for how to call the endpoint.

## In the metrics view query APIs

The runtime's `MetricsViewAggregation` API accepts the same compute. In the REST API, the `expression` object goes directly on the measure:

```bash
curl -X POST "http://localhost:9009/v1/instances/default/queries/metrics-views/sales_metrics/aggregation" \
-H "Content-Type: application/json" \
-d '{
"dimensions": [{"name": "region"}],
"measures": [
{"name": "revenue"},
{"name": "margin_pct", "expression": {"expression": "(revenue - cost) / revenue", "displayName": "Margin %"}}
],
"sort": [{"name": "margin_pct", "desc": true}]
}'
```

The `MetricsViewTimeSeries` API takes adhoc measures in `ephemeralMeasures`, alongside or instead of `measureNames`. Only the `expression` compute is supported there:

```bash
curl -X POST "http://localhost:9009/v1/instances/default/queries/metrics-views/sales_metrics/timeseries" \
-H "Content-Type: application/json" \
-d '{
"measureNames": ["revenue"],
"ephemeralMeasures": [
{"name": "avg_order_value", "expression": {"expression": "round(revenue / orders, 2)"}}
],
"timeGranularity": "TIME_GRAIN_DAY"
}'
```

## Validation and security

Rill parses the expression before it runs the query and returns an error when the expression is invalid, for example when it references an unknown measure or uses an aggregate function such as `sum()`. It never passes your expression text to the database: it generates the SQL from the parsed expression, and division by zero returns `null`.

Referenced measures are subject to the metrics view's [security policies](/developers/build/metrics-view/security). A caller can only reference measures they have access to, and row filters apply to the result as they do for any other query.
37 changes: 37 additions & 0 deletions docs/docs/developers/build/dashboards/canvas-widgets/data.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,43 @@ Tables display detailed data in a structured format with customizable columns.
codeLanguage="yaml"
/>

## Adhoc measures

Tables, pivots, KPIs, KPI grids, leaderboards, and charts can define their own [adhoc measures](/guide/dashboards/explore/adhoc-measures) with `adhoc_measures`. An adhoc measure combines the metrics view's measures with an arithmetic expression, and you reference it by `name` wherever the widget accepts a measure.

```yaml
- pivot:
metrics_view: sales_metrics
row_dimensions:
- region
measures:
- revenue
- margin_pct
adhoc_measures:
- name: margin_pct
display_name: Margin %
expression: (revenue - cost) / revenue
format_preset: percentage
```

In the canvas editor, select **Create adhoc measure** at the bottom of a widget's measure selector to open the same dialog as in Explore dashboards. Rill writes the definition to the widget's `adhoc_measures`, and the measure selector shows an edit action next to it.

| Property | Description |
|----------|-------------|
| `name` | Required. The name you reference in `measures`, `columns`, or a chart field. It must start with a letter, contain only letters, numbers, and underscores, and not match a dimension or measure in the metrics view. |
| `expression` | Required. An arithmetic expression over the metrics view's measure names. See the [expression reference](/guide/dashboards/explore/adhoc-measures#expression-reference). |
| `display_name` | The label shown in the widget. Defaults to `name`. |
| `format_preset` | One of `humanize` (default), `none`, `currency_usd`, `currency_eur`, or `percentage`. |
| `description` | Text shown in the measure's tooltip instead of the expression. |

Adhoc measures belong to a single widget: to use the same calculation in two widgets, define it in both. When you write `adhoc_measures` by hand, follow the same rules as the editor:

- Reference only measures that don't use a window function, don't have required dimensions, and aren't time-comparison measures.
- Don't end a `name` with a comparison suffix, such as `_prev`, `_delta`, `_delta_perc`, or `_percent_of_total`, and don't include `_rill_` in it.
- Define at most 10 adhoc measures per widget.

For a calculation that many widgets or dashboards share, add a measure to the [metrics view](/developers/build/metrics-view) instead.

## Navigation

All Data widgets also provide a button to "Go to explore" that can navigate to the Explore dashboard if available.
Expand Down
100 changes: 100 additions & 0 deletions docs/docs/guide/dashboards/explore/adhoc-measures.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
---
title: "Adhoc Measures"
description: Define your own measures from existing ones, directly in an Explore dashboard
sidebar_label: "Adhoc Measures"
sidebar_position: 35
---

Adhoc measures let you define a new measure on the fly by combining the measures a dashboard already has, for example `revenue - cost` or `round(revenue / orders, 2)`. You don't need to edit the metrics view or wait for a developer to add the measure.

An adhoc measure behaves like any other measure: it appears in the big numbers, time series charts, leaderboards, dimension tables, [Time Dimension Detail](/guide/dashboards/explore/tdd), and [pivot tables](/guide/dashboards/explore/pivot). It is computed by Rill on top of the aggregated values of the measures it references, so it respects your filters and time range.

:::tip When to ask for a real measure
Adhoc measures are ideal for one-off analysis and for sharing an idea with a colleague. If a calculation is used across many dashboards, reports, or alerts, ask your project developer to add it to the [metrics view](/developers/build/metrics-view) so it has a single, governed definition.
:::

## Create an adhoc measure

1. Open the **All Measures** menu above the time series charts, and select **Create adhoc measure** at the bottom. In the pivot view, you can also select the **+** next to **Measures** in the sidebar.
2. Enter a **Name**, for example `Profit Margin`. This is the label shown in the dashboard.
3. Write the **Expression**. Type `@` to open a picker of the dashboard's measures, then use the arrow keys and **Enter**, or click, to insert one. You can search the picker by display name or by measure name. You can also click a measure under **Insert a measure** to add it at the cursor.
4. Optionally, add a **Description**. It is shown in the measure's tooltip instead of the expression.
5. Choose a **Format**: **Humanize** (the default), **None**, **Currency (USD)**, **Currency (EUR)**, or **Percentage**.
6. Select **Save**.

![Creating an adhoc measure, with the @ measure picker open](/img/explore/adhoc-measures/create-dialog.png)

Rill validates the expression as you type and shows an error below the input if it references an unknown measure or uses unsupported syntax. The new measure is added to the dashboard's visible measures, or as a column when you create it from the pivot view.

Once saved, you can select the adhoc measure anywhere you select a measure, for example in the leaderboard's **Showing** menu:

![A leaderboard ranked by the Profit Margin adhoc measure](/img/explore/adhoc-measures/leaderboard.png)

## Write an expression

An expression combines the measures in the dashboard with numbers, arithmetic operators, and a small set of functions. The measures are already aggregated, so the expression works on their totals for each row, not on individual records.

| Use case | Expression |
|----------|------------|
| Difference | `revenue - cost` |
| Ratio | `revenue / orders` |
| Percentage | `(revenue - cost) / revenue` with the **Percentage** format |
| Rounding | `round(revenue / orders, 2)` |
| Treat a missing value as zero | `coalesce(returns, 0) / orders` |
| Growth over a target | `revenue / 1000000 - 1` |

The **Percentage** format multiplies the value by 100, so write ratios as fractions, such as `(revenue - cost) / revenue`, instead of multiplying by 100 yourself.

### Expression reference

| Element | Supported |
|---------|-----------|
| Measure references | Measure names, such as `revenue`. The `@` picker inserts the name for you. Names that start with a digit, contain special characters, or are SQL keywords must be double-quoted, such as `"1d_qps"`. |
| Numbers | Integer and decimal literals, such as `100` or `0.25`, and `NULL` |
| Operators | `+`, `-`, `*`, `/`, `%` (modulo), unary minus, and parentheses |
| Functions | `abs`, `round`, `floor`, `ceil`, `sqrt`, `ln`, `exp`, `power`, `coalesce`, `nullif`, `greatest`, `least` |

Division is safe: dividing by zero returns an empty (null) value instead of an error.

The following are not allowed: dimensions or column names, strings, comments, aggregate functions such as `sum()` or `count()`, `CASE`, casts, comparisons, and subqueries. An expression must reference at least one measure, can be at most 1,024 characters long, and can nest at most 32 levels deep.

## Edit or delete an adhoc measure

Adhoc measures are marked with an **ƒx** icon. To change one:

- In the **All Measures** menu, select the pencil icon next to the measure to open **Edit adhoc measure**.
- In the pivot view, click the measure's chip and select **Edit** or **Delete**.
- In [Time Dimension Detail](/guide/dashboards/explore/tdd), use the edit action next to the measure in the measure selector.

![The All Measures menu, with the edit icon next to an adhoc measure](/img/explore/adhoc-measures/measures-menu.png)

![Edit and Delete actions on an adhoc measure in the pivot view](/img/explore/adhoc-measures/pivot-edit-menu.png)

The **Edit adhoc measure** dialog also has a **Delete** button. Deleting an adhoc measure removes it from every view of the dashboard.

## Share adhoc measures

Adhoc measures are saved in the dashboard URL, in the `adhoc_m` parameter, so they travel with the dashboard state:

- **Links:** When you copy the URL, anyone who opens it sees the same adhoc measures.
- **[Bookmarks](/guide/dashboards/bookmarks):** A bookmark restores the adhoc measures that were in use when you saved it.

The URL only includes the adhoc measures that the current view uses, such as the visible measures, the leaderboard measure, or the pivot's columns. This keeps links short.

Your browser also keeps a personal library of every adhoc measure you create for a metrics view. When you open any dashboard built on the same metrics view in that browser, your adhoc measures are available again, even if the URL doesn't include them. The library is stored only in your browser: other people see your adhoc measures only through a link or bookmark.

## Limits and rules

- **Up to 10 per dashboard.** A dashboard can hold at most 10 adhoc measures at a time.
- **Only the dashboard's measures can be referenced.** An expression can reference measures that are included in the dashboard, but not dimensions or other adhoc measures.
- **Some measures can't be referenced.** Measures that use a window function, have required dimensions, or are time-comparison measures are not offered in the picker and can't be used in an expression. See [advanced measures](/developers/build/metrics-view/measures/windows) for how these are defined.
- **Names are generated from the display name.** Rill derives the measure's internal name from its display name, for example `Profit Margin` becomes `profit_margin`, and adds a numeric suffix when it would collide with an existing field.

## Security

Adhoc measures follow the metrics view's [access policies](/developers/build/metrics-view/security). An expression can only reference measures you are allowed to see, and the values are computed with the same row filters that apply to you. Anyone who opens a shared link sees the result computed with their own access.

## Use adhoc measures elsewhere

- **Canvas dashboards:** Developers can define adhoc measures on canvas tables, pivots, charts, KPIs, and leaderboards. See [adhoc measures in canvas widgets](/developers/build/dashboards/canvas-widgets/data#adhoc-measures).
- **APIs:** Custom APIs and the metrics view query APIs accept the same expressions. See [adhoc measures in APIs](/developers/build/custom-apis/adhoc-measures).
12 changes: 12 additions & 0 deletions docs/docs/reference/project-files/component.md
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,18 @@ _[object]_ - (no description)

- **`measures`** - _[array of string]_ - List of measures to display _(required)_

- **`adhoc_measures`** - _[array of object]_ - Adhoc measures defined on this component, derived from the metrics view's measures with an arithmetic expression. Reference them by `name` in `measures`. See [Adhoc measures](/developers/build/dashboards/canvas-widgets/data#adhoc-measures).

- **`name`** - _[string]_ - Name used to reference the measure. Must not match a dimension or measure in the metrics view. _(required)_

- **`display_name`** - _[string]_ - Label shown in the component. Defaults to `name`.

- **`expression`** - _[string]_ - Arithmetic expression over the metrics view's measure names, for example `(revenue - cost) / revenue`. _(required)_

- **`format_preset`** - _[string]_ - Format preset for the values. Defaults to `humanize`.

- **`description`** - _[string]_ - Text shown in the measure's tooltip instead of the expression.

- **`time_range`** - _[string]_ - Time range for the table _(required)_

- **`row_dimensions`** - _[array of string]_ - Dimensions for table rows
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 26 additions & 0 deletions runtime/parser/schema/project.schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3301,6 +3301,32 @@ definitions:
items:
type: string
description: List of measures to display
adhoc_measures:
type: array
description: Adhoc measures defined on this component, derived from the metrics view's measures with an arithmetic expression. Reference them by `name` in `measures`. See [Adhoc measures](/developers/build/dashboards/canvas-widgets/data#adhoc-measures).
items:
type: object
properties:
name:
type: string
description: Name used to reference the measure. Must not match a dimension or measure in the metrics view.
display_name:
type: string
description: Label shown in the component. Defaults to `name`.
expression:
type: string
description: Arithmetic expression over the metrics view's measure names, for example `(revenue - cost) / revenue`.
format_preset:
type: string
enum: ["humanize", "none", "currency_usd", "currency_eur", "percentage"]
description: Format preset for the values. Defaults to `humanize`.
description:
type: string
description: Text shown in the measure's tooltip instead of the expression.
required:
- name
- expression
additionalProperties: false
time_range:
type: string
description: Time range for the table
Expand Down
Loading