Documentation is available at monitor-defs.php
- <?php
- /* ******************************************************************** */
- /* CATALYST PHP Source Code */
- /* -------------------------------------------------------------------- */
- /* This program is free software; you can redistribute it and/or modify */
- /* it under the terms of the GNU General Public License as published by */
- /* the Free Software Foundation; either version 2 of the License, or */
- /* (at your option) any later version. */
- /* */
- /* This program is distributed in the hope that it will be useful, */
- /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
- /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
- /* GNU General Public License for more details. */
- /* */
- /* You should have received a copy of the GNU General Public License */
- /* along with this program; if not, write to: */
- /* The Free Software Foundation, Inc., 59 Temple Place, Suite 330, */
- /* Boston, MA 02111-1307 USA */
- /* -------------------------------------------------------------------- */
- /* */
- /* Filename: monitor-defs.php */
- /* Author: Paul Waite */
- /* Description: A generic set of monitor classes to enable convenient */
- /* checking of systems and services. */
- /* */
- /* ******************************************************************** */
- /** @package monitor */
- include_once("datetime-defs.php");
- /** Lockfile manager */
- ("lockfile-defs.php");
- // ----------------------------------------------------------------------
- // DEFINITIONS & CONSTANTS
- // Condition types..
- /** Condition for a passed test */
- ("COND_OK", 0);
- /** Warning condition */
- ("COND_WARNING", 1);
- /** Critical error condition */
- ("COND_CRITICAL", 2);
- /** Condition is undefined */
- ("COND_UNKNOWN", -1);
- /** Aggregate: no conditions */
- ("COND_NONE", -2);
- /** Aggregate: all conditions */
- ("COND_ALL", -3);
- /** Array of condition descriptions */
- = array(
- COND_UNKNOWN => "UNKNOWN",
- COND_OK => "OK",
- COND_WARNING => "WARNING",
- COND_CRITICAL => "CRITICAL"
- );
- // ----------------------------------------------------------------------
- /**
- * A generic monitor class which is used to derive the specific classes
- * which deal with monitoring particular things, such as Postgres,
- * file space, file activity etc. Apart from a few utility methods
- * this is mainly a container for messages, and the current condition
- * level of the monitor.
- * @package monitor
- * @access private
- */
- class generic_monitor {
- /** Type of monitor this is */
- var $type = "unspec";
- /** Current condition of this monitor */
- var $condition = COND_UNKNOWN;
- /** Condition to set, on failure. */
- var $fail_condition = COND_CRITICAL;
- /** Set of messages for email, per condition */
- var $report_msgs = array();
- /** Set of messages for SMS, per condition */
- var $smstxt_msgs = array();
- /** Conditions which we should ignore */
- var $suppressed_conditions = array();
- // ....................................................................
- /** Define a new generic monitor object. */
- function generic_monitor($type="") {
- global $condition_desc;
- if ($type != "") {
- $this->type = $type;
- }
- // Initialise all known messages to blank..
- foreach ($condition_desc as $cond => $desc) {
- $this->set_messages($cond, "");
- }
- }
- // ....................................................................
- /** Set the error condition messages for email and SMS.
- * @param integer $condition Condition messages are to be set for
- * @param string $report Report text if error raised
- * @param string $smstxt SMS txt if error raised
- */
- function set_messages($condition, $report, $smstxt="") {
- $this->report_msgs[$condition] = $report;
- $this->smstxt_msgs[$condition] = $smstxt;
- } // set_default_messages
- // ....................................................................
- /** Set the default error condition messages for email and SMS. We
- * only set these messages if there are none already set.
- * @param integer $condition Condition messages are to be set for
- * @param string $report Report text if error raised
- * @param string $smstxt SMS txt if error raised
- */
- function set_default_messages($condition, $report, $smstxt="") {
- if (!isset($this->report_msgs[$condition]) || $this->report_msgs[$condition] == "") {
- $this->report_msgs[$condition] = $report;
- }
- if (!isset($this->smstxt_msgs[$condition]) || $this->smstxt_msgs[$condition] == "") {
- $this->smstxt_msgs[$condition] = $smstxt;
- }
- } // set_default_messages
- // ....................................................................
- /** Suppress the given condition, so it won't be notified */
- function suppress_condition($condition) {
- if (!in_array($condition, $this->suppressed_conditions)) {
- $this->suppressed_conditions[] = $condition;
- }
- } // suppress_condition
- // ....................................................................
- /** Append the given addendum to the end of all the messages
- * that are stored. Used to append dynamic values to the ends
- * of static message content.
- * @param string $addendum String to append to all monitor messages.
- */
- function all_messages_append($addendum) {
- $newmsgs = array();
- foreach ($this->report_msgs as $cond => $msg) {
- $newmsgs[$cond] = $msg . $addendum;
- }
- $this->report_msgs = $newmsgs;
- $newmsgs = array();
- foreach ($this->smstxt_msgs as $cond => $msg) {
- $newmsgs[$cond] = $msg . $addendum;
- }
- $this->smstxt_msgs = $newmsgs;
- } // all_messages_append
- // ....................................................................
- /** Set the monitor condition.
- * @param integer $condition Condition to set the monitor to.
- */
- function set_condition($condition) {
- $this->condition = $condition;
- } // set_condition
- // ....................................................................
- /** Set the monitor condition value to use for 'failed' status. This
- * can be set for certain monitors, such as the 'postgres_monitor' which
- * basically returns a boolean status of Ok/Failed. For more complex
- * multi-condition monitors it is not used. Allows you to be more flexible
- * in what gets returned.
- * @param integer $condition Condition to set the monitor to on failure
- */
- function set_fail_condition($condition) {
- $this->fail_condition = $condition;
- } // set_fail_condition
- // ....................................................................
- /** Return condition message for current condition
- * @return string The monitor message which is to be reported via email
- */
- function reportmsg() {
- $msg = "";
- if (isset($this->report_msgs[$this->condition])) {
- $msg = $this->report_msgs[$this->condition];
- }
- return $msg;
- } // reportmsg
- // ....................................................................
- /** Return the sms text message for current condition
- * @return string The monitor message which is to be reported via SMS
- */
- function smstxtmsg() {
- $msg = "";
- if (isset($this->smstxt_msgs[$this->condition])) {
- $msg = $this->smstxt_msgs[$this->condition];
- }
- return $msg;
- } // smstxtmsg
- // ....................................................................
- /** Make the check.
- * @return integer The condition level determined by the checking process.
- */
- function check() {
- // Return condition..
- return $this->condition;
- } // check
- } // generic_monitor class
- // ----------------------------------------------------------------------
- /**
- * A monitor class to exec a script/program on the OS. This allows you
- * to hook up an external script or program to the monitoring system
- * with the flexibility to determine success/failure by return value
- * or by comparing output with an expected (regex) pattern. The default
- * test is to test the output of the script/program and if it is nullstring
- * (''), then the check is deemed to be successful, otherwise not.
- * There is also a flag, in the constructor ($publish_output) which,
- * if true, directs the monitor to include any script output in the email
- * or SMS messages. This can sometimes be useful for providing extra
- * information in error reports.
- * @package monitor
- */
- class exec_monitor extends generic_monitor {
- var $execpath = "";
- var $execparms = "";
- var $success_value = "";
- var $success_regex = "";
- var $publish_output = false;
- // ....................................................................
- /**
- * Define a new exec check object.
- * @param string $exec Script/program to execute, including any parameters
- * @param string $success_regex Regex to match with the output of script/program
- * @param boolean $publish_output Publish script/program output in all messages
- */
- function exec_monitor($exec, $success_regex="", $publish_output=false) {
- $this->generic_monitor("exec");
- $bits = explode(" ", $exec);
- $this->execpath = array_shift($bits);
- $this->execparms = implode(" ", $bits);
- $this->success_regex = $success_regex;
- $this->publish_output = $publish_output;
- } // exec_monitor
- // ....................................................................
- /**
- * Allows you to specify a string value which, if returned as output by
- * the called script/program, will indicate success.
- * The default value for success is already nullstring, so no need to
- * specify it in that particular case.
- * @param integer $code Return value which indicates success
- */
- function set_success_value($success="") {
- $this->success_value = $success;
- } // set_success_value
- // ....................................................................
- /**
- * Allows you to specify a regular expression which will be applied to
- * the output of the executed script/program and if matched will be
- * taken to mean the check was successful. If specified, this takes
- * the place of the default behaviour of checking the return code.
- * @param string $regex Regular expression to match on output for success
- */
- function set_success_regex($success_regex) {
- $this->success_regex = $success_regex;
- } // set_success_regex
- // ....................................................................
- /** Make the check by executing the script/program which has been
- * specified. We check that this exists and is executable, and raise
- * warnings if not. The success/failure of the check is determined
- * by the settings, but is either done via return code or by returned
- * output matching.
- * @return integer Condition determined by this check
- */
- function check() {
- if (file_exists($this->execpath)) {
- if (is_executable($this->execpath)) {
- $prog = $this->execpath;
- if ($this->execparms != "") {
- $prog .= " $this->execparms";
- }
- // Execute it..
- $output = shell_exec($prog);
- // Check for success or failure..
- if ($this->success_regex != "") {
- $matches = array();
- $success = (preg_match("/$this->success_regex/", $output, $matches) == 1);
- }
- else {
- $success = ($this->success_value == $output);
- }
- if ($success === false) {
- $this->set_condition($this->fail_condition);
- $this->set_default_messages(
- $this->fail_condition,
- "$this->execpath failed",
- "$this->execpath FAILED"
- );
- }
- else {
- $this->set_condition(COND_OK);
- $this->set_default_messages(
- COND_OK,
- "$this->execpath succeeded",
- "$this->execpath OK"
- );
- }
- if ($this->publish_output && $output != "") {
- $this->all_messages_append( " " . $output);
- }
- }
- else {
- $this->set_condition(COND_WARNING);
- $this->set_default_messages(
- COND_WARNING,
- "$this->execpath not executable"
- );
- }
- }
- else {
- $this->set_condition(COND_WARNING);
- $this->set_default_messages(
- COND_WARNING,
- "$this->execpath not found"
- );
- }
- // Return condition..
- return $this->condition;
- } // check
- } // exec_monitor class
- // ----------------------------------------------------------------------
- /**
- * A monitor class to check when files/directories were last modified.
- * This is a general class which can be used to set limits on how long
- * a file or directory can remain un-modified before warnings and/or
- * errors are issued.
- * @package monitor
- */
- class file_monitor extends generic_monitor {
- // Public
- // Private
- /** Path to the file to monitor
- @access private */
- var $filepath = "";
- /** Seconds before warning message
- @access private */
- var $warnsecs = 0;
- /** Seconds before error condition
- @access private */
- var $critsecs = 0;
- // ....................................................................
- /**
- * Define a new file check object.
- * @param string $filepath Path to file or directory to check
- * @param integer $warnmins Minutes file can be idle before warning issued
- * @param integer $critmins Minutes file can be idle before critical error raised
- */
- function file_monitor($filepath, $warnmins, $critmins) {
- $this->generic_monitor("file");
- $this->filepath = $filepath;
- $this->warnsecs = $warnmins * 60;
- $this->critsecs = $critmins * 60;
- } // file_monitor
- // ....................................................................
- /** Make the check on the time the file was last modified and if this
- * is longer than this->warnsecs ago but less than this->errsecs then
- * issue a warning. Otherwise if it is longer than this->errsecs ago
- * then we issue an error message.
- * @return integer Condition determined by this check
- */
- function check() {
- clearstatcache();
- if (file_exists($this->filepath)) {
- $idlesecs = time() - filemtime($this->filepath);
- $hours = floor($idlesecs / 3600);
- $mins = floor(($idlesecs % 3600) / 60);
- $idletime = $hours . "hrs $mins" . "mins";
- if ($idlesecs >= $this->warnsecs && $idlesecs < $this->critsecs) {
- $this->set_condition(COND_WARNING);
- $this->set_default_messages(
- COND_WARNING,
- "$this->filepath idle for",
- "$this->filepath IDLE"
- );
- }
- elseif ($idlesecs > $this->critsecs) {
- $this->set_condition($this->fail_condition);
- $this->set_default_messages(
- $this->fail_condition,
- "$this->filepath idle for",
- "$this->filepath IDLE"
- );
- }
- else {
- $this->set_condition(COND_OK);
- $this->set_default_messages(
- COND_OK,
- "$this->filepath modified at",
- "$this->filepath MOD AT"
- );
- }
- $this->all_messages_append(" $idletime");
- }
- else {
- $this->set_condition(COND_WARNING);
- $this->set_default_messages(
- COND_WARNING,
- "$this->filepath not found"
- );
- }
- // Return condition..
- return $this->condition;
- } // check
- } // file_monitor class
- // ----------------------------------------------------------------------
- /**
- * A monitor class to check if a given process is running. This can be
- * achieved by consulting a pidfile, or by checking the process status
- * listing for the given process name (the default behaviour).
- * @package monitor
- */
- class process_monitor extends generic_monitor {
- // Public
- // Private
- /** Name of the process being monitored.
- @access private */
- var $procname = "";
- /** Path to the PID file containing a process ID for the running process. Leave
- this as nullstring to check using the $procname case-insensitively by searching the full process listing for the
- process name.
- @access private */
- var $pidfile = "";
- /** The 'ps' command to use for a specific process ID#. This allows override
- of the default, in cases of use on systems requiring differing path or options.
- @access private */
- var $ps_pid_cmd = "ps --no-headers -p";
- /** The 'ps' command to use for an 'all processes list. This allows override
- of the default, in cases of use on systems requiring differing path or options.
- @access private */
- var $ps_all_cmd = "ps ax";
- // ....................................................................
- /**
- * Defines a new process monitoring object and provides matching info.
- * @param string $procname Name of the process to search for using 'ps'.
- * @param string $pidfile Path to PID file, or nullstring if matching on $procname.
- * @param string $ps_all_cmd The 'ps' command to use for 'all processes' listing.
- * @param string $ps_pid_cmd The 'ps' command to use for a specific process.
- */
- function process_monitor($procname, $pidfile="", $ps_all_cmd="", $ps_pid_cmd="") {
- $this->generic_monitor("proc");
- $this->procname = $procname;
- $this->pidfile = $pidfile;
- if ($ps_all_cmd != "") {
- $this->ps_all_cmd = $ps_all_cmd;
- }
- if ($ps_pid_cmd != "") {
- $this->ps_pid_cmd = $ps_pid_cmd;
- }
- } // file_monitor
- // ....................................................................
- /** Make the check on the time the file was last modified and if this
- * is longer than this->warnsecs ago but less than this->errsecs then
- * issue a warning. Otherwise if it is longer than this->errsecs ago
- * then we issue an error message.
- * @return integer Condition determined by this check
- */
- function check() {
- if ($this->procname != "") {
- $ps = "";
- // Default is to match procname in process listing..
- if ($this->pidfile == "") {
- $ps = shell_exec("$this->ps_all_cmd");
- if (stristr($ps, $this->procname) === false) {
- $this->set_condition($this->fail_condition);
- $this->set_default_messages(
- $this->fail_condition,
- "Process ($this->procname) is not running.",
- "Proc ($this->procname) not running."
- );
- }
- else {
- $this->set_condition(COND_OK);
- $this->set_default_messages(
- COND_OK,
- "Process ($this->procname) is running.",
- "Proc ($this->procname) ok."
- );
- }
- }
- // Search for specific PIDfile & process ID..
- else {
- if (file_exists($this->pidfile)) {
- $pid = trim(shell_exec("cat $this->pidfile"));
- if ($pid != "") {
- $ps = shell_exec("$this->ps_pid_cmd $pid");
- }
- if ($ps == "") {
- $this->set_condition($this->fail_condition);
- $this->set_default_messages(
- $this->fail_condition,
- "Process $this->procname ($pid) is not running.",
- "Proc $this->procname ($pid) dead."
- );
- }
- else {
- $this->set_condition(COND_OK);
- $this->set_default_messages(
- COND_OK,
- "Process $this->procname ($pid) is running.",
- "Proc $this->procname ($pid) ok."
- );
- }
- }
- else {
- $this->set_condition($this->fail_condition);
- $this->set_default_messages(
- $this->fail_condition,
- "Process $this->procname no pidfile ($this->pidfile).",
- "Proc $this->procname no pidfile."
- );
- }
- }
- }
- // Return condition..
- return $this->condition;
- } // check
- } // process_monitor class
- // ----------------------------------------------------------------------
- /**
- * A monitor class to check if Postgres is up and about. You need to
- * specify a database and a user (and if required, a password) which can
- * be use to test-connect to Postgres. Optionally you can specify the
- * host and port number if connection is over TCP.
- * @package monitor
- */
- class postgres_monitor extends generic_monitor {
- // Public
- // Private
- /** Database connection resource ID
- @access private */
- var $dbid = false;
- /** Name of the database to connect to
- @access private */
- var $dbname = "";
- /** Username to connect as
- @access private */
- var $user = "";
- /** Password of username to connect as
- @access private */
- var $password = "";
- /** For TCP connections: hostname to connect to
- @access private */
- var $host = "";
- /** For TCP connections: port to connect to
- @access private */
- var $port = "";
- // ....................................................................
- /**
- * Define a new Postgres monitor object.
- * @param string $dbname Name of the Postgres database
- * @param string $user Username to connect as
- * @param string $password User password, if required
- * @param string $host Hostname for TCP connections
- * @param string $port Port number for TCP connections
- */
- function postgres_monitor($dbname, $user, $password="", $host="", $port="") {
- $this->generic_monitor("postgres");
- $this->dbname = $dbname;
- $this->user = $user;
- $this->password = $password;
- $this->host = $host;
- $this->port = $port;
- } // postgres_monitor
- // ....................................................................
- /** Make the check, as to whether we can connect to the Postgres DB.
- * If not then return false, else return true.
- * @return boolean True if Postgres could be connected to.
- */
- function check() {
- if ($this->connect()) {
- $this->disconnect();
- $this->set_condition(COND_OK);
- $this->set_default_messages(
- COND_OK,
- "Postgres ($this->dbname) connection success.",
- "POSTGRES ($this->dbname) OK"
- );
- }
- else {
- $this->set_condition($this->fail_condition);
- $this->set_default_messages(
- $this->fail_condition,
- "Postgres ($this->dbname) connection failed.",
- "POSTGRES ($this->dbname) FAILED"
- );
- }
- // Return condition..
- return $this->condition;
- } // check
- // ....................................................................
- /** Connect to the DB. If we succeed, return true, else false.
- * @access private
- */
- function connect() {
- $connstr = "";
- if ($this->host != "") $connstr .= " host=" . $this->host;
- if ($this->port != 0 ) $connstr .= " port=" . $this->port;
- $connstr .= " dbname=" . $this->dbname;
- $connstr .= " user=" . $this->user;
- if ($this->password != "") $connstr .= " password=" . $this->password;
- $connstr = trim($connstr);
- $this->dbid = pg_connect("$connstr");
- return ($this->dbid !== false);
- } // connect
- // ....................................................................
- /** Disconnect from the DB.
- * @access private
- */
- function disconnect() {
- if ($this->dbid !== false) {
- pg_close($this->dbid);
- $this->dbid = false;
- }
- } // diconnect
- } // postgres_monitor class
- // ----------------------------------------------------------------------
- /** A monitor class to check if the search engine is up and about
- * @package monitor
- */
- class searchengine_monitor extends generic_monitor {
- // Public
- // Private
- /** The search engine search object
- @access private */
- var $searcher;
- /** Expected no. of hits
- @access private */
- var $hits = 0;
- /** Search engine host
- @access private */
- var $host = "";
- /** Search engine port
- @access private */
- var $port = "";
- /** Search engine host abbreviation
- @access private */
- var $host_abbrev = "";
- // ....................................................................
- /**
- * Define a new Search Engine monitor object. We register the query to use
- * and the number of hits we expect. You can also specify the hostname
- * and port of the Search server here, although Axyl users can leave these
- * out (blank) if they have configured them with setup-system.php.
- * @param string $searcher Search object, ready to execute
- * @param integer $hits No of results expected back from search
- * @param string $host Hostname of the server
- * @param string $port Port number of the server
- */
- function searchengine_monitor($searcher, $hits, $host="", $port="") {
- $this->generic_monitor("searchengine");
- $this->searcher = $searcher;
- $this->hits = $hits;
- // Retreive Axyl search engine connection information if available..
- if ($host == "" && class_exists("configuration")) {
- $config = new configuration("sys_control");
- $host = $config->value("Search Engine Host");
- $port = $config->value("Search Engine Port");
- }
- $this->host = $host;
- $this->port = $port;
- // Abbreviated version of hostname for messages..
- $bits = explode(".", $this->host);
- $this->host_abbrev = $bits[0];
- } // searchengine_monitor
- // ....................................................................
- /** Make the check on Lucene by firing the query off and checking for
- * the expected number of hits coming back.
- * @return boolean True if Lucene delivered correct number of hits.
- */
- function check() {
- $res = false;
- if (is_object($this->searcher) && method_exists($this->searcher, "execute")) {
- $this->searcher->execute();
- // VALID RESPONSE..
- if ($this->searcher->response->valid) {
- if ($this->searcher->hitcount() == $this->hits) {
- $res = true;
- $this->set_condition(COND_OK);
- $this->set_default_messages(
- COND_OK,
- "Search Engine ($this->host_abbrev:$this->port) hits: " . $this->searcher->hitcount() . "/" . $this->hits,
- "SRCH ENG $this->host_abbrev HITS: " . $this->searcher->hitcount() . "/" . $this->hits
- );
- }
- else {
- $this->set_condition($this->fail_condition);
- $this->set_default_messages(
- $this->fail_condition,
- "Search Engine ($this->luhost_abbrev:$this->luport) hits: " . $this->lusearch->hitcount() . "/" . $this->luhits,
- "SRCH ENG $this->host_abbrev HITS: " . $this->searcher->hitcount() . "/" . $this->hits
- );
- }
- }
- // INVALID RESPONSES..
- else {
- if ($this->searcher->response->error_message != "") {
- $this->set_condition($this->fail_condition);
- $this->set_default_messages(
- $this->fail_condition,
- "Search Engine ($this->host_abbrev:$this->port) error: " . $this->searcher->response->error_message,
- "SRCH ENG $this->host_abbrev ERROR: " . $this->searcher->response->error_message
- );
- }
- else {
- $this->set_condition($this->fail_condition);
- $this->set_default_messages(
- $this->fail_condition,
- "Search Engine ($this->host_abbrev:$this->port) failed. Search engine/network problems?",
- "SRCH ENG $this->host_abbrev UNKNOWN FAILURE."
- );
- }
- }
- }
- // Return condition..
- return $this->condition;
- } // check
- } // searchengine_monitor class
- // ----------------------------------------------------------------------
- /**
- * Class which checks for a disk free space condition.
- * @package monitor
- */
- class diskspace_monitor extends generic_monitor {
- // Public
- // Private
- /** Directory to check
- @access private */
- var $fsdir = "";
- /** Threshold (bytes) before warning condition
- @access private */
- var $warnspace = 0;
- /** Threshold (bytes) before error condition
- @access private */
- var $minspace = 0;
- // ....................................................................
- /**
- * @param integer $fsdir A directory on the filesystem to check
- * @param integer $warnspace The threshold to warn of low space (bytes)
- * @param integer $minspace The threshold for critical errors (bytes)
- */
- function diskspace_monitor($fsdir, $warnspace, $minspace) {
- $this->generic_monitor("diskspace");
- $this->fsdir = $fsdir;
- $this->warnspace = $warnspace;
- $this->minspace = $minspace;
- }
- // ....................................................................
- /**
- * Check the space on the filesystem of the directory specified.
- * @return object The report generated by the checking process.
- */
- function check() {
- if (file_exists($this->fsdir)) {
- $df = disk_free_space($this->fsdir);
- $MB = floor($df / MEGABYTE) . "MB";
- if ($df < $this->warnspace) {
- $this->set_condition(COND_WARNING);
- $this->set_default_messages(
- COND_WARNING,
- "Filesystem of $this->fsdir low on space",
- "FILESYS OF $this->fsdir LOW"
- );
- }
- elseif ($df < $this->minspace) {
- $this->set_condition($this->fail_condition);
- $this->set_default_messages(
- $this->fail_condition,
- "Filesystem of $this->fsdir critical!",
- "FILESYS OF $this->fsdir CRIT!"
- );
- }
- else {
- $this->set_condition(COND_OK);
- $this->set_default_messages(
- COND_OK,
- "Filesystem of $this->fsdir ok",
- "FILESYS OF $this->fsdir OK"
- );
- }
- $this->all_messages_append(" $MB");
- }
- else {
- $this->set_condition(COND_WARNING);
- $this->set_default_messages(
- COND_WARNING,
- "$this->fsdir not found.",
- "$this->fsdir NOT FOUND"
- );
- }
- // Return condition..
- return $this->condition;
- } // check
- } // diskspace_monitor class
- // ----------------------------------------------------------------------
- /** The monitor class. This is the entity which contains the details
- * of what is to be monitored, how it is to be monitored and what to
- * do if a given condition arises.
- * @package monitor
- */
- class monitor {
- // Public
- /** The name of this monitor instance */
- var $name = "";
- /** Address to email monitor messages */
- var $emailto = "";
- /** Address monitor messages come from */
- var $emailfrom = "";
- /** Address to email SMS txt messages */
- var $emailpager = "";
- /** Whether to emit a status message to stdout. If true the monitor will
- * emit the current status, plus the message associated with the highest
- * priority (most severe) condition in the monitor. Format will be:
- * 'CRITICAL: some message goes here'. */
- var $emit_status = false;
- /** Monitor lockfile path */
- var $lockfilepath = "";
- // Private
- /** Local hostname we are running monitor on
- @access private */
- var $hostname = "";
- /** Whether to use a lockfile
- @access private */
- var $use_lockfile = true;
- /** Monitor lockfile object
- @access private */
- var $lockfile;
- /** True if we are locked via lockfile
- @access private */
- var $locked = false;
- /** Monitor highest priority condition
- @access private */
- var $condition = COND_OK;
- /** Monitor highest priority message */
- var $message = "";
- /** Report staging for email
- @access private */
- var $reportmsg = "";
- /** Report staging for SMS txt
- @access private */
- var $smstxtmsg = "";
- /** Threshold condition for emailing
- @access private */
- var $email_condition_threshold = COND_WARNING;
- /** Threshold condition for paging
- @access private */
- var $pager_condition_threshold = COND_CRITICAL;
- /** The current Unix timestamp
- @access private */
- var $tinow;
- /** Condition to stop on. If this condition is defined then we
- stop checking monitors the first time it is raised.
- @access private */
- var $stop_on_condition = COND_NONE;
- /** Schedule of named timeslots for this monitor
- @access private */
- var $schedule;
- /** Array of monitors which do the work
- @access private */
- var $monitors = array();
- // ....................................................................
- /**
- * Create a new monitor object. This is the container for all of the
- * monitors which you can define and use to monitor a complete system.
- * @param string $name Name of this monitor instance (message prefix)
- * @param string $emailto Email address to send monitor messages to
- * @param string $emailfrom Email from-address for monitor messages
- * @param string $emailpager Email address for pager TXT messages
- * @param string $lockfilepath Path to lockfile (optional)
- */
- function monitor($name="", $emailto="", $emailfrom="", $emailpager="", $lockfilepath="") {
- // Determine hostname..
- $returnlines = "";
- exec("hostname", $returnlines);
- if (isset($returnlines[0]) && $returnlines[0] != "") {
- $this->hostname = $returnlines[0];
- }
- // Deal with parameters..
- if ($name == "") {
- $name = "Monitor";
- }
- if ($emailto == "") {
- if (defined("WEBMASTER_EMAIL")) {
- $emailto = WEBMASTER_EMAIL;
- if (defined("APP_NAME")) {
- $emailto = "\"" . APP_NAME . "\" <$emailto>";
- }
- }
- }
- if ($emailfrom == "") {
- if (defined("WEBMASTER_EMAIL")) {
- $emailfrom = WEBMASTER_EMAIL;
- if (defined("APP_NAME")) {
- $emailfrom = "\"" . APP_NAME . "\" <$emailfrom>";
- }
- }
- }
- // Set lockfile path. We also interpret the value 'nolockfile'
- // for this parameter as disabling the locking feature..
- if ($lockfilepath == "") {
- $lockfilepath = str_replace(" ", "_", $name);
- if ($lockfilepath == "") {
- $lockfilepath = "monitor";
- if ( defined("APP_PREFIX")) {
- $lockfilepath .= "_" . APP_PREFIX;
- }
- }
- $lockfilepath .= ".LCK";
- }
- elseif ($lockfilepath == "nolockfile") {
- $this->use_lockfile = false;
- }
- // Store all the parameters..
- $this->name = $name;
- $this->lockfilepath = $lockfilepath;
- $this->emailto = $emailto;
- $this->emailfrom = $emailfrom;
- $this->emailpager = $emailpager;
- // Other settings..
- $this->tinow = time();
- $this->schedule = new schedule();
- } // monitor
- // ....................................................................
- /** Clear all the monitors. */
- function clear() {
- $this->monitors = array();
- $this->reportmsg = "";
- $this->smstxtmsg = "";
- $this->condition = COND_OK;
- $this->message = "";
- } // clear
- // ....................................................................
- /** Control the emission of status and status message associated with
- * the most sever monitor error. The monitor defaults to not doing this
- * so you should call this method without parameters to turn it on.
- * @param boolean $mode If true then turn on status emission mode.
- */
- function set_emit_status($mode=true) {
- $this->emit_status = $mode;
- } // set_emit_status
- // ....................................................................
- /**
- * Lock the monitor. This is a private method which tries to lock the
- * monitor using the lockfile assigned to it.
- * @return boolean True if lock was obtained.
- * @access private
- */
- function lock() {
- global $_ENV;
- $LCK = new lockfile($this->lockfilepath);
- $LCK->set_timelimits(5, 15);
- if ($LCK->create()) {
- $this->locked = true;
- $this->lockfile = $LCK;
- }
- else {
- $lockmon = new generic_monitor();
- switch ($LCK->errorcode) {
- case LCK_E_CREFAIL:
- case LCK_E_FROZEN:
- case LCK_E_READFAIL:
- $lockmon->set_condition(COND_CRITICAL);
- $lockmon->set_default_messages(
- COND_CRITICAL,
- $LCK->errormsg(),
- $LCK->errormsg()
- );
- $this->raise_condition($lockmon);
- break;
- case LCK_E_KILLED:
- case LCK_E_KILLED9:
- case LCK_E_IMMORTAL:
- case LCK_E_ORPHAN:
- $lockmon->set_condition(COND_WARNING);
- $lockmon->set_default_messages(
- COND_WARNING,
- $LCK->errormsg(),
- $LCK->errormsg()
- );
- $this->raise_condition($lockmon);
- break;
- }
- }
- return $this->locked;
- } // lock
- // ....................................................................
- /**
- * Unlock the monitor. This is a private method which deletes the
- * lockfile which was being used to block multiple instances.
- * @access private
- */
- function unlock() {
- $res = true;
- if ($this->locked) {
- if ($this->lockfile->remove()) {
- $this->locked = false;
- }
- }
- return $res;
- } // unlock
- // ....................................................................
- /**
- * Sets the threshold at which we will send messages to email & pager.
- * Any conditions equal or worse than the threshold will be sent if
- * the message is not nullstring.
- * @param integer $email_cond Conditions >= this will be reported via email
- * @param integer $pager_cond Conditions >= this will be reported via pager
- */
- function set_condition_thresholds($email_cond, $pager_cond) {
- $this->email_condition_threshold = $email_cond;
- $this->pager_condition_threshold = $pager_cond;
- }
- // ....................................................................
- /** Set the condition to stop checking monitor on. If this is set to something
- * other than COND_NONE, then the first time a monitor is raised to this
- * condition the checking process is stopped.
- * @param int $cond Condition to stop the checking process on.
- */
- function set_stop_on_condition($cond) {
- $this->stop_on_condition = $cond;
- } // set_stop_on_condition
- // ....................................................................
- /**
- * Raise a condition. The single parameter to this method is a monitor
- * object which will have had its check() method called. This contains the
- * resulting condition and any messages to notify.
- * @param object $monitor Monitor object which has had its check() method run
- */
- function raise_condition($monitor) {
- global $condition_desc;
- // Set overall condition, if escalated..
- if ($monitor->condition > $this->condition) {
- $this->condition = $monitor->condition;
- $this->message = $monitor->reportmsg();
- }
- // Report content..
- if ($monitor->reportmsg() != ""
- && $monitor->condition >= $this->email_condition_threshold) {
- $this->reportmsg .= "\r\n" . $condition_desc[$monitor->condition] . ": " . $monitor->reportmsg() . "\r\n";
- }
- // SMS message content..
- if ($monitor->smstxtmsg() != ""
- && $monitor->condition >= $this->pager_condition_threshold) {
- if ($this->smstxtmsg != "") $this->smstxtmsg .= " ";
- $this->smstxtmsg .= $monitor->smstxtmsg();
- }
- } // raise_condition
- // ....................................................................
- /** Method to send notification(s).. */
- function notify() {
- global $condition_desc;
- // Send to mailbox if above email threshold, and we have someone to
- // email to, and we have something to say..
- if ($this->condition >= $this->email_condition_threshold
- && $this->emailto != ""
- && $this->reportmsg != "") {
- $subject = "$this->name ($this->hostname): Monitor Status: " . $condition_desc[$this->condition];
- $headers = "From: $this->emailfrom\n";
- $headers .= "Reply-To: $this->emailfrom\n";
- $headers .= "Errors-To: $this->emailfrom\n";
- $headers .= "Content-Type: text/plain\n";
- $headers .= "X-Mailer: PHP/" . phpversion();
- mail($this->emailto, $subject, $this->reportmsg, $headers);
- }
- // Send to pager if above pager threshold, and we have someone to
- // email-page, and we have something to TXT..
- if ($this->condition >= $this->pager_condition_threshold
- && $this->emailpager != ""
- && $this->smstxtmsg != "") {
- $subject = "$this->name ($this->hostname): " . $condition_desc[$this->condition];
- $headers = "From: $this->emailfrom\n";
- mail($this->emailpager, $subject, $this->smstxtmsg, $headers);
- }
- } // notify
- // ....................................................................
- /** Iterate through all our monitors, checking in each case. Each
- * monitor will implement its own kind of checking and set its condition afterward.
- * We also check to see if we have to abort monitor checking on a given monitor condition.
- */
- function check_all_monitors() {
- // Iterate through our monitors..
- foreach ($this->monitors as $mon) {
- $mon->check();
- if (!in_array($mon->condition, $mon->suppressed_conditions)) {
- $this->raise_condition( $mon );
- if ($this->stop_on_condition != COND_NONE && $mon->condition == $this->stop_on_condition) {
- break;
- }
- }
- }
- } // check_all_monitors
- // ....................................................................
- /**
- * Check all monitors. Just iterate through them and raise the conditions
- * contained in the reports each one returns. After collecting the
- * details, we notify anyone which needs to know. If any condition
- * returned from a check is CRITICAL, then the rule is we stop processing
- * any further checks. Processing is done in order of definition of the
- * monitors added, so put your critical ones first.
- * NOTE: This method always performs a lock() before processing all the
- * monitors, then performs an unlock() at the end.
- */
- function check() {
- global $condition_desc;
- // Process if we are not in a 'skip' timeslot..
- $timeslot = $this->schedule->timeslot($this->tinow);
- switch ($timeslot) {
- case "skip":
- return RET_OK;
- break;
- case "warnings":
- $this->set_condition_thresholds(COND_WARN, COND_WARN);
- break;
- case "critical":
- $this->set_condition_thresholds(COND_CRITICAL, COND_CRITICAL);
- break;
- case "verbose":
- $this->set_condition_thresholds(COND_ALL, COND_CRITICAL);
- break;
- case "testing":
- $this->set_condition_thresholds(COND_ALL, COND_ALL);
- break;
- } // switch
- // Lock the monitor, if we are using a lockfile. If this
- // fails then it is regarded as a critical error..
- if ($this->use_lockfile) {
- if ($this->lock()) {
- $this->check_all_monitors();
- // Unlock monitor now..
- $this->unlock();
- }
- else {
- // Lock failed, notify them & die..
- $this->notify();
- }
- }
- // If no lockfile, just do it..
- else {
- $this->check_all_monitors();
- }
- // Notify people who want it..
- $this->notify();
- // Emit stuff if we have been asked to..
- if ($this->emit_status) {
- echo $condition_desc[$this->condition] . ": $this->message";
- }
- // Provide return code for caller..
- return $this->condition;
- } // check
- // ....................................................................
- /**
- * Add a time slot to the schedule. This requires two times as per 24hr
- * clock which define a time interval during the day, and gives it a
- * name. You can define any number of these. Timeslots have to be in HH:MM
- * format, separated by a dash "-", eg: '07:30-11:45'.
- * @param mixed $start Start time for timeslot, string datetime or Unix timestamp
- * @param mixed $end End time for timeslot, string datetime or Unix timestamp
- * @param string $name The name or ID associated with this timeslot.
- */
- function add_timeslot($start, $end, $name) {
- $this->schedule->add_timeslot($start, $end, $name);
- } // add_timeslot
- // ....................................................................
- /**
- * Add a new monitor. Eg. file_monitor, postgres_monitor etc. This just
- * stuffs the object in an array ready to be checked.
- * @param object $monitor New monitor object to add to our list
- */
- function add_monitor($monitor) {
- $this->monitors[] = $monitor;
- } // add_monitor
- } // monitor class
- // ----------------------------------------------------------------------
- ?>
Documentation generated by phpDocumentor 1.3.0RC3