Setting up a maintenance page that automatically reports back a problem

June 18, 2011

It’s a good idea to theme the error pages on your site. It looks more professional and provides a better experience for your users. A lot of people have a soft spot for the Twitter fail whale. Some people really love it. You can also add functionality to help keep your visitors on the site when they get an error.

For example, 404 Page Not Found errors are much friendlier if they contain a search form. As usual with Drupal, there’s a module for that. On busy Drupal sites that get a lot of 404s, you can improve performance by using static 404 pages.

What not so many people do is theme the maintenance page. By default, if there is a problem connecting to the database, or if the site is down for some reason, Drupal 6 serves maintenance-page.tpl.php in the Minnelli theme. I recently had a phone call from a client who was freaking out because she saw the Druplicon and thought that a virus had taken control of her server. This made me realise it’s a good idea to override this. I also thought it would be good for me to find out as soon as possible that the site is down. Here’s how:

  1. Edit settings.php
    Uncomment the following lines (line numbers are from the standard 6.22 file) and enter the name of your theme.
    Line 203: $conf = array(  
    Line 215: #   'maintenance_theme' => 'minnelli',  
    Line 244:   ); 
  2. Create a maintenance-page.tpl.php in your theme
  3. Parse the XML of the error message
  4. // The XML parser won't complete if it comes across an hr element.
    $stripped = '<xml>' . str_replace('<hr />', '', $content) . '</xml>';
    $message = $_SERVER['HTTP_HOST']. ' is not accessible. ';
    $message .= 'The error message is as follows:\n';
    $parser = xml_parser_create();
    xml_parse_into_struct($parser,$stripped,$valuesarray);
    foreach ($valuesarray as $key => $value) {
      // database errors are surrounded by <em> tags, so fetch them
      if ($value['tag'] == 'EM') {
          $message .= $value['value'] . ' ';
      }
    }         
    xml_parser_free($parser);
  5. Check if the maintenance page has been accessed within the last 24 hours. If not, then it's a new problem, so send an email. If it has been accessed recently, skip sending the email, so as not to bombard the site admin with emails.
  6. // check when the last error was logged and update the log file
    $filename = 'log.txt';
    $logfile = fopen($filename, 'r+');
    $existing_date = fread($logfile, filesize($filename));
    rewind($logfile);
    $date = date('U');
    fwrite($logfile, $date);
    fclose($logfile);
            
    // if this is the first error for at least 24 hours, send an email if no email 
    if($date - $existing_date > (24 * 60 * 60)) {
       mail($to, $_SERVER['HTTP_HOST'] . ' error', $message);
    }