picture of Mattias Nilsson
What to do if your domain host does not allow you to read the server log for your domain, stopping you from analyzing your website traffic the way you'd like to? Well, create your own logfile of course !
I recently set up a new domain (coolt.nu, it's in Swedish, you might not want to visit it :) and faced the problem that my domain host wouldn't generate the statistics I wanted. I also found that they would not let me read/process the logfile myself. Darn shame, but I did find a second-best solution: I created my own logfile. It didn't give me quite as much information as I would have wanted, but I it had to be enough.
The only thing you can log from within PHP is actual hits, no errors, no '304 Not Modified' and no 'Internal Server Error' entries can be generated, as your code will have to be executed to be able to generate logfile entries. This was not a problem to me, because all I wanted to know was which pages on my site got the actual hits, and when they occurred.
I ended up with a small script that extracted all the appropriate environment variables, put them together as a Common Logfile Format entry and wrote it to a file. Good enough for me, because then I could use any logfile analyzer that supports that format (and there's lots of those).
The next problem I ran into was that I would get inacurate (or no) filesize specifications in the log because it's not possible to find out how much content that gets generated from your PHP script. I ended up recording the original size of the PHP3 file, as this would at least give me a hint about how much data is actually sent each day/week/month (it's an option - use it or don't).
Well, not much more to say except "Here's the code, use it!" Just include this file the first thing you do in all your PHP scripts.

<?php

/*
 * Common Logfile Format script.
 * 
 * Author: Mattias Nilsson <mattias_at_coolt.nu>
 *
 */ 

/* User definable variables */ 
$logfile =  "clf.log";    /* Filename of log to write to */ 
$timezone =  "+0100";     /* Timezone correction */ 
$lookup_size true;     /* Set to true to enable filesize lookup */ 
$document_root =  "/usr/local/apache/share/htdocs";

/* A note about the lookup_size directive:
 * This will make this script lookup the size of the original file on disk,
 * which may or may not be the same amount of data sent to the client.
 * It does give you a hint though..
 * Oh, you have to set $document_root aswell if this should work..
 */ 

function write_to_log($str) {
    if(
$fd = @fopen($GLOBALS"logfile"],  "a")) {
    
fputs($fd$str);
    
fclose($fd);
    }
}

function 
get_var($name,$default) {
    if(
$var getenv($name)) {
    return 
$var;
    } else {
    return 
$default;
    }
}

if(
$remote_host get_var"REMOTE_HOST"false)) {
    
$remote_host get_var"REMOTE_ADDR",  "-");
}
$remote_user get_var"REMOTE_USER",  "-");
$remote_ident get_var"REMOTE_IDENT",  "-");
$server_port get_var"SERVER_PORT"80);
if(
$server_port!=80) {
    
$server_port =  ":" $server_port;
} else {
    
$server_port =  "";
}
$server_name get_var"SERVER_NAME",  "-");
$request_method get_var"REQUEST_METHOD",  "GET");
$request_uri get_var"REQUEST_URI",  "");
$user_agent get_var"HTTP_USER_AGENT",  "");
if(
$lookup_size == true && $document_root) {
    
$filename ereg_replace"\?.*",  ""$request_uri);
    
$filename =  "$document_root$filename";
    if(!
$size filesize($filename)) {
    
$size 0;
    }
} else {
    
$size 0;
}

$date gmdate"d/M/Y:H:i:s");
$log "$remote_host $remote_ident $remote_user [$date $timezone] \"".
    
"$request_method http://$server_name$server_port$request_uri\" 200 $size\n";

write_to_log($log);

?>
--Mattias