---
title: "How to Monitor your Model or Policy"
description: "Track the health and performance of your models and policies in production."
---

<div style="padding: 14px 16px; border: 0.5px solid #AFA9EC; border-radius: 12px; background: #EEEDFE; margin-bottom: 1.5rem;">
  <div style="display: flex; align-items: center; gap: 7px; margin-bottom: 8px;">
    <svg width="16" height="16" viewBox="0 0 16 16" fill="none">
      <path d="M9 2L4 9h4l-1 5 5-7H8l1-5z" stroke="#7f77dd" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
    </svg>
    <span style="font-size: 11px; font-weight: 500; letter-spacing: 0.05em; text-transform: uppercase; color: #534AB7;">TL;DR</span>
  </div>
  <div style="font-size: 13px; color: #3C3489; line-height: 1.65;">
    Set up a Monitoring Dashboard with a data schema, refresh schedule, and refresh logic to track review dates, performance metrics, and approval status across your model or policy inventory. Configure alerts from the dashboard's <strong>Alert Settings</strong> tab to get notified when something needs attention.
  </div>
</div>

## What is it?

The **Monitoring Dashboard** is where you keep an eye on your model or policy inventory after objects are approved and running. It tracks attributes you care about (review dates, performance metrics, approval status), refreshes them on a schedule you choose, and fires alerts when something needs attention.

A single Monitoring Dashboard can cover objects registered on the platform and objects managed externally (for example, models trained outside Corridor that you still want governed in one place).

Each dashboard has four tabs:

<table class="attr-table">
  <thead>
    <tr>
      <th style="width: 22%;">Tab</th>
      <th>What it does</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td class="field-cell">Details</td>
      <td>Defines the schema, refresh schedule, and refresh logic. The setup section.</td>
    </tr>
    <tr>
      <td class="field-cell">Reports</td>
      <td>Shows the tracked data in tables, pivots, and custom views. Where uploaded files land.</td>
    </tr>
    <tr>
      <td class="field-cell">Triggered Alerts</td>
      <td>Lists alerts that have fired, with filters and bulk actions.</td>
    </tr>
    <tr>
      <td class="field-cell">Alert Settings</td>
      <td>Where you configure the alert rules. See <a href="../setup-alerts/">Set up Alerts</a>.</td>
    </tr>
  </tbody>
</table>

## Before you start

* You need write access to the Monitoring Dashboard module.
* If you plan to ingest data from a file, have the CSV or Excel file ready. It must contain a column that uniquely identifies each row.

## How to Set Up

<details open class="step">
<summary>

#### Open the Monitoring Dashboard

</summary>

Navigate to the right module:

* **For Models**: Model Studio → Monitoring Dashboard.
* **For Policies**: Prospecting, Underwriting, or Customer Management → Monitoring Dashboard.

The dashboard opens on the **Details** tab.

</details>

<details open class="step">
<summary>

#### Define the Data Schema

</summary>

The Data Schema is the list of columns the dashboard will track. Click **Add Column** to add a row; drag the move handle to reorder.

<table class="attr-table">
  <thead>
    <tr>
      <th style="width: 22%;">Field</th>
      <th>What to enter</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td class="field-cell">Column Name<span class="req">Required</span></td>
      <td>A unique variable-style name (no spaces; for example, <code>next_review_date</code>, <code>ks_metric</code>). This is also how you refer to the column in refresh logic.</td>
    </tr>
    <tr>
      <td class="field-cell">Column Type<span class="req">Required</span></td>
      <td>The data type: <code>String</code>, <code>Numerical</code>, <code>DateTime</code>, or <code>Boolean</code>.</td>
    </tr>
    <tr>
      <td class="field-cell">Color</td>
      <td>(Optional) Pick a color used to render the column in dashboard views.</td>
    </tr>
    <tr>
      <td class="field-cell">Editable</td>
      <td>If checked, users with access can edit values for this column directly in <strong>Reports → Data View</strong>. System fields are not editable.</td>
    </tr>
  </tbody>
</table>

:::tip
Add only columns you actually want to monitor or alert on. The schema can be extended later, but renaming or removing a column after data is loaded needs cleanup.
:::

</details>

<details open class="step">
<summary>

#### Schedule the Data Refresh

</summary>

Tell the dashboard when to run.

<table class="attr-table">
  <thead>
    <tr>
      <th style="width: 22%;">Field</th>
      <th>What to enter</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td class="field-cell">Start Date</td>
      <td>The first run date. Leave empty to use today.</td>
    </tr>
    <tr>
      <td class="field-cell">Time</td>
      <td>The time of day to run. Leave empty to run immediately on save. Times snap to the nearest half hour.</td>
    </tr>
    <tr>
      <td class="field-cell">Recurrence</td>
      <td>How often the refresh repeats (daily, weekly, monthly, and so on). Once set, the form previews the next few iteration dates.</td>
    </tr>
  </tbody>
</table>

</details>

<details open class="step">
<summary>

#### Write the Data Refresh Logic

</summary>

This is a Python function that produces the data the dashboard tracks. Open the **Data Refresh Logic** editor and write logic that returns a Pandas DataFrame.

You can pull from three sources:

* **`file_data`** (Pandas DataFrame): the contents of any CSV or Excel file uploaded in **Reports → Data View**.
* **`dashboard_data`** (Pandas DataFrame): whatever is currently visible in **Reports → Data View**.
* **Platform data**: query objects registered in Corridor using the `corridor` package. For example, `corridor.model.all()` returns every registered Model.

The refresh runs:

* At the scheduled time you set in Step 3.
* Immediately whenever someone uploads a file in **Reports → Data View**.
* Whenever someone saves in-grid edits in **Reports → Data View** with **Save Changes**.

A common starting pattern is "use the uploaded file if there is one, otherwise keep the existing data":

```python
if file_data is not None:
    file_data['_index'] = file_data['<your_id_column>']  # uniquely identifies each row
    return file_data
else:
    return dashboard_data
```

:::caution
Be cautious when changing this logic on a running dashboard. The next refresh replaces the dashboard data, so a mistake here can wipe out the values you were tracking.
:::

</details>

<details open class="step">
<summary>

#### Save

</summary>

Click **Save Changes** at the bottom of the form. The dashboard runs at its first scheduled time, or immediately if no time was set.

</details>

## Loading Data

Once the dashboard is set up, populate it from the **Reports** tab.

* **Reports → Data View**: drag a CSV or Excel into the grid, or upload via the toolbar. The refresh logic runs and the data appears in the grid.
* Reports also exposes pivot views and custom views you can build for executive summaries (for example, *Models due for review in the next 30 days*).

## Setting Up Alerts

Once data is flowing, switch to the **Alert Settings** tab to define rules that fire when conditions are met (a metric breach, an approaching review date). See [Set up Alerts](/user-guide/how-tos/setup-alerts/) for the full walkthrough.

Fired alerts collect under the **Triggered Alerts** tab, where you can filter, close, or bulk-delete them.

## What's next

* [Set up Alerts](/user-guide/how-tos/setup-alerts/) so the dashboard nudges you instead of you nudging it.
* [Approve an Object](/user-guide/how-tos/approve-an-object/) when a model or policy needs sign-off on its monitoring setup.
