PHP
  Home arrow PHP arrow Page 4 - A Basic Monitoring Engine in PHP
Dev Shed Forums 
Administration  
AJAX  
Apache  
BrainDump  
DHTML  
Flash  
Java  
JavaScript  
Multimedia  
MySQL  
Oracle  
Perl  
PHP  
Practices  
Python  
Reviews  
Security  
Style-Sheets  
Web Services  
XML  
Zend  
Zope  
Forums Sitemap 
IBM® developerWorks 
Sun Developer Network 
Dedicated Servers 
E-Commerce Hosting 
Linux Web Hosting 
Managed Hosting 
Small Business Hosting 
Moblin 
JMSL Numerical Library 
VPS Hosting 
Weekly Newsletter

 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid 
Request Media Kit
Contact Us 
Site Map 
Privacy Policy 
Support 
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
PHP

A Basic Monitoring Engine in PHP
By: Sams Publishing
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: 4 stars4 stars4 stars4 stars4 stars / 5
    2006-09-14

    Table of Contents:
  • A Basic Monitoring Engine in PHP
  • Giving Up Privileges
  • Combining What You've Learned: Monitoring Services
  • Sample ServiceLogger Process

  • Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      Del.ici.ous Digg
      Blink Simpy
      Google Spurl
      Y! MyWeb Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article
     
     
    ADVERTISEMENT


    A Basic Monitoring Engine in PHP - Sample ServiceLogger Process


    (Page 4 of 4 )

    Here is a sample ServiceLogger process that sends an email to an on-call person when a service goes down:

    class EmailMe_ServiceLogger implements
    ServiceLogger { public function log_service_event(ServiceCheck
    $service) { if($service->current_status ==
    ServiceCheck::FAILURE) { $message = "Problem with
    {$service->description()}\r\n"; mail('oncall@example.com', 'Service Event',
    $message); if($service->consecutive_failures() > 5) { mail('oncall_backup@example.com', 'Service
    Event', $message); } } } public function log_current_status(ServiceCheck
    $service) { return; } }

    If the failure persists beyond the fifth time, the process also sends a message to a backup address. It does not implement a meaningful log_current_status() method.

    You implement a ServiceLogger process that writes to the PHP error log whenever a service changes status as follows:

    class ErrorLog_ServiceLogger implements
    ServiceLogger { public function log_service_event(ServiceCheck
    $service) { if($service->current_status() !==
    $service->previous_status()) { if($service->current_status() ===
    ServiceCheck::FAILURE) { $status = 'DOWN'; } else { $status = 'UP'; } error_log("{$service->description()} changed
    status to $status"); } } public function log_current_status(ServiceCheck
    $service) { error_log("{$service->description()}: $status"); } }

    The log_current_status() method means that if the process is sent a SIGUSR1 signal, it dumps the complete current status to your PHP error log.

    The engine takes a configuration file like the following:

    <config>
    <loggers>
    <logger>
    <id>errorlog</id>
    <class>ErrorLog_ServiceLogger</class>
    </logger>
    <logger>
    <id>emailme</id>
    <class>EmailMe_ServiceLogger</class>
    </logger>
    </loggers>
    <services>
    <service>
    <class>HTTP_ServiceCheck</class>
    <params>
    <description>OmniTI HTTP Check</description>
    <url>http://www.omniti.com</url>
    <timeout>30</timeout>
    <frequency>900</frequency>
    </params>
    <loggers>
    <logger>errorlog</logger>
    <logger>emailme</logger>
    </loggers>
    </service>
    <service>
    <class>HTTP_ServiceCheck</class>
    <params>
    <description>Home Page HTTP Check</description>
    <url>http://www.schlossnagle.org/~george</url>
    <timeout>30</timeout>
    <frequency>3600</frequency>
    </params>
    <loggers>
    <logger>errorlog</logger>
    </loggers>
    </service>
    </services>
    </config>

    When passed this XML file, the ServiceCheckRunner constructor instantiates a logger for each specified logger. Then it instantiates a ServiceCheck object for each specified service.


    Note - The constructor uses the Reflection_Class class to introspect the service and logger classes before you try to instantiate them. This is not necessary, but it is a nice demonstration of the new Reflection API in PHP 5. In addition to classes, the Reflection API provides classes for introspecting almost any internal entity (class, method, or function) in PHP.


    To use the engine you've built, you still need some wrapper code. The monitor should prohibit you from starting it twice—you don't need double messages for every event. It should also accept some options, including the following:

    Option

    Description

    [-f]

    A location for the engine's configuration file, which defaults to monitor.xml.

    [-n]

    The size of the child process pool the engine will allow, which defaults to 5.

    [-d]

    A flag to disable the engine from daemonizing. This is useful if you write a debugging ServiceLogger process that outputs information to stdout or stderr.


    Here is the finalized monitor script, which parses options, guarantees exclusivity, and runs the service checks:

    require_once "Service.inc";
    require_once "Console/Getopt.php";
    $shortoptions = "n:f:d";
    $default_opts = array('n' => 5, 'f' =>
    'monitor.xml'); $args = getOptions($default_opts, $shortoptions,
    null); $fp = fopen("/tmp/.lockfile", "a"); if(!$fp || !flock($fp, LOCK_EX | LOCK_NB)) { fputs($stderr, "Failed to acquire lock\n"); exit; } if(!$args['d']) { if(pcntl_fork()) { exit; } posix_setsid(); if(pcntl_fork()) { exit; } } fwrite($fp, getmypid()); fflush($fp); $engine = new ServiceCheckRunner($args['f'],
    $args['n']); $engine->loop();

    Notice that this example uses the custom getOptions() function defined earlier in this chapter to make life simpler regarding parsing options.

    After writing an appropriate configuration file, you can start the script as follows:

    > ./monitor.php -f /etc/monitor.xml 

    This daemonizes and continues monitoring until the machine is shut down or the script is killed.

    This script is fairly complex, but there are still some easy improvements that are left as an exercise to the reader:

    • Add a SIGHUP handler that reparses the configuration file so that you can change the configuration without restarting the server.

    • Write a ServiceLogger that logs to a database for persistent data that can be queried.

    • Write a Web front end to provide a nice GUI to the whole monitoring system.

    Further Reading

    There are not many resources for shell scripting in PHP. Perl has a much longer heritage of being a useful language for administrative tasks. Perl for Systems Administration by David N. Blank-Edelman is a nice text, and the syntax and feature similarity between Perl and PHP make it easy to port the book's Perl examples to PHP.

    php|architect, an electronic (and now print as well) periodical, has a good article by Marco Tabini on building interactive terminal-based applications with PHP and the ncurses extension in Volume 1, Issue 12. php|architect is available online at http://www.phparch.com.

    Although there is not space to cover it here, PHP-GTK is an interesting project aimed at writing GUI desktop applications in PHP, using the GTK graphics toolkit. Information on PHP-GTK is available at http://gtk.php.net.

    A good open-source resource monitoring system is Nagios, available at http://nagios.org. The monitoring script presented in this chapter was inspired by Nagios and designed to allow authoring of all your tests in PHP in an integrated fashion. Also, having your core engine in PHP makes it easy to customize your front end. (Nagios is written in C and is CGI based, making customization difficult.)


    DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware.

       · This article is an excerpt from the book "Advanced PHP Programming," published by...
     

    Buy this book now. This article is excerpted from chapter five of the book Advanced PHP Programming, written by George Schlossnagle (Sams; ISBN: 0672325616). Check it out today at your favorite bookstore. Buy this book now.

       

    PHP ARTICLES

    - Paginating Database Records with the Code Ig...
    - HTTP Headers in Web Development
    - Project Management: Administration
    - Building a Database-Driven Application with ...
    - User Authentication for a Project Management...
    - Introduction to the CodeIgniter PHP Framework
    - Adding Users for a Project Management Applic...
    - Migrating Class Code for a MIME Email to PHP...
    - Login and Logout Authentication for a Projec...
    - Composing Messages in HTML for MIME Email wi...
    - Project Management: Authentication
    - A Better Way to Determine MIME Types for MIM...
    - Project Management Overview
    - Handling Attachments in MIME Email with PHP
    - Completing the Project Management Application





    © 2003-2008 by Developer Shed. All rights reserved. DS Cluster 5 hosted by Hostway