> For the complete documentation index, see [llms.txt](https://v2.dataos.info/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://v2.dataos.info/build/v1/productize/assets/metrics.md).

# Metrics

A metric is the primary interface that consumers and dashboards use. It takes a measure from a semantic model, adds a time column and a default granularity, and turns into one queryable time series.

Define one metric per file, in `models/metrics/`. Defining a metric once is how every dashboard, report, and AI agent ends up using the same definition of a number.

## The shape

The smallest valid metric needs 4 fields:

```yaml
kind: metric
name: daily_sales_performance
measure: daily_sales.total_daily_revenue
ts: daily_sales.order_date
granularity: day
```

The full form adds grouping dimensions, segments, and discovery metadata:

```yaml
kind: metric
name: daily_sales_performance
measure: daily_sales.total_daily_revenue
ts: daily_sales.order_date
granularity: day
dimensions:
  - name: region
    ref: daily_sales.region_name
  - name: category
    ref: daily_sales.category
segments:
  - daily_sales.high_revenue_days
description: Daily revenue trends by region and category.
tags:
  - sales
  - revenue
```

Every metric needs:

* `kind: metric`
* a unique `name`
* a `measure`, referencing `semantic.measure`
* a `ts` time column, referencing `semantic.column`
* a `granularity`, from `second` through `year`

`measure` and `ts` must point at different references.

{% hint style="warning" %}
`ts` must resolve to a strict timestamp column (`TIMESTAMP`, `TIMESTAMPTZ`, `DATETIME`, or equivalent). `DATE`, `TIME`, and `INTERVAL` columns are rejected outright. Cast to `TIMESTAMP` upstream in the physical model's `SELECT`, since semantic dimensions are plain column references with no `expression` field to cast in.
{% endhint %}

## What the parts do

* **`measure`** is the number to compute, from a semantic model.
* **`ts`** is the time axis for the series.
* **`granularity`** is the default bucket. Consumers can override it at query time, so you don't need separate daily, weekly, and monthly metrics for the same measure.
* **`dimensions`** let consumers slice the metric. Use a bare reference (`daily_sales.region_name`) to derive the name, or a named slice (`name` + `ref`) when you want a different display name, when two columns would collide, or when you want to override that field's `description`, `tags`, `terms`, or `ai_context` for this metric only.
* **`segments`** apply predefined filters from the semantic model by reference. Unlike dimensions, segment entries must be plain qualified-ref strings: no per-entry metadata; edit the segment on its semantic model instead.
* **`tags`** and **`terms`** make the metric discoverable in the Data Product Hub.

## Cross-model metrics

A metric can draw its measure, time column, and dimensions from different semantic models, as long as the models are connected through joins. By default (`join_path: directed`), the path must follow **outgoing** join edges starting from the `measure`'s anchor model. A reference reachable only by walking a join backwards fails validation. Set `join_path: connected` on the metric (or `metric_join_path: connected` project-wide) to allow any path regardless of direction; this is common when the only usable path runs against a reciprocal join's non-BI-facing side.

`customer_lifetime_value` is an example. It takes its measure and dimensions from `customer_profile`, which already joins to the underlying silver models.

## Validation and legacy keys

Running `vulcan plan` checks that:

* the `measure` and `ts` references are valid
* the `granularity` is recognized
* dimension and segment references resolve
* cross-model join paths exist, per the effective `join_path` mode

Two old keys are rejected: use `ts` instead of `time`, and `dimensions` instead of `slices`.

`measure`, `time`, and `ts` are reserved: you can't use them as a dimension `name` or as a segment's auto-derived name (`<semantic_name>_<segment_name>`).

For the full reference, including join-path resolution, see [References → Vulcan → Models → Business metrics](https://v2.dataos.info/references/resources/vulcan/models/semantic-models).

With assets in place, make the product enforce its own contract: [Data quality](/build/v1/productize/data-quality.md), [Assertions](/build/v1/productize/assertions.md), and [Unit Test](/build/v1/productize/unit-test.md).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://v2.dataos.info/build/v1/productize/assets/metrics.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
