=^.^=

Crossfire Ping Monitoring Part 2: Collecting the Data

karma

In the previous installment of this series we set up a ping monitoring script on each of our servers set up to ping every other server in the pool. For this example the logs are made available for download via HTTP.

We're going to re-use the HTTP GET class I posted earlier this week: Portable PHP HTTP(S) GET Request with HTTP Basic Authentication.

Create two tables, one will contain our hosts and one will contain the logs:

CREATE TABLE `hosts` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `ip` varchar(64) NOT NULL,
  `location` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
);

INSERT INTO `hosts` VALUES (1,'Waveride','10.10.10.10','http://my.vps.net/crossfire.log'),(2,'VPS Database','10.10.10.11','http://my.vps.net/crossfire.log'),(3,'Iniz','10.10.10.12','http://my.vps.net/crossfire.log'),(4,'Prometeus','10.10.10.13','http://my.vps.net/crossfire.log'),(5,'domVPS','10.10.10.14','http://my.vps.net/crossfire.log');


CREATE TABLE `logs` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `date` int(11) NOT NULL,
  `collected` int(11) NOT NULL,
  `host` int(11) NOT NULL,
  `ip` varchar(64) NOT NULL,
  `packets` int(11) NOT NULL,
  PRIMARY KEY (`id`)
);

Now we're going to create a cron script that will fetch the data, parse it, and put it into the database. This is a very inefficient script; I'm sure you can find a better way of running the checks. We're going to run through the entire log file every time we fetch it so if "headquarters" isn't able to connect to the VPS for a while we won't miss any entries. A better way of doing this would be to find the last entry from that host in the logs then skip all of the crossfire.log entries to that point.

<?php

$sql_host = '';
$sql_user = '';
$sql_pass = '';
$sql_base = '';

$sql_h = mysql_pconnect($sql_host, $sql_user, $sql_pass);
$sql_d = mysql_select_db($sql_base, $sql_h);

class HTTPRequest
{
    var $_fp;          // HTTP socket
    var $_url;         // full URL
    var $_host;        // HTTP host
    var $_protocol;    // protocol (HTTP/HTTPS)
    var $_uri;         // request URI
    var $_port;        // port
    var $_user;        // HTTP Basic Auth User
    var $_pass;        // HTTP Basic Auth Password
   
    // scan url
    function _scan_url()
    {
        $req = $this->_url;
       
        $pos = strpos($req, '://');
        $this->_protocol = strtolower(substr($req, 0, $pos));
       
        $req = substr($req, $pos+3);
        $pos = strpos($req, '/');
        if($pos === false)
            $pos = strlen($req);
        $host = substr($req, 0, $pos);
       
        if(strpos($host, ':') !== false)
        {
            list($this->_host, $this->_port) = explode(':', $host);
        }
        else
        {
            $this->_host = $host;
            $this->_port = ($this->_protocol == 'https') ? 443 : 80;
        }
       
        $this->_uri = substr($req, $pos);
        if($this->_uri == '')
            $this->_uri = '/';
    }
   
    // constructor
    function HTTPRequest($url, $user='', $pass='')
    {
        $this->_url = $url;
        $this->_scan_url();
        $this->_user = $user;
        $this->_pass = $pass;
    }
   
    // download URL to string
    function DownloadToString()
    {
        $crlf = "\r\n";
       
        // generate request
        $req = 'GET ' . $this->_uri . ' HTTP/1.0' . $crlf
            .    'Host: ' . $this->_host . $crlf;
            if(!empty($this->_user))
                 $req .= "Authorization: Basic " . base64_encode($this->_user . ':' . $this->_pass) . $crlf;
       $req .= $crlf;
       
        // fetch
        $this->_fp = fsockopen(($this->_protocol == 'https' ? 'ssl://' : '') . $this->_host, $this->_port);
        fwrite($this->_fp, $req);
        while(is_resource($this->_fp) && $this->_fp && !feof($this->_fp))
            $response .= fread($this->_fp, 1024);
        fclose($this->_fp);
       
        // split header and body
        $pos = strpos($response, $crlf . $crlf);
        if($pos === false)
            return($response);
        $header = substr($response, 0, $pos);
        $body = substr($response, $pos + 2 * strlen($crlf));
       
        // parse headers
        $headers = array();
        $lines = explode($crlf, $header);
        foreach($lines as $line)
            if(($pos = strpos($line, ':')) !== false)
                $headers[strtolower(trim(substr($line, 0, $pos)))] = trim(substr($line, $pos+1));
       
        // redirection?
        if(isset($headers['location']))
        {
            $http = new HTTPRequest($headers['location']);
            return($http->DownloadToString($http));
        }
        else
        {
            return($body);
        }
    }
}

$h_result = mysql_query("select * from `hosts` order by `id` desc");
while($h_object = mysql_fetch_object($h_result))
{
	$r = new HTTPRequest($h_object->location);
	$response = trim($r->DownloadToString());

	$lines = explode("\n", $response);
	foreach($lines as $line)
	{
		$line = str_replace('  ', ' ', $line);
		$e = explode(' ', $line);
		$date = strtotime($e[0].' '.$e[1].' '.$e[2].' '.$e[3].' '.$e[4].' '.$e[5]);
		$ip = mysql_real_escape_string($e[6]);
		$packets = (int) $e[9];
		$check_result = mysql_query("select * from `logs` where `host` = '$h_object->id' and `date` = '$date' and `ip` = '$ip'");
		if(mysql_num_rows($check_result) == 0)
		{
			mysql_query("insert into `logs` (`date`, `collected`, `host`, `ip`, `packets`) values ('$date', '".time()."', '{$h_object->id}', '$ip', '$packets')");
		}
	}
}

?>

Drop this into your crontab to make it collect every so often, I'm going with 5 minutes here but it doesn't matter if you only collect the logs daily.

*/5 * * * * apache /usr/bin/php /path/to/import.php

Comments

There are no comments for this item.