--- name: database-observability license: Apache-2.0 description: > Grafana Cloud Database Observability — query-level performance insights for MySQL and PostgreSQL. Covers setup with Grafana Alloy, query samples, visual explain plans, RED metrics, pg_stat_statements and Performance Schema integration, and correlation with application traces. Use when monitoring database performance, diagnosing slow queries, setting up database observability for MySQL or PostgreSQL (self-managed, RDS, Aurora, Azure, Cloud SQL), or correlating DB metrics with APM data. --- # Grafana Cloud Database Observability > **Docs**: https://grafana.com/docs/grafana-cloud/monitor-applications/database-observability/ Provides query-level insights (RED metrics, query samples, explain plans) for MySQL and PostgreSQL without application code changes. Generally Available as of April 2026. ## Supported Databases | Database | Variants | |----------|---------| | **MySQL** | Self-managed, RDS MySQL, Aurora MySQL, Cloud SQL MySQL, Azure Database for MySQL | | **PostgreSQL** | Self-managed, RDS PostgreSQL, Aurora PostgreSQL, Cloud SQL PostgreSQL, Azure Database for PostgreSQL | ## Prerequisites ### PostgreSQL ```sql -- 1. Enable pg_stat_statements in postgresql.conf -- shared_preload_libraries = 'pg_stat_statements' -- Then restart PostgreSQL -- 2. Create monitoring user CREATE USER grafana_monitoring WITH PASSWORD 'secret'; GRANT pg_monitor TO grafana_monitoring; GRANT CONNECT ON DATABASE mydb TO grafana_monitoring; -- 3. Enable the extension CREATE EXTENSION IF NOT EXISTS pg_stat_statements; ``` ### MySQL ```sql -- Create monitoring user with least-privilege permissions CREATE USER 'grafana_monitoring'@'%' IDENTIFIED BY 'secret'; GRANT SELECT, PROCESS, REPLICATION CLIENT ON *.* TO 'grafana_monitoring'@'%'; GRANT SELECT ON performance_schema.* TO 'grafana_monitoring'@'%'; FLUSH PRIVILEGES; ``` ## Alloy Configuration ### PostgreSQL ```alloy database_observability.postgres "mydb" { data_source_name = "postgresql://grafana_monitoring:secret@localhost:5432/mydb?sslmode=disable" enable_collectors = ["pg_stat_statements", "query_samples", "schema_details"] forward_metrics_to = [prometheus.remote_write.cloud.receiver] forward_logs_to = [loki.write.cloud.receiver] } prometheus.remote_write "cloud" { endpoint { url = sys.env("PROMETHEUS_URL") basic_auth { username = sys.env("PROMETHEUS_USER") password = sys.env("GRAFANA_CLOUD_API_KEY") } } } loki.write "cloud" { endpoint { url = sys.env("LOKI_URL") basic_auth { username = sys.env("LOKI_USER") password = sys.env("GRAFANA_CLOUD_API_KEY") } } } ``` ### MySQL ```alloy database_observability.mysql "mydb" { data_source_name = "grafana_monitoring:secret@tcp(localhost:3306)/mydb" enable_collectors = ["query_samples", "explain_plans", "schema_details"] forward_metrics_to = [prometheus.remote_write.cloud.receiver] forward_logs_to = [loki.write.cloud.receiver] } ``` ## Key Metrics ```promql # Query rate by database rate(db_query_total{db_instance="mydb"}[5m]) # P95 query latency histogram_quantile(0.95, rate(db_query_duration_seconds_bucket[5m])) # Error rate rate(db_query_errors_total[5m]) / rate(db_query_total[5m]) # Slow queries (over 1 second) count(db_query_duration_seconds > 1) by (db_query_digest) # Active connections db_connections_active{db_instance="mydb"} ``` ## What You Get **Query Performance Dashboard** (auto-provisioned): - Top queries by total time, call count, mean latency - Query samples with actual parameters and timing - Visual explain plans showing index usage, scan types, costs - RED metrics per query digest **Correlation with APM:** - Link slow DB queries to the application traces that triggered them - `db.statement`, `db.system`, `db.name` OTel attributes connect DB spans to query samples - Drill from service latency spike → specific slow SQL query → explain plan ## Alert Rules ```yaml groups: - name: database-observability rules: - alert: SlowQueryDetected expr: histogram_quantile(0.95, rate(db_query_duration_seconds_bucket[5m])) > 1 for: 5m labels: severity: warning annotations: summary: "P95 query latency > 1s on {{ $labels.db_instance }}" - alert: HighDBErrorRate expr: rate(db_query_errors_total[5m]) / rate(db_query_total[5m]) > 0.05 for: 5m labels: severity: critical annotations: summary: "DB error rate > 5% on {{ $labels.db_instance }}" - alert: TooManyConnections expr: db_connections_active / db_connections_max > 0.8 for: 5m labels: severity: warning annotations: summary: "DB connection pool >80% on {{ $labels.db_instance }}" ``` ## Setup Checklist 1. Enable `pg_stat_statements` (PostgreSQL) or Performance Schema (MySQL) 2. Create least-privilege monitoring user 3. Add `database_observability.*` block to Alloy config 4. Verify metrics appear in Grafana Cloud → Database Observability 5. Set up alerting on slow queries and error rates 6. Enable trace correlation by ensuring app uses `db.statement` span attributes