Add complete enterprise-level reliability, security, and performance systems: ## Core Monitoring Systems - **Health Monitor**: 8 automated health checks with email alerts and REST API - **Error Recovery**: 4 recovery strategies (retry, fallback, circuit breaker, graceful failure) - **Security Monitor**: Real-time threat detection with automatic IP blocking - **Performance Monitor**: Performance tracking with automated benchmarks and alerts ## Data Protection & Optimization - **Backup Manager**: Automated backups with encryption, compression, and disaster recovery - **Cache Optimizer**: Intelligent caching with 3 strategies and 5 specialized cache groups ## Enterprise Features - Automated scheduling with WordPress cron integration - Admin dashboards for all systems under Tools menu - REST API endpoints for external monitoring - WP-CLI commands for automation and CI/CD - Comprehensive documentation (docs/MONITORING-SYSTEMS.md) - Emergency response systems with immediate email alerts - Circuit breaker pattern for external service failures - Smart cache warming and invalidation - Database query caching and optimization - File integrity monitoring - Performance degradation detection ## Integration - Plugin architecture updated with proper initialization - Singleton pattern for all monitoring classes - WordPress hooks and filters integration - Background job processing system - Comprehensive error handling and logging Systems provide enterprise-grade reliability with automated threat response, proactive performance monitoring, and complete disaster recovery capabilities. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
951 lines
No EOL
34 KiB
PHP
951 lines
No EOL
34 KiB
PHP
<?php
|
|
/**
|
|
* HVAC Performance Monitor
|
|
*
|
|
* Provides real-time performance monitoring, benchmarking, and automated
|
|
* alerts for slow queries, memory leaks, and performance degradation
|
|
*
|
|
* @package HVAC_Community_Events
|
|
* @since 1.0.8
|
|
*/
|
|
|
|
if (!defined('ABSPATH')) {
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* HVAC_Performance_Monitor class
|
|
*/
|
|
class HVAC_Performance_Monitor {
|
|
|
|
/**
|
|
* Performance thresholds
|
|
*/
|
|
const THRESHOLDS = [
|
|
'slow_query_time' => 2.0, // 2 seconds
|
|
'memory_usage_mb' => 128, // 128 MB
|
|
'page_load_time' => 3.0, // 3 seconds
|
|
'cpu_usage_percent' => 80, // 80%
|
|
'db_query_count' => 100, // 100 queries per request
|
|
'cache_hit_rate' => 70 // 70% cache hit rate
|
|
];
|
|
|
|
/**
|
|
* Performance metrics
|
|
*/
|
|
private static $metrics = [];
|
|
private static $query_log = [];
|
|
private static $memory_checkpoints = [];
|
|
private static $start_time;
|
|
private static $start_memory;
|
|
|
|
/**
|
|
* Alert settings
|
|
*/
|
|
private static $alert_settings = [
|
|
'email_alerts' => true,
|
|
'slack_webhook' => '',
|
|
'alert_threshold' => 3, // Number of incidents before alert
|
|
'alert_cooldown' => 1800, // 30 minutes between alerts
|
|
'benchmark_frequency' => 'daily'
|
|
];
|
|
|
|
/**
|
|
* Initialize performance monitoring
|
|
*/
|
|
public static function init() {
|
|
// Load settings
|
|
self::$alert_settings = array_merge(
|
|
self::$alert_settings,
|
|
get_option('hvac_performance_settings', [])
|
|
);
|
|
|
|
// Set initial measurements
|
|
self::$start_time = microtime(true);
|
|
self::$start_memory = memory_get_usage(true);
|
|
|
|
// Hook into WordPress performance points
|
|
add_action('init', [__CLASS__, 'start_monitoring'], 0);
|
|
add_action('wp_loaded', [__CLASS__, 'checkpoint_loaded']);
|
|
add_action('wp_footer', [__CLASS__, 'checkpoint_footer']);
|
|
add_action('shutdown', [__CLASS__, 'finalize_monitoring']);
|
|
|
|
// Database query monitoring
|
|
add_filter('query', [__CLASS__, 'monitor_query']);
|
|
add_action('wp_db_query', [__CLASS__, 'log_query_completion']);
|
|
|
|
// Memory monitoring
|
|
add_action('wp_loaded', [__CLASS__, 'checkpoint_memory']);
|
|
add_action('wp_footer', [__CLASS__, 'checkpoint_memory']);
|
|
|
|
// Schedule performance benchmarks
|
|
if (!wp_next_scheduled('hvac_performance_benchmark')) {
|
|
$frequency = self::$alert_settings['benchmark_frequency'];
|
|
wp_schedule_event(time(), $frequency, 'hvac_performance_benchmark');
|
|
}
|
|
|
|
add_action('hvac_performance_benchmark', [__CLASS__, 'run_performance_benchmark']);
|
|
|
|
// Admin interface
|
|
if (is_admin()) {
|
|
add_action('admin_menu', [__CLASS__, 'add_admin_menu']);
|
|
add_action('wp_ajax_hvac_performance_action', [__CLASS__, 'handle_performance_action']);
|
|
add_action('admin_bar_menu', [__CLASS__, 'add_admin_bar_stats'], 999);
|
|
}
|
|
|
|
// REST API endpoints
|
|
add_action('rest_api_init', [__CLASS__, 'register_rest_endpoints']);
|
|
|
|
// WP-CLI integration
|
|
if (defined('WP_CLI') && WP_CLI) {
|
|
WP_CLI::add_command('hvac performance', [__CLASS__, 'wp_cli_performance']);
|
|
}
|
|
|
|
// Emergency alerts for critical performance issues
|
|
add_action('hvac_critical_performance_issue', [__CLASS__, 'handle_critical_issue']);
|
|
}
|
|
|
|
/**
|
|
* Start monitoring
|
|
*/
|
|
public static function start_monitoring() {
|
|
// Only monitor frontend requests and specific admin pages
|
|
if (!self::should_monitor()) {
|
|
return;
|
|
}
|
|
|
|
self::$metrics['start_time'] = microtime(true);
|
|
self::$metrics['start_memory'] = memory_get_usage(true);
|
|
self::$metrics['query_count'] = 0;
|
|
self::$metrics['slow_queries'] = [];
|
|
|
|
// Set up query monitoring
|
|
global $wpdb;
|
|
$wpdb->save_queries = true;
|
|
}
|
|
|
|
/**
|
|
* Check if we should monitor this request
|
|
*/
|
|
private static function should_monitor() {
|
|
// Skip monitoring for certain requests
|
|
if (wp_doing_ajax() || wp_doing_cron() || (defined('WP_CLI') && WP_CLI)) {
|
|
return false;
|
|
}
|
|
|
|
// Skip for admin unless it's a plugin page
|
|
if (is_admin()) {
|
|
$screen = get_current_screen();
|
|
if (!$screen || strpos($screen->id, 'hvac') === false) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Skip for REST API unless it's our endpoints
|
|
if (defined('REST_REQUEST') && REST_REQUEST) {
|
|
$request_uri = $_SERVER['REQUEST_URI'] ?? '';
|
|
if (strpos($request_uri, '/hvac/v1/') === false) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Monitor database queries
|
|
*/
|
|
public static function monitor_query($query) {
|
|
if (!isset(self::$metrics['start_time'])) {
|
|
return $query;
|
|
}
|
|
|
|
$start_time = microtime(true);
|
|
|
|
// Store query info for monitoring
|
|
self::$query_log[] = [
|
|
'query' => $query,
|
|
'start_time' => $start_time,
|
|
'backtrace' => debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5)
|
|
];
|
|
|
|
return $query;
|
|
}
|
|
|
|
/**
|
|
* Log query completion
|
|
*/
|
|
public static function log_query_completion($result) {
|
|
if (empty(self::$query_log)) {
|
|
return;
|
|
}
|
|
|
|
$current_query = &self::$query_log[count(self::$query_log) - 1];
|
|
$execution_time = microtime(true) - $current_query['start_time'];
|
|
$current_query['execution_time'] = $execution_time;
|
|
|
|
self::$metrics['query_count']++;
|
|
|
|
// Check for slow queries
|
|
if ($execution_time > self::THRESHOLDS['slow_query_time']) {
|
|
self::$metrics['slow_queries'][] = [
|
|
'query' => substr($current_query['query'], 0, 200),
|
|
'time' => $execution_time,
|
|
'backtrace' => $current_query['backtrace']
|
|
];
|
|
|
|
// Log slow query
|
|
HVAC_Logger::warning(
|
|
"Slow query detected: {$execution_time}s - " . substr($current_query['query'], 0, 100),
|
|
'Performance Monitor'
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Memory checkpoint
|
|
*/
|
|
public static function checkpoint_memory($checkpoint = null) {
|
|
if (!isset(self::$metrics['start_time'])) {
|
|
return;
|
|
}
|
|
|
|
$current_memory = memory_get_usage(true);
|
|
$peak_memory = memory_get_peak_usage(true);
|
|
|
|
if ($checkpoint === null) {
|
|
$checkpoint = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0]['function'];
|
|
}
|
|
|
|
self::$memory_checkpoints[] = [
|
|
'checkpoint' => $checkpoint,
|
|
'time' => microtime(true),
|
|
'current_memory' => $current_memory,
|
|
'peak_memory' => $peak_memory,
|
|
'memory_mb' => round($current_memory / 1024 / 1024, 2)
|
|
];
|
|
|
|
// Check for memory threshold breach
|
|
$memory_mb = $current_memory / 1024 / 1024;
|
|
if ($memory_mb > self::THRESHOLDS['memory_usage_mb']) {
|
|
HVAC_Logger::warning(
|
|
"High memory usage detected: {$memory_mb}MB at checkpoint: $checkpoint",
|
|
'Performance Monitor'
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Checkpoint: WordPress loaded
|
|
*/
|
|
public static function checkpoint_loaded() {
|
|
self::checkpoint_memory('wp_loaded');
|
|
}
|
|
|
|
/**
|
|
* Checkpoint: Footer
|
|
*/
|
|
public static function checkpoint_footer() {
|
|
self::checkpoint_memory('wp_footer');
|
|
}
|
|
|
|
/**
|
|
* Finalize monitoring
|
|
*/
|
|
public static function finalize_monitoring() {
|
|
if (!isset(self::$metrics['start_time'])) {
|
|
return;
|
|
}
|
|
|
|
$end_time = microtime(true);
|
|
$total_time = $end_time - self::$metrics['start_time'];
|
|
$peak_memory = memory_get_peak_usage(true);
|
|
$peak_memory_mb = $peak_memory / 1024 / 1024;
|
|
|
|
// Finalize metrics
|
|
self::$metrics['total_time'] = $total_time;
|
|
self::$metrics['peak_memory'] = $peak_memory;
|
|
self::$metrics['peak_memory_mb'] = $peak_memory_mb;
|
|
self::$metrics['timestamp'] = time();
|
|
|
|
// Calculate cache hit rate if object cache is available
|
|
if (function_exists('wp_cache_get_stats')) {
|
|
$cache_stats = wp_cache_get_stats();
|
|
if (isset($cache_stats['cache_hits']) && isset($cache_stats['cache_misses'])) {
|
|
$total_requests = $cache_stats['cache_hits'] + $cache_stats['cache_misses'];
|
|
if ($total_requests > 0) {
|
|
self::$metrics['cache_hit_rate'] = ($cache_stats['cache_hits'] / $total_requests) * 100;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Check thresholds and send alerts
|
|
self::check_performance_thresholds();
|
|
|
|
// Store metrics for analysis
|
|
self::store_performance_metrics();
|
|
|
|
// Log performance summary for slow requests
|
|
if ($total_time > self::THRESHOLDS['page_load_time']) {
|
|
HVAC_Logger::warning(
|
|
"Slow page load: {$total_time}s, Memory: {$peak_memory_mb}MB, Queries: " . self::$metrics['query_count'],
|
|
'Performance Monitor'
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check performance thresholds
|
|
*/
|
|
private static function check_performance_thresholds() {
|
|
$alerts = [];
|
|
|
|
// Check page load time
|
|
if (self::$metrics['total_time'] > self::THRESHOLDS['page_load_time']) {
|
|
$alerts[] = [
|
|
'type' => 'slow_page_load',
|
|
'message' => 'Page load time exceeded threshold',
|
|
'value' => self::$metrics['total_time'],
|
|
'threshold' => self::THRESHOLDS['page_load_time']
|
|
];
|
|
}
|
|
|
|
// Check memory usage
|
|
if (self::$metrics['peak_memory_mb'] > self::THRESHOLDS['memory_usage_mb']) {
|
|
$alerts[] = [
|
|
'type' => 'high_memory_usage',
|
|
'message' => 'Memory usage exceeded threshold',
|
|
'value' => self::$metrics['peak_memory_mb'],
|
|
'threshold' => self::THRESHOLDS['memory_usage_mb']
|
|
];
|
|
}
|
|
|
|
// Check query count
|
|
if (self::$metrics['query_count'] > self::THRESHOLDS['db_query_count']) {
|
|
$alerts[] = [
|
|
'type' => 'excessive_queries',
|
|
'message' => 'Database query count exceeded threshold',
|
|
'value' => self::$metrics['query_count'],
|
|
'threshold' => self::THRESHOLDS['db_query_count']
|
|
];
|
|
}
|
|
|
|
// Check slow queries
|
|
if (count(self::$metrics['slow_queries']) > 0) {
|
|
$alerts[] = [
|
|
'type' => 'slow_queries',
|
|
'message' => 'Slow queries detected',
|
|
'value' => count(self::$metrics['slow_queries']),
|
|
'threshold' => 0
|
|
];
|
|
}
|
|
|
|
// Check cache hit rate
|
|
if (isset(self::$metrics['cache_hit_rate']) &&
|
|
self::$metrics['cache_hit_rate'] < self::THRESHOLDS['cache_hit_rate']) {
|
|
$alerts[] = [
|
|
'type' => 'low_cache_hit_rate',
|
|
'message' => 'Cache hit rate below threshold',
|
|
'value' => self::$metrics['cache_hit_rate'],
|
|
'threshold' => self::THRESHOLDS['cache_hit_rate']
|
|
];
|
|
}
|
|
|
|
// Process alerts
|
|
if (!empty($alerts)) {
|
|
self::process_performance_alerts($alerts);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Process performance alerts
|
|
*/
|
|
private static function process_performance_alerts($alerts) {
|
|
// Count recent alerts to avoid spam
|
|
$recent_alerts = self::get_recent_alerts(1800); // Last 30 minutes
|
|
|
|
if (count($recent_alerts) >= self::$alert_settings['alert_threshold']) {
|
|
return; // Cooldown period
|
|
}
|
|
|
|
// Store alerts
|
|
$stored_alerts = get_option('hvac_performance_alerts', []);
|
|
foreach ($alerts as $alert) {
|
|
$alert['timestamp'] = time();
|
|
$alert['request_uri'] = $_SERVER['REQUEST_URI'] ?? '';
|
|
$alert['user_agent'] = $_SERVER['HTTP_USER_AGENT'] ?? '';
|
|
$stored_alerts[] = $alert;
|
|
}
|
|
|
|
// Keep only last 1000 alerts
|
|
if (count($stored_alerts) > 1000) {
|
|
$stored_alerts = array_slice($stored_alerts, -1000);
|
|
}
|
|
|
|
update_option('hvac_performance_alerts', $stored_alerts);
|
|
|
|
// Send notifications
|
|
if (self::$alert_settings['email_alerts']) {
|
|
self::send_performance_alert_email($alerts);
|
|
}
|
|
|
|
// Check for critical issues
|
|
$critical_alerts = array_filter($alerts, function($alert) {
|
|
return $alert['type'] === 'slow_page_load' && $alert['value'] > 10 ||
|
|
$alert['type'] === 'high_memory_usage' && $alert['value'] > 256 ||
|
|
$alert['type'] === 'excessive_queries' && $alert['value'] > 500;
|
|
});
|
|
|
|
if (!empty($critical_alerts)) {
|
|
do_action('hvac_critical_performance_issue', $critical_alerts);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get recent alerts
|
|
*/
|
|
private static function get_recent_alerts($timeframe = 1800) {
|
|
$stored_alerts = get_option('hvac_performance_alerts', []);
|
|
$cutoff_time = time() - $timeframe;
|
|
|
|
return array_filter($stored_alerts, function($alert) use ($cutoff_time) {
|
|
return $alert['timestamp'] >= $cutoff_time;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Send performance alert email
|
|
*/
|
|
private static function send_performance_alert_email($alerts) {
|
|
$admin_email = get_option('admin_email');
|
|
$site_name = get_bloginfo('name');
|
|
|
|
$subject = "[$site_name] Performance Alert";
|
|
$message = "Performance issues detected on $site_name:\n\n";
|
|
|
|
foreach ($alerts as $alert) {
|
|
$message .= "• {$alert['message']}\n";
|
|
$message .= " Value: {$alert['value']} (Threshold: {$alert['threshold']})\n\n";
|
|
}
|
|
|
|
$message .= "Request: " . ($_SERVER['REQUEST_URI'] ?? 'Unknown') . "\n";
|
|
$message .= "Time: " . date('Y-m-d H:i:s') . "\n";
|
|
$message .= "\nCheck the performance monitor for detailed analysis.";
|
|
|
|
wp_mail($admin_email, $subject, $message);
|
|
}
|
|
|
|
/**
|
|
* Store performance metrics
|
|
*/
|
|
private static function store_performance_metrics() {
|
|
// Store in database for trend analysis
|
|
global $wpdb;
|
|
|
|
$metrics_data = [
|
|
'timestamp' => time(),
|
|
'page_load_time' => self::$metrics['total_time'],
|
|
'peak_memory_mb' => self::$metrics['peak_memory_mb'],
|
|
'query_count' => self::$metrics['query_count'],
|
|
'slow_query_count' => count(self::$metrics['slow_queries']),
|
|
'cache_hit_rate' => self::$metrics['cache_hit_rate'] ?? null,
|
|
'request_uri' => $_SERVER['REQUEST_URI'] ?? '',
|
|
];
|
|
|
|
// Store in options (simple approach - could use custom table for high-volume sites)
|
|
$stored_metrics = get_option('hvac_performance_metrics', []);
|
|
$stored_metrics[] = $metrics_data;
|
|
|
|
// Keep only last 1000 metrics
|
|
if (count($stored_metrics) > 1000) {
|
|
$stored_metrics = array_slice($stored_metrics, -1000);
|
|
}
|
|
|
|
update_option('hvac_performance_metrics', $stored_metrics);
|
|
}
|
|
|
|
/**
|
|
* Run performance benchmark
|
|
*/
|
|
public static function run_performance_benchmark() {
|
|
$benchmark_results = [
|
|
'timestamp' => time(),
|
|
'database_benchmark' => self::benchmark_database(),
|
|
'memory_benchmark' => self::benchmark_memory(),
|
|
'cache_benchmark' => self::benchmark_cache(),
|
|
'file_io_benchmark' => self::benchmark_file_io()
|
|
];
|
|
|
|
// Store benchmark results
|
|
update_option('hvac_performance_benchmark', $benchmark_results);
|
|
|
|
HVAC_Logger::info(
|
|
'Performance benchmark completed: ' . json_encode($benchmark_results),
|
|
'Performance Monitor'
|
|
);
|
|
|
|
// Check if performance has degraded
|
|
$previous_benchmark = get_option('hvac_previous_benchmark', null);
|
|
if ($previous_benchmark) {
|
|
$degradation = self::check_performance_degradation($previous_benchmark, $benchmark_results);
|
|
if ($degradation) {
|
|
self::send_performance_alert_email([
|
|
[
|
|
'type' => 'performance_degradation',
|
|
'message' => 'Performance degradation detected',
|
|
'details' => $degradation
|
|
]
|
|
]);
|
|
}
|
|
}
|
|
|
|
update_option('hvac_previous_benchmark', $benchmark_results);
|
|
}
|
|
|
|
/**
|
|
* Benchmark database performance
|
|
*/
|
|
private static function benchmark_database() {
|
|
global $wpdb;
|
|
|
|
$start_time = microtime(true);
|
|
|
|
// Simple query benchmark
|
|
$wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->posts}");
|
|
$simple_query_time = microtime(true) - $start_time;
|
|
|
|
// Complex query benchmark
|
|
$start_time = microtime(true);
|
|
$wpdb->get_results("
|
|
SELECT p.*, pm.meta_value
|
|
FROM {$wpdb->posts} p
|
|
LEFT JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id
|
|
WHERE p.post_type = 'post'
|
|
AND p.post_status = 'publish'
|
|
LIMIT 10
|
|
");
|
|
$complex_query_time = microtime(true) - $start_time;
|
|
|
|
return [
|
|
'simple_query_time' => round($simple_query_time, 4),
|
|
'complex_query_time' => round($complex_query_time, 4)
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Benchmark memory performance
|
|
*/
|
|
private static function benchmark_memory() {
|
|
$start_memory = memory_get_usage();
|
|
|
|
// Create test data
|
|
$test_data = [];
|
|
for ($i = 0; $i < 1000; $i++) {
|
|
$test_data[] = str_repeat('x', 1000);
|
|
}
|
|
|
|
$peak_memory = memory_get_usage();
|
|
$memory_used = $peak_memory - $start_memory;
|
|
|
|
unset($test_data);
|
|
|
|
return [
|
|
'memory_used_mb' => round($memory_used / 1024 / 1024, 2),
|
|
'peak_memory_mb' => round(memory_get_peak_usage() / 1024 / 1024, 2)
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Benchmark cache performance
|
|
*/
|
|
private static function benchmark_cache() {
|
|
$iterations = 100;
|
|
$test_key = 'hvac_performance_test_' . time();
|
|
$test_data = str_repeat('x', 1000);
|
|
|
|
// Write benchmark
|
|
$start_time = microtime(true);
|
|
for ($i = 0; $i < $iterations; $i++) {
|
|
wp_cache_set($test_key . $i, $test_data, 'hvac_perf_test', 60);
|
|
}
|
|
$write_time = microtime(true) - $start_time;
|
|
|
|
// Read benchmark
|
|
$start_time = microtime(true);
|
|
for ($i = 0; $i < $iterations; $i++) {
|
|
wp_cache_get($test_key . $i, 'hvac_perf_test');
|
|
}
|
|
$read_time = microtime(true) - $start_time;
|
|
|
|
// Cleanup
|
|
for ($i = 0; $i < $iterations; $i++) {
|
|
wp_cache_delete($test_key . $i, 'hvac_perf_test');
|
|
}
|
|
|
|
return [
|
|
'write_time' => round($write_time, 4),
|
|
'read_time' => round($read_time, 4),
|
|
'writes_per_second' => round($iterations / $write_time, 2),
|
|
'reads_per_second' => round($iterations / $read_time, 2)
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Benchmark file I/O performance
|
|
*/
|
|
private static function benchmark_file_io() {
|
|
$upload_dir = wp_upload_dir()['basedir'];
|
|
$test_file = $upload_dir . '/hvac_perf_test.txt';
|
|
$test_data = str_repeat('Performance test data. ', 1000);
|
|
|
|
// Write benchmark
|
|
$start_time = microtime(true);
|
|
file_put_contents($test_file, $test_data);
|
|
$write_time = microtime(true) - $start_time;
|
|
|
|
// Read benchmark
|
|
$start_time = microtime(true);
|
|
$read_data = file_get_contents($test_file);
|
|
$read_time = microtime(true) - $start_time;
|
|
|
|
// Cleanup
|
|
if (file_exists($test_file)) {
|
|
unlink($test_file);
|
|
}
|
|
|
|
return [
|
|
'write_time' => round($write_time, 4),
|
|
'read_time' => round($read_time, 4),
|
|
'data_size_kb' => round(strlen($test_data) / 1024, 2)
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Check performance degradation
|
|
*/
|
|
private static function check_performance_degradation($previous, $current) {
|
|
$degradation_threshold = 0.5; // 50% increase
|
|
$issues = [];
|
|
|
|
// Check database performance
|
|
$db_degradation = ($current['database_benchmark']['complex_query_time'] /
|
|
$previous['database_benchmark']['complex_query_time']) - 1;
|
|
if ($db_degradation > $degradation_threshold) {
|
|
$issues[] = "Database queries " . round($db_degradation * 100, 1) . "% slower";
|
|
}
|
|
|
|
// Check cache performance
|
|
$cache_degradation = ($current['cache_benchmark']['read_time'] /
|
|
$previous['cache_benchmark']['read_time']) - 1;
|
|
if ($cache_degradation > $degradation_threshold) {
|
|
$issues[] = "Cache reads " . round($cache_degradation * 100, 1) . "% slower";
|
|
}
|
|
|
|
return empty($issues) ? false : $issues;
|
|
}
|
|
|
|
/**
|
|
* Handle critical performance issues
|
|
*/
|
|
public static function handle_critical_issue($alerts) {
|
|
// Log critical issue
|
|
HVAC_Logger::error(
|
|
'Critical performance issue detected: ' . json_encode($alerts),
|
|
'Performance Monitor'
|
|
);
|
|
|
|
// Send immediate alert
|
|
$admin_email = get_option('admin_email');
|
|
$site_name = get_bloginfo('name');
|
|
|
|
$subject = "[$site_name] CRITICAL Performance Issue";
|
|
$message = "CRITICAL performance issues detected:\n\n";
|
|
|
|
foreach ($alerts as $alert) {
|
|
$message .= "• {$alert['message']}: {$alert['value']}\n";
|
|
}
|
|
|
|
$message .= "\nImmediate attention required!";
|
|
|
|
wp_mail($admin_email, $subject, $message);
|
|
|
|
// Trigger error recovery if available
|
|
if (class_exists('HVAC_Error_Recovery')) {
|
|
do_action('hvac_operation_failed', 'performance', 'Critical performance degradation', $alerts);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get performance statistics
|
|
*/
|
|
public static function get_performance_stats() {
|
|
$metrics = get_option('hvac_performance_metrics', []);
|
|
$alerts = get_option('hvac_performance_alerts', []);
|
|
$benchmark = get_option('hvac_performance_benchmark', null);
|
|
|
|
if (empty($metrics)) {
|
|
return [
|
|
'avg_page_load_time' => 0,
|
|
'avg_memory_usage' => 0,
|
|
'avg_query_count' => 0,
|
|
'total_requests' => 0,
|
|
'recent_alerts' => 0,
|
|
'benchmark' => null
|
|
];
|
|
}
|
|
|
|
$total_requests = count($metrics);
|
|
$recent_cutoff = time() - 86400; // Last 24 hours
|
|
|
|
// Calculate averages
|
|
$avg_page_load_time = array_sum(array_column($metrics, 'page_load_time')) / $total_requests;
|
|
$avg_memory_usage = array_sum(array_column($metrics, 'peak_memory_mb')) / $total_requests;
|
|
$avg_query_count = array_sum(array_column($metrics, 'query_count')) / $total_requests;
|
|
|
|
// Recent alerts
|
|
$recent_alerts = count(array_filter($alerts, function($alert) use ($recent_cutoff) {
|
|
return $alert['timestamp'] >= $recent_cutoff;
|
|
}));
|
|
|
|
return [
|
|
'avg_page_load_time' => round($avg_page_load_time, 3),
|
|
'avg_memory_usage' => round($avg_memory_usage, 2),
|
|
'avg_query_count' => round($avg_query_count, 1),
|
|
'total_requests' => $total_requests,
|
|
'recent_alerts' => $recent_alerts,
|
|
'benchmark' => $benchmark
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Add admin menu
|
|
*/
|
|
public static function add_admin_menu() {
|
|
if (current_user_can('manage_options')) {
|
|
add_management_page(
|
|
'HVAC Performance Monitor',
|
|
'HVAC Performance',
|
|
'manage_options',
|
|
'hvac-performance-monitor',
|
|
[__CLASS__, 'admin_page']
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add admin bar stats
|
|
*/
|
|
public static function add_admin_bar_stats($admin_bar) {
|
|
if (!current_user_can('manage_options') || !isset(self::$metrics['start_time'])) {
|
|
return;
|
|
}
|
|
|
|
$current_memory = round(memory_get_usage(true) / 1024 / 1024, 1);
|
|
$query_count = get_num_queries();
|
|
|
|
$admin_bar->add_node([
|
|
'id' => 'hvac-performance',
|
|
'title' => "HVAC: {$current_memory}MB | {$query_count}Q",
|
|
'href' => admin_url('tools.php?page=hvac-performance-monitor')
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Admin page
|
|
*/
|
|
public static function admin_page() {
|
|
$stats = self::get_performance_stats();
|
|
$recent_alerts = array_slice(get_option('hvac_performance_alerts', []), -20, 20, true);
|
|
$current_metrics = self::$metrics;
|
|
|
|
?>
|
|
<div class="wrap">
|
|
<h1>HVAC Performance Monitor</h1>
|
|
|
|
<div class="performance-overview">
|
|
<div class="card">
|
|
<h2>Performance Overview</h2>
|
|
<p><strong>Average Page Load Time:</strong> <?php echo $stats['avg_page_load_time']; ?>s</p>
|
|
<p><strong>Average Memory Usage:</strong> <?php echo $stats['avg_memory_usage']; ?>MB</p>
|
|
<p><strong>Average Query Count:</strong> <?php echo $stats['avg_query_count']; ?></p>
|
|
<p><strong>Total Requests Monitored:</strong> <?php echo $stats['total_requests']; ?></p>
|
|
<p><strong>Recent Alerts (24h):</strong> <?php echo $stats['recent_alerts']; ?></p>
|
|
</div>
|
|
|
|
<?php if (!empty($current_metrics)): ?>
|
|
<div class="card">
|
|
<h2>Current Request Stats</h2>
|
|
<p><strong>Load Time:</strong> <?php echo isset($current_metrics['total_time']) ? round($current_metrics['total_time'], 3) . 's' : 'In progress'; ?></p>
|
|
<p><strong>Peak Memory:</strong> <?php echo isset($current_metrics['peak_memory_mb']) ? round($current_metrics['peak_memory_mb'], 2) . 'MB' : round(memory_get_peak_usage(true) / 1024 / 1024, 2) . 'MB'; ?></p>
|
|
<p><strong>Queries:</strong> <?php echo $current_metrics['query_count'] ?? get_num_queries(); ?></p>
|
|
<p><strong>Slow Queries:</strong> <?php echo count($current_metrics['slow_queries'] ?? []); ?></p>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($stats['benchmark']): ?>
|
|
<div class="card">
|
|
<h2>Latest Benchmark</h2>
|
|
<p><strong>Date:</strong> <?php echo date('Y-m-d H:i:s', $stats['benchmark']['timestamp']); ?></p>
|
|
<p><strong>Database (simple):</strong> <?php echo $stats['benchmark']['database_benchmark']['simple_query_time']; ?>s</p>
|
|
<p><strong>Database (complex):</strong> <?php echo $stats['benchmark']['database_benchmark']['complex_query_time']; ?>s</p>
|
|
<p><strong>Cache Reads/sec:</strong> <?php echo $stats['benchmark']['cache_benchmark']['reads_per_second']; ?></p>
|
|
<p>
|
|
<button type="button" id="run-benchmark" class="button button-primary">Run New Benchmark</button>
|
|
</p>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h2>Recent Performance Alerts</h2>
|
|
<table class="wp-list-table widefat fixed striped">
|
|
<thead>
|
|
<tr>
|
|
<th>Time</th>
|
|
<th>Type</th>
|
|
<th>Message</th>
|
|
<th>Value</th>
|
|
<th>Threshold</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php if (empty($recent_alerts)): ?>
|
|
<tr>
|
|
<td colspan="5">No recent performance alerts</td>
|
|
</tr>
|
|
<?php else: ?>
|
|
<?php foreach (array_reverse($recent_alerts) as $alert): ?>
|
|
<tr>
|
|
<td><?php echo date('Y-m-d H:i:s', $alert['timestamp']); ?></td>
|
|
<td><?php echo esc_html($alert['type']); ?></td>
|
|
<td><?php echo esc_html($alert['message']); ?></td>
|
|
<td><?php echo esc_html($alert['value']); ?></td>
|
|
<td><?php echo esc_html($alert['threshold']); ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
<?php endif; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h2>Performance Thresholds</h2>
|
|
<p>The following thresholds trigger performance alerts:</p>
|
|
<ul>
|
|
<li><strong>Slow Query Time:</strong> <?php echo self::THRESHOLDS['slow_query_time']; ?>s</li>
|
|
<li><strong>Memory Usage:</strong> <?php echo self::THRESHOLDS['memory_usage_mb']; ?>MB</li>
|
|
<li><strong>Page Load Time:</strong> <?php echo self::THRESHOLDS['page_load_time']; ?>s</li>
|
|
<li><strong>Database Query Count:</strong> <?php echo self::THRESHOLDS['db_query_count']; ?> queries</li>
|
|
<li><strong>Cache Hit Rate:</strong> <?php echo self::THRESHOLDS['cache_hit_rate']; ?>%</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<style>
|
|
.performance-overview { display: flex; gap: 20px; margin-bottom: 20px; }
|
|
.performance-overview .card { flex: 1; }
|
|
</style>
|
|
|
|
<script>
|
|
document.getElementById('run-benchmark')?.addEventListener('click', function() {
|
|
this.disabled = true;
|
|
this.textContent = 'Running Benchmark...';
|
|
|
|
fetch(ajaxurl, {
|
|
method: 'POST',
|
|
body: new URLSearchParams({
|
|
action: 'hvac_performance_action',
|
|
performance_action: 'run_benchmark',
|
|
nonce: '<?php echo wp_create_nonce('hvac_performance_action'); ?>'
|
|
})
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
location.reload();
|
|
} else {
|
|
alert('Benchmark failed');
|
|
this.disabled = false;
|
|
this.textContent = 'Run New Benchmark';
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
</div>
|
|
<?php
|
|
}
|
|
|
|
/**
|
|
* Handle performance actions
|
|
*/
|
|
public static function handle_performance_action() {
|
|
check_ajax_referer('hvac_performance_action', 'nonce');
|
|
|
|
if (!current_user_can('manage_options')) {
|
|
wp_send_json_error('Insufficient permissions');
|
|
}
|
|
|
|
$action = sanitize_text_field($_POST['performance_action']);
|
|
|
|
switch ($action) {
|
|
case 'run_benchmark':
|
|
self::run_performance_benchmark();
|
|
wp_send_json_success('Benchmark completed');
|
|
break;
|
|
|
|
default:
|
|
wp_send_json_error('Unknown action');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Register REST endpoints
|
|
*/
|
|
public static function register_rest_endpoints() {
|
|
register_rest_route('hvac/v1', '/performance/stats', [
|
|
'methods' => 'GET',
|
|
'callback' => [__CLASS__, 'rest_performance_stats'],
|
|
'permission_callback' => function() {
|
|
return current_user_can('manage_options');
|
|
}
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* REST API performance stats
|
|
*/
|
|
public static function rest_performance_stats() {
|
|
$stats = self::get_performance_stats();
|
|
|
|
return new WP_REST_Response([
|
|
'stats' => $stats,
|
|
'timestamp' => time()
|
|
], 200);
|
|
}
|
|
|
|
/**
|
|
* WP-CLI performance command
|
|
*/
|
|
public static function wp_cli_performance($args, $assoc_args) {
|
|
$subcommand = $args[0] ?? 'stats';
|
|
|
|
switch ($subcommand) {
|
|
case 'stats':
|
|
$stats = self::get_performance_stats();
|
|
WP_CLI::line('HVAC Performance Statistics:');
|
|
WP_CLI::line('Average Page Load: ' . $stats['avg_page_load_time'] . 's');
|
|
WP_CLI::line('Average Memory: ' . $stats['avg_memory_usage'] . 'MB');
|
|
WP_CLI::line('Average Queries: ' . $stats['avg_query_count']);
|
|
WP_CLI::line('Recent Alerts: ' . $stats['recent_alerts']);
|
|
break;
|
|
|
|
case 'benchmark':
|
|
WP_CLI::line('Running performance benchmark...');
|
|
self::run_performance_benchmark();
|
|
WP_CLI::success('Benchmark completed');
|
|
break;
|
|
|
|
default:
|
|
WP_CLI::error('Unknown subcommand. Use: stats, benchmark');
|
|
}
|
|
}
|
|
}
|