From 9c79bc90ecb0637e6f2606210183ec39d52665c3 Mon Sep 17 00:00:00 2001 From: Pepijn Over Date: Fri, 28 Mar 2014 00:35:57 +0100 Subject: [PATCH] issue #40: archive uptime records after 1 month --- .../Controller/ServerController.class.php | 4 +- src/psm/Util/Install/Installer.class.php | 25 ++++ src/psm/Util/Updater/Autorun.class.php | 7 + src/psm/Util/Updater/StatusArchiver.class.php | 140 ++++++++++++++++++ 4 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 src/psm/Util/Updater/StatusArchiver.class.php diff --git a/src/psm/Module/Server/Controller/ServerController.class.php b/src/psm/Module/Server/Controller/ServerController.class.php index 842865b8..2a3a6091 100755 --- a/src/psm/Module/Server/Controller/ServerController.class.php +++ b/src/psm/Module/Server/Controller/ServerController.class.php @@ -93,7 +93,7 @@ class ServerController extends AbstractServerController { if($servers[$x]['status'] == 'on' && $servers[$x]['warning_threshold_counter'] > 0) { $servers[$x]['status'] = 'warning'; } - + $servers[$x]['type'] = psm_get_lang('servers', 'type_' . $servers[$x]['type']); } // add servers to template @@ -213,6 +213,8 @@ class ServerController extends AbstractServerController { if($res->rowCount() == 1) { $this->db->delete(PSM_DB_PREFIX.'log', array('server_id' => $id)); $this->db->delete(PSM_DB_PREFIX.'users_servers', array('server_id' => $id)); + $this->db->delete(PSM_DB_PREFIX.'servers_uptime', array('server_id' => $id)); + $this->db->delete(PSM_DB_PREFIX.'servers_history', array('server_id' => $id)); } $this->addMessage(psm_get_lang('system', 'deleted')); } diff --git a/src/psm/Util/Install/Installer.class.php b/src/psm/Util/Install/Installer.class.php index 19c05504..21e65cf2 100755 --- a/src/psm/Util/Install/Installer.class.php +++ b/src/psm/Util/Install/Installer.class.php @@ -192,6 +192,18 @@ class Installer { PRIMARY KEY (`servers_uptime_id`), KEY `server_id` (`server_id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;", + PSM_DB_PREFIX . 'servers_history' => "CREATE TABLE IF NOT EXISTS `" . PSM_DB_PREFIX . "servers_history` ( + `servers_history_id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `server_id` int(11) unsigned NOT NULL, + `date` date NOT NULL, + `latency_min` float(9,7) NOT NULL, + `latency_avg` float(9,7) NOT NULL, + `latency_max` float(9,7) NOT NULL, + `checks_total` int(11) unsigned NOT NULL, + `checks_failed` int(11) unsigned NOT NULL, + PRIMARY KEY (`servers_history_id`), + UNIQUE KEY `server_id_date` (`server_id`,`date`) + ) ENGINE=MyISAM DEFAULT CHARSET=utf8;", ); foreach($tables as $name => $sql) { @@ -286,6 +298,19 @@ class Installer { KEY `server_id` (`server_id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;"; + $queries[] = "CREATE TABLE IF NOT EXISTS `" . PSM_DB_PREFIX . "servers_history` ( + `servers_history_id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `server_id` int(11) unsigned NOT NULL, + `date` date NOT NULL, + `latency_min` float(9,7) NOT NULL, + `latency_avg` float(9,7) NOT NULL, + `latency_max` float(9,7) NOT NULL, + `checks_total` int(11) unsigned NOT NULL, + `checks_failed` int(11) unsigned NOT NULL, + PRIMARY KEY (`servers_history_id`), + UNIQUE KEY `server_id_date` (`server_id`,`date`) + ) ENGINE=MyISAM DEFAULT CHARSET=utf8;"; + $queries[] = "CREATE TABLE `" . PSM_DB_PREFIX . "users_servers` ( `user_id` INT( 11 ) UNSIGNED NOT NULL , `server_id` INT( 11 ) UNSIGNED NOT NULL , diff --git a/src/psm/Util/Updater/Autorun.class.php b/src/psm/Util/Updater/Autorun.class.php index c5250c71..0f602dce 100755 --- a/src/psm/Util/Updater/Autorun.class.php +++ b/src/psm/Util/Updater/Autorun.class.php @@ -79,11 +79,18 @@ class Autorun { $updater = new StatusUpdater($this->db); $notifier = new StatusNotifier($this->db); + $archiver = new StatusArchiver($this->db); + $cleanup_date = new \DateTime(); + $cleanup_date->modify('-1 month'); + foreach($servers as $server) { $status_old = ($server['status'] == 'on') ? true : false; $status_new = $updater->update($server['server_id']); // notify the nerds if applicable $notifier->notify($server['server_id'], $status_old, $status_new); + + // clean-up time!! archive all records older than 1 month + $archiver->archive($server['server_id'], $cleanup_date); } } diff --git a/src/psm/Util/Updater/StatusArchiver.class.php b/src/psm/Util/Updater/StatusArchiver.class.php new file mode 100644 index 00000000..9ddb33f6 --- /dev/null +++ b/src/psm/Util/Updater/StatusArchiver.class.php @@ -0,0 +1,140 @@ +. + * + * @package phpservermon + * @author Pepijn Over + * @copyright Copyright (c) 2008-2014 Pepijn Over + * @license http://www.gnu.org/licenses/gpl.txt GNU GPL v3 + * @version Release: @package_version@ + * @link http://www.phpservermonitor.org/ + **/ + +/** + * The archiver class moves active data from the uptime table to the history table. + * + * Because the uptime table has a record for every single run of the status-check, + * it will grow very large over time. For this reason, uptime records are only kept for a limited time + * to provide detailed statistics. After that, the archiver comes in and saves the averages per day + * in the history table. That way we can always show statistics regarding average latency and failed checks per day, + * but we only need 1 record per server per day. + * + * @see \psm\Util\Updater\Autorun + */ +namespace psm\Util\Updater; +use psm\Service\Database; + +class StatusArchiver { + + /** + * Database service + * @var \psm\Service\Database $db + */ + protected $db; + + function __construct(Database $db) { + $this->db = $db; + } + + /** + * Archive the active records of a server before a certain date. + * + * Archiving means calculating averages per day, and storing 1 single + * history row for each day for this server. + * + * @param int $server_id + * @param \DateTime $date_before archive all records before this date + */ + public function archive($server_id, \DateTime $date_before) { + // get all uptime records for this server + $q_records = $this->db->pdo()->prepare(" + SELECT `date`,`status`,`latency` + FROM `".PSM_DB_PREFIX."servers_uptime` + WHERE `server_id` = :server_id AND `date` < :latest_date + "); + $q_records->execute(array( + 'server_id' => $server_id, + 'latest_date' => $date_before->format('Y-m-d 00:00:00'), + )); + $records = $q_records->fetchAll(); + + if(empty($records)) { + return false; + } + + $data_by_day = array(); + + // first group all records by day + foreach($records as $record) { + $day = date('Y-m-d', strtotime($record['date'])); + if(!isset($data_by_day[$day])) { + $data_by_day[$day] = array(); + } + $data_by_day[$day][] = $record; + } + + // now lets sort out and save the history day by day + foreach($data_by_day as $day => $day_records) { + $history = $this->getHistoryForDay($day, $day_records); + $history['server_id'] = $server_id; + + // store the history for this day in the history table + $this->db->save(PSM_DB_PREFIX.'servers_history', $history); + } + + // now remove all records from the uptime table + $q_records_cleanup = $this->db->pdo()->prepare(" + DELETE FROM `".PSM_DB_PREFIX."servers_uptime` + WHERE `server_id` = :server_id AND `date` < :latest_date + "); + $q_records_cleanup->execute(array( + 'server_id' => $server_id, + 'latest_date' => $date_before->format('Y-m-d 00:00:00'), + )); + } + + /** + * Build a history array for a certain day and its records + * @param string $day + * @param array $day_records + * @return array + */ + protected function getHistoryForDay($day, $day_records) { + $latencies = array(); + $checks_failed = 0; + + foreach($day_records as $day_record) { + $latencies[] = $day_record['latency']; + + if($day_record['status'] == 0) { + $checks_failed++; + } + } + sort($latencies, SORT_NUMERIC); + + $history = array( + 'date' => $day, + 'latency_min' => min($latencies), + 'latency_avg' => array_sum($latencies) / count($latencies), + 'latency_max' => max($latencies), + 'checks_total' => count($day_records), + 'checks_failed' => $checks_failed, + ); + return $history; + } +} \ No newline at end of file