文章目录
-
- 在当今数字化时代,网站的可用性直接关系到企业的声誉、客户信任和收入。根据行业研究,即使是短短几分钟的停机时间,也可能导致数千美元的损失,更不用说对搜索引擎排名和用户体验的长期负面影响。对于使用WordPress构建的网站而言,由于其动态特性和插件依赖,面临停机风险的可能性更高。 传统的监控解决方案往往需要第三方服务,这些服务可能价格昂贵,或者无法完全满足个性化需求。通过WordPress代码二次开发,我们可以创建一个轻量级、高度可定制的Uptime监控与报警系统,不仅能够实时监测网站状态,还能在发现问题时立即通知管理员,大大缩短故障响应时间。 本文将详细介绍如何通过WordPress代码二次开发,实现一个完整的网站Uptime监控与停机报警系统。我们将从基础概念讲起,逐步深入到具体实现,最终打造一个功能完善、稳定可靠的监控解决方案。
-
- 一个完整的Uptime监控系统通常包含以下核心组件: 监控代理:定期检查网站状态 状态存储:记录检查结果和历史数据 报警引擎:分析状态数据并触发报警 通知系统:向管理员发送报警信息 管理界面:配置和查看监控状态 对于WordPress集成方案,我们可以利用其现有的数据库结构、调度系统和插件架构,将这些组件无缝整合到WordPress生态中。
- WordPress本身提供了许多可用于构建监控系统的功能: Cron调度系统:可以定期执行监控任务 数据库抽象层:方便存储监控数据 用户角色系统:控制不同用户对监控功能的访问权限 REST API:可以扩展为监控API端点 丰富的钩子系统:允许在适当位置插入监控逻辑
- 在设计监控系统时,需要平衡监控频率与服务器负载。过于频繁的检查会增加服务器负担,而间隔太长则可能无法及时发现故障。对于大多数网站,5-10分钟的检查间隔是一个合理的起点。我们将设计一个可配置的监控频率系统,允许管理员根据实际需求进行调整。
-
- 首先,我们需要创建一个独立的WordPress插件来承载监控功能。以下是插件的基本目录结构: wp-uptime-monitor/ ├── wp-uptime-monitor.php # 主插件文件 ├── includes/ │ ├── class-monitor-core.php # 监控核心类 │ ├── class-checker.php # 网站检查器 │ ├── class-notifier.php # 通知处理器 │ └── class-database.php # 数据库操作类 ├── admin/ │ ├── css/ │ │ └── admin-style.css # 管理界面样式 │ ├── js/ │ │ └── admin-script.js # 管理界面脚本 │ └── class-admin-panel.php # 管理面板 ├── public/ │ └── class-public-display.php # 前端显示 └── templates/ ├── settings-page.php # 设置页面模板 └── status-page.php # 状态页面模板
- 在wp-uptime-monitor.php中,我们需要设置插件的基本信息和初始化逻辑: <?php /** * Plugin Name: WordPress Uptime Monitor * Plugin URI: https://yourwebsite.com/uptime-monitor * Description: 一个完整的网站Uptime监控与停机报警系统 * Version: 1.0.0 * Author: Your Name * License: GPL v2 or later * Text Domain: wp-uptime-monitor */ // 防止直接访问 if (!defined('ABSPATH')) { exit; } // 定义插件常量 define('WUM_VERSION', '1.0.0'); define('WUM_PLUGIN_DIR', plugin_dir_path(__FILE__)); define('WUM_PLUGIN_URL', plugin_dir_url(__FILE__)); define('WUM_CHECK_INTERVAL', 300); // 默认检查间隔:5分钟 // 自动加载类文件 spl_autoload_register(function ($class_name) { $prefix = 'WUM_'; $base_dir = WUM_PLUGIN_DIR . 'includes/'; $len = strlen($prefix); if (strncmp($prefix, $class_name, $len) !== 0) { return; } $relative_class = substr($class_name, $len); $file = $base_dir . 'class-' . str_replace('_', '-', strtolower($relative_class)) . '.php'; if (file_exists($file)) { require $file; } }); // 初始化插件 function wum_init_plugin() { // 检查WordPress版本 if (version_compare(get_bloginfo('version'), '5.0', '<')) { add_action('admin_notices', function() { echo '<div class="notice notice-error"><p>'; echo __('WordPress Uptime Monitor需要WordPress 5.0或更高版本。', 'wp-uptime-monitor'); echo '</p></div>'; }); return; } // 初始化核心组件 $monitor_core = new WUM_Monitor_Core(); $monitor_core->init(); // 初始化管理界面 if (is_admin()) { $admin_panel = new WUM_Admin_Panel(); $admin_panel->init(); } } add_action('plugins_loaded', 'wum_init_plugin'); // 插件激活时执行的操作 register_activation_hook(__FILE__, function() { require_once WUM_PLUGIN_DIR . 'includes/class-database.php'; $database = new WUM_Database(); $database->create_tables(); // 设置默认选项 $default_options = array( 'check_interval' => WUM_CHECK_INTERVAL, 'notification_emails' => get_option('admin_email'), 'enable_sms' => false, 'sms_phone' => '', 'enable_discord' => false, 'discord_webhook' => '', 'uptime_goal' => 99.9, 'check_timeout' => 30, ); add_option('wum_settings', $default_options); // 调度监控任务 if (!wp_next_scheduled('wum_perform_check')) { wp_schedule_event(time(), 'wum_five_minutes', 'wum_perform_check'); } }); // 插件停用时执行的操作 register_deactivation_hook(__FILE__, function() { // 清除调度任务 $timestamp = wp_next_scheduled('wum_perform_check'); if ($timestamp) { wp_unschedule_event($timestamp, 'wum_perform_check'); } // 可选:保留数据以便重新激活时使用 // 或者添加设置选项让用户选择是否删除数据 }); // 添加自定义Cron调度间隔 add_filter('cron_schedules', function($schedules) { $schedules['wum_five_minutes'] = array( 'interval' => 300, 'display' => __('每5分钟', 'wp-uptime-monitor') ); $schedules['wum_ten_minutes'] = array( 'interval' => 600, 'display' => __('每10分钟', 'wp-uptime-monitor') ); $schedules['wum_thirty_minutes'] = array( 'interval' => 1800, 'display' => __('每30分钟', 'wp-uptime-monitor') ); return $schedules; });
- 监控系统需要存储检查结果和历史数据。在includes/class-database.php中创建必要的数据库表: <?php class WUM_Database { public function create_tables() { global $wpdb; $charset_collate = $wpdb->get_charset_collate(); $table_name = $wpdb->prefix . 'wum_checks'; $history_table = $wpdb->prefix . 'wum_history'; $incidents_table = $wpdb->prefix . 'wum_incidents'; // 检查结果表 $sql = "CREATE TABLE IF NOT EXISTS $table_name ( id bigint(20) NOT NULL AUTO_INCREMENT, check_time datetime DEFAULT CURRENT_TIMESTAMP NOT NULL, response_code int(11) NOT NULL, response_time float NOT NULL, status varchar(20) NOT NULL, error_message text, PRIMARY KEY (id), KEY check_time (check_time), KEY status (status) ) $charset_collate;"; // 历史统计表(每日汇总) $sql .= "CREATE TABLE IF NOT EXISTS $history_table ( id bigint(20) NOT NULL AUTO_INCREMENT, date date NOT NULL, total_checks int(11) NOT NULL DEFAULT 0, successful_checks int(11) NOT NULL DEFAULT 0, total_response_time float NOT NULL DEFAULT 0, downtime_minutes int(11) NOT NULL DEFAULT 0, PRIMARY KEY (id), UNIQUE KEY date (date) ) $charset_collate;"; // 故障事件表 $sql .= "CREATE TABLE IF NOT EXISTS $incidents_table ( id bigint(20) NOT NULL AUTO_INCREMENT, start_time datetime NOT NULL, end_time datetime, duration_minutes int(11), resolved tinyint(1) DEFAULT 0, notification_sent tinyint(1) DEFAULT 0, PRIMARY KEY (id), KEY start_time (start_time), KEY resolved (resolved) ) $charset_collate;"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql); } }
-
- 创建includes/class-checker.php,实现网站状态检查功能: <?php class WUM_Checker { private $timeout; private $check_url; public function __construct() { $settings = get_option('wum_settings', array()); $this->timeout = isset($settings['check_timeout']) ? $settings['check_timeout'] : 30; $this->check_url = home_url(); } /** * 执行网站状态检查 */ public function perform_check() { $start_time = microtime(true); // 使用WordPress HTTP API进行请求 $response = wp_remote_get($this->check_url, array( 'timeout' => $this->timeout, 'sslverify' => false, 'redirection' => 0 )); $response_time = microtime(true) - $start_time; // 分析响应 if (is_wp_error($response)) { return $this->handle_error($response, $response_time); } $response_code = wp_remote_retrieve_response_code($response); // 判断是否成功(2xx和3xx状态码视为成功) $is_success = ($response_code >= 200 && $response_code < 400); return array( 'success' => $is_success, 'response_code' => $response_code, 'response_time' => round($response_time, 3), 'error_message' => $is_success ? '' : 'HTTP错误: ' . $response_code, 'check_time' => current_time('mysql') ); } /** * 处理请求错误 */ private function handle_error($error, $response_time) { $error_message = $error->get_error_message(); // 根据错误类型分类 if (strpos($error_message, 'cURL error 28') !== false) { $error_message = '请求超时 (' . $this->timeout . '秒)'; } elseif (strpos($error_message, 'cURL error 6') !== false) { $error_message = '无法解析主机名'; } elseif (strpos($error_message, 'cURL error 7') !== false) { $error_message = '无法连接到主机'; } return array( 'success' => false, 'response_code' => 0, 'response_time' => round($response_time, 3), 'error_message' => $error_message, 'check_time' => current_time('mysql') ); } /** * 执行深度检查(检查关键页面和功能) */ public function perform_deep_check() { $checks = array(); // 检查首页 $checks['homepage'] = $this->check_specific_url(home_url()); // 检查WP REST API端点 $checks['rest_api'] = $this->check_specific_url(rest_url('wp/v2/posts')); // 检查登录页面 $checks['login_page'] = $this->check_specific_url(wp_login_url()); // 检查数据库连接 $checks['database'] = $this->check_database(); // 检查磁盘空间 $checks['disk_space'] = $this->check_disk_space(); return $checks; } /** * 检查特定URL */ private function check_specific_url($url) { $response = wp_remote_get($url, array( 'timeout' => 10, 'sslverify' => false )); return !is_wp_error($response) && wp_remote_retrieve_response_code($response) == 200; } /** * 检查数据库连接 */ private function check_database() { global $wpdb; $start_time = microtime(true); $result = $wpdb->get_var("SELECT 1"); $query_time = microtime(true) - $start_time; return array( 'success' => ($result === '1'), 'query_time' => round($query_time, 3) ); } /** * 检查磁盘空间 */ private function check_disk_space() { if (function_exists('disk_free_space')) { $free_space = disk_free_space(ABSPATH); $total_space = disk_total_space(ABSPATH); if ($total_space > 0) { $percentage_free = ($free_space / $total_space) * 100; return array( 'free_gb' => round($free_space / 1024 / 1024 / 1024, 2), 'total_gb' => round($total_space / 1024 / 1024 / 1024, 2), 'percentage_free' => round($percentage_free, 1), 'warning' => $percentage_free < 10 ); } } return array( 'free_gb' => 0, 'total_gb' => 0, 'percentage_free' => 0, 'warning' => false ); } }
- 创建includes/class-monitor-core.php,实现监控系统的核心逻辑: <?php class WUM_Monitor_Core { private $checker; private $notifier; private $last_status; public function __construct() { $this->checker = new WUM_Checker(); $this->notifier = new WUM_Notifier(); $this->last_status = $this->get_last_status(); } public function init() { // 注册监控检查动作 add_action('wum_perform_check', array($this, 'perform_scheduled_check')); // 注册AJAX端点用于手动检查 add_action('wp_ajax_wum_manual_check', array($this, 'ajax_manual_check')); // 注册REST API端点 add_action('rest_api_init', array($this, 'register_rest_routes')); } /** * 执行计划检查 */ public function perform_scheduled_check() { global $wpdb; // 执行基本检查 $check_result = $this->checker->perform_check(); // 保存检查结果 $table_name = $wpdb->prefix . 'wum_checks'; $wpdb->insert($table_name, array( 'response_code' => $check_result['response_code'], 'response_time' => $check_result['response_time'], 'status' => $check_result['success'] ? 'up' : 'down', 'error_message' => $check_result['error_message'] )); // 更新历史统计 $this->update_daily_stats($check_result['success'], $check_result['response_time']); // 检查状态变化并处理 $this->handle_status_change($check_result['success'], $check_result['error_message']); // 如果状态为down,执行深度检查 if (!$check_result['success']) { $deep_checks = $this->checker->perform_deep_check(); $this->log_deep_checks($deep_checks); } // 清理旧数据(保留30天) $this->cleanup_old_data(); } /** * 处理状态变化 */ private function handle_status_change($current_status, $error_message = '') { // 如果状态没有变化,直接返回 if ($this->last_status === $current_status) { return; } // 状态从up变为down:记录故障开始 if ($this->last_status === true && $current_status === false) { $this->record_incident_start($error_message); } // 状态从down变为up:记录故障结束 if ($this->last_status === false && $current_status === true) { $this->record_incident_end(); } // 更新最后状态 $this->update_last_status($current_status); } /** * 记录故障开始 */ private function record_incident_start($error_message) { global $wpdb; $table_name = $wpdb->prefix . 'wum_incidents'; $wpdb->insert($table_name, array( 'start_time' => current_time('mysql'), 'resolved' => 0, 'notification_sent' => 0 )); $incident_id = $wpdb->insert_id; // 发送故障通知 $this->notifier->send_downtime_notification($incident_id, $error_message); // 标记通知已发送 $wpdb->update($table_name, array('notification_sent' => 1), array('id' => $incident_id) ); } /** * 记录故障结束 */ private function record_incident_end() { global $wpdb; $table_name = $wpdb->prefix . 'wum_incidents'; // 获取未解决的故障 $unresolved = $wpdb->get_row( "SELECT * FROM $table_name WHERE resolved = 0 ORDER BY start_time DESC LIMIT 1" ); if ($unresolved) { $end_time = current_time('mysql'); $start_time = strtotime($unresolved->start_time); $duration_minutes = round((strtotime($end_time) - $start_time) / 60); $wpdb->update($table_name, array( 'end_time' => $end_time, 'duration_minutes' => $duration_minutes, 'resolved' => 1 ), array('id' => $unresolved->id) ); // 发送恢复通知 $this->notifier->send_recovery_notification($unresolved->id, $duration_minutes); } } /** * 更新每日统计 */ private function update_daily_stats($success, $response_time) { global $wpdb; $today = current_time('Y-m-d'); $table_name = $wpdb->prefix . 'wum_history'; // 检查今天是否已有记录 $existing = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $table_name WHERE date = %s", $today) ); if ($existing) { // 更新现有记录 $data = array( 'total_checks' => $existing->total_checks + 1, 'total_response_time' => $existing->total_response_time + $response_time ); if ($success) { $data['successful_checks'] = $existing->successful_checks + 1; } else { $data['downtime_minutes'] = $existing->downtime_minutes + 5; // 假设5分钟检查间隔 } $wpdb->update($table_name, $data, array('id' => $existing->id)); } else { // 创建新记录 $data = array( 'date' => $today, 'total_checks' => 1, 'successful_checks' => $success ? 1 : 0, 'total_response_time' => $response_time, 'downtime_minutes' => $success ? 0 : 5 ); $wpdb->insert($table_name, $data); } } /** * 记录深度检查结果 */ private function log_deep_checks($deep_checks) { // 这里可以将深度检查结果记录到单独的日志表或选项 update_option('wum_last_deep_check', array( 'time' => current_time('mysql'), 'results' => $deep_checks )); } /** * 清理旧数据 */ private function cleanup_old_data() { global $wpdb; $retention_days = 30; $delete_before = date('Y-m-d H:i:s', strtotime("-$retention_days days")); // 删除旧的检查记录 $checks_table = $wpdb->prefix . 'wum_checks'; $wpdb->query( $wpdb->prepare("DELETE FROM $checks_table WHERE check_time < %s", $delete_before) ); // 删除旧的故障记录(只保留已解决的) $incidents_table = $wpdb->prefix . 'wum_incidents'; $wpdb->query( $wpdb->prepare( "DELETE FROM $incidents_table WHERE resolved = 1 AND start_time < %s", $delete_before ) ); } /** * 获取最后状态 */ private function get_last_status() { global $wpdb; $table_name = $wpdb->prefix . 'wum_checks'; $last_check = $wpdb->get_row( "SELECT status FROM $table_name ORDER BY check_time DESC LIMIT 1" ); return $last_check ? ($last_check->status === 'up') : true; } /** * 更新最后状态 */ private function update_last_status($status) { $this->last_status = $status; } /** * AJAX手动检查 */ public function ajax_manual_check() { // 检查权限 if (!current_user_can('manage_options')) { wp_die('权限不足'); } // 执行检查 $check_result = $this->checker->perform_check(); $deep_checks = $this->checker->perform_deep_check(); // 保存结果 $this->perform_scheduled_check(); // 返回结果 wp_send_json_success(array( 'basic_check' => $check_result, 'deep_checks' => $deep_checks, 'timestamp' => current_time('mysql') )); } /** * 注册REST API路由 */ public function register_rest_routes() { register_rest_route('wum/v1', '/status', array( 'methods' => 'GET', 'callback' => array($this, 'rest_get_status'), 'permission_callback' => array($this, 'rest_permission_check') )); register_rest_route('wum/v1', '/stats', array( 'methods' => 'GET', 'callback' => array($this, 'rest_get_stats'), 'permission_callback' => array($this, 'rest_permission_check') )); } /** * REST API权限检查 */ public function rest_permission_check() { // 可以设置为需要API密钥或用户权限 return current_user_can('manage_options') || $this->validate_api_key($_GET['api_key'] ?? ''); } /** * 验证API密钥 */ private function validate_api_key($api_key) { $stored_key = get_option('wum_api_key', ''); return !empty($stored_key) && hash_equals($stored_key, $api_key); } /** * 获取状态REST端点 */ public function rest_get_status() { global $wpdb; $table_name = $wpdb->prefix . 'wum_checks'; $last_check = $wpdb->get_row( "SELECT * FROM $table_name ORDER BY check_time DESC LIMIT 1" ); $incidents_table = $wpdb->prefix . 'wum_incidents'; $active_incident = $wpdb->get_row( "SELECT * FROM $incidents_table WHERE resolved = 0 ORDER BY start_time DESC LIMIT 1" ); return rest_ensure_response(array( 'status' => $last_check ? $last_check->status : 'unknown', 'last_check' => $last_check ? $last_check->check_time : null, 'response_time' => $last_check ? $last_check->response_time : null, 'active_incident' => $active_incident ? true : false, 'incident_start' => $active_incident ? $active_incident->start_time : null )); } /** * 获取统计REST端点 */ public function rest_get_stats() { global $wpdb; $history_table = $wpdb->prefix . 'wum_history'; // 获取最近30天数据 $recent_stats = $wpdb->get_results( "SELECT * FROM $history_table ORDER BY date DESC LIMIT 30" ); // 计算总体统计 $total_checks = 0; $successful_checks = 0; $total_downtime = 0; foreach ($recent_stats as $stat) { $total_checks += $stat->total_checks; $successful_checks += $stat->successful_checks; $total_downtime += $stat->downtime_minutes; } $uptime_percentage = $total_checks > 0 ? ($successful_checks / $total_checks) * 100 : 100; return rest_ensure_response(array( 'uptime_percentage' => round($uptime_percentage, 2), 'total_checks' => $total_checks, 'successful_checks' => $successful_checks, 'total_downtime_minutes' => $total_downtime, 'recent_stats' => $recent_stats )); } } ## 第四部分:实现多通道报警通知系统 ### 4.1 通知处理器基础类 创建`includes/class-notifier.php`,实现多通道通知功能: <?phpclass WUM_Notifier { private $settings; public function __construct() { $this->settings = get_option('wum_settings', array()); } /** * 发送停机通知 */ public function send_downtime_notification($incident_id, $error_message) { $subject = '🚨 网站停机警报 - ' . get_bloginfo('name'); $message = $this->build_downtime_message($incident_id, $error_message); // 发送到所有启用的通道 $this->send_to_all_channels($subject, $message, 'downtime'); } /** * 发送恢复通知 */ public function send_recovery_notification($incident_id, $duration_minutes) { $subject = '✅ 网站恢复通知 - ' . get_bloginfo('name'); $message = $this->build_recovery_message($incident_id, $duration_minutes); $this->send_to_all_channels($subject, $message, 'recovery'); } /** * 构建停机消息 */ private function build_downtime_message($incident_id, $error_message) { $site_name = get_bloginfo('name'); $site_url = home_url(); $current_time = current_time('Y-m-d H:i:s'); $message = "🚨 网站停机警报nn"; $message .= "网站名称: $site_namen"; $message .= "网站地址: $site_urln"; $message .= "故障时间: $current_timen"; $message .= "故障ID: #$incident_idn"; $message .= "错误信息: $error_messagenn"; $message .= "请立即检查服务器状态。n"; $message .= "监控系统将持续检查,恢复后将发送通知。"; return $message; } /** * 构建恢复消息 */ private function build_recovery_message($incident_id, $duration_minutes) { $site_name = get_bloginfo('name'); $site_url = home_url(); $current_time = current_time('Y-m-d H:i:s'); $message = "✅ 网站恢复通知nn"; $message .= "网站名称: $site_namen"; $message .= "网站地址: $site_urln"; $message .= "恢复时间: $current_timen"; $message .= "故障ID: #$incident_idn"; $message .= "停机时长: $duration_minutes 分钟nn"; $message .= "网站现已恢复正常运行。n"; $message .= "建议检查日志以确定故障原因。"; return $message; } /** * 发送到所有通道 */ private function send_to_all_channels($subject, $message, $type) { // 电子邮件通知 if (!empty($this->settings['notification_emails'])) { $this->send_email_notification($subject, $message); } // SMS通知(需要集成第三方服务) if (!empty($this->settings['enable_sms']) && !empty($this->settings['sms_phone'])) { $this->send_sms_notification($message); } // Discord Webhook通知 if (!empty($this->settings['enable_discord']) && !empty($this->settings['discord_webhook'])) { $this->send_discord_notification($subject, $message, $type); } // Slack Webhook通知 if (!empty($this->settings['enable_slack']) && !empty($this->settings['slack_webhook'])) { $this->send_slack_notification($subject, $message, $type); } // 微信通知(需要企业微信或Server酱) if (!empty($this->settings['enable_wechat']) && !empty($this->settings['wechat_key'])) { $this->send_wechat_notification($subject, $message); } // 执行自定义动作 do_action('wum_notification_sent', $type, $subject, $message); } /** * 发送电子邮件通知 */ private function send_email_notification($subject, $message) { $emails = explode(',', $this->settings['notification_emails']); $emails = array_map('trim', $emails); $headers = array('Content-Type: text/plain; charset=UTF-8'); foreach ($emails as $email) { if (is_email($email)) { wp_mail($email, $subject, $message, $headers); } } } /** * 发送SMS通知(示例:使用Twilio) */ private function send_sms_notification($message) { // 这里需要集成SMS服务提供商,如Twilio、阿里云等 $phone = $this->settings['sms_phone']; $api_key = $this->settings['sms_api_key'] ?? ''; $api_secret = $this->settings['sms_api_secret'] ?? ''; // 示例:使用Twilio if (class_exists('TwilioRestClient') && $api_key && $api_secret) { try { $client = new TwilioRestClient($api_key, $api_secret); $client->messages->create( $phone, array( 'from' => $this->settings['sms_from_number'], 'body' => substr($message, 0, 160) // SMS长度限制 ) ); } catch (Exception $e) { error_log('WUM SMS发送失败: ' . $e->getMessage()); } } } /** * 发送Discord通知 */ private function send_discord_notification($subject, $message, $type) { $webhook_url = $this->settings['discord_webhook']; // 根据类型设置颜色和标题 $color = $type === 'downtime' ? 15158332 : 3066993; // 红色或绿色 $title = $type === 'downtime' ? '🚨 网站停机警报' : '✅ 网站恢复通知'; $embed = array( 'title' => $title, 'description' => $message, 'color' => $color, 'timestamp' => date('c'), 'footer' => array( 'text' => get_bloginfo('name') . ' 监控系统' ) ); $data = array('embeds' => array($embed)); $response = wp_remote_post($webhook_url, array( 'headers' => array('Content-Type' => 'application/json'), 'body' => json_encode($data), 'timeout' => 10 )); if (is_wp_error($response)) { error_log('WUM Discord通知发送失败: ' . $response->get_error_message()); } } /** * 发送Slack通知 */ private function send_slack_notification($subject, $message, $type) { $webhook_url = $this->settings['slack_webhook']; $icon = $type === 'downtime' ? ':warning:' : ':white_check_mark:'; $color = $type === 'downtime' ? 'danger' : 'good'; $attachments = array(array( 'fallback' => $subject, 'color' => $color, 'title' => $subject, 'text' => $message, 'footer' => get_bloginfo('name'), 'ts' => time() )); $data = array( 'attachments' => $attachments, 'icon_emoji' => $icon ); $response = wp_remote_post($webhook_url, array( 'headers' => array('Content-Type
在当今数字化时代,网站的可用性直接关系到企业的声誉、客户信任和收入。根据行业研究,即使是短短几分钟的停机时间,也可能导致数千美元的损失,更不用说对搜索引擎排名和用户体验的长期负面影响。对于使用WordPress构建的网站而言,由于其动态特性和插件依赖,面临停机风险的可能性更高。
传统的监控解决方案往往需要第三方服务,这些服务可能价格昂贵,或者无法完全满足个性化需求。通过WordPress代码二次开发,我们可以创建一个轻量级、高度可定制的Uptime监控与报警系统,不仅能够实时监测网站状态,还能在发现问题时立即通知管理员,大大缩短故障响应时间。
本文将详细介绍如何通过WordPress代码二次开发,实现一个完整的网站Uptime监控与停机报警系统。我们将从基础概念讲起,逐步深入到具体实现,最终打造一个功能完善、稳定可靠的监控解决方案。
一个完整的Uptime监控系统通常包含以下核心组件:
- 监控代理:定期检查网站状态
- 状态存储:记录检查结果和历史数据
- 报警引擎:分析状态数据并触发报警
- 通知系统:向管理员发送报警信息
- 管理界面:配置和查看监控状态
对于WordPress集成方案,我们可以利用其现有的数据库结构、调度系统和插件架构,将这些组件无缝整合到WordPress生态中。
WordPress本身提供了许多可用于构建监控系统的功能:
- Cron调度系统:可以定期执行监控任务
- 数据库抽象层:方便存储监控数据
- 用户角色系统:控制不同用户对监控功能的访问权限
- REST API:可以扩展为监控API端点
- 丰富的钩子系统:允许在适当位置插入监控逻辑
在设计监控系统时,需要平衡监控频率与服务器负载。过于频繁的检查会增加服务器负担,而间隔太长则可能无法及时发现故障。对于大多数网站,5-10分钟的检查间隔是一个合理的起点。我们将设计一个可配置的监控频率系统,允许管理员根据实际需求进行调整。
首先,我们需要创建一个独立的WordPress插件来承载监控功能。以下是插件的基本目录结构:
wp-uptime-monitor/
├── wp-uptime-monitor.php # 主插件文件
├── includes/
│ ├── class-monitor-core.php # 监控核心类
│ ├── class-checker.php # 网站检查器
│ ├── class-notifier.php # 通知处理器
│ └── class-database.php # 数据库操作类
├── admin/
│ ├── css/
│ │ └── admin-style.css # 管理界面样式
│ ├── js/
│ │ └── admin-script.js # 管理界面脚本
│ └── class-admin-panel.php # 管理面板
├── public/
│ └── class-public-display.php # 前端显示
└── templates/
├── settings-page.php # 设置页面模板
└── status-page.php # 状态页面模板
在wp-uptime-monitor.php中,我们需要设置插件的基本信息和初始化逻辑:
<?php
/**
* Plugin Name: WordPress Uptime Monitor
* Plugin URI: https://yourwebsite.com/uptime-monitor
* Description: 一个完整的网站Uptime监控与停机报警系统
* Version: 1.0.0
* Author: Your Name
* License: GPL v2 or later
* Text Domain: wp-uptime-monitor
*/
// 防止直接访问
if (!defined('ABSPATH')) {
exit;
}
// 定义插件常量
define('WUM_VERSION', '1.0.0');
define('WUM_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('WUM_PLUGIN_URL', plugin_dir_url(__FILE__));
define('WUM_CHECK_INTERVAL', 300); // 默认检查间隔:5分钟
// 自动加载类文件
spl_autoload_register(function ($class_name) {
$prefix = 'WUM_';
$base_dir = WUM_PLUGIN_DIR . 'includes/';
$len = strlen($prefix);
if (strncmp($prefix, $class_name, $len) !== 0) {
return;
}
$relative_class = substr($class_name, $len);
$file = $base_dir . 'class-' . str_replace('_', '-', strtolower($relative_class)) . '.php';
if (file_exists($file)) {
require $file;
}
});
// 初始化插件
function wum_init_plugin() {
// 检查WordPress版本
if (version_compare(get_bloginfo('version'), '5.0', '<')) {
add_action('admin_notices', function() {
echo '<div class="notice notice-error"><p>';
echo __('WordPress Uptime Monitor需要WordPress 5.0或更高版本。', 'wp-uptime-monitor');
echo '</p></div>';
});
return;
}
// 初始化核心组件
$monitor_core = new WUM_Monitor_Core();
$monitor_core->init();
// 初始化管理界面
if (is_admin()) {
$admin_panel = new WUM_Admin_Panel();
$admin_panel->init();
}
}
add_action('plugins_loaded', 'wum_init_plugin');
// 插件激活时执行的操作
register_activation_hook(__FILE__, function() {
require_once WUM_PLUGIN_DIR . 'includes/class-database.php';
$database = new WUM_Database();
$database->create_tables();
// 设置默认选项
$default_options = array(
'check_interval' => WUM_CHECK_INTERVAL,
'notification_emails' => get_option('admin_email'),
'enable_sms' => false,
'sms_phone' => '',
'enable_discord' => false,
'discord_webhook' => '',
'uptime_goal' => 99.9,
'check_timeout' => 30,
);
add_option('wum_settings', $default_options);
// 调度监控任务
if (!wp_next_scheduled('wum_perform_check')) {
wp_schedule_event(time(), 'wum_five_minutes', 'wum_perform_check');
}
});
// 插件停用时执行的操作
register_deactivation_hook(__FILE__, function() {
// 清除调度任务
$timestamp = wp_next_scheduled('wum_perform_check');
if ($timestamp) {
wp_unschedule_event($timestamp, 'wum_perform_check');
}
// 可选:保留数据以便重新激活时使用
// 或者添加设置选项让用户选择是否删除数据
});
// 添加自定义Cron调度间隔
add_filter('cron_schedules', function($schedules) {
$schedules['wum_five_minutes'] = array(
'interval' => 300,
'display' => __('每5分钟', 'wp-uptime-monitor')
);
$schedules['wum_ten_minutes'] = array(
'interval' => 600,
'display' => __('每10分钟', 'wp-uptime-monitor')
);
$schedules['wum_thirty_minutes'] = array(
'interval' => 1800,
'display' => __('每30分钟', 'wp-uptime-monitor')
);
return $schedules;
});
监控系统需要存储检查结果和历史数据。在includes/class-database.php中创建必要的数据库表:
<?php
class WUM_Database {
public function create_tables() {
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
$table_name = $wpdb->prefix . 'wum_checks';
$history_table = $wpdb->prefix . 'wum_history';
$incidents_table = $wpdb->prefix . 'wum_incidents';
// 检查结果表
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
id bigint(20) NOT NULL AUTO_INCREMENT,
check_time datetime DEFAULT CURRENT_TIMESTAMP NOT NULL,
response_code int(11) NOT NULL,
response_time float NOT NULL,
status varchar(20) NOT NULL,
error_message text,
PRIMARY KEY (id),
KEY check_time (check_time),
KEY status (status)
) $charset_collate;";
// 历史统计表(每日汇总)
$sql .= "CREATE TABLE IF NOT EXISTS $history_table (
id bigint(20) NOT NULL AUTO_INCREMENT,
date date NOT NULL,
total_checks int(11) NOT NULL DEFAULT 0,
successful_checks int(11) NOT NULL DEFAULT 0,
total_response_time float NOT NULL DEFAULT 0,
downtime_minutes int(11) NOT NULL DEFAULT 0,
PRIMARY KEY (id),
UNIQUE KEY date (date)
) $charset_collate;";
// 故障事件表
$sql .= "CREATE TABLE IF NOT EXISTS $incidents_table (
id bigint(20) NOT NULL AUTO_INCREMENT,
start_time datetime NOT NULL,
end_time datetime,
duration_minutes int(11),
resolved tinyint(1) DEFAULT 0,
notification_sent tinyint(1) DEFAULT 0,
PRIMARY KEY (id),
KEY start_time (start_time),
KEY resolved (resolved)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
}
}
创建includes/class-checker.php,实现网站状态检查功能:
<?php
class WUM_Checker {
private $timeout;
private $check_url;
public function __construct() {
$settings = get_option('wum_settings', array());
$this->timeout = isset($settings['check_timeout']) ? $settings['check_timeout'] : 30;
$this->check_url = home_url();
}
/**
* 执行网站状态检查
*/
public function perform_check() {
$start_time = microtime(true);
// 使用WordPress HTTP API进行请求
$response = wp_remote_get($this->check_url, array(
'timeout' => $this->timeout,
'sslverify' => false,
'redirection' => 0
));
$response_time = microtime(true) - $start_time;
// 分析响应
if (is_wp_error($response)) {
return $this->handle_error($response, $response_time);
}
$response_code = wp_remote_retrieve_response_code($response);
// 判断是否成功(2xx和3xx状态码视为成功)
$is_success = ($response_code >= 200 && $response_code < 400);
return array(
'success' => $is_success,
'response_code' => $response_code,
'response_time' => round($response_time, 3),
'error_message' => $is_success ? '' : 'HTTP错误: ' . $response_code,
'check_time' => current_time('mysql')
);
}
/**
* 处理请求错误
*/
private function handle_error($error, $response_time) {
$error_message = $error->get_error_message();
// 根据错误类型分类
if (strpos($error_message, 'cURL error 28') !== false) {
$error_message = '请求超时 (' . $this->timeout . '秒)';
} elseif (strpos($error_message, 'cURL error 6') !== false) {
$error_message = '无法解析主机名';
} elseif (strpos($error_message, 'cURL error 7') !== false) {
$error_message = '无法连接到主机';
}
return array(
'success' => false,
'response_code' => 0,
'response_time' => round($response_time, 3),
'error_message' => $error_message,
'check_time' => current_time('mysql')
);
}
/**
* 执行深度检查(检查关键页面和功能)
*/
public function perform_deep_check() {
$checks = array();
// 检查首页
$checks['homepage'] = $this->check_specific_url(home_url());
// 检查WP REST API端点
$checks['rest_api'] = $this->check_specific_url(rest_url('wp/v2/posts'));
// 检查登录页面
$checks['login_page'] = $this->check_specific_url(wp_login_url());
// 检查数据库连接
$checks['database'] = $this->check_database();
// 检查磁盘空间
$checks['disk_space'] = $this->check_disk_space();
return $checks;
}
/**
* 检查特定URL
*/
private function check_specific_url($url) {
$response = wp_remote_get($url, array(
'timeout' => 10,
'sslverify' => false
));
return !is_wp_error($response) && wp_remote_retrieve_response_code($response) == 200;
}
/**
* 检查数据库连接
*/
private function check_database() {
global $wpdb;
$start_time = microtime(true);
$result = $wpdb->get_var("SELECT 1");
$query_time = microtime(true) - $start_time;
return array(
'success' => ($result === '1'),
'query_time' => round($query_time, 3)
);
}
/**
* 检查磁盘空间
*/
private function check_disk_space() {
if (function_exists('disk_free_space')) {
$free_space = disk_free_space(ABSPATH);
$total_space = disk_total_space(ABSPATH);
if ($total_space > 0) {
$percentage_free = ($free_space / $total_space) * 100;
return array(
'free_gb' => round($free_space / 1024 / 1024 / 1024, 2),
'total_gb' => round($total_space / 1024 / 1024 / 1024, 2),
'percentage_free' => round($percentage_free, 1),
'warning' => $percentage_free < 10
);
}
}
return array(
'free_gb' => 0,
'total_gb' => 0,
'percentage_free' => 0,
'warning' => false
);
}
}
创建includes/class-monitor-core.php,实现监控系统的核心逻辑:
<?php
class WUM_Monitor_Core {
private $checker;
private $notifier;
private $last_status;
public function __construct() {
$this->checker = new WUM_Checker();
$this->notifier = new WUM_Notifier();
$this->last_status = $this->get_last_status();
}
public function init() {
// 注册监控检查动作
add_action('wum_perform_check', array($this, 'perform_scheduled_check'));
// 注册AJAX端点用于手动检查
add_action('wp_ajax_wum_manual_check', array($this, 'ajax_manual_check'));
// 注册REST API端点
add_action('rest_api_init', array($this, 'register_rest_routes'));
}
/**
* 执行计划检查
*/
public function perform_scheduled_check() {
global $wpdb;
// 执行基本检查
$check_result = $this->checker->perform_check();
// 保存检查结果
$table_name = $wpdb->prefix . 'wum_checks';
$wpdb->insert($table_name, array(
'response_code' => $check_result['response_code'],
'response_time' => $check_result['response_time'],
'status' => $check_result['success'] ? 'up' : 'down',
'error_message' => $check_result['error_message']
));
// 更新历史统计
$this->update_daily_stats($check_result['success'], $check_result['response_time']);
// 检查状态变化并处理
$this->handle_status_change($check_result['success'], $check_result['error_message']);
// 如果状态为down,执行深度检查
if (!$check_result['success']) {
$deep_checks = $this->checker->perform_deep_check();
$this->log_deep_checks($deep_checks);
}
// 清理旧数据(保留30天)
$this->cleanup_old_data();
}
/**
* 处理状态变化
*/
private function handle_status_change($current_status, $error_message = '') {
// 如果状态没有变化,直接返回
if ($this->last_status === $current_status) {
return;
}
// 状态从up变为down:记录故障开始
if ($this->last_status === true && $current_status === false) {
$this->record_incident_start($error_message);
}
// 状态从down变为up:记录故障结束
if ($this->last_status === false && $current_status === true) {
$this->record_incident_end();
}
// 更新最后状态
$this->update_last_status($current_status);
}
/**
* 记录故障开始
*/
private function record_incident_start($error_message) {
global $wpdb;
$table_name = $wpdb->prefix . 'wum_incidents';
$wpdb->insert($table_name, array(
'start_time' => current_time('mysql'),
'resolved' => 0,
'notification_sent' => 0
));
$incident_id = $wpdb->insert_id;
// 发送故障通知
$this->notifier->send_downtime_notification($incident_id, $error_message);
// 标记通知已发送
$wpdb->update($table_name,
array('notification_sent' => 1),
array('id' => $incident_id)
);
}
/**
* 记录故障结束
*/
private function record_incident_end() {
global $wpdb;
$table_name = $wpdb->prefix . 'wum_incidents';
// 获取未解决的故障
$unresolved = $wpdb->get_row(
"SELECT * FROM $table_name WHERE resolved = 0 ORDER BY start_time DESC LIMIT 1"
);
if ($unresolved) {
$end_time = current_time('mysql');
$start_time = strtotime($unresolved->start_time);
$duration_minutes = round((strtotime($end_time) - $start_time) / 60);
$wpdb->update($table_name,
array(
'end_time' => $end_time,
'duration_minutes' => $duration_minutes,
'resolved' => 1
),
array('id' => $unresolved->id)
);
// 发送恢复通知
$this->notifier->send_recovery_notification($unresolved->id, $duration_minutes);
}
}
/**
* 更新每日统计
*/
private function update_daily_stats($success, $response_time) {
global $wpdb;
$today = current_time('Y-m-d');
$table_name = $wpdb->prefix . 'wum_history';
// 检查今天是否已有记录
$existing = $wpdb->get_row(
$wpdb->prepare("SELECT * FROM $table_name WHERE date = %s", $today)
);
if ($existing) {
// 更新现有记录
$data = array(
'total_checks' => $existing->total_checks + 1,
'total_response_time' => $existing->total_response_time + $response_time
);
if ($success) {
$data['successful_checks'] = $existing->successful_checks + 1;
} else {
$data['downtime_minutes'] = $existing->downtime_minutes + 5; // 假设5分钟检查间隔
}
$wpdb->update($table_name, $data, array('id' => $existing->id));
} else {
// 创建新记录
$data = array(
'date' => $today,
'total_checks' => 1,
'successful_checks' => $success ? 1 : 0,
'total_response_time' => $response_time,
'downtime_minutes' => $success ? 0 : 5
);
$wpdb->insert($table_name, $data);
}
}
/**
* 记录深度检查结果
*/
private function log_deep_checks($deep_checks) {
// 这里可以将深度检查结果记录到单独的日志表或选项
update_option('wum_last_deep_check', array(
'time' => current_time('mysql'),
'results' => $deep_checks
));
}
/**
* 清理旧数据
*/
private function cleanup_old_data() {
global $wpdb;
$retention_days = 30;
$delete_before = date('Y-m-d H:i:s', strtotime("-$retention_days days"));
// 删除旧的检查记录
$checks_table = $wpdb->prefix . 'wum_checks';
$wpdb->query(
$wpdb->prepare("DELETE FROM $checks_table WHERE check_time < %s", $delete_before)
);
// 删除旧的故障记录(只保留已解决的)
$incidents_table = $wpdb->prefix . 'wum_incidents';
$wpdb->query(
$wpdb->prepare(
"DELETE FROM $incidents_table WHERE resolved = 1 AND start_time < %s",
$delete_before
)
);
}
/**
* 获取最后状态
*/
private function get_last_status() {
global $wpdb;
$table_name = $wpdb->prefix . 'wum_checks';
$last_check = $wpdb->get_row(
"SELECT status FROM $table_name ORDER BY check_time DESC LIMIT 1"
);
return $last_check ? ($last_check->status === 'up') : true;
}
/**
* 更新最后状态
*/
private function update_last_status($status) {
$this->last_status = $status;
}
/**
* AJAX手动检查
*/
public function ajax_manual_check() {
// 检查权限
if (!current_user_can('manage_options')) {
wp_die('权限不足');
}
// 执行检查
$check_result = $this->checker->perform_check();
$deep_checks = $this->checker->perform_deep_check();
// 保存结果
$this->perform_scheduled_check();
// 返回结果
wp_send_json_success(array(
'basic_check' => $check_result,
'deep_checks' => $deep_checks,
'timestamp' => current_time('mysql')
));
}
/**
* 注册REST API路由
*/
public function register_rest_routes() {
register_rest_route('wum/v1', '/status', array(
'methods' => 'GET',
'callback' => array($this, 'rest_get_status'),
'permission_callback' => array($this, 'rest_permission_check')
));
register_rest_route('wum/v1', '/stats', array(
'methods' => 'GET',
'callback' => array($this, 'rest_get_stats'),
'permission_callback' => array($this, 'rest_permission_check')
));
}
/**
* REST API权限检查
*/
public function rest_permission_check() {
// 可以设置为需要API密钥或用户权限
return current_user_can('manage_options') ||
$this->validate_api_key($_GET['api_key'] ?? '');
}
/**
* 验证API密钥
*/
private function validate_api_key($api_key) {
$stored_key = get_option('wum_api_key', '');
return !empty($stored_key) && hash_equals($stored_key, $api_key);
}
/**
* 获取状态REST端点
*/
public function rest_get_status() {
global $wpdb;
$table_name = $wpdb->prefix . 'wum_checks';
$last_check = $wpdb->get_row(
"SELECT * FROM $table_name ORDER BY check_time DESC LIMIT 1"
);
$incidents_table = $wpdb->prefix . 'wum_incidents';
$active_incident = $wpdb->get_row(
"SELECT * FROM $incidents_table WHERE resolved = 0 ORDER BY start_time DESC LIMIT 1"
);
return rest_ensure_response(array(
'status' => $last_check ? $last_check->status : 'unknown',
'last_check' => $last_check ? $last_check->check_time : null,
'response_time' => $last_check ? $last_check->response_time : null,
'active_incident' => $active_incident ? true : false,
'incident_start' => $active_incident ? $active_incident->start_time : null
));
}
/**
* 获取统计REST端点
*/
public function rest_get_stats() {
global $wpdb;
$history_table = $wpdb->prefix . 'wum_history';
// 获取最近30天数据
$recent_stats = $wpdb->get_results(
"SELECT * FROM $history_table ORDER BY date DESC LIMIT 30"
);
// 计算总体统计
$total_checks = 0;
$successful_checks = 0;
$total_downtime = 0;
foreach ($recent_stats as $stat) {
$total_checks += $stat->total_checks;
$successful_checks += $stat->successful_checks;
$total_downtime += $stat->downtime_minutes;
}
$uptime_percentage = $total_checks > 0 ?
($successful_checks / $total_checks) * 100 : 100;
return rest_ensure_response(array(
'uptime_percentage' => round($uptime_percentage, 2),
'total_checks' => $total_checks,
'successful_checks' => $successful_checks,
'total_downtime_minutes' => $total_downtime,
'recent_stats' => $recent_stats
));
}
}
## 第四部分:实现多通道报警通知系统
### 4.1 通知处理器基础类
创建`includes/class-notifier.php`,实现多通道通知功能:
<?php
class WUM_Notifier {
private $settings;
public function __construct() {
$this->settings = get_option('wum_settings', array());
}
/**
* 发送停机通知
*/
public function send_downtime_notification($incident_id, $error_message) {
$subject = '🚨 网站停机警报 - ' . get_bloginfo('name');
$message = $this->build_downtime_message($incident_id, $error_message);
// 发送到所有启用的通道
$this->send_to_all_channels($subject, $message, 'downtime');
}
/**
* 发送恢复通知
*/
public function send_recovery_notification($incident_id, $duration_minutes) {
$subject = '✅ 网站恢复通知 - ' . get_bloginfo('name');
$message = $this->build_recovery_message($incident_id, $duration_minutes);
$this->send_to_all_channels($subject, $message, 'recovery');
}
/**
* 构建停机消息
*/
private function build_downtime_message($incident_id, $error_message) {
$site_name = get_bloginfo('name');
$site_url = home_url();
$current_time = current_time('Y-m-d H:i:s');
$message = "🚨 网站停机警报nn";
$message .= "网站名称: $site_namen";
$message .= "网站地址: $site_urln";
$message .= "故障时间: $current_timen";
$message .= "故障ID: #$incident_idn";
$message .= "错误信息: $error_messagenn";
$message .= "请立即检查服务器状态。n";
$message .= "监控系统将持续检查,恢复后将发送通知。";
return $message;
}
/**
* 构建恢复消息
*/
private function build_recovery_message($incident_id, $duration_minutes) {
$site_name = get_bloginfo('name');
$site_url = home_url();
$current_time = current_time('Y-m-d H:i:s');
$message = "✅ 网站恢复通知nn";
$message .= "网站名称: $site_namen";
$message .= "网站地址: $site_urln";
$message .= "恢复时间: $current_timen";
$message .= "故障ID: #$incident_idn";
$message .= "停机时长: $duration_minutes 分钟nn";
$message .= "网站现已恢复正常运行。n";
$message .= "建议检查日志以确定故障原因。";
return $message;
}
/**
* 发送到所有通道
*/
private function send_to_all_channels($subject, $message, $type) {
// 电子邮件通知
if (!empty($this->settings['notification_emails'])) {
$this->send_email_notification($subject, $message);
}
// SMS通知(需要集成第三方服务)
if (!empty($this->settings['enable_sms']) && !empty($this->settings['sms_phone'])) {
$this->send_sms_notification($message);
}
// Discord Webhook通知
if (!empty($this->settings['enable_discord']) && !empty($this->settings['discord_webhook'])) {
$this->send_discord_notification($subject, $message, $type);
}
// Slack Webhook通知
if (!empty($this->settings['enable_slack']) && !empty($this->settings['slack_webhook'])) {
$this->send_slack_notification($subject, $message, $type);
}
// 微信通知(需要企业微信或Server酱)
if (!empty($this->settings['enable_wechat']) && !empty($this->settings['wechat_key'])) {
$this->send_wechat_notification($subject, $message);
}
// 执行自定义动作
do_action('wum_notification_sent', $type, $subject, $message);
}
/**
* 发送电子邮件通知
*/
private function send_email_notification($subject, $message) {
$emails = explode(',', $this->settings['notification_emails']);
$emails = array_map('trim', $emails);
$headers = array('Content-Type: text/plain; charset=UTF-8');
foreach ($emails as $email) {
if (is_email($email)) {
wp_mail($email, $subject, $message, $headers);
}
}
}
/**
* 发送SMS通知(示例:使用Twilio)
*/
private function send_sms_notification($message) {
// 这里需要集成SMS服务提供商,如Twilio、阿里云等
$phone = $this->settings['sms_phone'];
$api_key = $this->settings['sms_api_key'] ?? '';
$api_secret = $this->settings['sms_api_secret'] ?? '';
// 示例:使用Twilio
if (class_exists('TwilioRestClient') && $api_key && $api_secret) {
try {
$client = new TwilioRestClient($api_key, $api_secret);
$client->messages->create(
$phone,
array(
'from' => $this->settings['sms_from_number'],
'body' => substr($message, 0, 160) // SMS长度限制
)
);
} catch (Exception $e) {
error_log('WUM SMS发送失败: ' . $e->getMessage());
}
}
}
/**
* 发送Discord通知
*/
private function send_discord_notification($subject, $message, $type) {
$webhook_url = $this->settings['discord_webhook'];
// 根据类型设置颜色和标题
$color = $type === 'downtime' ? 15158332 : 3066993; // 红色或绿色
$title = $type === 'downtime' ? '🚨 网站停机警报' : '✅ 网站恢复通知';
$embed = array(
'title' => $title,
'description' => $message,
'color' => $color,
'timestamp' => date('c'),
'footer' => array(
'text' => get_bloginfo('name') . ' 监控系统'
)
);
$data = array('embeds' => array($embed));
$response = wp_remote_post($webhook_url, array(
'headers' => array('Content-Type' => 'application/json'),
'body' => json_encode($data),
'timeout' => 10
));
if (is_wp_error($response)) {
error_log('WUM Discord通知发送失败: ' . $response->get_error_message());
}
}
/**
* 发送Slack通知
*/
private function send_slack_notification($subject, $message, $type) {
$webhook_url = $this->settings['slack_webhook'];
$icon = $type === 'downtime' ? ':warning:' : ':white_check_mark:';
$color = $type === 'downtime' ? 'danger' : 'good';
$attachments = array(array(
'fallback' => $subject,
'color' => $color,
'title' => $subject,
'text' => $message,
'footer' => get_bloginfo('name'),
'ts' => time()
));
$data = array(
'attachments' => $attachments,
'icon_emoji' => $icon
);
$response = wp_remote_post($webhook_url, array(
'headers' => array('Content-Type


