Database Monitoring
Monitor PostgreSQL and MySQL databases with essential performance metrics
Database Monitoring
Netwarden provides essential monitoring for PostgreSQL and MySQL/MariaDB databases, collecting key performance metrics without impacting database operations.
Overview
Database monitoring automatically detects running database instances and collects performance metrics. The agent uses a minimal-privilege monitoring account to gather statistics without accessing user data or affecting database performance.
Supported Databases
PostgreSQL
- Versions: 10+ supported
- Auto-detection: Process
postgresor socket file detection - Connection: Local socket (preferred) or TCP
- Optional Extension: pg_stat_statements (for slow query tracking)
MySQL/MariaDB
- MySQL Versions: 5.7, 8.0+
- MariaDB Versions: 10.3+
- Auto-detection: Process
mysqldor socket file detection - Connection: Local socket (preferred) or TCP
Important: The agent monitors one MySQL instance and one PostgreSQL instance per host.
Quick Setup
Automatic Detection
The agent automatically detects and monitors databases when they're running:
ini# /etc/netwarden/netwarden.conf # Enable database monitoring enable_postgresql: true enable_mysql: true
The agent will automatically:
- Detect running database processes
- Locate socket files across different Linux distributions
- Attempt to connect and collect metrics
- Cache statistics for 30 seconds to minimize database load
Manual Configuration
For specific requirements or when auto-detection doesn't work:
ini# PostgreSQL configuration enable_postgresql: true postgresql_host: localhost:5432 postgresql_user: svc-netwarden postgresql_password: your_secure_password_here postgresql_database: postgres postgresql_socket: /var/run/postgresql/.s.PGSQL.5432 # Or leave empty for auto-detect # MySQL configuration enable_mysql: true mysql_host: localhost:3306 mysql_user: svc-netwarden mysql_password: your_secure_password_here mysql_socket: /var/run/mysqld/mysqld.sock # Or leave empty for auto-detect
PostgreSQL Setup
1. Create Monitoring User
Connect as the PostgreSQL superuser and run:
sql-- Create monitoring user with secure random password -- Replace 'X3kP9mL2nR8vQ5wT' with your own random password CREATE USER svc_netwarden WITH PASSWORD 'X3kP9mL2nR8vQ5wT'; -- Grant monitoring role (PostgreSQL 10+) -- This provides read-only access to system statistics GRANT pg_monitor TO svc_netwarden; -- Grant database connection GRANT CONNECT ON DATABASE postgres TO svc_netwarden; -- Optional: Enable slow query tracking CREATE EXTENSION IF NOT EXISTS pg_stat_statements; GRANT SELECT ON pg_stat_statements TO svc_netwarden;
For PostgreSQL versions before 10:
sql-- Create user CREATE USER svc_netwarden WITH PASSWORD 'X3kP9mL2nR8vQ5wT'; -- Grant necessary permissions GRANT CONNECT ON DATABASE postgres TO svc_netwarden; GRANT SELECT ON pg_stat_activity TO svc_netwarden; GRANT SELECT ON pg_stat_database TO svc_netwarden;
2. Configure Authentication
Edit pg_hba.conf to allow the monitoring user to connect:
conf# Local socket connection local all svc_netwarden md5 # TCP/IP connection from localhost host all svc_netwarden 127.0.0.1/32 md5 host all svc_netwarden ::1/128 md5
Reload PostgreSQL configuration:
bashsudo systemctl reload postgresql
3. Test Connection
bashpsql -h localhost -U svc_netwarden -d postgres -c "SELECT version();"
4. Update Agent Configuration
ini# /etc/netwarden/netwarden.conf enable_postgresql: true postgresql_user: svc_netwarden postgresql_password: X3kP9mL2nR8vQ5wT postgresql_database: postgres
MySQL/MariaDB Setup
1. Create Monitoring User
Connect as the MySQL root user and run:
sql-- Create monitoring user with secure random password -- Replace 'Y7nM4kW9pL3xR6tQ' with your own random password CREATE USER 'svc_netwarden'@'localhost' IDENTIFIED BY 'Y7nM4kW9pL3xR6tQ'; -- Grant minimal required permissions -- PROCESS: Required for SHOW GLOBAL STATUS -- REPLICATION CLIENT: Optional, for replication lag monitoring GRANT PROCESS, REPLICATION CLIENT ON *.* TO 'svc_netwarden'@'localhost'; -- Apply privileges FLUSH PRIVILEGES;
What each privilege does:
PROCESS: AllowsSHOW GLOBAL STATUSquery (collects all metrics)REPLICATION CLIENT: Allows checking replication lag (optional, only needed for replicas)
2. Test Connection
bashmysql -h localhost -u svc_netwarden -p -e "SHOW GLOBAL STATUS LIKE 'Threads_connected';"
3. Update Agent Configuration
ini# /etc/netwarden/netwarden.conf enable_mysql: true mysql_user: svc_netwarden mysql_password: Y7nM4kW9pL3xR6tQ
Metrics Collected
PostgreSQL Metrics
The agent collects the following metrics every 30 seconds (cached):
| Metric Name | Description | Source |
|------------|-------------|---------|
| postgresql_up | Database process running (1=up, 0=down) | Process detection |
| postgresql_connections_active | Active connections executing queries | pg_stat_activity |
| postgresql_connections_idle | Idle connections | pg_stat_activity |
| postgresql_connections_idle_in_transaction | Connections idle in transaction | pg_stat_activity |
| postgresql_transactions_committed | Total committed transactions | pg_stat_database |
| postgresql_transactions_rollback | Total rolled back transactions | pg_stat_database |
| postgresql_blocks_hit | Blocks read from buffer cache | pg_stat_database |
| postgresql_blocks_read | Blocks read from disk | pg_stat_database |
| postgresql_buffer_hit_ratio | Buffer cache hit ratio (calculated %) | Calculated |
| postgresql_dead_tuples | Dead tuples needing vacuum | pg_stat_database |
| postgresql_locks_count | Current number of locks | pg_locks |
| postgresql_replication_lag_seconds | Replication lag in seconds (replica only) | pg_last_xact_replay_timestamp |
| postgresql_slow_queries_count | Queries slower than 1s (requires pg_stat_statements) | pg_stat_statements |
| postgresql_connection_failed | Connection failure indicator | Agent status |
Note: All metrics include a host label with the hostname.
MySQL Metrics
The agent collects the following metrics from SHOW GLOBAL STATUS:
| Metric Name | Description | Source |
|------------|-------------|---------|
| mysql_up | Database process running (1=up, 0=down) | Process detection |
| mysql_connections_current | Current open connections | Threads_connected |
| mysql_connections_max_used | Maximum connections ever used | Max_used_connections |
| mysql_queries_total | Total queries executed | Queries |
| mysql_slow_queries_total | Total slow queries | Slow_queries |
| mysql_innodb_buffer_pool_read_requests | Buffer pool read requests | Innodb_buffer_pool_read_requests |
| mysql_innodb_buffer_pool_reads | Physical reads from disk | Innodb_buffer_pool_reads |
| mysql_buffer_pool_hit_ratio | Buffer pool hit ratio (calculated %) | Calculated |
| mysql_table_locks_waited | Table locks that had to wait | Table_locks_waited |
| mysql_replication_lag_seconds | Replication lag in seconds (replica only) | Seconds_Behind_Master |
| mysql_connection_failed | Connection failure indicator | Agent status |
Note: All metrics include a host label with the hostname.
Alert Examples
PostgreSQL Alerts
Configure alerts using the actual metric names collected by the agent:
yaml# High active connections Name: PostgreSQL High Active Connections Metric: postgresql_connections_active Condition: > 90 Duration: 5 minutes # Low buffer cache hit ratio Name: PostgreSQL Cache Hit Ratio Low Metric: postgresql_buffer_hit_ratio Condition: < 85 Duration: 10 minutes # Replication lag (for replicas) Name: PostgreSQL Replication Lag Metric: postgresql_replication_lag_seconds Condition: > 30 Duration: 5 minutes # Too many dead tuples Name: PostgreSQL Dead Tuples High Metric: postgresql_dead_tuples Condition: > 100000 Duration: 15 minutes # Database down Name: PostgreSQL Down Metric: postgresql_up Condition: = 0 Duration: 1 minute
MySQL Alerts
yaml# High connection usage Name: MySQL High Connections Metric: mysql_connections_current Condition: > 100 Duration: 5 minutes # Low buffer pool hit ratio Name: MySQL Buffer Pool Hit Ratio Low Metric: mysql_buffer_pool_hit_ratio Condition: < 90 Duration: 10 minutes # High slow queries Name: MySQL Slow Queries Increasing Metric: mysql_slow_queries_total Condition: rate > 10/min Duration: 5 minutes # Replication lag (for replicas) Name: MySQL Replication Lag Metric: mysql_replication_lag_seconds Condition: > 30 Duration: 5 minutes # Database down Name: MySQL Down Metric: mysql_up Condition: = 0 Duration: 1 minute
Socket Auto-Detection
The agent automatically searches for database socket files in common locations:
MySQL Socket Paths (checked in order):
/var/run/mysqld/mysqld.sock(Ubuntu/Debian/Arch)/var/lib/mysql/mysql.sock(RHEL/CentOS/Fedora)/var/run/mysql/mysql.sock(SUSE)/run/mysqld/mysqld.sock(Alpine)/tmp/mysql.sock(Fallback)
PostgreSQL Socket Paths (checked in order):
/var/run/postgresql/(Most distributions)/run/postgresql/(Alpine/containers)/tmp/(Fallback)
The agent looks for .s.PGSQL.5432 or .s.PGSQL.5433 socket files in these directories.
Connection Pooling
The agent uses conservative connection pooling to minimize database load:
- Max Open Connections: 3
- Max Idle Connections: 1
- Connection Lifetime: 5 minutes
- Query Timeout: 5 seconds (initial), 2 seconds (health checks)
Performance Impact
The agent minimizes performance impact through:
- 30-second caching: Database statistics are cached for 30 seconds
- Lightweight queries: Only reads system statistics tables
- No table scans: Never queries user data tables
- Conservative pooling: Maximum 3 connections per database
- Read-only access: Monitoring users cannot modify data
Troubleshooting
Connection Issues
Test database connectivity:
bash# PostgreSQL psql -h localhost -U svc_netwarden -d postgres -c "SELECT version();" # MySQL mysql -h localhost -u svc_netwarden -p -e "SELECT VERSION();"
Check agent logs:
bash# View database-related logs sudo journalctl -u netwarden -n 100 | grep -i "postgres\|mysql\|database" # Check for connection errors sudo journalctl -u netwarden -n 100 | grep -i "failed to connect\|connection refused"
Permission Errors
Verify PostgreSQL permissions:
sql-- Check role memberships \du svc_netwarden -- Verify pg_monitor role (PostgreSQL 10+) SELECT rolname FROM pg_roles WHERE pg_has_role('svc_netwarden', oid, 'member');
Verify MySQL permissions:
sql-- Check granted privileges SHOW GRANTS FOR 'svc_netwarden'@'localhost'; -- Should show at least PROCESS privilege -- Example output: -- GRANT PROCESS, REPLICATION CLIENT ON *.* TO `svc_netwarden`@`localhost`
Missing Metrics
Check if database is detected:
bash# PostgreSQL process check ps aux | grep postgres # MySQL process check ps aux | grep mysqld # Socket file check ls -l /var/run/postgresql/.s.PGSQL.5432 ls -l /var/run/mysqld/mysqld.sock
Verify configuration:
bash# Check agent configuration sudo cat /etc/netwarden/netwarden.conf | grep -E "enable_postgres|enable_mysql" # Restart agent after configuration changes sudo systemctl restart netwarden sudo systemctl status netwarden
Limitations
Current Limitations:
- One Database Per Type: The agent monitors one MySQL instance and one PostgreSQL instance per host
- No Multi-Instance Support: Cannot monitor multiple PostgreSQL or MySQL instances on different ports
- No Custom Queries: Cannot define custom SQL queries for metrics
- No Table-Level Metrics: Only database-level statistics are collected
- No Query Details: Individual query text and execution plans are not captured
- Local Monitoring Only: Designed for monitoring databases on the same host as the agent
Workaround for Multiple Instances: Install a separate Netwarden agent instance with a different configuration file for each database instance you want to monitor.
Security Best Practices
- Use Dedicated Monitoring Users: Never use root, postgres, or administrative accounts
- Strong Passwords: Use random passwords of at least 16 characters
- Principle of Least Privilege: Grant only PROCESS (MySQL) or pg_monitor (PostgreSQL) roles
- Local Connections Only: Restrict monitoring user to localhost connections
- Secure Configuration Files: Ensure
/etc/netwarden/netwarden.confhas permissions 640 - Regular Password Rotation: Rotate monitoring user passwords periodically
- Audit Monitoring Access: Review database audit logs for monitoring user activity
Generating Secure Passwords
Generate a secure random password for your monitoring user:
bash# Linux/macOS - Generate 20-character random password openssl rand -base64 20 # Alternative method head /dev/urandom | tr -dc A-Za-z0-9 | head -c 20 ; echo