Skip to content

Commit f9c085d

Browse files
michaelperaltaclaudejeff-morgan-dd
authored
[DOCS] Add custom metrics documentation for Database Monitoring (#35923)
* Add custom metrics documentation for Database Monitoring - Add database_monitoring/custom_metrics/_index.md: explains custom_queries config for PostgreSQL, MySQL, and SQL Server with shared reference table and per-database examples using tabs - Add database_monitoring/custom_metrics/exploring_custom_metrics.md: covers the Custom Metrics section in the instance detail page UI, including column types, collection interval, and the View SQL query button - Add Collecting Custom Metrics to sidebar nav (weight 11, under Connecting DBM and Traces) - Add link to custom metrics section from DBM landing page Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Update content/en/database_monitoring/custom_metrics/exploring_custom_metrics.md Co-authored-by: jeff-morgan-dd <jeff.morgan@datadoghq.com> * Update content/en/database_monitoring/custom_metrics/_index.md Co-authored-by: jeff-morgan-dd <jeff.morgan@datadoghq.com> * Update content/en/database_monitoring/custom_metrics/exploring_custom_metrics.md Co-authored-by: jeff-morgan-dd <jeff.morgan@datadoghq.com> * Update content/en/database_monitoring/custom_metrics/exploring_custom_metrics.md Co-authored-by: jeff-morgan-dd <jeff.morgan@datadoghq.com> * Update content/en/database_monitoring/custom_metrics/exploring_custom_metrics.md Co-authored-by: jeff-morgan-dd <jeff.morgan@datadoghq.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: jeff-morgan-dd <jeff.morgan@datadoghq.com>
1 parent a0b505e commit f9c085d

4 files changed

Lines changed: 340 additions & 7 deletions

File tree

config/_default/menus/main.en.yaml

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4933,41 +4933,51 @@ menu:
49334933
parent: dbm
49344934
identifier: dbm_data_collected
49354935
weight: 10
4936+
- name: Collecting Custom Metrics
4937+
url: database_monitoring/custom_metrics/
4938+
parent: dbm
4939+
identifier: dbm_custom_metrics
4940+
weight: 11
4941+
- name: Exploring Custom Metrics
4942+
url: database_monitoring/custom_metrics/exploring_custom_metrics
4943+
parent: dbm_custom_metrics
4944+
identifier: dbm_custom_metrics_exploring
4945+
weight: 1
49364946
- name: Exploring Database Hosts
49374947
url: database_monitoring/database_hosts/
49384948
parent: dbm
49394949
identifier: dbm_database_hosts
4940-
weight: 11
4950+
weight: 12
49414951
- name: Exploring Query Metrics
49424952
url: database_monitoring/query_metrics/
49434953
parent: dbm
49444954
identifier: dbm_query_metrics
4945-
weight: 12
4955+
weight: 13
49464956
- name: Exploring Query Samples
49474957
url: database_monitoring/query_samples/
49484958
parent: dbm
49494959
identifier: dbm_query_samples
4950-
weight: 13
4960+
weight: 14
49514961
- name: Exploring Database Schemas
49524962
url: database_monitoring/schema_explorer
49534963
parent: dbm
49544964
identifier: dbm_schema_explorer
4955-
weight: 14
4965+
weight: 15
49564966
- name: Exploring Recommendations
49574967
url: database_monitoring/recommendations/
49584968
parent: dbm
49594969
identifier: dbm_recommendations
4960-
weight: 15
4970+
weight: 16
49614971
- name: Troubleshooting
49624972
url: database_monitoring/troubleshooting/
49634973
parent: dbm
49644974
identifier: dbm_troubleshooting
4965-
weight: 16
4975+
weight: 17
49664976
- name: Guides
49674977
url: database_monitoring/guide/
49684978
parent: dbm
49694979
identifier: dbm_guides
4970-
weight: 17
4980+
weight: 18
49714981
- name: Data Streams Monitoring
49724982
url: data_streams/
49734983
pre: datastreams-monitoring

content/en/database_monitoring/_index.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ The [Query Samples view][3] helps you understand which queries are running at a
113113

114114
{{< img src="database_monitoring/dbm-explain-plan-3.png" alt="Database Monitoring" style="width:100%;">}}
115115

116+
### Collect custom metrics
117+
118+
Use [`custom_queries`][7] to collect metrics from your own database tables — application state, business counters, queue depths, or any data you want correlated with query performance.
119+
116120
### Visualize everything on enriched dashboards
117121

118122
Quickly pinpoint problem areas by viewing database and system metrics together on enriched integration dashboards for both self-hosted and cloud-managed instances. Clone dashboards for customization and enhancement with your own custom metrics. Click the **Dashboards** link at the top of the Query Metrics and Query Samples pages to go to the Database Monitoring dashboards.
@@ -146,3 +150,4 @@ The [Recommendations page][6] highlights problems and optimization opportunities
146150
[4]: /database_monitoring/query_metrics/#explain-plans
147151
[5]: /database_monitoring/database_hosts/
148152
[6]: /database_monitoring/recommendations/
153+
[7]: /database_monitoring/custom_metrics/
Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
---
2+
title: Collecting Custom Metrics with Database Monitoring
3+
description: Use the custom_queries option to collect metrics from your own database tables.
4+
further_reading:
5+
- link: "/database_monitoring/"
6+
tag: "Documentation"
7+
text: "Database Monitoring"
8+
- link: "/metrics/types/"
9+
tag: "Documentation"
10+
text: "Metric Types"
11+
---
12+
13+
Use `custom_queries` to collect metrics from any table the Agent's database user can read. This extends the data available in Datadog beyond the query performance metrics that Database Monitoring collects natively, such as application state tables, business counters, or queue depths.
14+
15+
## Before you begin
16+
17+
The Datadog Agent must be installed and the database integration configured. The Agent's database user needs `SELECT` on any tables you query.
18+
19+
## Configuration
20+
21+
Add `custom_queries` to your integration's `conf.yaml` file. Each entry in the list runs one SQL query and maps its output columns to metrics or tags.
22+
23+
| Option | Required | Description |
24+
| --- | --- | --- |
25+
| `metric_prefix` | Yes | All metrics emitted by this query begin with this prefix. |
26+
| `query` | Yes | The SQL to execute. All returned rows are evaluated. Use the pipe character (`\|`) for multi-line queries. |
27+
| `columns` | Yes | A list of columns in the same order as your `SELECT`. Each column requires a `name` and a `type`. Set `type` to `gauge`, `count`, `rate`, or another [metric type][1] to emit a metric, or `tag` to apply the column value as a tag on every metric from this query. |
28+
| `tags` | No | A list of static tags applied to every metric from this query. |
29+
30+
**Notes:**
31+
- The number of `columns` entries must equal the number of columns returned by the query.
32+
- The order of `columns` entries must match the order of columns returned by the query.
33+
- At least one entry in `columns` must be a metric type (not `tag`).
34+
35+
## Examples
36+
37+
{{< tabs >}}
38+
{{% tab "PostgreSQL" %}}
39+
40+
Add `custom_queries` to your `postgres.d/conf.yaml` file.
41+
42+
If the query reads from a table the `datadog` user cannot already access, grant the permission first:
43+
44+
```sql
45+
GRANT SELECT ON <TABLE_NAME> TO datadog;
46+
```
47+
48+
**Example:** The following `company` table contains employee records:
49+
50+
```text
51+
id | name | age | address | salary
52+
---------------------------------------
53+
1 | Paul | 32 | California | 20000
54+
2 | Allen | 25 | Texas | 30000
55+
3 | Teddy | 23 | Norway | 45000
56+
```
57+
58+
To collect `age` and `salary` as metrics with `name` and `address` as tags:
59+
60+
```yaml
61+
custom_queries:
62+
- metric_prefix: postgresql.employee
63+
query: SELECT age, salary, name, address FROM company
64+
columns:
65+
- name: employee_age
66+
type: gauge
67+
- name: employee_salary
68+
type: gauge
69+
- name: name
70+
type: tag
71+
- name: address
72+
type: tag
73+
tags:
74+
- source:hr_db
75+
```
76+
77+
After you update the file, [restart the Agent][2].
78+
79+
For the full configuration reference, see [Postgres Custom Metric Collection][3].
80+
81+
[2]: /agent/configuration/agent-commands/#restart-the-agent
82+
[3]: /integrations/faq/postgres-custom-metric-collection-explained/
83+
{{% /tab %}}
84+
85+
{{% tab "MySQL" %}}
86+
87+
Add `custom_queries` to your `mysql.d/conf.yaml` file.
88+
89+
**Important:** All table references must include the database name (`database_name.table_name`). If you omit the database name, the Agent fails with the error: `No database selected`.
90+
91+
**Example:** The following `company` table in the `testdb` database contains employee records:
92+
93+
```text
94+
id | name | age | address | salary
95+
---------------------------------------
96+
1 | Paul | 32 | California | 20000
97+
2 | Allen | 25 | Texas | 30000
98+
3 | Teddy | 23 | Norway | 45000
99+
```
100+
101+
To collect `age` and `salary` as metrics with `name` and `address` as tags:
102+
103+
```yaml
104+
custom_queries:
105+
- metric_prefix: mysql.employee
106+
query: SELECT age, salary, name, address FROM testdb.company
107+
columns:
108+
- name: employee_age
109+
type: gauge
110+
- name: employee_salary
111+
type: gauge
112+
- name: name
113+
type: tag
114+
- name: address
115+
type: tag
116+
tags:
117+
- source:hr_db
118+
```
119+
120+
After you update the file, [restart the Agent][2].
121+
122+
For the full configuration reference, see [MySQL Custom Queries][3].
123+
124+
[2]: /agent/configuration/agent-commands/#restart-the-agent
125+
[3]: /integrations/guide/mysql-custom-queries/
126+
{{% /tab %}}
127+
128+
{{% tab "SQL Server" %}}
129+
130+
SQL Server supports two approaches for collecting custom metrics: [custom queries](#custom-queries) or [performance counters](#performance-counters).
131+
132+
### Custom queries
133+
134+
Add `custom_queries` to your `sqlserver.d/conf.yaml` file to collect metrics from any table.
135+
136+
**Example:** The following `company` table in `testdb` contains employee records:
137+
138+
```text
139+
id | name | age | address | salary
140+
---------------------------------------
141+
1 | Paul | 32 | California | 20000
142+
2 | Allen | 25 | Texas | 30000
143+
3 | Teddy | 23 | Norway | 45000
144+
```
145+
146+
To collect `age` and `salary` as metrics with `name` and `address` as tags:
147+
148+
```yaml
149+
custom_queries:
150+
- metric_prefix: sqlserver.employee
151+
query: SELECT age, salary, name, address FROM testdb.dbo.company
152+
columns:
153+
- name: employee_age
154+
type: gauge
155+
- name: employee_salary
156+
type: gauge
157+
- name: name
158+
type: tag
159+
- name: address
160+
type: tag
161+
tags:
162+
- source:hr_db
163+
```
164+
165+
### Performance counters
166+
167+
Use `custom_metrics` to collect metrics from `sys.dm_os_performance_counters` and other system DMVs.
168+
169+
```yaml
170+
custom_metrics:
171+
- name: sqlserver.clr.execution
172+
counter_name: CLR Execution
173+
```
174+
175+
| Option | Required | Description |
176+
| --- | --- | --- |
177+
| `name` | Yes | The metric name in Datadog. |
178+
| `counter_name` | Yes | The counter name from `sys.dm_os_performance_counters`. |
179+
| `instance_name` | No | A specific counter instance. Use `ALL` to collect all instances (requires `tag_by`). |
180+
| `tag_by` | No | Tag name used to differentiate instances when `instance_name: ALL`. |
181+
182+
After you update the file, [restart the Agent][2].
183+
184+
For the full configuration reference, including performance counter details and the legacy stored procedure method, see [Collect SQL Server Custom Metrics][3].
185+
186+
[2]: /agent/configuration/agent-commands/#restart-the-agent
187+
[3]: /integrations/guide/collect-sql-server-custom-metrics/
188+
{{% /tab %}}
189+
{{< /tabs >}}
190+
191+
## Validation
192+
193+
After the Agent runs, search for your metrics in the [Metrics Explorer][4].
194+
195+
To check for configuration errors, [run the Agent's status subcommand][5] and look for your integration under the Checks section:
196+
197+
```text
198+
postgres
199+
--------
200+
- instance #0 [ERROR]: 'Missing metric_prefix parameter in custom_queries'
201+
- Collected 0 metrics, 0 events & 0 service checks
202+
```
203+
204+
## Further Reading
205+
206+
{{< partial name="whats-next/whats-next.html" >}}
207+
208+
[1]: /metrics/types/
209+
[4]: /metrics/explorer/
210+
[5]: /agent/configuration/agent-commands/#agent-status-and-information
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
---
2+
title: Exploring Custom Metrics
3+
description: Explore timeseries graphs for custom queries on the database instance detail page.
4+
further_reading:
5+
- link: "/database_monitoring/custom_metrics/"
6+
tag: "Documentation"
7+
text: "Collecting Custom Metrics with Database Monitoring"
8+
- link: "/database_monitoring/"
9+
tag: "Documentation"
10+
text: "Database Monitoring"
11+
---
12+
13+
The **Custom Metrics** section appears on the database instance detail page and displays timeseries graphs for any custom queries you have defined in your Datadog Agent configuration.
14+
15+
## Overview
16+
17+
If you have configured `custom_queries` in your Datadog Agent's database integration, this section automatically discovers those queries and visualizes each metric column as a timeseries graph. This lets you monitor business-specific or environment-specific database metrics alongside the standard Database Monitoring metrics, all in one place.
18+
19+
## How it works
20+
21+
1. Define custom queries in your Agent config. Each query specifies:
22+
- A SQL statement
23+
- One or more metric columns (with types like `gauge`, `count`, or `rate`)
24+
- Optional tag columns
25+
- An optional metric prefix
26+
- An optional collection interval
27+
2. The Agent collects the metrics by running your SQL queries on the configured interval (default: every 15 seconds) and emitting the results as Datadog metrics.
28+
3. The Custom Metrics section displays a graph for each metric column from your custom queries, scoped to the current database instance. Metrics are named `<prefix>.<column_name>` (for example, `postgresql.my_table_row_count`).
29+
30+
## Example Agent configuration
31+
32+
The following PostgreSQL example tracks table size and row counts per table:
33+
34+
```yaml
35+
init_config:
36+
37+
instances:
38+
- dbm: true
39+
host: localhost
40+
port: 5432
41+
username: datadog
42+
password: <PASSWORD>
43+
custom_queries:
44+
- metric_prefix: postgresql.custom
45+
query: |
46+
SELECT
47+
table_name,
48+
pg_total_relation_size(quote_ident(table_name)) AS total_bytes,
49+
n_live_tup AS live_rows,
50+
n_dead_tup AS dead_rows
51+
FROM information_schema.tables
52+
JOIN pg_stat_user_tables USING (table_name)
53+
WHERE table_schema = 'public'
54+
columns:
55+
- name: table_name
56+
type: tag
57+
- name: total_bytes
58+
type: gauge
59+
- name: live_rows
60+
type: gauge
61+
- name: dead_rows
62+
type: gauge
63+
collection_interval: 60
64+
tags:
65+
- env:production
66+
- service:my-app
67+
```
68+
69+
This configuration produces three metrics, each broken down by `table_name`:
70+
71+
- `postgresql.custom.total_bytes`
72+
- `postgresql.custom.live_rows`
73+
- `postgresql.custom.dead_rows`
74+
75+
All three appear as separate timeseries graphs in the Custom Metrics section of the instance detail page.
76+
77+
## Column types
78+
79+
Each column in a custom query is assigned a type that controls how the metric is aggregated and displayed:
80+
81+
| Type | Description |
82+
| --- | --- |
83+
| `gauge` | A value that can go up or down (for example, table size). |
84+
| `count` | A count of events since the last collection. |
85+
| `rate` | A per-second rate. |
86+
| `monotonic_count` | A counter that only increases. |
87+
| `monotonic_gauge` | A monotonically increasing gauge. |
88+
| `temporal_percent` | A percentage of time. |
89+
| `time_elapsed` | Duration in time units. |
90+
| `tag` | Groups or filters metrics; not plotted as its own graph. |
91+
92+
`count` and `monotonic_count` columns are aggregated as `sum`. All other metric types are aggregated as `avg`.
93+
94+
## Viewing the source SQL
95+
96+
Each graph has a **View SQL query** button in the top-right corner. Clicking it shows the raw SQL statement that produces the metric, so you can understand and audit what is being measured.
97+
98+
## Collection interval
99+
100+
The section subtitle shows how often the metrics are collected (for example, "collected every 15s"). If you have multiple custom queries with different intervals, the range is shown (for example, "collected every 15s–60s").
101+
102+
## Requirements
103+
104+
Custom queries must be defined under the `custom_queries` key in the database integration configuration. The Custom Metrics section is hidden if no custom queries are configured.
105+
106+
## Further Reading
107+
108+
{{< partial name="whats-next/whats-next.html" >}}

0 commit comments

Comments
 (0)