upskill-event-manager/includes/class-hvac-health-monitor.php
bengizmo afc221a98a feat: Implement comprehensive enterprise monitoring and optimization infrastructure
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>
2025-08-07 04:08:52 -03:00

761 lines
No EOL
25 KiB
PHP

<?php
/**
* HVAC Health Monitor
*
* Provides automated testing and health monitoring for critical plugin functionality
*
* @package HVAC_Community_Events
* @since 1.0.8
*/
if (!defined('ABSPATH')) {
exit;
}
/**
* HVAC_Health_Monitor class
*/
class HVAC_Health_Monitor {
/**
* Health check types
*/
const CHECK_TYPES = [
'database' => 'Database Connectivity',
'cache' => 'Cache System',
'authentication' => 'User Authentication',
'events' => 'Event Management',
'certificates' => 'Certificate Generation',
'background_jobs' => 'Background Jobs',
'file_permissions' => 'File Permissions',
'third_party' => 'Third Party Integrations'
];
/**
* Health status constants
*/
const STATUS_HEALTHY = 'healthy';
const STATUS_WARNING = 'warning';
const STATUS_CRITICAL = 'critical';
/**
* Health check results cache
*/
const CACHE_KEY = 'hvac_health_checks';
const CACHE_DURATION = 300; // 5 minutes
/**
* Initialize health monitoring
*/
public static function init() {
// Schedule recurring health checks
if (!wp_next_scheduled('hvac_health_check')) {
wp_schedule_event(time(), 'hourly', 'hvac_health_check');
}
// Hook health check action
add_action('hvac_health_check', [__CLASS__, 'run_automated_checks']);
// Admin integration
if (is_admin()) {
add_action('admin_menu', [__CLASS__, 'add_admin_menu']);
add_action('wp_ajax_hvac_run_health_check', [__CLASS__, 'ajax_run_health_check']);
add_action('admin_notices', [__CLASS__, 'show_health_warnings']);
}
// REST API endpoint for external monitoring
add_action('rest_api_init', [__CLASS__, 'register_rest_endpoints']);
// WP-CLI integration
if (defined('WP_CLI') && WP_CLI) {
WP_CLI::add_command('hvac health', [__CLASS__, 'wp_cli_health_check']);
}
}
/**
* Run all health checks
*
* @param bool $force_refresh Force refresh cached results
* @return array Health check results
*/
public static function run_all_checks($force_refresh = false) {
if (!$force_refresh) {
$cached_results = get_transient(self::CACHE_KEY);
if ($cached_results !== false) {
return $cached_results;
}
}
$results = [
'timestamp' => time(),
'overall_status' => self::STATUS_HEALTHY,
'checks' => []
];
foreach (self::CHECK_TYPES as $type => $name) {
$check_result = self::run_health_check($type);
$results['checks'][$type] = $check_result;
// Update overall status based on worst result
if ($check_result['status'] === self::STATUS_CRITICAL) {
$results['overall_status'] = self::STATUS_CRITICAL;
} elseif ($check_result['status'] === self::STATUS_WARNING &&
$results['overall_status'] !== self::STATUS_CRITICAL) {
$results['overall_status'] = self::STATUS_WARNING;
}
}
// Cache results
set_transient(self::CACHE_KEY, $results, self::CACHE_DURATION);
// Log critical issues
if ($results['overall_status'] === self::STATUS_CRITICAL) {
$critical_checks = array_filter($results['checks'], function($check) {
return $check['status'] === self::STATUS_CRITICAL;
});
$critical_names = array_keys($critical_checks);
HVAC_Logger::error(
'Critical health check failures: ' . implode(', ', $critical_names),
'Health Monitor'
);
}
return $results;
}
/**
* Run individual health check
*
* @param string $type Check type
* @return array Check result
*/
private static function run_health_check($type) {
$start_time = microtime(true);
try {
switch ($type) {
case 'database':
$result = self::check_database();
break;
case 'cache':
$result = self::check_cache_system();
break;
case 'authentication':
$result = self::check_authentication();
break;
case 'events':
$result = self::check_event_management();
break;
case 'certificates':
$result = self::check_certificate_system();
break;
case 'background_jobs':
$result = self::check_background_jobs();
break;
case 'file_permissions':
$result = self::check_file_permissions();
break;
case 'third_party':
$result = self::check_third_party_integrations();
break;
default:
$result = [
'status' => self::STATUS_WARNING,
'message' => 'Unknown check type',
'details' => []
];
}
} catch (Exception $e) {
$result = [
'status' => self::STATUS_CRITICAL,
'message' => 'Check failed with exception: ' . $e->getMessage(),
'details' => ['exception' => get_class($e)]
];
}
$result['execution_time'] = round(microtime(true) - $start_time, 4);
$result['timestamp'] = time();
$result['name'] = self::CHECK_TYPES[$type];
return $result;
}
/**
* Check database connectivity and integrity
*/
private static function check_database() {
global $wpdb;
// Test basic connection
$test_query = $wpdb->get_var("SELECT 1");
if ($test_query !== '1') {
return [
'status' => self::STATUS_CRITICAL,
'message' => 'Database connection failed',
'details' => ['error' => $wpdb->last_error]
];
}
// Check plugin tables exist
$required_tables = [
$wpdb->prefix . 'posts',
$wpdb->prefix . 'postmeta',
$wpdb->prefix . 'users',
$wpdb->prefix . 'usermeta'
];
$missing_tables = [];
foreach ($required_tables as $table) {
$exists = $wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $table));
if (!$exists) {
$missing_tables[] = $table;
}
}
if (!empty($missing_tables)) {
return [
'status' => self::STATUS_CRITICAL,
'message' => 'Required tables missing',
'details' => ['missing_tables' => $missing_tables]
];
}
// Check for recent database errors
if ($wpdb->last_error) {
return [
'status' => self::STATUS_WARNING,
'message' => 'Recent database error detected',
'details' => ['last_error' => $wpdb->last_error]
];
}
return [
'status' => self::STATUS_HEALTHY,
'message' => 'Database connectivity is healthy',
'details' => ['tables_checked' => count($required_tables)]
];
}
/**
* Check cache system functionality
*/
private static function check_cache_system() {
// Test WordPress object cache
$test_key = 'hvac_health_test_' . time();
$test_value = 'test_data_' . wp_generate_password(10, false);
// Set cache
$set_result = wp_cache_set($test_key, $test_value, 'hvac_health', 60);
if (!$set_result) {
return [
'status' => self::STATUS_WARNING,
'message' => 'Cache set operation failed',
'details' => []
];
}
// Get cache
$cached_value = wp_cache_get($test_key, 'hvac_health');
if ($cached_value !== $test_value) {
return [
'status' => self::STATUS_WARNING,
'message' => 'Cache retrieval failed or returned incorrect data',
'details' => ['expected' => $test_value, 'actual' => $cached_value]
];
}
// Test master dashboard cache
if (class_exists('HVAC_Master_Dashboard_Data')) {
$dashboard_data = new HVAC_Master_Dashboard_Data();
$events_count = $dashboard_data->get_total_events_count();
if (!is_numeric($events_count)) {
return [
'status' => self::STATUS_WARNING,
'message' => 'Master dashboard cache returning invalid data',
'details' => ['events_count' => $events_count]
];
}
}
// Clean up test cache
wp_cache_delete($test_key, 'hvac_health');
return [
'status' => self::STATUS_HEALTHY,
'message' => 'Cache system is functioning correctly',
'details' => ['test_key' => $test_key]
];
}
/**
* Check authentication system
*/
private static function check_authentication() {
// Check if trainer roles exist
$required_roles = ['hvac_trainer', 'hvac_master_trainer'];
$missing_roles = [];
foreach ($required_roles as $role) {
if (!get_role($role)) {
$missing_roles[] = $role;
}
}
if (!empty($missing_roles)) {
return [
'status' => self::STATUS_CRITICAL,
'message' => 'Required user roles are missing',
'details' => ['missing_roles' => $missing_roles]
];
}
// Check for users with trainer roles
$trainer_count = count(get_users(['role__in' => $required_roles]));
if ($trainer_count === 0) {
return [
'status' => self::STATUS_WARNING,
'message' => 'No users found with trainer roles',
'details' => ['trainer_count' => $trainer_count]
];
}
// Test capability system
if (!current_user_can('read')) {
return [
'status' => self::STATUS_WARNING,
'message' => 'Capability system may have issues',
'details' => []
];
}
return [
'status' => self::STATUS_HEALTHY,
'message' => 'Authentication system is healthy',
'details' => ['trainer_count' => $trainer_count]
];
}
/**
* Check event management system
*/
private static function check_event_management() {
// Check if The Events Calendar is active
if (!class_exists('Tribe__Events__Main')) {
return [
'status' => self::STATUS_CRITICAL,
'message' => 'The Events Calendar plugin is not active',
'details' => []
];
}
// Check for events
$events_count = wp_count_posts('tribe_events');
$total_events = ($events_count->publish ?? 0) + ($events_count->private ?? 0);
if ($total_events === 0) {
return [
'status' => self::STATUS_WARNING,
'message' => 'No events found in the system',
'details' => ['events_count' => $total_events]
];
}
// Check event creation capability
$can_create_events = post_type_exists('tribe_events');
if (!$can_create_events) {
return [
'status' => self::STATUS_CRITICAL,
'message' => 'Event post type is not registered',
'details' => []
];
}
return [
'status' => self::STATUS_HEALTHY,
'message' => 'Event management system is functioning',
'details' => ['total_events' => $total_events]
];
}
/**
* Check certificate system
*/
private static function check_certificate_system() {
// Check if certificate pages exist
$certificate_pages = [
'trainer/certificate-reports',
'trainer/generate-certificates'
];
$missing_pages = [];
foreach ($certificate_pages as $page_slug) {
if (!get_page_by_path($page_slug)) {
$missing_pages[] = $page_slug;
}
}
if (!empty($missing_pages)) {
return [
'status' => self::STATUS_WARNING,
'message' => 'Certificate pages are missing',
'details' => ['missing_pages' => $missing_pages]
];
}
// Check uploads directory permissions
$upload_dir = wp_upload_dir();
if (!wp_is_writable($upload_dir['basedir'])) {
return [
'status' => self::STATUS_CRITICAL,
'message' => 'Uploads directory is not writable',
'details' => ['upload_dir' => $upload_dir['basedir']]
];
}
return [
'status' => self::STATUS_HEALTHY,
'message' => 'Certificate system appears functional',
'details' => ['pages_found' => count($certificate_pages) - count($missing_pages)]
];
}
/**
* Check background jobs system
*/
private static function check_background_jobs() {
if (!class_exists('HVAC_Background_Jobs')) {
return [
'status' => self::STATUS_WARNING,
'message' => 'Background jobs system not available',
'details' => []
];
}
// Check if cron is working
$cron_test = wp_next_scheduled('hvac_process_background_jobs');
if (!$cron_test) {
return [
'status' => self::STATUS_WARNING,
'message' => 'Background job processing is not scheduled',
'details' => []
];
}
// Check queue stats
$stats = HVAC_Background_Jobs::get_queue_stats();
if ($stats['total'] > 100) {
return [
'status' => self::STATUS_WARNING,
'message' => 'Background job queue is very large',
'details' => ['queue_size' => $stats['total']]
];
}
return [
'status' => self::STATUS_HEALTHY,
'message' => 'Background jobs system is operational',
'details' => ['queue_size' => $stats['total']]
];
}
/**
* Check file permissions
*/
private static function check_file_permissions() {
$critical_paths = [
WP_CONTENT_DIR,
wp_upload_dir()['basedir'],
HVAC_PLUGIN_DIR . 'assets'
];
$permission_issues = [];
foreach ($critical_paths as $path) {
if (!is_dir($path) || !wp_is_writable($path)) {
$permission_issues[] = $path;
}
}
if (!empty($permission_issues)) {
return [
'status' => self::STATUS_CRITICAL,
'message' => 'Critical directories have permission issues',
'details' => ['problematic_paths' => $permission_issues]
];
}
return [
'status' => self::STATUS_HEALTHY,
'message' => 'File permissions are correct',
'details' => ['paths_checked' => count($critical_paths)]
];
}
/**
* Check third-party integrations
*/
private static function check_third_party_integrations() {
$integrations = [];
// Check The Events Calendar
if (class_exists('Tribe__Events__Main')) {
$integrations['events_calendar'] = 'active';
} else {
$integrations['events_calendar'] = 'missing';
}
// Check Astra theme integration
if (defined('ASTRA_THEME_VERSION')) {
$integrations['astra_theme'] = 'active';
} else {
$integrations['astra_theme'] = 'not_detected';
}
// Check for critical missing integrations
if ($integrations['events_calendar'] === 'missing') {
return [
'status' => self::STATUS_CRITICAL,
'message' => 'Critical integration missing: The Events Calendar',
'details' => $integrations
];
}
return [
'status' => self::STATUS_HEALTHY,
'message' => 'Third-party integrations are functional',
'details' => $integrations
];
}
/**
* Run automated health checks
*/
public static function run_automated_checks() {
$results = self::run_all_checks(true);
// Send alerts for critical issues
if ($results['overall_status'] === self::STATUS_CRITICAL) {
self::send_health_alert($results);
}
HVAC_Logger::info(
"Health check completed: {$results['overall_status']}",
'Health Monitor'
);
}
/**
* Send health alert
*
* @param array $results Health check results
*/
private static function send_health_alert($results) {
$admin_email = get_option('admin_email');
$site_name = get_bloginfo('name');
$critical_issues = array_filter($results['checks'], function($check) {
return $check['status'] === self::STATUS_CRITICAL;
});
$subject = "[$site_name] Critical Health Check Alert";
$message = "Critical issues detected in HVAC Community Events plugin:\n\n";
foreach ($critical_issues as $type => $check) {
$message .= "{$check['name']}: {$check['message']}\n";
}
$message .= "\nPlease check the admin dashboard for more details.";
wp_mail($admin_email, $subject, $message);
}
/**
* Add admin menu
*/
public static function add_admin_menu() {
if (current_user_can('manage_options')) {
add_management_page(
'HVAC Health Monitor',
'HVAC Health',
'manage_options',
'hvac-health-monitor',
[__CLASS__, 'admin_page']
);
}
}
/**
* Admin page
*/
public static function admin_page() {
$results = self::run_all_checks();
?>
<div class="wrap">
<h1>HVAC Health Monitor</h1>
<div class="card">
<h2>Overall Status:
<span class="status-<?php echo esc_attr($results['overall_status']); ?>">
<?php echo esc_html(strtoupper($results['overall_status'])); ?>
</span>
</h2>
<p>Last checked: <?php echo date('Y-m-d H:i:s', $results['timestamp']); ?></p>
<p>
<button type="button" id="run-health-check" class="button button-primary">Run Health Check</button>
</p>
</div>
<div class="health-checks">
<?php foreach ($results['checks'] as $type => $check): ?>
<div class="card health-check status-<?php echo esc_attr($check['status']); ?>">
<h3><?php echo esc_html($check['name']); ?></h3>
<p class="status">Status: <?php echo esc_html(strtoupper($check['status'])); ?></p>
<p class="message"><?php echo esc_html($check['message']); ?></p>
<p class="execution-time">Checked in: <?php echo $check['execution_time']; ?>s</p>
<?php if (!empty($check['details'])): ?>
<details>
<summary>Details</summary>
<pre><?php echo esc_html(json_encode($check['details'], JSON_PRETTY_PRINT)); ?></pre>
</details>
<?php endif; ?>
</div>
<?php endforeach; ?>
</div>
<style>
.status-healthy { color: #46b450; }
.status-warning { color: #ffb900; }
.status-critical { color: #dc3232; }
.health-check { margin: 10px 0; }
.health-check.status-critical { border-left: 4px solid #dc3232; }
.health-check.status-warning { border-left: 4px solid #ffb900; }
.health-check.status-healthy { border-left: 4px solid #46b450; }
</style>
<script>
document.getElementById('run-health-check').addEventListener('click', function() {
this.disabled = true;
this.textContent = 'Running...';
fetch(ajaxurl, {
method: 'POST',
body: new URLSearchParams({
action: 'hvac_run_health_check',
nonce: '<?php echo wp_create_nonce('hvac_health_check'); ?>'
})
})
.then(response => response.json())
.then(data => {
location.reload();
})
.catch(error => {
console.error('Health check failed:', error);
this.disabled = false;
this.textContent = 'Run Health Check';
});
});
</script>
</div>
<?php
}
/**
* AJAX health check
*/
public static function ajax_run_health_check() {
check_ajax_referer('hvac_health_check', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error('Insufficient permissions');
}
$results = self::run_all_checks(true);
wp_send_json_success($results);
}
/**
* Show admin warnings
*/
public static function show_health_warnings() {
if (!current_user_can('manage_options')) {
return;
}
$results = self::run_all_checks();
if ($results['overall_status'] === self::STATUS_CRITICAL) {
echo '<div class="notice notice-error"><p>';
echo '<strong>HVAC Plugin Health Alert:</strong> Critical issues detected. ';
echo '<a href="' . admin_url('tools.php?page=hvac-health-monitor') . '">View Details</a>';
echo '</p></div>';
}
}
/**
* Register REST endpoints
*/
public static function register_rest_endpoints() {
register_rest_route('hvac/v1', '/health', [
'methods' => 'GET',
'callback' => [__CLASS__, 'rest_health_check'],
'permission_callback' => function() {
return current_user_can('manage_options');
}
]);
}
/**
* REST API health check
*/
public static function rest_health_check() {
$results = self::run_all_checks();
return new WP_REST_Response([
'status' => $results['overall_status'],
'timestamp' => $results['timestamp'],
'checks' => $results['checks']
], 200);
}
/**
* WP-CLI health check command
*/
public static function wp_cli_health_check($args, $assoc_args) {
WP_CLI::line('Running HVAC health checks...');
$results = self::run_all_checks(true);
WP_CLI::line('Overall Status: ' . strtoupper($results['overall_status']));
WP_CLI::line('');
foreach ($results['checks'] as $type => $check) {
$status_color = $check['status'] === self::STATUS_HEALTHY ? '%G' :
($check['status'] === self::STATUS_WARNING ? '%Y' : '%R');
WP_CLI::line(sprintf(
'%s: ' . $status_color . '%s%n - %s',
$check['name'],
strtoupper($check['status']),
$check['message']
));
}
if ($results['overall_status'] !== self::STATUS_HEALTHY) {
WP_CLI::error('Health checks failed with issues', false);
} else {
WP_CLI::success('All health checks passed');
}
}
}