---
title: Custom Dashboards
description: Build your own Grafana dashboards on top of QMonitor's Metrics API.

url: https://help.qmonitor.app/docs/tasks/dashboards/metrics/index.md
lastmod: 2026-10-06T19:56:52+02:00
---


Custom Dashboards let you create your own Grafana dashboards and charts, using the
metrics QMonitor already collects for your organization. They live only in your
organization and are only visible to your users.

## Creating a custom dashboard

1. In the QMonitor side menu, open **Custom Dashboards** and click **New dashboard**.
2. Give it a name and confirm. The dashboard opens in edit mode.
3. Add a panel. The data source is already set to **Metrics** and cannot be changed:
   every custom dashboard reads from this single, read-only source.
4. In the panel query, keep the Infinity query type and set the **URL** to a measurement
   name (see below).

To delete a dashboard, use the trash icon next to it in the **Custom Dashboards** menu.

## How the Metrics API works

You never write a raw database query. You pick a **measurement** (one of the standard
ones below, or one of your organization's own Custom Queries) and pass structured
parameters. QMonitor builds a safe, read-only query against your organization's data.

The data source already points at the API, so in a panel the **URL is just the
measurement name** — nothing else:

```
custom_db_size
```

Use Grafana's time macros so the panel follows the dashboard time picker:

```
sqlserver_cpu?from=${__from}&to=${__to}&fn=mean
```

### Query parameters

| Parameter | Description |
|-----------|-------------|
| `from`, `to` | Time range, in epoch milliseconds. Use `${__from}` and `${__to}` so the panel follows the dashboard time picker. |
| `fn` | Aggregation applied to each field: `mean` (default), `max`, `min`, `sum`, `last`, `first`, `count`, `median`. |
| `interval` | Aggregation bucket, in seconds. Optional; defaults to the measurement's interval. |
| `fields` | Comma-separated list of fields to return. Optional; defaults to all fields of the measurement. |
| `tags` | Comma-separated list of tags to group by. Optional. |

### Discovering what you can query

Leave the panel **URL empty** to list every measurement available to your organization
(standard measurements plus your own Custom Queries), with their fields and tags.

### What the endpoints return

Both endpoints return a JSON array (Infinity "table" format).

A **measurement** query returns one object per time bucket, per series: the tags you grouped
by, a `time` field (epoch milliseconds), and each requested field already aggregated by `fn`.

```json
[
  { "sql_instance": "SRV01\\MSSQL", "time": 1730289600000, "sqlserver_process_cpu": 2.3 },
  { "sql_instance": "SRV01\\MSSQL", "time": 1730289660000, "sqlserver_process_cpu": 2.1 }
]
```

Which tag columns appear depends on the `tags` you group by; which value columns appear
depends on `fields` (by default, all of the measurement's fields).

The **catalog** (empty URL) returns one object per available measurement:

```json
[
  {
    "organization": "acme",
    "orgId": 12,
    "source": "standard",
    "measurement": "sqlserver_cpu",
    "description": "SQL Server vs other-process CPU usage (%).",
    "interval": "60s",
    "fields": ["sqlserver_process_cpu", "other_process_cpu"],
    "tags": ["sql_instance", "host"]
  }
]
```

`source` is `standard` for native measurements or `custom` for your organization's own
Custom Queries (`interval` is set for Custom Queries).

## Standard measurements

These native QMonitor measurements are available to every organization. In a panel, type
the measurement name as the URL.

| Measurement | Description | Fields | Tags |
|-------------|-------------|--------|------|
| `sqlserver_cpu` | SQL Server vs other-process CPU usage (%). | `sqlserver_process_cpu`, `other_process_cpu` | `sql_instance`, `host` |
| `sqlserver_waitstats` | Wait statistics by wait type. | `wait_time_ms`, `waiting_tasks_count`, `max_wait_time_ms` | `sql_instance`, `wait_type`, `wait_category` |
| `sqlserver_database_io` | Per-file I/O: reads, writes, bytes and latency. | `reads`, `writes`, `read_bytes`, `write_bytes`, `read_latency_ms`, `write_latency_ms` | `sql_instance`, `database_name`, `logical_filename`, `file_type` |
| `sqlserver_volume_space` | Disk volume space (bytes). | `total_space_bytes`, `available_space_bytes`, `used_space_bytes` | `sql_instance`, `volume_mount_point` |
| `sqlserver_performance` | Raw performance counters (filter by the `counter`/`instance` tags). | `value` | `sql_instance`, `object`, `counter`, `instance` |
| `sqlserver_memory_clerks` | Memory usage by memory clerk type (KB). | `size_kb` | `sql_instance`, `clerk_type` |
| `sqlserver_server_properties` | Instance properties: uptime, cpu count, memory, database counts. | `uptime`, `cpu_count`, `server_memory`, `db_online`, `db_offline` | `sql_instance`, `host` |
| `sqlazure_resource_stats` | Azure SQL resource usage (%). | `avg_cpu_percent`, `avg_data_io_percent`, `avg_log_write_percent`, `dtu_consumption_percent` | `sql_instance`, `database_name`, `elastic_pool_name` |

Your organization's own **Custom Queries** appear in the catalog alongside these, with
the measurement, fields and tags you defined for them.

## Limits

To keep the shared platform healthy, each query is capped: the time range cannot exceed
30 days, data is always aggregated into buckets of at least 60 seconds, and a single
query returns at most 10,000 points across at most 50 series. If a chart hits these
limits, narrow the time range, widen the bucket (`interval`), or group by fewer tags.

