Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Performance Monitor

CSM monitors server performance metrics and generates findings when thresholds are exceeded.

Critical Checks (every 10 min)

CheckWhat it monitors
perf_loadCPU load average vs core count (critical/high/warning thresholds)
perf_php_processesPHP process count and total memory usage
perf_memorySwap usage percentage and OOM killer activity

Deep Checks (every 60 min)

CheckWhat it monitors
perf_php_handlerPHP handler type (DSO vs CGI vs FPM) and configuration
perf_mysql_configMySQL my.cnf settings (buffer pool, connections, query cache)
perf_redis_configRedis memory limits, persistence, eviction policy
perf_error_logsError log file sizes (bloat detection)
perf_wp_configWordPress wp-config.php hardening and debug settings
perf_wp_transientsWordPress database transient bloat
perf_wp_cronWordPress cron scheduling (missed crons, excessive events)

Web UI

The Performance page (/performance) shows real-time metrics:

  • Server load and CPU usage
  • PHP process and memory charts
  • MySQL and Redis health
  • WordPress performance indicators

The findings list also exposes admin-only fixes, per-row and as a Bulk fix dropdown that applies one fix to every matching finding at once:

  • perf_error_logs: truncate a bloated error_log in place. The inode is preserved so running PHP processes keep writing to the same file.

  • perf_wp_config: disable display_errors in .user.ini, php.ini, or .htaccess by commenting the matched line and appending an Off override.

  • perf_wp_cron: add define('DISABLE_WP_CRON', true) to wp-config.php and install a per-user system cron that runs wp-cron.php on a fixed interval. Disabling WP-Cron alone would stop scheduled WordPress tasks, so the cron is installed in the account owner’s own crontab (visible and editable by the customer). The cron is installed before the define is written, so a crontab failure leaves WordPress scheduling unchanged. The define is inserted before the “stop editing” marker (or the wp-settings.php require); insertion points inside multiline comments or heredocs are ignored, and the fix refuses a wp-config.php with no safe insertion point rather than corrupt it.

    The installed schedule is staggered per account and docroot (for example 7-59/15) instead of a wall-clock-aligned */15, so many managed sites do not all fire in the same second and spike the host load. Non-divisor intervals use a shifted minute list so the gap stays within the configured interval. The command also runs under flock -n with a per-docroot lock file in the account home, so a slow pass skips the next run instead of overlapping it. On daemon start, managed crontab lines installed by older releases are upgraded to this format automatically (only lines under the # CSM WP-Cron marker are touched; customer-authored cron entries are never rewritten).

These actions are limited to configured account roots, reject symlinks and unsupported file types, and remove the fixed row from the active findings view after a successful edit.

WP-Cron fix settings

Tune the WP-Cron remediation under Settings -> Performance:

  • performance.wp_cron_fix.interval_minutes (default 15, range 1-60): how often the installed system cron runs wp-cron.php. The interval only bounds task latency – WordPress keeps its own event schedule and a cron pass with nothing due is a wasted full bootstrap – so 15 minutes is right for most sites. Lower it per host only when busy stores need tighter Action Scheduler latency.
  • performance.wp_cron_fix.php_bin (default empty = auto-detect): the PHP interpreter for the cron line. CLI php is used instead of an HTTP request so the job never ties up a web worker.

To let the daemon apply this fix automatically on every WP-Cron finding, set auto_response.fix_wp_cron: true (default false; requires auto_response.enabled: true). It is opt-in because it edits customer wp-config.php files and crontabs.

MySQL telemetry auth

The MySQL panel runs mysql -e "SHOW STATUS LIKE 'Threads_connected'" from the csm process. The client needs to authenticate against the local server, and csm supports two setups out of the box:

  • A ~/.my.cnf for the csm runtime user with credentials for a MySQL account that holds at least the PROCESS privilege. cPanel and CloudLinux ship /root/.my.cnf for the root user; csm running as root picks it up automatically.

  • A unix-socket grant for the csm OS user, e.g. on Debian/Ubuntu MariaDB:

    CREATE USER 'root'@'localhost' IDENTIFIED VIA unix_socket;
    GRANT PROCESS ON *.* TO 'root'@'localhost';
    

If neither is configured, the MYSQL card renders n/a / n/a instead of a misleading 0 conn. csm makes no attempt to connect over TCP or store credentials on its own.

Redis telemetry auth

The Redis panel connects to local Redis at 127.0.0.1:6379. If Redis requires a password, set REDISCLI_AUTH in the csm daemon environment. The dashboard uses that password for its in-process Redis client.

API

GET /api/v1/performance    Current performance metrics snapshot
POST /api/v1/perf/fix-error-log
POST /api/v1/perf/fix-display-errors
POST /api/v1/perf/fix-wp-cron