#! /usr/bin/perl -w

# rsmf 1.1d by andrew wales <rsmf@meow.org.uk>

use POSIX qw(strftime);
use Time::Local;

%statusdefs = (
    '200' => 'OK',
    '206' => 'Partial Content',
    '301' => 'Moved Permanently',
    '302' => 'Moved Temporarily',
    '304' => 'Not Modified',
    '403' => 'Forbidden',
    '404' => 'Not Found',
    '500' => 'Internal Server Error',
);

for $month (0..11) {
    $monthname = strftime "%b", localtime(timelocal(0,0,0,1,$month,70));
    $mname{$monthname}=$month;
}

%statuses=();
%methods=();
%protocolvers=();
%useragents=();
%hostnames=();
%filenames=();
$numreqs=$totalsize=$idents=$remoteusers=$referers=0;
$earliest=time; $latest=0;
while (defined ($line=<>)) {
    chomp($line);

    next if ($line eq "");

    ($hostname, $ident, $remoteuser, $timestamp, $request, $status, $size, $referer, $useragent) =
            ($line =~ m/^(.*?) +(.*?) +(.*?) +(\[.*?\]) +\"(.*?)\" +(\d*) +([\d-]*) +\"(.*?)\" +\"(.*?)\"/);

    $numreqs++;

    $hostnames{$hostname}++;
    $idents++ unless ($ident eq "-");
    $remoteusers++ unless ($remoteuser eq "-");

    ($mday,$mon,$year,$hours,$min,$sec) =
        ($timestamp =~ m#^\[(\d+)/(\w+)/(\d+):(\d+):(\d+):(\d+).*$#);
    $etime = timelocal($sec,$min,$hours,$mday,$mname{$mon},$year-1900);

    $earliest = $etime if ($etime < $earliest);
    $latest = $etime if ($etime > $latest );

#   print "$request\n" if ($request =~ m/\/\//);

    ($method, $filename, $protocol) = ($request =~ m/^(\w+) ([^?]*).* (HTTP\/[\d\.]*)/);
    $methods{$method}++;
    $filenames{$filename}++;
    $protocolvers{$protocol}++;

    $statuses{$status}++;
    $totalsize+=$size unless ($size eq "-");
    $referers++ unless ($referer eq "-");
    $useragents{$useragent}++;
}


($user, $system, undef, undef) = times;

print "\n";

print "$totalsize total bytes served in $numreqs requests\n";

$timespan = ($latest-$earliest)/86400;
$timespan++ if ($timespan == 0);
printf ("requests per day: %0.2f\n", $numreqs/$timespan);

printf "seconds per request: %0.2f\n", (($latest-$earliest)/$numreqs);

print "average of ",int($totalsize/$numreqs)," bytes/req\n";
print "requests with valid idents: $idents\n";
print "requests with valid remote users: $remoteusers\n";
print "requests with referers: $referers ";
printf ("(%1.1f%%)\n", 100*($referers/$numreqs));

print "\nstatus summary:\n";
for (sort keys %statuses) {
    printf("\t%03d\t%d\t(%1.1f%%)", $_, $statuses{$_}, 100*($statuses{$_}/$numreqs));
    if ($statusdefs{$_}) {
        print "\t",$statusdefs{$_};
    }
    print "\n";
}

print "\nmethod summary:\n";
for (sort keys %methods) {
    printf ("\t%s\t%s\t(%1.1f%%)\n", $_, $methods{$_}, 100*($methods{$_}/$numreqs));
}

print "\nprotocol version summary:\n";
for (sort keys %protocolvers) {
    printf( "\t%s\t%s\t(%1.1f%%)\n", $_, $protocolvers{$_}, 100*($protocolvers{$_}/$numreqs) );
}

$uniquseragents=0;
for (keys %useragents) {
    $uniquseragents++;
}
print "\nno of unique user agents: $uniquseragents\n";
print "(avg reqs/agent: ",int($numreqs/$uniquseragents),")\n";

$uniqhostnames=0;
for (keys %hostnames) {
    $uniqhostnames++;
}
print "\nno of unique hostnames: $uniqhostnames\n";
print "(avg reqs/hostname: ",int($numreqs/$uniqhostnames),")\n";

$uniqfilenames=0;
for (keys %filenames) {
    $uniqfilenames++;
}
print "\nno of unique filenames in reqs: $uniqfilenames\n";

print "\n(${user}s, ${system}s, ";
printf "%0.2f lines/sec)\n", $numreqs/$user;