You are on page 1of 2

Download the source code for the HTTP log analyzer First, let's decide what we want to do with

our analyzer. Instead of showing all of the reports we generate at once, we'll show only those the user selects. Second, we'll let the user choose whether each report shows the entire list of items, or the top 10, 20 or 50 sorted by access count. We'll use a form such as this for our user interface:
<FORM ACTION="/cgi-bin/http-report.pl" METHOD=POST> <P>Select the reports you want to see:</P> <P><INPUT <INPUT <INPUT <INPUT </P> TYPE=checkbox TYPE=checkbox TYPE=checkbox TYPE=checkbox NAME=report NAME=report NAME=report NAME=report VALUE=url>URLs requested<BR> VALUE=status>Status codes<BR> VALUE=hour>Requests by hour<BR> VALUE=type>File types

<P><SELECT NAME="number"> <OPTION VALUE="ALL">Show all <OPTION VALUE="10">Show top 10 <OPTION VALUE="20">Show top 20 <OPTION VALUE="50">Show top 50 </SELECT></P> <INPUT TYPE=submit VALUE="Show report"> </FORM>

(Remember that you may need to change the URL!) We're sending two different types of form item in this HTML page. One is a series of checkbox widgets, which set values for the form item report. The other is a single dropdown list which will assign a single value to number: either ALL, 10, 20 or 50. Take a look at the original HTTP log analyzer. We'll start with two simple changes. First, the original program gets the filename of the usage log from a command-line argument:
# We will use a command line argument to determine the log filename. $logfile = $ARGV[0];

We obviously can't do that now, since the Web server won't allow us to enter a command line for our CGI program! Instead, we'll hard-code the value of $logfile. I'll use "/var/log/httpd/access_log" as a sample value.
$logfile = "/var/log/httpd/access_log";

Second, we must make sure that we output all the necessary headers to our Web server before we print anything else:
print header(); print start_html( -title => "HTTP Log report" );

Now look at the report() sub from our original program. It has one problem, relative to our new goals: It outputs all the reports instead of only the ones we've selected. We'll rewrite

report()

so that it will cycle through all the values of the report form item and show the appropriate report for each.
sub report { for $i (param('report')) { if ($i eq 'url') { report_section("URL requests", %url_requests); } elsif ($i eq 'status') { report_section("Status code requests", %status_requests); } elsif ($i eq 'hour') { report_section("Requests by hour", %hour_requests); } elsif ($i eq 'type') { report_section("Requests by file type", %type_requests); } } }

Finally, we rewrite the report_section() sub to output HTML instead of plain text. (We'll discuss the new way we're using sort in a moment.)
sub report_section { my ($header, %type) = @_; my (@type_keys); # Are we sorting by the KEY, or by the NUMBER of accesses? if (param('number') ne 'ALL') { @type_keys = sort { $type{$b} <=> $type{$a}; } keys %type; # Chop the list if we have too many results if ($#type_keys > param('number') - 1) { $#type_keys = param('number') - 1; } } else { @type_keys = sort keys %type; } # Begin a HTML table print "<TABLE>\n"; # Print a table row containing a header for the table print "<TR><TH COLSPAN=2>", $header, "</TH></TR>\n"; # Print a table row containing each item and its value for $i (@type_keys) { print "<TR><TD>", $i, "</TD><TD>", $type{$i}, "</TD></TR>\n"; } # Finish the table print "</TABLE>\n"; }

You might also like