From 6415d0ed2e3f6935febcfabfaff63f63bcc92b63 Mon Sep 17 00:00:00 2001 From: Pepijn Over Date: Fri, 21 Mar 2014 16:38:48 +0100 Subject: [PATCH] issue #15: adding warning threshold to server update, and separating notification/status functionality adding warning threshold to insert form and adding tooltips adding warning_threshold fields to install --- src/includes/functions.inc.php | 4 +- src/lang/bg.lang.php | 3 + src/lang/br.lang.php | 3 + src/lang/de.lang.php | 3 + src/lang/en.lang.php | 3 + src/lang/fr.lang.php | 3 + src/lang/kr.lang.php | 3 + src/lang/nl.lang.php | 3 + .../AbstractServerController.class.php | 4 +- .../Controller/ServerController.class.php | 15 +- .../Controller/StatusController.class.php | 5 + src/psm/Util/Install/Installer.class.php | 8 +- src/psm/Util/Updater/Autorun.class.php | 40 +- src/psm/Util/Updater/Status.class.php | 389 ------------------ src/psm/Util/Updater/StatusNotifier.class.php | 292 +++++++++++++ src/psm/Util/Updater/StatusUpdater.class.php | 232 +++++++++++ src/templates/main.tpl.html | 1 + src/templates/servers.tpl.html | 36 +- src/templates/status.tpl.html | 8 +- static/css/style.css | 3 + static/js/scripts.js | 10 +- 21 files changed, 623 insertions(+), 445 deletions(-) mode change 100644 => 100755 src/lang/bg.lang.php mode change 100644 => 100755 src/psm/Module/Server/Controller/AbstractServerController.class.php mode change 100644 => 100755 src/psm/Util/Updater/Autorun.class.php delete mode 100755 src/psm/Util/Updater/Status.class.php create mode 100755 src/psm/Util/Updater/StatusNotifier.class.php create mode 100755 src/psm/Util/Updater/StatusUpdater.class.php mode change 100644 => 100755 static/css/style.css mode change 100644 => 100755 static/js/scripts.js diff --git a/src/includes/functions.inc.php b/src/includes/functions.inc.php index 2849b9b3..9fa71663 100755 --- a/src/includes/functions.inc.php +++ b/src/includes/functions.inc.php @@ -192,13 +192,13 @@ function psm_log_uptime($server_id, $status, $latency) { /** * Parses a string from the language file with the correct variables replaced in the message * - * @param string $status is either 'on' or 'off' + * @param boolean $status * @param string $type is either 'sms' or 'email' * @param array $server information about the server which may be placed in a message: %KEY% will be replaced by your value * @return string parsed message */ function psm_parse_msg($status, $type, $vars) { - $message = ''; + $status = ($status == true) ? 'on' : 'off'; $message = psm_get_lang('notifications', $status . '_' . $type); diff --git a/src/lang/bg.lang.php b/src/lang/bg.lang.php old mode 100644 new mode 100755 index 75127276..c3288e2a --- a/src/lang/bg.lang.php +++ b/src/lang/bg.lang.php @@ -95,6 +95,7 @@ $sm_lang = array( 'port' => 'Порт', 'type' => 'Тип', 'pattern' => 'Търсене на образец/схема', + 'pattern_description' => 'If this pattern is not found on the website, the server will be marked offline. Regular expressions are allowed.', 'last_check' => 'Последна проверка', 'last_online' => 'Последно на линия', 'monitoring' => 'Мониторинг', @@ -103,6 +104,8 @@ $sm_lang = array( 'updated' => 'Информацията за сървъра е обновена.', 'inserted' => 'Сървърът е добвен успешно.', 'rtime' => 'Пинг', + 'warning_threshold' => 'Warning threshold', + 'warning_threshold_description' => 'Number of failed checks required before it is marked offline.', ), 'config' => array( 'general' => 'Основни настройки', diff --git a/src/lang/br.lang.php b/src/lang/br.lang.php index e165d52c..009f2239 100755 --- a/src/lang/br.lang.php +++ b/src/lang/br.lang.php @@ -95,6 +95,7 @@ $sm_lang = array( 'port' => 'Porta', 'type' => 'Tipo', 'pattern' => 'Search string/pattern', + 'pattern_description' => 'If this pattern is not found on the website, the server will be marked offline. Regular expressions are allowed.', 'last_check' => 'Última verificação', 'last_online' => 'Última vez online', 'monitoring' => 'Monitoramento', @@ -103,6 +104,8 @@ $sm_lang = array( 'updated' => 'Servidor atualizado.', 'inserted' => 'Servidor adicionar.', 'rtime' => 'Tempo de resposta', + 'warning_threshold' => 'Warning threshold', + 'warning_threshold_description' => 'Number of failed checks required before it is marked offline.', ), 'config' => array( 'general' => 'Geral', diff --git a/src/lang/de.lang.php b/src/lang/de.lang.php index c0324c76..cbd0fe47 100755 --- a/src/lang/de.lang.php +++ b/src/lang/de.lang.php @@ -95,6 +95,7 @@ $sm_lang = array( 'port' => 'Port', 'type' => 'Type', 'pattern' => 'Search string/pattern', + 'pattern_description' => 'If this pattern is not found on the website, the server will be marked offline. Regular expressions are allowed.', 'last_check' => 'Letzter Check', 'last_online' => 'Letztes mal Online', 'monitoring' => 'Monitoring', @@ -103,6 +104,8 @@ $sm_lang = array( 'updated' => 'Server aktualisiert.', 'inserted' => 'Server eingetragen.', 'rtime' => 'Antwortzeit', + 'warning_threshold' => 'Warning threshold', + 'warning_threshold_description' => 'Number of failed checks required before it is marked offline.', ), 'config' => array( 'general' => 'General', diff --git a/src/lang/en.lang.php b/src/lang/en.lang.php index 9fbc4bc0..0e54017a 100755 --- a/src/lang/en.lang.php +++ b/src/lang/en.lang.php @@ -95,6 +95,7 @@ $sm_lang = array( 'port' => 'Port', 'type' => 'Type', 'pattern' => 'Search string/pattern', + 'pattern_description' => 'If this pattern is not found on the website, the server will be marked offline. Regular expressions are allowed.', 'last_check' => 'Last check', 'last_online' => 'Last online', 'monitoring' => 'Monitoring', @@ -103,6 +104,8 @@ $sm_lang = array( 'updated' => 'Server updated.', 'inserted' => 'Server added.', 'rtime' => 'Response time', + 'warning_threshold' => 'Warning threshold', + 'warning_threshold_description' => 'Number of failed checks required before it is marked offline.', ), 'config' => array( 'general' => 'General', diff --git a/src/lang/fr.lang.php b/src/lang/fr.lang.php index 2ea9ecea..015f5fbd 100755 --- a/src/lang/fr.lang.php +++ b/src/lang/fr.lang.php @@ -95,6 +95,7 @@ $sm_lang = array( 'port' => 'Port', 'type' => 'Type', 'pattern' => 'Rechercher un texte/motif', + 'pattern_description' => 'If this pattern is not found on the website, the server will be marked offline. Regular expressions are allowed.', 'last_check' => 'Dernière vérification', 'last_online' => 'Dernière fois OK', 'monitoring' => 'Serveillé', @@ -103,6 +104,8 @@ $sm_lang = array( 'updated' => 'Serveur mis à jour.', 'inserted' => 'Serveur ajouté.', 'rtime' => 'Temps de réponse', + 'warning_threshold' => 'Warning threshold', + 'warning_threshold_description' => 'Number of failed checks required before it is marked offline.', ), 'config' => array( 'general' => 'Général', diff --git a/src/lang/kr.lang.php b/src/lang/kr.lang.php index fa484581..86413756 100755 --- a/src/lang/kr.lang.php +++ b/src/lang/kr.lang.php @@ -95,6 +95,7 @@ $sm_lang = array( 'port' => 'Port', 'type' => 'Type', 'pattern' => 'Search string/regex', + 'pattern_description' => 'If this pattern is not found on the website, the server will be marked offline. Regular expressions are allowed.', 'last_check' => '최근체크', 'last_online' => '최근접속', 'monitoring' => '확인중', @@ -103,6 +104,8 @@ $sm_lang = array( 'updated' => '서버가 수정되었습니다.', 'inserted' => '서버가 추가되었습니다.', 'rtime' => '응답', + 'warning_threshold' => 'Warning threshold', + 'warning_threshold_description' => 'Number of failed checks required before it is marked offline.', ), 'config' => array( 'general' => '일반', diff --git a/src/lang/nl.lang.php b/src/lang/nl.lang.php index 70153078..2d486c45 100755 --- a/src/lang/nl.lang.php +++ b/src/lang/nl.lang.php @@ -95,6 +95,7 @@ $sm_lang = array( 'port' => 'Poort', 'type' => 'Type', 'pattern' => 'Zoek voor tekst/regex', + 'pattern_description' => 'If this pattern is not found on the website, the server will be marked offline. Regular expressions are allowed.', 'last_check' => 'Laatst gecontroleerd', 'last_online' => 'Laatst online', 'monitoring' => 'Monitoring', @@ -103,6 +104,8 @@ $sm_lang = array( 'updated' => 'Server gewijzigd.', 'inserted' => 'Server toegevoegd.', 'rtime' => 'Response tijd', + 'warning_threshold' => 'Warning threshold', + 'warning_threshold_description' => 'Number of failed checks required before it is marked offline.', ), 'config' => array( 'general' => 'Algemeen', diff --git a/src/psm/Module/Server/Controller/AbstractServerController.class.php b/src/psm/Module/Server/Controller/AbstractServerController.class.php old mode 100644 new mode 100755 index 8eb4207e..433481df --- a/src/psm/Module/Server/Controller/AbstractServerController.class.php +++ b/src/psm/Module/Server/Controller/AbstractServerController.class.php @@ -66,7 +66,9 @@ abstract class AbstractServerController extends AbstractController { IF(`s`.`last_online`='0000-00-00 00:00:00', 'never', DATE_FORMAT(`s`.`last_online`, '%d-%m-%y %H:%i')) AS `last_online`, `s`.`active`, `s`.`email`, - `s`.`sms` + `s`.`sms`, + `s`.`warning_threshold`, + `s`.`warning_threshold_counter` FROM `".PSM_DB_PREFIX."servers` AS `s` {$sql_join} ORDER BY `active` ASC, `status` DESC, `type` ASC, `label` ASC"; diff --git a/src/psm/Module/Server/Controller/ServerController.class.php b/src/psm/Module/Server/Controller/ServerController.class.php index f79a127c..bc8fe215 100755 --- a/src/psm/Module/Server/Controller/ServerController.class.php +++ b/src/psm/Module/Server/Controller/ServerController.class.php @@ -84,6 +84,10 @@ class ServerController extends AbstractServerController { // add link to label $servers[$x]['ip'] = ''.$servers[$x]['ip'].''; } + + if($servers[$x]['status'] == 'on' && $servers[$x]['warning_threshold_counter'] > 0) { + $servers[$x]['status'] = 'warning'; + } } // add servers to template $this->tpl->addTemplateDataRepeat($this->getTemplateId(), 'servers', $servers); @@ -106,13 +110,16 @@ class ServerController extends AbstractServerController { $server_id = isset($_GET['id']) ? intval($_GET['id']) : 0; - $tpl_data = array(); + $tpl_data = array( + 'url_go_back' => psm_build_url(array('mod' => 'server')), + ); switch(intval($server_id)) { case 0: // insert mode $tpl_data['titlemode'] = psm_get_lang('system', 'insert'); $tpl_data['edit_server_id'] = '0'; + $tpl_data['edit_value_warning_threshold'] = '1'; break; default: // edit mode @@ -133,6 +140,7 @@ class ServerController extends AbstractServerController { 'edit_value_ip' => $edit_server['ip'], 'edit_value_port' => $edit_server['port'], 'edit_value_pattern' => $edit_server['pattern'], + 'edit_value_warning_threshold' => $edit_server['warning_threshold'], 'edit_type_selected_' . $edit_server['type'] => 'selected="selected"', 'edit_active_selected_' . $edit_server['active'] => 'selected="selected"', 'edit_email_selected_' . $edit_server['email'] => 'selected="selected"', @@ -162,6 +170,7 @@ class ServerController extends AbstractServerController { 'port' => intval($_POST['port']), 'type' => in_array($_POST['type'], array('website', 'service')) ? $_POST['type'] : 'website', 'pattern' => $_POST['pattern'], + 'warning_threshold' => intval($_POST['warning_threshold']), 'active' => in_array($_POST['active'], array('yes', 'no')) ? $_POST['active'] : 'no', 'email' => in_array($_POST['email'], array('yes', 'no')) ? $_POST['email'] : 'no', 'sms' => in_array($_POST['sms'], array('yes', 'no')) ? $_POST['sms'] : 'no', @@ -214,14 +223,18 @@ class ServerController extends AbstractServerController { 'label_port' => psm_get_lang('servers', 'port'), 'label_type' => psm_get_lang('servers', 'type'), 'label_pattern' => psm_get_lang('servers', 'pattern'), + 'label_pattern_description' => psm_get_lang('servers', 'pattern_description'), 'label_last_check' => psm_get_lang('servers', 'last_check'), 'label_rtime' => psm_get_lang('servers', 'rtime'), 'label_last_online' => psm_get_lang('servers', 'last_online'), 'label_monitoring' => psm_get_lang('servers', 'monitoring'), 'label_send_email' => psm_get_lang('servers', 'send_email'), 'label_send_sms' => psm_get_lang('servers', 'send_sms'), + 'label_warning_threshold' => psm_get_lang('servers', 'warning_threshold'), + 'label_warning_threshold_description' => psm_get_lang('servers', 'warning_threshold_description'), 'label_action' => psm_get_lang('system', 'action'), 'label_save' => psm_get_lang('system', 'save'), + 'label_go_back' => psm_get_lang('system', 'go_back'), 'label_edit' => psm_get_lang('system', 'edit') . ' ' . psm_get_lang('servers', 'server'), 'label_delete' => psm_get_lang('system', 'delete') . ' ' . psm_get_lang('servers', 'server'), 'label_yes' => psm_get_lang('system', 'yes'), diff --git a/src/psm/Module/Server/Controller/StatusController.class.php b/src/psm/Module/Server/Controller/StatusController.class.php index a48f38a2..fe1fdb52 100755 --- a/src/psm/Module/Server/Controller/StatusController.class.php +++ b/src/psm/Module/Server/Controller/StatusController.class.php @@ -61,6 +61,8 @@ class StatusController extends AbstractServerController { 'offline_fg' => '#f7cece', 'online_bg' => '#53a000', 'online_fg' => '#d8f7ce', + 'warning_bg' => '#FAA732', + 'warning_fg' => '#F3F3B1', 'label_last_check' => psm_get_lang('servers', 'last_check'), 'label_last_online' => psm_get_lang('servers', 'last_online'), 'label_rtime' => psm_get_lang('servers', 'rtime'), @@ -76,6 +78,9 @@ class StatusController extends AbstractServerController { if ($server['status'] == "off") { $offline[$server['server_id']] = $server; + } elseif($server['warning_threshold_counter'] > 0) { + $server['class_warning'] = 'warning'; + $offline[$server['server_id']] = $server; } else { $online[$server['server_id']] = $server; } diff --git a/src/psm/Util/Install/Installer.class.php b/src/psm/Util/Install/Installer.class.php index 0525d651..0f6caaa0 100755 --- a/src/psm/Util/Install/Installer.class.php +++ b/src/psm/Util/Install/Installer.class.php @@ -167,7 +167,7 @@ class Installer { PSM_DB_PREFIX . 'servers' => "CREATE TABLE `" . PSM_DB_PREFIX . "servers` ( `server_id` int(11) unsigned NOT NULL AUTO_INCREMENT, `ip` varchar(100) NOT NULL, - `port` int(5) NOT NULL, + `port` int(5) unsigned NOT NULL, `label` varchar(255) NOT NULL, `type` enum('service','website') NOT NULL default 'service', `pattern` varchar(255) NOT NULL, @@ -179,6 +179,8 @@ class Installer { `active` enum('yes','no') NOT NULL default 'yes', `email` enum('yes','no') NOT NULL default 'yes', `sms` enum('yes','no') NOT NULL default 'no', + `warning_threshold` mediumint(1) unsigned NOT NULL DEFAULT '1', + `warning_threshold_counter` mediumint(1) unsigned NOT NULL DEFAULT '0', PRIMARY KEY (`server_id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;", PSM_DB_PREFIX . 'servers_uptime' => "CREATE TABLE IF NOT EXISTS `" . PSM_DB_PREFIX . "servers_uptime` ( @@ -248,7 +250,11 @@ class Installer { $queries = array(); $queries[] = "ALTER TABLE `" . PSM_DB_PREFIX . "log` CHANGE `log_id` `log_id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT;"; $queries[] = "ALTER TABLE `" . PSM_DB_PREFIX . "log` CHANGE `server_id` `server_id` INT( 11 ) UNSIGNED NOT NULL;"; + $queries[] = "ALTER TABLE `" . PSM_DB_PREFIX . "servers` CHANGE `server_id` `server_id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT;"; + $queries[] = "ALTER TABLE `" . PSM_DB_PREFIX . "servers` ADD `warning_threshold` MEDIUMINT( 1 ) UNSIGNED NOT NULL DEFAULT '1';"; + $queries[] = "ALTER TABLE `" . PSM_DB_PREFIX . "servers` ADD `warning_threshold_counter` MEDIUMINT( 1 ) UNSIGNED NOT NULL DEFAULT '0';"; + $queries[] = "ALTER TABLE `" . PSM_DB_PREFIX . "users` CHANGE `user_id` `user_id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT;"; $queries[] = "ALTER TABLE `" . PSM_DB_PREFIX . "users` ADD `user_name` varchar(64) COLLATE utf8_general_ci NOT NULL COMMENT 'user\'s name, unique' AFTER `user_id`, diff --git a/src/psm/Util/Updater/Autorun.class.php b/src/psm/Util/Updater/Autorun.class.php old mode 100644 new mode 100755 index 1732cfca..c5250c71 --- a/src/psm/Util/Updater/Autorun.class.php +++ b/src/psm/Util/Updater/Autorun.class.php @@ -23,7 +23,7 @@ * @license http://www.gnu.org/licenses/gpl.txt GNU GPL v3 * @version Release: @package_version@ * @link http://www.phpservermonitor.org/ - * @since phpservermon 2.2.0 + * @since phpservermon 2.2.0 **/ namespace psm\Util\Updater; @@ -76,42 +76,14 @@ class Autorun { $servers = $this->db->query($sql); - $updater = new Status($this->db); + $updater = new StatusUpdater($this->db); + $notifier = new StatusNotifier($this->db); foreach($servers as $server) { - $status_org = $server['status']; - // remove the old status from the array to avoid confusion between the new and old status - unset($server['status']); - - $updater->setServer($server, $status_org); - - // check server status - // it returns the new status, and performs the update check automatically. - $status_new = $updater->getStatus(); + $status_old = ($server['status'] == 'on') ? true : false; + $status_new = $updater->update($server['server_id']); // notify the nerds if applicable - $updater->notify(); - - // update server status - $save = array( - 'last_check' => date('Y-m-d H:i:s'), - 'status' => $status_new, - 'error' => $updater->getError(), - 'rtime' => $updater->getRtime(), - ); - - // if the server is on, add the last_online value - if($save['status'] == 'on') { - $save['last_online'] = date('Y-m-d H:i:s'); - } - - $this->db->save( - PSM_DB_PREFIX . 'servers', - $save, - array('server_id' => $server['server_id']) - ); - - $log_status = ($status_new == 'on') ? 1 : 0; - psm_log_uptime($server['server_id'], $log_status, $updater->getRtime()); + $notifier->notify($server['server_id'], $status_old, $status_new); } } diff --git a/src/psm/Util/Updater/Status.class.php b/src/psm/Util/Updater/Status.class.php deleted file mode 100755 index 8a748839..00000000 --- a/src/psm/Util/Updater/Status.class.php +++ /dev/null @@ -1,389 +0,0 @@ -. - * - * @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 status class is for checking a server and notifying if necessary. - * - * You will need to provide an array with all - * server information to the setServer() method, run update() and notify() if you want to. - * If you are looking for a check-all, see the Autorun class. - * @see \psm\Util\Updater\Autorun - */ -namespace psm\Util\Updater; -use psm\Service\Database; - -class Status { - public $error; - public $notify; - public $rtime = 0; - public $server; - public $status_org = false; - public $status_new = false; - - public $db; - - function __construct(Database $db) { - $this->db = $db; - } - - /** - * Set a new server - * - * @param array $server - * @param string $status_org either 'on' or 'off' - */ - public function setServer($server, $status_org) { - $this->clearResults(); - - $this->server = $server; - $this->status_org = $status_org; - } - - /** - * Get the new status of the selected server. If the update has not been performed yet it will do so first - * - * @return string - */ - public function getStatus() { - if(!$this->server) { - return false; - } - if(!$this->status_new) { - $this->update(); - } - return $this->status_new; - } - - /** - * The function its all about. This one checks whether the given ip and port are up and running! - * If the server check fails it will try one more time - * - * @param int $max_runs how many times should the script recheck the server if unavailable. default is 2 - * @return string new status - */ - public function update($max_runs = 2) { - switch($this->server['type']) { - case 'service': - $result = $this->updateService($max_runs); - break; - case 'website': - $result = $this->updateWebsite($max_runs); - break; - } - return $result; - - } - - protected function updateService($max_runs, $run = 1) { - // save response time - $time = explode(' ', microtime()); - $starttime = $time[1] + $time[0]; - - @$fp = fsockopen ($this->server['ip'], $this->server['port'], $errno, $errstr, 10); - - $time = explode(" ", microtime()); - $endtime = $time[1] + $time[0]; - $this->rtime = ($endtime - $starttime); - - - $this->status_new = ($fp === false) ? 'off' : 'on'; - $this->error = $errstr; - // add the error to the server array for when parsing the messages - $this->server['error'] = $this->error; - - @fclose($fp); - - // check if server is available and rerun if asked. - if($this->status_new == 'off' && $run < $max_runs) { - return $this->updateService($max_runs, $run + 1); - } - - return $this->status_new; - } - - protected function updateWebsite($max_runs, $run = 1) { - // save response time - $time = explode(' ', microtime()); - $starttime = $time[1] + $time[0]; - - // We're only interested in the header, because that should tell us plenty! - // unless we have a pattern to search for! - $curl_result = psm_curl_get( - $this->server['ip'], - true, - ($this->server['pattern'] == '' ? false : true) - ); - - $time = explode(" ", microtime()); - $endtime = $time[1] + $time[0]; - $this->rtime = ($endtime - $starttime); - - // the first line would be the status code.. - $status_code = strtok($curl_result, "\r\n"); - // keep it general - // $code[1][0] = status code - // $code[2][0] = name of status code - preg_match_all("/[A-Z]{2,5}\/\d\.\d\s(\d{3})\s(.*)/", $status_code, $code_matches); - - if(empty($code_matches[0])) { - // somehow we dont have a proper response. - $this->server['error'] = $this->error = 'no response from server'; - $this->status_new = 'off'; - } else { - $code = $code_matches[1][0]; - $msg = $code_matches[2][0]; - - // All status codes starting with a 4 or higher mean trouble! - if(substr($code, 0, 1) >= '4') { - $this->server['error'] = $this->error = $code . ' ' . $msg; - $this->status_new = 'off'; - } else { - $this->status_new = 'on'; - } - } - if($this->server['pattern'] != '') { - // Check to see if the pattern was found. - if(!preg_match("/{$this->server['pattern']}/i", $curl_result)) { - $this->server['error'] = $this->error = 'Pattern not found.'; - $this->status_new = 'off'; - } - } - - // check if server is available and rerun if asked. - if($this->status_new == 'off' && $run < $max_runs) { - return $this->updateWebsite($max_runs, $run + 1); - } - - return $this->status_new; - } - - /** - * This function initializes the sending (text msg & email) and logging - * - */ - public function notify() { - if(psm_get_conf('email_status') == false && psm_get_conf('sms_status') == false && psm_get_conf('log_status') == false) { - // seems like we have nothing to do. skip the rest - return false; - } - $notify = false; - - // check which type of alert the user wants - switch(psm_get_conf('alert_type')) { - case 'always': - if($this->status_new == 'off') { - // server is offline. we are in error state. - $notify = true; - } - break; - case 'offline': - // only send a notification if the server goes down for the first time! - if($this->status_new == 'off' && $this->status_org == 'on') { - $notify = true; - } - break; - case 'status': - if($this->status_new != $this->status_org) { - // status has been changed! - $notify = true; - } - break; - } - - // first add to log (we use the same text as the SMS message because its short..) - if(psm_get_conf('log_status')) { - psm_add_log( - $this->server['server_id'], - 'status', - psm_parse_msg($this->status_new, 'sms', $this->server) - ); - } - - if(!$notify) { - return false; - } - - // check if email is enabled for this server - if(psm_get_conf('email_status') && $this->server['email'] == 'yes') { - // send email - $this->notifyByEmail(); - } - - // check if sms is enabled for this server - if(psm_get_conf('sms_status') && $this->server['sms'] == 'yes') { - // yay lets wake those nerds up! - $this->notifyByTxtMsg(); - } - return true; - } - - /** - * This functions performs the email notifications - * - * @return boolean - */ - protected function notifyByEmail() { - $userlist = array(); - - $users = $this->getUsers($this->server['server_id']); - - if (empty($users)) { - return false; - } - - // build mail object with some default values - $mail = psm_build_mail(); - $mail->Subject = psm_parse_msg($this->status_new, 'email_subject', $this->server); - $mail->Priority = 1; - - $body = psm_parse_msg($this->status_new, 'email_body', $this->server); - $mail->Body = $body; - $mail->AltBody = str_replace('
', "\n", $body); - - // go through empl - foreach ($users as $user) { - // we sent a seperate email to every single user. - $userlist[] = $user['user_id']; - $mail->AddAddress($user['email'], $user['name']); - $mail->Send(); - $mail->ClearAddresses(); - } - - if(psm_get_conf('log_email')) { - // save to log - psm_add_log($this->server['server_id'], 'email', $body, implode(',', $userlist)); - } - } - - /** - * This functions performs the text message notifications - * - * @return unknown - */ - protected function notifyByTxtMsg() { - // send sms to all users for this server using defined gateway - $users = $this->getUsers($this->server['server_id']); - - if (empty($users)) { - return false; - } - - // we have to build an userlist for the log table.. - $userlist = array(); - - // open the right class - // not making this any more dynamic, because perhaps some gateways need custom settings (like Mollie) - switch(strtolower(psm_get_conf('sms_gateway'))) { - case 'mosms': - $sms = new \psm\Txtmsg\Mosms(); - break; - case 'inetworx': - $sms = new \psm\Txtmsg\Inetworx(); - break; - case 'mollie': - $sms = new \psm\Txtmsg\Mollie(); - $sms->setGateway(1); - break; - case 'spryng': - $sms = new \psm\Txtmsg\Spryng(); - break; - case 'clickatell': - $sms = new \psm\Txtmsg\Clickatell(); - break; - case 'textmarketer': - $sms = new \psm\Txtmsg\Textmarketer(); - break; - } - - // copy login information from the config file - $sms->setLogin(psm_get_conf('sms_gateway_username'), psm_get_conf('sms_gateway_password')); - $sms->setOriginator(psm_get_conf('sms_from')); - - // add all users to the recipients list - foreach ($users as $user) { - $userlist[] = $user['user_id']; - $sms->addRecipients($user['mobile']); - } - - $message = psm_parse_msg($this->status_new, 'sms', $this->server); - - // Send sms - $result = $sms->sendSMS($message); - - if(psm_get_conf('log_sms')) { - // save to log - psm_add_log($this->server['server_id'], 'sms', $message, implode(',', $userlist)); - } - return $result; - } - - /** - * Get the error returned by the update function - * - * @return string - */ - public function getError() { - return $this->error; - } - - /** - * Get the response time of the server - * - * @return string - */ - public function getRtime() { - return $this->rtime; - } - - /** - * Clear all the results that are left from the previous run - * - */ - protected function clearResults() { - $this->error = ''; - $this->status_org = false; - $this->status_new = false; - } - - /** - * Get all users for the provided server id - * @param int $server_id - * @return array - */ - public function getUsers($server_id) { - // find all the users with this server listed - $users = $this->db->query(" - SELECT `u`.`user_id`, `u`.`name`,`u`.`email`, `u`.`mobile` - FROM `".PSM_DB_PREFIX."users` AS `u` - JOIN `".PSM_DB_PREFIX."users_servers` AS `us` ON ( - `us`.`user_id`=`u`.`user_id` - AND `us`.`server_id` = {$server_id} - ) - "); - return $users; - } -} diff --git a/src/psm/Util/Updater/StatusNotifier.class.php b/src/psm/Util/Updater/StatusNotifier.class.php new file mode 100755 index 00000000..e41c7480 --- /dev/null +++ b/src/psm/Util/Updater/StatusNotifier.class.php @@ -0,0 +1,292 @@ +. + * + * @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 status updater is for sending notifications to the users. + * + * @see \psm\Util\Updater\StatusUpdater + * @see \psm\Util\Updater\Autorun + */ +namespace psm\Util\Updater; +use psm\Service\Database; + +class StatusNotifier { + + /** + * Database service + * @var \psm\Service\Database $db + */ + protected $db; + + /** + * Send emails? + * @var boolean $send_emails + */ + protected $send_emails = false; + + /** + * Send sms? + * @var boolean $send_sms + */ + protected $send_sms = false; + + /** + * Save log records? + * @var boolean $save_log + */ + protected $save_logs = false; + + /** + * Server id + * @var int $server_id + */ + protected $server_id; + + /** + * Server information + * @var array $server + */ + protected $server; + + /** + * Old status + * @var boolean $status_old + */ + protected $status_old; + + /** + * New status + * @var boolean $status_new + */ + protected $status_new; + + function __construct(Database $db) { + $this->db = $db; + + $this->send_emails = psm_get_conf('email_status'); + $this->send_sms = psm_get_conf('sms_status'); + $this->save_logs = psm_get_conf('log_status'); + } + + /** + * This function initializes the sending (text msg & email) and logging + * + * @param int $server_id + * @param boolean $status_old + * @param boolean $status_new + * @return boolean + */ + public function notify($server_id, $status_old, $status_new) { + if(!$this->send_emails && !$this->send_sms && !$this->save_logs) { + // seems like we have nothing to do. skip the rest + return false; + } + + $this->server_id = $server_id; + $this->status_old = $status_old; + $this->status_new = $status_new; + + // get server info from db + $this->server = $this->db->selectRow(PSM_DB_PREFIX . 'servers', array( + 'server_id' => $server_id, + ), array( + 'server_id', 'ip', 'port', 'label', 'type', 'pattern', 'status', 'error', 'active', 'email', 'sms', + )); + if(empty($this->server)) { + return false; + } + + $notify = false; + + // check which type of alert the user wants + switch(psm_get_conf('alert_type')) { + case 'always': + if($status_new == false) { + // server is offline. we are in error state. + $notify = true; + } + break; + case 'offline': + // only send a notification if the server goes down for the first time! + if($status_new == false && $status_old == true) { + $notify = true; + } + break; + case 'status': + if($status_new != $status_old) { + // status has been changed! + $notify = true; + } + break; + } + + // first add to log (we use the same text as the SMS message because its short..) + if($this->save_logs) { + psm_add_log( + $this->server_id, + 'status', + psm_parse_msg($status_new, 'sms', $this->server) + ); + } + + if(!$notify) { + return false; + } + + // check if email is enabled for this server + if($this->send_emails && $this->server['email'] == 'yes') { + // send email + $this->notifyByEmail(); + } + + // check if sms is enabled for this server + if($this->send_sms && $this->server['sms'] == 'yes') { + // yay lets wake those nerds up! + $this->notifyByTxtMsg(); + } + + return $notify; + } + + /** + * This functions performs the email notifications + * + * @return boolean + */ + protected function notifyByEmail() { + $userlist = array(); + + $users = $this->getUsers($this->server_id); + + if (empty($users)) { + return false; + } + + // build mail object with some default values + $mail = psm_build_mail(); + $mail->Subject = psm_parse_msg($this->status_new, 'email_subject', $this->server); + $mail->Priority = 1; + + $body = psm_parse_msg($this->status_new, 'email_body', $this->server); + $mail->Body = $body; + $mail->AltBody = str_replace('
', "\n", $body); + + // go through empl + foreach ($users as $user) { + // we sent a seperate email to every single user. + $userlist[] = $user['user_id']; + $mail->AddAddress($user['email'], $user['name']); + $mail->Send(); + $mail->ClearAddresses(); + } + + if(psm_get_conf('log_email')) { + // save to log + psm_add_log($this->server_id, 'email', $body, implode(',', $userlist)); + } + } + + /** + * This functions performs the text message notifications + * + * @return unknown + */ + protected function notifyByTxtMsg() { + // send sms to all users for this server using defined gateway + $users = $this->getUsers($this->server_id); + + if (empty($users)) { + return false; + } + + // we have to build an userlist for the log table.. + $userlist = array(); + + // open the right class + // not making this any more dynamic, because perhaps some gateways need custom settings (like Mollie) + switch(strtolower(psm_get_conf('sms_gateway'))) { + case 'mosms': + $sms = new \psm\Txtmsg\Mosms(); + break; + case 'inetworx': + $sms = new \psm\Txtmsg\Inetworx(); + break; + case 'mollie': + $sms = new \psm\Txtmsg\Mollie(); + $sms->setGateway(1); + break; + case 'spryng': + $sms = new \psm\Txtmsg\Spryng(); + break; + case 'clickatell': + $sms = new \psm\Txtmsg\Clickatell(); + break; + case 'textmarketer': + $sms = new \psm\Txtmsg\Textmarketer(); + break; + } + + // copy login information from the config file + $sms->setLogin(psm_get_conf('sms_gateway_username'), psm_get_conf('sms_gateway_password')); + $sms->setOriginator(psm_get_conf('sms_from')); + + // add all users to the recipients list + foreach ($users as $user) { + $userlist[] = $user['user_id']; + $sms->addRecipients($user['mobile']); + } + + $message = psm_parse_msg($this->status_new, 'sms', $this->server); + + // Send sms + $result = $sms->sendSMS($message); + + if(psm_get_conf('log_sms')) { + // save to log + psm_add_log($this->server_id, 'sms', $message, implode(',', $userlist)); + } + return $result; + } + + /** + * Get all users for the provided server id + * @param int $server_id + * @return array + */ + public function getUsers($server_id) { + // find all the users with this server listed + $users = $this->db->query(" + SELECT `u`.`user_id`, `u`.`name`,`u`.`email`, `u`.`mobile` + FROM `".PSM_DB_PREFIX."users` AS `u` + JOIN `".PSM_DB_PREFIX."users_servers` AS `us` ON ( + `us`.`user_id`=`u`.`user_id` + AND `us`.`server_id` = {$server_id} + ) + "); + return $users; + } +} \ No newline at end of file diff --git a/src/psm/Util/Updater/StatusUpdater.class.php b/src/psm/Util/Updater/StatusUpdater.class.php new file mode 100755 index 00000000..3963b06e --- /dev/null +++ b/src/psm/Util/Updater/StatusUpdater.class.php @@ -0,0 +1,232 @@ +. + * + * @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 status class is for checking the status of a server. + * + * @see \psm\Util\Updater\StatusNotifier + * @see \psm\Util\Updater\Autorun + */ +namespace psm\Util\Updater; +use psm\Service\Database; + +class StatusUpdater { + public $error = ''; + + public $rtime = 0; + + public $status_new = false; + + /** + * Database service + * @var \psm\Service\Database $db + */ + protected $db; + + /** + * Server id to check + * @var int $server_id + */ + protected $server_id; + + /** + * Server information + * @var array $server + */ + protected $server; + + function __construct(Database $db) { + $this->db = $db; + } + + /** + * The function its all about. This one checks whether the given ip and port are up and running! + * If the server check fails it will try one more time, depending on the $max_runs. + * + * @param int $server_id + * @param int $max_runs how many times should the script recheck the server if unavailable. default is 2 + * @return boolean TRUE if server is up, FALSE otherwise + */ + public function update($server_id, $max_runs = 2) { + $this->server_id = $server_id; + $this->error = ''; + $this->rtime = ''; + + // get server info from db + $this->server = $this->db->selectRow(PSM_DB_PREFIX . 'servers', array( + 'server_id' => $server_id, + ), array( + 'server_id', 'ip', 'port', 'label', 'type', 'pattern', 'status', 'active', 'warning_threshold', 'warning_threshold_counter', + )); + if(empty($this->server)) { + return false; + } + + switch($this->server['type']) { + case 'service': + $this->status_new = $this->updateService($max_runs); + break; + case 'website': + $this->status_new = $this->updateWebsite($max_runs); + break; + } + + // update server status + $save = array( + 'last_check' => date('Y-m-d H:i:s'), + 'error' => $this->error, + 'rtime' => $this->rtime, + ); + + if($this->status_new == true) { + // if the server is on, add the last_online value and reset the error threshold counter + $save['status'] = 'on'; + $save['last_online'] = date('Y-m-d H:i:s'); + $save['warning_threshold_counter'] = 0; + } else { + // server is offline, increase the error counter + $save['warning_threshold_counter'] = $this->server['warning_threshold_counter'] + 1; + + if($save['warning_threshold_counter'] < $this->server['warning_threshold']) { + // the server is offline but the error threshold has not been met yet. + // so we are going to leave the status "on" for now while we are in a sort of warning state.. + $save['status'] = 'on'; + } else { + $save['status'] = 'off'; + } + } + + $this->db->save(PSM_DB_PREFIX . 'servers', $save, array('server_id' => $this->server_id)); + psm_log_uptime($this->server_id, (int) $this->status_new, $this->rtime); + + return $this->status_new; + + } + + /** + * Check the current server as a service + * @param int $max_runs + * @param int $run + * @return boolean + */ + protected function updateService($max_runs, $run = 1) { + $errno = 0; + // save response time + $starttime = microtime(true); + + $fp = fsockopen ($this->server['ip'], $this->server['port'], $errno, $this->error, 10); + + $status = ($fp === false) ? false : true; + $this->rtime = (microtime(true) - $starttime); + + fclose($fp); + + // check if server is available and rerun if asked. + if(!$status && $run < $max_runs) { + return $this->updateService($max_runs, $run + 1); + } + + return $status; + } + + /** + * Check the current server as a website + * @param int $max_runs + * @param int $run + * @return boolean + */ + protected function updateWebsite($max_runs, $run = 1) { + $starttime = microtime(true); + + // We're only interested in the header, because that should tell us plenty! + // unless we have a pattern to search for! + $curl_result = psm_curl_get( + $this->server['ip'], + true, + ($this->server['pattern'] == '' ? false : true) + ); + + $this->rtime = (microtime(true) - $starttime); + + // the first line would be the status code.. + $status_code = strtok($curl_result, "\r\n"); + // keep it general + // $code[1][0] = status code + // $code[2][0] = name of status code + $code_matches = array(); + preg_match_all("/[A-Z]{2,5}\/\d\.\d\s(\d{3})\s(.*)/", $status_code, $code_matches); + + if(empty($code_matches[0])) { + // somehow we dont have a proper response. + $this->error = 'no response from server'; + $result = false; + } else { + $code = $code_matches[1][0]; + $msg = $code_matches[2][0]; + + // All status codes starting with a 4 or higher mean trouble! + if(substr($code, 0, 1) >= '4') { + $this->error = $code . ' ' . $msg; + $result = false; + } else { + $result = true; + } + } + if($this->server['pattern'] != '') { + // Check to see if the pattern was found. + if(!preg_match("/{$this->server['pattern']}/i", $curl_result)) { + $this->error = 'Pattern not found.'; + $result = false; + } + } + + // check if server is available and rerun if asked. + if(!$result && $run < $max_runs) { + return $this->updateWebsite($max_runs, $run + 1); + } + + return $result; + } + + /** + * Get the error returned by the update function + * + * @return string + */ + public function getError() { + return $this->error; + } + + /** + * Get the response time of the server + * + * @return string + */ + public function getRtime() { + return $this->rtime; + } +} diff --git a/src/templates/main.tpl.html b/src/templates/main.tpl.html index ae51a537..b5ff4c1c 100755 --- a/src/templates/main.tpl.html +++ b/src/templates/main.tpl.html @@ -22,6 +22,7 @@ diff --git a/src/templates/servers.tpl.html b/src/templates/servers.tpl.html index 02d7fc75..da5278c7 100755 --- a/src/templates/servers.tpl.html +++ b/src/templates/servers.tpl.html @@ -71,40 +71,40 @@
- +
- -
-
-
- -
- +
-
+
+ +
+ +
+
- +
- @@ -113,7 +113,7 @@
- @@ -122,15 +122,21 @@
-
+
+ +
+ +
+
- - + + {label_go_back}
diff --git a/src/templates/status.tpl.html b/src/templates/status.tpl.html index 0d645fcd..717941c2 100755 --- a/src/templates/status.tpl.html +++ b/src/templates/status.tpl.html @@ -35,6 +35,12 @@ border: 2px solid {offline_fg}; } + .offline .entity.warning { + background: {warning_bg}; + color: {warning_fg}; + border: 2px solid {warning_fg}; + } + .online { margin-left: 320px; } @@ -50,7 +56,7 @@
-
+

{label}

{label_last_online}: {last_online_nice}

{label_last_check}: {last_checked_nice}

diff --git a/static/css/style.css b/static/css/style.css old mode 100644 new mode 100755 index dee4e905..7d4018a4 --- a/static/css/style.css +++ b/static/css/style.css @@ -10,6 +10,9 @@ body.install{ .label-status-off{ background-color: #B94A48; } +.label-status-warning{ + background-color: #FAA732; +} .label a{ color:#FFF; text-decoration:none; diff --git a/static/js/scripts.js b/static/js/scripts.js old mode 100644 new mode 100755 index 2470584c..493e5f0b --- a/static/js/scripts.js +++ b/static/js/scripts.js @@ -1,11 +1,19 @@ function sm_delete(id, mod) { var del = confirm("Are you sure you want to delete this record?"); - if (del == true) { + if (del === true) { var loc = 'index.php?action=delete&id=' + id + '&mod=' + mod; window.location = loc; } } +function psm_tooltips() { + $('input[data-toggle="tooltip"]').tooltip({ + 'trigger':'focus', + 'placement': 'right', + 'container': 'body' + }); +} + function trim(str) { return str.replace(/^\s+|\s+$/g,""); }