Zend - The PHP Company




HTTP

Add Code


Apache Web Server Log File Display Script  

Type: application
Added by: munkfish
Entered: 12/09/2001
Last modified: 09/12/2000
Rating: - (fewer than 3 votes)
Views: 8758
Parses an apache web server log file and displays each entry to the browser in html tables. Allows for filtering of output based on the 'status' field of the logfile entry (ie 404, 200, 304 etc). Still basic and obviously not recommended for users with low bandwidth and large logfiles(!). I did this because I couldn't find any existing scripts - plus I learnt a bit about log files in process. More than likely you will have to change the way the script extracts the logfile fields from each line, but at least the script gives you an idea how you could do it... I have a simpler version of the script which doesn't do filtering (just outputs two tables - 'success' and 'failure'(though failure includes 304 as well as 404 page requests)). This is perhaps easier to read - email me if you want it.


<?php
///////////////////////////////////////////////////////////////////////////
// file:    serverlog.php
///////////////////////////////////////////////////////////////////////////
// author:    jez hancock jezhanco@lineone.net
///////////////////////////////////////////////////////////////////////////
// description:
// Parse each line of an apache log file into it's component parts.
// Output the component parts into an html table for ease of viewing
// remotely via a browser.
// Sample log line is included below - 
// check your log file format and change script appropriately.
///////////////////////////////////////////////////////////////////////////

// Log file lines this script is based on.
// You will need to change the function parseLog_status() below if your logfile format is different.
// server4.carpediem-it.co.uk - - [08/Sep/2001:00:12:23 -0700] "GET /bands/viewband.php?bandID=21 HTTP/1.0" 200 1572 "http://sonictown.php4hosting.com/bands/listbands.php" "Lynx/2.8rel.2 libwww-FM/2.14" PID28905
//
// r113.easily.co.uk - - [08/Sep/2001:00:13:42 -0700] "GET /cgi-bin/cgiirc/irc.cgi HTTP/1.0" 404 216 "-" "PHP/4.0.3pl1" PID24054
// 
// host62-6-86-132.dialup.lineone.co.uk - - [08/Sep/2001:00:14:08 -0700] "GET /bands/viewband.php?bandID=21 HTTP/1.1" 200 1572 "http://sonictown.php4hosting.com/bands/listbands.php" "Mozilla/4.0 (compatible; MSIE 5.0; Windows 95; DigExt)" PID29244



// Full path to access log file on server:
$log="access_log";

// attempt to open the log file:
$lines=file($log) or die("Cannot open logfile");    

// page title:
$pageTitle="Apache Combined Server Log Viewer";

// total lines:
$totalLines=count($lines);

// will hold lines according to status field of log line:
$status_200=$status_404=$status_304=$status_other=array();

// will hold first and last times in log:
$firstTime=$lastTime="";

// START MAIN EXECUTION
###############
// Do the do:
parseLog_status($lines);
pageOpen();

// display results based on filter:
switch($filter){
    case 
"200":
        
doResults($status_200);
        break;
    case 
"304":
        
doResults($status_304);
        break;
    case 
"404":
        
doResults($status_404);
        break;
    case 
"other":
        
doResults($status_other);
        break;
    default:
        
doResults($status_200);
        
doResults($status_304);
        
doResults($status_404);
        
doResults($status_other);
        break;    
}
pageClose();
// END MAIN EXECUTION

####################################
/////////////
// FUNCTIONS
/////////////
####################################
/******************************************************
 * Function Name : pageOpen 
 *
 * Task : build the page
 *
 * Arguments : none
 *
 * Returns : none
 *
 ******************************************************/
function pageOpen() {
    global 
$status_200,$status_404,$status_304,$status_other,
            
$totalLines,$firstTime,$lastTime,$pageTitle,$log;
?>
<html>
<head>
<title><?php echo $pageTitle ?></title>
</head>

<body>
<h1>Reports for <?php echo($GLOBALS[SERVER_NAME]) ?></h1>
<h2>Access logfile: <?php echo $log ?> </h2>
<h2>Period: <?php print("<b>$firstTime</b> to <b>$lastTime</b>n"?></h2>
<?php    
    
print("<pre>n");
    print(
"404 pages (page not found):        ".count($status_404)."n");
    print(
"200 pages (successful request):    ".count($status_200)."n");
    print(
"304 pages: (page not changed):     ".count($status_304)."n");
    print(
"other pages:                       ".count($status_other)."n");
    print(
"Lines in Log:                      ".$totalLines."n");
    print(
"</pre>n");
?>
<form action="<?php print($GLOBALS[PHP_SELF])?>" method="POST">
Filter Results On Status: <select name="filter">
<option selected>select
<option value="200">200
<option value="404">404
<option value="304">304
<option value="other">Other
</select><input type="submit" name="submit" value="submit">
</form>
<?php
// end func


/******************************************************
 * Function Name : parseLog_status($lines) 
 *
 * Task : parse each logfile line into array depending on status
 *
 * Arguments : $lines - lines from logfile
 *
 * Returns : none
 *
 ******************************************************/
function parseLog_status($lines) {
    global 
$status_200,$status_404,$status_304,$status_other,$firstTime,$lastTime,$totalLines;

    
// inc counter - used to check if first or last item in logfile:
    
$count=0;

    
// parse each line:
    
foreach($lines as $line){
        
// trim spaces just in case:
        
$line=trim($line);

        
// split each line of log file at spaces - assumes log file fields are space delimited:
        
$fields=split(" "$line);

        
// SERVER SPECIFIC:
        // LAST FIELD IN $FIELDS IS PID, POP THIS OFF STACK:
        
array_pop($fields);

    
// server4.carpediem-it.co.uk - - [08/Sep/2001:00:12:02 -0700] "GET /bands/listbands.php HTTP/1.0" 200 1093 "-" "Lynx/2.8rel.2 libwww-FM/2.14" PID22731

        // and assign each field a readable name:
        
$host=$fields[0];
        
$ident=$fields[1];
        
$uname=$fields[2];
        
$dateLong=substr($fields[3], 1);

        
// get time strings:
        
$tmp=split(":"$dateLong);
        
array_shift($tmp);
        
$UStime=join(":"$tmp);
        
$UKhr=($tmp[0]+8)%24 ;
        
$UKhr=str_pad($UKhr2"0"STR_PAD_LEFT);
        
$UKtime$UKhr.":".$tmp[1].":".$tmp[2];

        
$dateOffset=substr($fields[4], 05);
        
$requestType=substr($fields[5], 1);
        
$requestURI=$fields[6];
        
$uaProtocol=substr($fields[7], 0, -1);
        
$status=$fields[8];
        
$bytes=$fields[9];
        
$referer=substr($fields[10], 1, -1);    
        
$ua=implode(" "array_slice($fields11));

        
// create array of fields for this line:
        
$result=array(
                        
$host,
                        
$ident,
                        
$uname,
                        
$UStime,
                        
$UKtime,
                        
$requestType,
                        
$requestURI,
                        
$uaProtocol,                            
                        
$bytes,
                        
$referer,
                        
$ua
        
);

        
// Push $result onto an array depending on $status:
        
switch($status){
            case 
"200":
                
array_push($status_200$result);
                break;
            case 
"304":
                
array_push($status_304$result);
                break;
            case 
"404":
                
array_push($status_404$result);
                break;
            default:
                
array_push($status_other$result);
                break;
        }

        
// check if first or last line - if so get start/end time for period
        
switch($count){
            case 
0:
                
// track first timestamp in log:
                
$firstTime=$dateLong;
                break;
            case 
$totalLines-1:
                
// track last timestamp in log:
                
$lastTime=$dateLong;
        }

        
// increment counter:
        
$count++;
    }
// end func




/******************************************************
 * Function Name : doResults($title, $results)
 *
 * Task : display a table of results/log lines
 *
 * Arguments : string $title - title of result table
                array $results - array of lines to show
 *
 * Returns : none
 *
 ******************************************************/
function doResults($results) {
    global 
$filter;
    
    isset(
$filter)?"":$filter="All";

    print(
"<h3>$filter Accesses</h3>n");

    if(!empty(
$results)){
        
// rpint out results:
?>
<br>
<table border="1" cellpadding="2" cellspacing="1">
<tr>
    <th> Host </th>
    <th> ID </th>
    <th> Usr </th>
    <th> Time: <br>US<br>(UK)</th>
    <th> Request </th>
    <th> URI </th>
    <th> Protocol </th>
    <th> Bytes </th>
    <th> Referer </th>
    <th> User Agent </th>
</tr>
    <?php
    
foreach($results as $result) {
    
?>
<tr>
    <td><?php echo $result[0]; ?></td>
    <td><?php echo $result[1]; ?></td>
    <td><?php echo $result[2]; ?></td>
    <td><?php echo $result[3]."<br>(".$result[4].")"?></td>
    <td><?php echo $result[5]; ?></td>
    <td><?php echo $result[6]; ?></td>
    <td><?php echo $result[7]; ?></td>
    <td><?php echo $result[8]; ?></td>
    <td><?php echo $result[9]; ?></td>
    <td><?php echo $result[10]; ?></td>
</tr>
        <?php
        
}
        print(
"</table>n");
    } else {
        print(
"No entries of type: $filter<br><br>n");
    }
// end func doResults($title, $results)


/******************************************************
 * Function Name : pageClose() 
 *
 * Task : close page - ending html tags
 *
 * Arguments : none
 *
 * Returns : none
 *
 ******************************************************/
function pageClose() {
    
?>
</body>
</html>
<?php
// end func pageClose()
?>


Usage Example


Sorry, no example for security reasons.


Rate This Script





Search



This Category All Categories