Login   Register  
PHP Classes
elePHPant
Icontem

File: as_dbserver_check.php

Recommend this page to a friend!
Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of Alexander Selifonov  >  Database servers down alarm  >  as_dbserver_check.php  >  Download  
File: as_dbserver_check.php
Role: Class source
Content type: text/plain
Description: main class module
Class: Database servers down alarm
Send alarm messages when databases are down
Author: By
Last change: small changes
Date: 2009-06-23 02:26
Size: 8,867 bytes
 

Contents

Class file image Download
<?php
/**
* @package as_dbserver_check.php - checking DBMS server(s) live state
* @version 1.00.001
* first creation date: 17.06.2009 (dd.mm.yyyy)
* modified 23.06.2009
* @Author Alexander Selifonov,  <alex@selifan.ru>
* @link http://www.selifan.ru
**/
if(!defined('DBTYPE_MYSQL')) define('DBTYPE_MYSQL',1);
if(!
defined('DBTYPE_MSQL')) define('DBTYPE_MSQL',2);
if(!
defined('DBTYPE_POSTGRESQL')) define('DBTYPE_POSTGRESQL',3);
if(!
defined('DBTYPE_ORACLE')) define('DBTYPE_ORACLE',4);
if(!
defined('DBTYPE_MSSQL')) define('DBTYPE_MSSQL',5);
if(!
defined('DBTYPE_DB2')) define('DBTYPE_DB2',6);

class 
CDbChecker {
  var 
$title '';
  var 
$servers = array();
  var 
$ajaxflags = array();
  var 
$homefolder './'# here all 'flag' files for last fb state will be auto-created.
  
var $adminemail ''# primary Admin email(s), all alarms will be sent to this addr.
  
var $ispemail ''# email of your ISP support, to notify them about DB problems
  
var $isptext ''# if message is sent to ISP, Here must be Your text containing client name and/or ID
  
var $emailcharset '';
  var 
$sms_engine ''# sending SMS engine can be attached (external function name !)
  
var $b_errors false;
  var 
$othereason 0# 1 if connect failked due to other reason (wrong login/pass etc) but server is online
  
function CDbChecker($title=''$homefolder=''$isptext='') {
    
$this->title=$title;
    if(
$homefolder!=''$this->homefolder $homefolder;
    
$this->isptext $isptext;
  }
  
/**
  * adds server description to check state
  *
  * @param integer $dbtype (see DBTYPE_xxx constants)
  * @param string $address hostname, connection string (depends on db type)
  * @param string $login
  * @param string $passwd
  * @param string $connfunc explicit function that tries to connect to DB server (used if dbtype undefined)
  * @param string $downtime "hh:mm-hh:mm" - known time interval for database maintenance, when it CAN be down
  */
  
function AddServer($dbtype,$address,$login='',$passwd='',$connfunc=false,$downtime='') {
    
$this->servers[] = array('dbtype'=>$dbtype'address'=>$address,'login'=>$login,'password'=>$passwd'connfunc'=>$connfunc,'downtime'=>$downtime);
  }
  function 
SetEmails($adminemail,$ispemail=''$emailcset='') {
    
$this->adminemail=$adminemail;
    
$this->ispemail=$ispemail;
    if(!empty(
$emailcset)) $this->emailcharset=$emailcset;
  }
  function 
SetSMSEngine($smsfunc='') { $this->sms_engine $smsfunc; }
  
/**
  * main method, it checks all DB servers for 'alive' state and sends alarm merssage if anyone is down.
  *
  */
  
function CheckDbState() { #<2>
    
$alarmtext '';
    
$oktext '';
    
$dbtypestr 'undefined type';
    foreach(
$this->servers as $no=>$srv) { #<3-foreach>
      
$address $srv['address'];
      
$downtime $srv['downtime'];
      
$this->othereason false;
      if(!empty(
$downtime)) {
        
$allow_arr is_array($downtime)? $downtimesplit('-',$downtime);
        
$now date('H:i');
        if(
count($allow_arr)>&& $now>=$allow_arr[0] && $now<=$allow_arr[1])
          echo 
"Database [$address] can be in maintenance mode ({$allow_arr[0]}-$allow_arr[1]), checking skipped...<br />\n";
          continue; 
# registered down time. Don't check
      
}
      
$login $srv['login'];
      
$lnk false;
      
$dberr '';
      switch(
$srv['dbtype']) {

        case 
DBTYPE_MYSQL:
          
$dbtypestr='MySQL';
          
$lnk = @mysql_connect($address$srv['login'],$srv['password']);
          if(
is_resource($lnk)) mysql_close($lnk);
          else 
$dberr = @mysql_error();
          if(
strpos(strtolower($dberr),"can't connect to")===false$this->othereason=true;
          break;

        case 
DBTYPE_MSQL:
          
$dbtypestr='MSQL';
          
$lnk = @msql_connect($address$srv['login'],$srv['password']);
          if(
is_resource($lnk)) msql_close($lnk);
          else 
$dberr = @msql_error();
          
# TODO: define sql errors that not related to server down, an so make $this->othereason=true
          
break;

        case 
DBTYPE_MSSQL:
          
$dbtypestr='MS SQL';
          if(
function_exists('mssql_connect')) {
            
$lnk=mssql_connect($address$srv['login'],$srv['password']);
            if(
is_resource($lnk)) mssql_close($lnk);
          }
          elseif(!empty(
$srv['connfunc']) && function_exists($srv['connfunc'])) {
            
$lnk = @call_user_func($srv['connfunc'], $address,$srv['login'],$srv['password']);
          }
          else continue; 
# extension not loaded, just skip this check
          
break;

        case 
DBTYPE_DB2:
          
$dbtypestr='DB2';
          
$lnk = @db2_connect($address$srv['login'],$srv['password']);
          if(
is_resource($lnk)) db2_close($lnk);
          break;

        case 
DBTYPE_ORACLE:
          
$dbtypestr='Oracle';
          if(
function_exists('oci_connect')) {
            
$lnk= @oci_connect $srv['login'],$srv['password'],$address);
            if(
is_resource($lnk)) oci_close($lnk);
          }
          elseif(
function_exists('ocilogon')) {
            
$lnk= @ocilogon$srv['login'],$srv['password'],$address);
            if(
is_resource($lnk)) ocilogoff($lnk);
          }
          elseif(!empty(
$srv['connfunc']) && function_exists($srv['connfunc'])) {
            
$lnk = @call_user_func($srv['connfunc'], $address,$srv['login'],$srv['password']);
          }
          else continue;
          break;

        case 
DBTYPE_POSTGRESQL:
          
$dbtypestr='PostgreSQL';
          if(
strpos($address,'=')) $addrstrk $address# user passed full connect string: host=XXX user=xxx ..."
          
else {
            
$addrstk '';
            if(
$address$addrstrk.=" host=$address";
            if(!empty(
$srv['login'])) $addrstrk.= ' user='.$srv['login'];
            if(!empty(
$srv['password'])) $addrstrk.= ' password='.$srv['password'];
          }
          
$lnk = @pg_connect($addrstk);
          if(
is_resource($lnk)) pg_close($lnk);
           break;

        default: 
# other DB types must have user defined function for making connect
          
if(!empty($srv['connfunc']) && function_exists($srv['connfunc'])) {
            
$lnk = @call_user_func($srv['connfunc'], $address,$srv['login'],$srv['password']);
          }
          break;
      }
      
$flagfile $this->homefolder."dbserver-down-$no.log";
      
$laststate = !file_exists($flagfile); # true if last state was 'alive', and false if it was dead
      
if($laststate) {
        if(empty(
$lnk)) { # DB server state changed from "alive" to "dead", alarm it !
          
$this->b_errors=true;
          
$fout fopen($flagfile,'w');
          if(
$fout) {
            
fwrite($fout"Server [$address] inaccessible, ".date('Y-m-d H:i'));
            
fclose($fout);
          }
          
$eventxt = ($this->othereason)? 'inaccessible with current credencials':'DOWN';
          
$alarmtext .= "Database Server [$address] is $eventxt, detected time: ".date('Y-m-d H:i').",\n  reason: ($dberr).\n";
        }
      }
      else { 
# previous state - "DEAD",
        
if($lnk) { # DB server state changed from "dead" to "alive"
          
@unlink($flagfile);
          
$oktext .= "Database Server [$address] become alive, detected time: ".date('Y-m-d H:i')."\n";
        }
        else 
$this->b_errors=true;
      }
    } 
#<3-foreach>

    
if(!empty($alarmtext)) { #<3>
      
$headers "Priority:High\r\nX-Mailer: as_dbserver_check";
      if(!empty(
$this->emailcharset)) $headers.="\r\nContent-Type:text/plain; charset=\"{$this->emailcharset}\"";
      
$res1 $res2 'xx';
      if(
$this->adminemail$res1=@mail($this->adminemail,'DB server(s) down/inaccessible !',($this->title."\n".$alarmtext),$headers);
      if(
$this->ispemail && !$this->othereason$res2=@mail($this->ispemail,'DB server(s) down !',($this->isptext."\n".$alarmtext),$headers);
      echo 
"$alarmtext<br />\nemail sending result: {$this->adminemail}: ($res1{$this->ispemail}:($res2)";

      
# call SMS sending function :
      
if(!empty($this->sms_engine) && function_exists($this->sms_engine)) call_user_func($this->sms_engine,$alarmtext);
    } 
#<3>

    
if(!empty($oktext) ) { #<3>
      
if(!empty($this->adminemail)) $res = @mail($this->adminemail,'DB server(s) up',$oktext,$headers);
      echo 
"$oktext<br />\nemail sending result: {$this->adminemail}: ($res)";

      
# call SMS sending function :
      
if(!empty($this->sms_engine) && function_exists($this->sms_engine)) call_user_func($this->sms_engine,$oktext);
    } 
#<3>

    
if(empty($alarmtext) && empty($oktext))
      echo 
"No changes in servers state, ".($this->b_errors?'Some servers are DOWN':'Everything is OK')."<br />\n";

    return 
$this->b_errors;
  } 
#<2>
# CDbChecker class end
?>