SERVER EVENT COUNT FILE ---------------------------------------------------------------------- by Darren Duncan SYNOPSIS use CGI::EventCountFile; MAIN: { $self->mail_me_and_reset_counts_if_new_day( "counts.txt" ); $self->update_one_count_file( "counts.txt", (map { "\$ENV{$_} = \"$ENV{$_}\"" } qw( REQUEST_METHOD SERVER_NAME SCRIPT_FILENAME HTTP_HOST SCRIPT_NAME SERVER_SOFTWARE HTTP_REFERER ) ) ); } sub update_one_count_file { my ($self, $file_path, @keys_to_inc) = @_; push( @keys_to_inc, '__total__' ); my $count_file = CGI::EventCountFile->new( $file_path, 1 ); $count_file->open_and_lock( 1 ) or return( 0 ); $count_file->read_all_records(); foreach my $key (@keys_to_inc) { $key eq '' and $key = '__nil__'; $count_file->key_increment( $key ); } $count_file->write_all_records(); $count_file->unlock_and_close(); } sub mail_me_and_reset_counts_if_new_day { my ($self, $file_path) = @_; my $dcm_file = CGI::EventCountFile->new( $file_path, 1 ); $dcm_file->open_and_lock( 1 ) or do { print "\n"; return( undef ); }; $dcm_file->read_all_records(); if( $dcm_file->key_was_incremented_today( '__total__' ) ) { $dcm_file->unlock_and_close(); return( 1 ); } $dcm_file->key_increment( '__total__' ); $dcm_file->set_all_day_counts_to_zero(); $dcm_file->write_all_records(); $dcm_file->unlock_and_close(); my @mail_body = (); push( @mail_body, "\n\ncontent of '$file_path':\n\n" ); push( @mail_body, $dcm_file->get_sorted_file_content() ); open(MAIL, "|/usr/lib/sendmail -t") or do { print "\n"; return( undef ); }; print MAIL "To: site_owner\@their_host\n"; print MAIL "From: spying anonymous \n"; print MAIL "Subject: daily hit count update\n\n"; print MAIL "@mail_body\n\n"; close (MAIL); } DESCRIPTION This Perl 5 object class provides an easy-to-use interface for a plain text file format that is capable of storing an unordered list of events. Each event is identified by a string and has 4 attributes: date of first and last occurances, count of all occurances between first and last, count of only today's occurances. A common use for this class is to track web site usage. Usage events that can be counted include: which site pages were viewed, which external urls we redirect visitors to, which external urls have a link to us (that were used), which internal site pages had links that were clicked on to go to other pages, which web browsers the visitors are using, where the visitors are from, and miscellaneous environment details like GET vs POST vs HEAD requests. However, events can be anything at all that we want to keep counts of. This class is designed to facilitate ease of compiling and sorting count information for being e-mailed to the site owner once per day for backup/report purposes. All event names have control characters (ascii 0 thru 31) removed prior to storage, so they don't interfere with file parsing; no escaping is done to preserve binary values as it is assumed they won't be used. Event names can be any length. Dates are all stored in ISO 8601 format ("1994-02-03 14:15:29") with precision to the second, and dates are all in Universal Coordinated Time (UTC), aka Greenwich Mean Time (GMT). It is assumed that any dates provided using key_store are in UTC and formatted as ISO 8601 (six numbers in descending order of importance). That format allows for dates to be easily string-sorted without parsing. If you want to display in another time zone, you must do the conversion externally. FILE FORMAT EXAMPLE /guestbook 2000-05-16 12:31:41 UTC 2000-05-30 11:36:55 UTC 16 0 /guestbook/sign 2000-05-16 20:37:25 UTC 2000-05-30 11:36:32 UTC 7 0 /links 2000-05-16 14:18:48 UTC 2000-05-30 18:02:12 UTC 14 0 /mailme 2000-05-16 14:17:57 UTC 2000-05-30 16:54:39 UTC 17 0 /myperl 2000-05-16 09:16:22 UTC 2000-05-31 17:54:12 UTC 103 3 /myperl/base/1 2000-05-29 08:07:51 UTC 2000-05-29 08:07:51 UTC 1 0 /myperl/eventcountfile/1 2000-05-29 23:54:38 UTC 2000-05-29 23:54:38 UTC 1 0 /myperl/guestbook/1 2000-05-17 13:17:59 UTC 2000-05-29 08:40:39 UTC 3 0 /myperl/hashofarrays/1 2000-05-16 11:35:40 UTC 2000-05-30 20:58:32 UTC 6 0 /myperl/htmlformmaker/1 2000-05-17 06:41:04 UTC 2000-05-17 06:49:05 UTC 2 0 /myperl/htmltagmaker/1 2000-05-16 18:18:54 UTC 2000-05-31 17:05:23 UTC 4 1 /myperl/mailme/1 2000-05-16 11:36:08 UTC 2000-05-29 08:35:09 UTC 2 0 /myperl/methodparamparser/1 2000-05-16 15:31:58 UTC 2000-05-18 04:47:10 UTC 2 0 /myperl/segtextdoc/1 2000-05-18 03:11:53 UTC 2000-05-18 03:11:53 UTC 1 0 /myperl/sequentialfile/1 2000-05-16 15:30:54 UTC 2000-05-29 08:08:29 UTC 3 0 /myperl/static/1 2000-05-16 12:31:07 UTC 2000-05-16 15:47:29 UTC 2 0 /myperl/webpagecontent/1 2000-05-29 22:48:30 UTC 2000-05-30 11:11:16 UTC 2 0 /myperl/websiteglobals/1 2000-05-16 15:33:02 UTC 2000-05-29 18:57:29 UTC 5 0 /myperl/websitemanager/1 2000-05-16 17:37:05 UTC 2000-05-29 22:46:04 UTC 7 0 /mysites 2000-05-15 22:58:30 UTC 2000-05-31 01:40:52 UTC 78 1 /resume 2000-05-15 23:26:23 UTC 2000-05-30 16:52:11 UTC 57 0 __nil__ 2000-05-15 07:57:37 UTC 2000-05-31 17:59:02 UTC 201 5 __total__ 2000-05-15 07:57:37 UTC 2000-05-31 17:59:02 UTC 720 11 external 2000-05-15 22:59:16 UTC 2000-05-31 01:41:03 UTC 186 1 For a complete description, please refer to the POD that is contained in the module itself. KEEPING UP TO DATE These modules are constantly under development. You should be able to find the newest versions at my website, "http://www.DarrenDuncan.net", on the page called "Perl Libraries I Made" (name subject to change). They can also be found on CPAN under the author name of "DUNCAND". I am inclined to update the copies on my web site more often, but those intermediate versions are more likely to have been tested less, and the modules may be updated day by day without increasing the version numbers. However, the copies on CPAN are guaranteed to have unique version numbers when the module has changed. REQUIREMENTS This module requires Perl 5.004 or newer due partly to bug fixes implemented there with regards to file management (eg: flush before unlock). This module also requires the standard Fcntl module to provide it with some constant values. INSTALLATION I haven't gotten around to doing makefiles, so you will have to install this the old fashioned way, by copying. The file "EventCountFile.pm" goes inside the "CGI" folder which is in the "lib" folder that came with your Perl 5 distribution. Or alternately, put it anywhere you want, but you will need to have that location added to your include path by your main program using something like this: use lib '/users/me/www_files/lib'; Any existing POD is embedded in the module itself, so you will have to look there to see it, or run a POD extractor on it yourself, or look at the copy on CPAN that is dutifully extracted and turned to HTML. SUPPORT Currently I don't have any support arranged with other people, lists, newsgroups, or otherwise. Feel free to ask me if you can't figure things out on your own, or another person whom you know has used this. AUTHOR Copyright (c) 1999-2000, Darren R. Duncan. All rights reserved. These modules are free software; you can redistribute them and/or modify them under the same terms as Perl itself. However, I do request that their copyright information remains attached to the files. If you modify this module and redistribute a changed version then please attach a note listing the modifications. I am always interested in knowing how my work helps others, so if you put this module to use in any of your own code then please send me the URL. Also, if you make modifications to the module because it doesn't work the way you need, please send me a copy so that I can roll desirable changes into the main release. Address comments, suggestions, and bug reports to perl@DarrenDuncan.net. Share and Enjoy!