Location: PHPKode > scripts > WAMP Error Log Watcher > wawa/wawa.php
  Copyright, © 2013, jReply LLC
  This code is made available under the terms of the
  MIT License - http://opensource.org/licenses/MIT
  This script returns the ten latest errors in your
  Apache Error log. 
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache'); 

$lfile = $_SERVER['DOCUMENT_ROOT']."/../logs/apache_error.log";//LOCATION OF ERROR LOG

 $lfile is the location of the Apache error log file.
 For a standard WAMP installation on windows the default setting
 above should work just fine. For a non-standard installation you 
 should edit it.
 If you use this on a real LAMP server the error log file path
 will have to be altered significantly. There are many points to note
 1. If you are running your own server, or a VM that gives 
     you complete control you are OK
 2. If you are running a cheap shared hosting account it is almost certain
    that you will not have the privileges requried to run this script
 3. The script uses PHP_EOL which should make it platform independent but
    it is best to check nevertheless	
 4. You will have to examine two things
    a. open_basedir restrictions in effect that might stop PHP from reaching the
       folder where the log file is stored.
    b. Read-Write-Execute (the ususal 644, 755, etc) privileges for each of the
       ancestor folders all the way up to the folder containing the error log file  	
 5. There is a security issue here.  One could take the view that you should never
    have to run such a script on a REAL server since all your scripts should be perfect
    and never trigger any error log entries.  Yeah, right! In the interests of 
    adequately protecting your server consider doing one or more of the following

    a. Force SSL access to the folder from which this script is served up
    b. Enforce http security (in the form of a username + password) for the
       folder from which this script is served up
    c. Use an obscure name containing mixed case letters, numbers and some
       non-alphanumeric characters for the name of the folder from which this
       script is served up.  Remember OBSCURITY !== SECURITY


function calcLP($fh,$fsize)
  Starting from the end of the error log file
  read 128 byte chunks. Cumulatively count the 
  number of PHP Warning, PHP Notice,PHP Fatal Error 
  and PHP Parse Error strings. Once this count reaches
  $numErrs stop.
  Return the position from the end of the error log
  starting from which $numErrs errors can be found 
 global $numErrs;
 $fpos = -128;
 $count = 0;
 while (($count < $numErrs) && ($fsize > -$fpos))
  $str = fread($fh,-$fpos);
	$count = substr_count($str,'PHP Warning:') + substr_count($str,'PHP Notice:') +
	         substr_count($str,'PHP Fatal error:') + substr_count($str,'PHP Parse error:');
	$fpos -= 128;
 $fpos = -$fpos;
 $fpos = ($fpos > $fsize)?$fsize:$fpos;
 return $fpos;

$fh = fopen($lfile,'r');
if (false === $fh)
 echo "data: Unable to open log file" . PHP_EOL;
 echo "retry:86400".PHP_EOL;
 echo PHP_EOL;
$fsize = filesize($lfile);
//open the error log and find its size.

$lsize = (isset($_SESSION['lsize']))?intval($_SESSION['lsize']):-1;
$changed = ($lsize != $fsize);
$_SESSION['lsize'] = $fsize;
 The size of the error log file when this script was
 last run is stored as a session variable. If the size
 has not changed we conclude that there are no new
 errors and terminate the script immediately

if (!$changed)

$lpos = calcLP($fh,$fsize);
//$lpos contains the position from the end where reading should begin

$str = fread($fh,$lpos);
$lines = explode(PHP_EOL,$str);
/*read the relevant bit of the error log
  if this script is used on a LAMP installation
  rather than on WAMP verify that PHP_EOL is
  working as expected
$out = '';

if (1 == $changed)
 foreach($lines as $line)
  $flag = (false === strpos($line,'PHP Notice:')) && (false === strpos($line,'PHP Warning:')) &&
         (false === strpos($line,'PHP Fatal error:')) && (false === strpos($line,'PHP Parse error:'));
  if ($flag) continue;
  //ignore lines not containing PHP NOTICE|WARNING|PARSE ERROR|FATAL ERROR

  $pos = strpos($line,'referer:');
  $line = (false === $pos)?$line:substr($line,0,$pos);
  //if there isa referer ignore the bit starting from referer
  $pos = strpos($line,']');
  $date = (false === $pos)?'Unknown date':substr($line,1,$pos - 1);
  //there should normally be a date but just in case... 

  $pos = strpos($line,'PHP');
  $line = substr($line,$pos);//get the bit starting at PHP...

  $colon = strpos($line,':');
  $reason = substr($line,0,$colon);
  //the subtring prior to the first : identifies the type of error

  $olp = strpos($line,'on line');
  $inp = strpos($line,' in ');

  $msg = substr($line,$colon,$inp - $colon);
  //the bit between the colon & the following ' in ' is the actual error message

  $inp += 4;
  $inp = substr($line,$inp,$olp - $inp);//identify the script causing the error

  $cpos = strrpos($line,',');
  $olp += 8;//skip past the 'on line ' bit
  $olp = (false === $cpos)?substr($line,$olp):substr($line,$olp,$cpos - $olp);
  //if there is extra text after the line  number ignore it

  switch ($reason)
   case 'PHP Notice':$cause = " class='trig'>N";break;
   case 'PHP Warning':$cause = " class='warn'>W";break;
   case 'PHP Fatal error':$cause = " class='fatal'>F";break;
   case 'PHP Parse error':$cause = " class='parse'>P";break;
   default:$cause = 'O';//should not normally happen
  $out .= "<h1>$date</h1>";
  $out .= "<div class='line'><span$cause</span> $msg <span class='olp'>L:$olp</span> of <span class='inp'> $inp</span></div>";
  //format the result

$out = json_encode(array('ticks'=>10000,'bdy'=>$out));
echo "data: $out" . PHP_EOL;
echo "retry:10000".PHP_EOL;
echo PHP_EOL;
Return current item: WAMP Error Log Watcher