# Quality Dashboard

The **Data Quality Dashboard** at `/data-quality` is the catalog's cross-entity quality view. It builds on top of the test results imported through the [Test Results Import](/features/data-quality/test-results-import.md) paths — Great Expectations, dbt, `odd-collector-profiler`, and custom frameworks — and renders them as one operator-friendly summary.

Quality checks are not performed inside ODD Platform — the dashboard surfaces results from the integrated tools.

{% hint style="info" %}
**The dashboard is visible to every signed-in user.** The `/data-quality` route carries no per-permission gate, and the aggregate it reads requires only that the caller be authenticated — there is no dedicated data-quality permission. Every signed-in user therefore sees the catalog-wide health of every dataset; under [`auth.type=DISABLED`](/configuration-and-deployment/enable-security/authentication/disabled-authentication.md) the dashboard is open to anyone who can reach the platform. The filters narrow what *you* are looking at; they do not restrict what a given user is *allowed* to see. If the mix of failing datasets is itself sensitive in your deployment, put the platform behind a network perimeter rather than relying on a dashboard-level permission that does not exist.
{% endhint %}

![Data Quality dashboard — three pie charts at the top (Table Health 88 tables broken into Healthy / Warning / Error slices; Test Results Breakdown 335 tests broken by latest-run status; Monitored Tables 98 split into monitored / unmonitored) and a per-test-category matrix on the right showing per-anomaly-class counts. The left rail carries two filter sets — one for tables, one for tests.](/files/EQofrkQNtYBqeETc10M0)

## Three breakdown rings

The dashboard's hero row is three pie charts, each computed across the catalog at the time the page is loaded:

* **Table Health** — the count of tables broken down by their aggregate health status. The UI labels the three slices **Healthy**, **Warning**, and **Error** (not "success / failed / broken"): a table is **Healthy** when none of its latest test runs is anything but a success, **Error** when any latest run is failed or broken, and **Warning** for everything in between. Searching the dashboard for a "broken tables" count will not find that label — the broken/failed runs roll up into the **Error** slice.
* **Test Results Breakdown** — the count of **tests by their latest run's status**. The ring renders a slice for whichever run statuses are present in the catalog — the full set is **Success**, **Failed**, **Skipped**, **Broken**, **Aborted**, and **Unknown** (the same six statuses as the per-test [Test Run History](/features/data-quality/test-run-history.md) status filter), not only passed / failed / skipped. See the disclosure below — this is **not** a count of individual runs.
* **Monitored Tables** — the count of tables broken down by whether they are monitored (have at least one DQ test) or unmonitored.

The "Monitored vs Unmonitored" framing applies specifically to **Table-type datasets** — the catalog's primary tabular entities.

{% hint style="warning" %}
**Test Results Breakdown counts tests, not runs.** The "Test Results Breakdown" ring (and every per-category total on the right-side matrix) aggregates **distinct tests, each represented by its latest run only**. A test that has failed 100 times in a row contributes a single entry to the "failed" count — the dashboard shows **1 failed**, not **100 failed**. The underlying table (`data_entity_task_last_run`) carries one row per test, keyed by the test's identifier, holding only the most recent run's status.

This matters most for **compliance and audit** reading. "How many test failures last week" answered from this dashboard returns "how many tests are currently failing on their latest run" — a smaller and structurally different number. For the per-run history of any individual test (every run, all states), open the test's [Test Run History](/features/data-quality/test-run-history.md) page from the test's detail surface.
{% endhint %}

## Six anomaly-class metrics

The right-side matrix shows the breakdown of failures across the six anomaly classes the platform recognises. The cards are ordered **alphabetically by category name** — not by failure count, severity, or test volume. An operator opening the dashboard to find "which category is failing worst" must scan all panels; the panel order conveys nothing about quality. Each metric represents a dimension of data quality:

* **Assertion Tests** — validations or checks put in place to ensure that specific conditions or assertions about the data are met.
* **Column Values Anomalies** — irregularities or unexpected values in the data that deviate from a predefined set of acceptable or standard values.
* **Freshness Anomalies** — staleness signals — checking whether the data is up-to-date and falls within the acceptable time frame.
* **Schema Changes** — modifications in the structure or organization of the data, with a focus on monitoring whether the data schema remains consistent over time.
* **Unknown Category** — data placed into a category that was not foreseen or specified in the established data model or schema.
* **Volume Anomalies** — unexpected changes in the quantity or volume of data.

Each per-category total at the top of the card uses the same latest-run-only semantic as the headline Test Results Breakdown ring — see the disclosure above.

For each of these metrics the dashboard assigns statuses to the checks, distinguished by colors for better visualization:

<figure><img src="/files/H0rNv7knQVLfTspBkq5L" alt="" height="74" width="700"><figcaption><p>Checks Statuses distinguished by colors</p></figcaption></figure>

## Monitored vs unmonitored portions

Beyond the per-anomaly breakdown, the dashboard reports what portion of data was monitored and what portion was skipped:

<figure><img src="/files/CsEChWQ0Ts1tiBKis6z9" alt="" height="496" width="413"><figcaption><p>Monitored / unmonitored tables portions</p></figcaption></figure>

This applies specifically to Table-type datasets — the catalog's primary tabular entities.

## Filtering

Filter the dashboard by five dimensions: **Namespace**, **Datasource**, **Owner**, **Title**, and **Tag**. The filters apply on **two separate sides**:

{% hint style="warning" %}
**"Title" is the ownership role, not the dataset name.** The **Title** filter matches the [ownership title](/configuration-and-deployment/enable-security/authorization/owners.md) — the role attached to an owner of an entity, such as `Steward`, `Subject Matter Expert`, or `On-call` — **not** the name of a dataset. Selecting `Title = Steward` narrows the rings to entities that have an owner holding the `Steward` role, which is a wider and different slice than "datasets called X." There is no filter for the dataset name on this dashboard; use [Search](/features/data-discovery/search.md) when you need to find a named entity.

**Owner and Title combine into a single owner match.** When you select **both** an Owner and a Title, the dashboard matches only entities where **that owner holds that title** on the entity (the two conditions are intersected on the same ownership row), not entities that have that owner *and*, separately, someone with that title. A combination no single owner satisfies returns an empty ring.

**"Namespace" includes the datasource's namespace.** The **Namespace** filter matches an entity when **either** the entity's own namespace **or** the namespace of its datasource is the one you selected. An entity inherits its datasource's namespace for this filter even if the entity itself was ingested into a different namespace, so the ring counts can be larger than a "entities whose namespace is X" query run elsewhere would return.
{% endhint %}

* **Tables-side filters** — narrow the Table Health and Monitored Tables rings to the selected slice of tables.

<figure><img src="/files/JOX4ILqXH9EFzxbCdoeW" alt="" height="374" width="700"><figcaption><p>Filters for tables</p></figcaption></figure>

* **Tests-side filters** — narrow the Test Results Breakdown ring to tests with the selected attributes.

<figure><img src="/files/oacyDv4mOYw1pagPCqEH" alt="" height="385" width="700"><figcaption><p>Filters for tests</p></figcaption></figure>

The two filter sets are independent — you can hold the tables-side filter at one slice and the tests-side at another, which is useful when reasoning about test coverage across a slice of tables.

ODD users can narrow down test results for datasets by multiple attributes simultaneously.

<figure><img src="/files/NEhk28JqJTsxdrTuwBVh" alt="" height="460" width="700"><figcaption><p>Filtering by multiple attributes simultaneously</p></figcaption></figure>

{% hint style="info" %}
**`AND`-only conjunction.** For simplicity the platform implements only one logical conjunction across filter dimensions — `AND`. The results displayed after filtering are the outcome of all selected filters intersected together.
{% endhint %}

{% hint style="warning" %}
**Filter selections are page-session state — they survive only if the URL survives.** The dashboard's filter state lives **per page mount**: selecting filters writes them to the URL query string in real time (a `replace` URL update, so the browser history isn't polluted), and re-opening the page re-reads the filters from that URL. The persistence is therefore tied to the URL, not to your session.

In practice:

* **Browser back** — preserves the URL → filters reconstruct correctly. Pick filters, drill into an entity, hit back, the filter row is the same.
* **Bookmarked or shared URL** — a `/data-quality?...` URL with filter parameters is a portable snapshot. Open it from a bookmark or paste it to a teammate; they land on the same filter set.
* **Clicking "Data Quality" in the top navigation** — that link points at bare `/data-quality` with no query string, so the page reopens with **all filters empty**. The most common surprise: you set up filters, navigate away through the top nav, click "Data Quality" again, and your selection is gone.
* **Re-opening the dashboard from another part of the catalog** — same as the top-nav case: unless you arrive via a URL that carries the filter parameters, the filter row starts empty.

The pattern (filter / cursor state resets when you leave the page through anything that doesn't preserve the URL) applies to a few other catalog surfaces — Owner Associations in Management, the DEG (Data Entity Group) lineage canvas, and the Dataset Structure compare view — but the Data Quality Dashboard is where most operators meet it first. To pin a working view, copy the URL from the address bar and bookmark or share it.
{% endhint %}

## Where to next

* [Test Results Import](/features/data-quality/test-results-import.md) — how the test results that populate the dashboard land in the catalog.
* [Dataset Quality Statuses (SLA)](/features/data-quality/sla-statuses.md) — operator-set severities on test results that feed the dataset-level SLA.
* [Alerting](/features/active-platform-features/alerting.md) — DQ-test-failed alerts feeding through the alert lifecycle.
* [Visibility for Data Quality Engineer](/use-cases/use-cases/dq-visibility.md) — the dashboard in the context of the DQ-engineer end-to-end workflow.


---

# Agent Instructions: 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:

```
GET https://docs.opendatadiscovery.org/features/data-quality/dashboard.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
