Page counters are one of the most-frequently-used web programmings. It is easy with CGI and even easier with SSI (if you don't need image). There are tons of implementatonis available and it is considered trivial to implement basic ones.
Is that really so?
Yes, if you don't care the performance. CGI is a complete process which needs to be invoked, run, and creaned up. in that sense CGI is no different from hefty emacs. And you know how many times the cgi gets called for the busiest pages in the World Wide Webs.
Yes if you don't care the sloppiness. With web server taking care of all these dirty jobs, you can go as sloppy as you like with CGI. All you have to do is read and write stdin/out. Making it a part of web server program is a completely different story. When you die, the whole web server dies altogether.
So here it is, a non-trivial, no-nonsense web server module which does count tracking and even image all by itself. Enjoy.
Bug reports are very welcome (as welcome as thank you note). Paches are even more welcome. Other thing welcome is the usage report--what platform you are using, how much performance gain (or losss) is achieved.
9-Dec-1998
Typo in typo in cntr/mod_cntr.module fixed.
Note 1.2.x users: The ugly #include "gdimini.c" still remains
(to make Configure happy) so if you are using apache 1.2.x AND PHP3 with GD support,
the conflict still remains. Time is high you switched to 1.3.x, maybe...
Though resulting counter faces look the same, it is now a different beast from head to foot. Read this section carefully if you are a ver 1.x user
It compiles both on 1.3.x and 1.2.x. It also supports APACI so it is automatically configured. It also supports DSO so you can add the module to binary distribution of Apache.
WebCounter used to store values (count, date first accessed) in plain text. Now it stores these values in binary format (32bit x 2), resulting more efficiency.
In other words, the old counter file is NOT COMPATIBLE with the new one. But don't worry, I have conversion script ready for you. See below for more details.
Yes, no cgi! With web server directly rendering counter image, it is far more efficient than cgi-based counter rendering. And even for those who would like to customize the counter program but too afreaid to dare touch the module, mod_cntr sets more environment variables to ease your programming.
Bare-text counter files are too innefficent so I have dropped the support. Sorry but if you are content with bare (CGI/SSI-based) counters with bare speed, there are tons of alternatives (many of which can be found athttp://www.digitmania.com/) as a result,(Server)CounterType directive is gone.
All directives and handlers are now configurable per-directory basis. You can customize these with .htaccess file. That way, non-root users can use thier own customization. Side-effect of this change is the complete disappearance of ServerCounter* directives. They are all integrated with Counter* counterparts.
Some of aux. scripts bundled in the package used to depend on cgi-lib.pl, a famous pre-perl5 cgi library. With perl 5.004 or later, CGI,pm comes standard so no extra package is needed to get full feature of the package
In addition to handlernize image rendering engine, I have renamed variables in more approprate, less confusing manners. Here is a List.
New | Old | Description |
---|---|---|
face= | type= | Digit face. Used to be called "Digit Type" but the word "type" is more ambiguous and confusing. |
path-info | url= | URL overriding when referer is not available |
ndigit= | length= | Number of digits rendered. |
fcount= | count= | Faked count. To punctuate the fact it is a fake, I have put "f" on the head. |
trans | (No Equivalent) | Transparent color from topleft corner of the image. New feature. |
There may be more but please read through.
You just lick the link on the right:http://www.dan.co.jp/software/webcounter-latest.tar.gz
When you get the tar ball above, just unpack it with
gzip webcounter-latest.tar.gz | tar xvf -
or
tar -zxvf webcounter-x.x.tar.gz
If your tar is GNU tar.
EXTRA_CFLAGS=-g -DHAVE_DB EXTRA_LIBS=-lm Module cntr_module mod_cntr.o
where HAVE_DB is one of HAVE_DB, HAVE_GDBM, or HAVE_DBM depending on the DBM package you have. For *BSD, Berkely DB comes in standard so use HAVE_DB.
WebCounter 2.x is known to work with platforms below. If you have successfully compiled it and your platform is not listed here, please mail me a note.
Platform | DBM Type | Apache version | Tested by: | ||
---|---|---|---|---|---|
1.2.x | 1.3.x | ||||
Static | DSO | ||||
FreeBSD 2.x | DB | OK | OK | OK | dankogai@dan.co.jp |
BSD/OS 2.1 | DB | OK | OK | OK | dankogai@dan.co.jp |
Linux 2.x | GDBM | ? | OK | OK | steffann@nederland.net dankogai@dan.co.jp |
HP-UX 10.20/11.00 | NDBM | ? | OK | OK | rv33100@GlaxoWellcome.co.uk |
Solaris 2.x | GDBM | ? | OK | OK | shaug@callamerica.net |
Here is a typical configuration for mod_cntr.c
# if you have made mod_cntr DSO, don't forget to add these # if you have not, just comment these out LoadModule cntr_module libexec/mod_cntr.so AddModule mod_cntr.c <IfModule mod_cntr.c> CounterAutoAdd On CounterFile logs/%v.count CounterTimeFmt "%A, %d-%b-%y %T %Z" CounterFaceDir /usr/local/apache/htdocs/digits </IfModule> <Location /server-cntr> SetHandler server-cntr </Location> <Location /server-cntr-debug> SetHandler server-cntr-debug </Location>
And here is what each directives means.
Default: Off
Context: directory, .htaccess
Override: Any
This direcitve determines whether URIs nonexistent on the counter file be added. If On, new entry will be created on the counter file. If Off, nonexistent URIs are simply ignored.
Default: None
Context: directory, .htaccess
Override: Any
You set the path to DBM file (without DBM suffix) here. Like many other directives whose value is path, you can use relative path here. for instance, if ServerRoot is /usr/local/apache and ServerCounterFile is logs/count, its absolute path will be /usr/local/apache/logs/count plus DBM suffix.
There is a %v macro which expands to virtualhost name (added by Sander Steffann).
Note: Remember owner of counter file is whatever you set in User directive (typically nobody). So the directory where counter file is stored must be writable by the user specified by User directive. This is the most common error so be carefuly!.
Syntax: see strftime(3)
Default: "%A, %d-%b-%y %T %Z"
Override: Any
Time format for URI_COUNT_RESET environment variable. As in "config timefmt=" of mod_include, format is the same as strftime(3).
Syntax: path to counter file (without DBM suffix)
Default: /usr/local/apache/htdocs/digits
Where counter seed graphics file are stored. see "The Face Files" below for details.
From 2.1, mod_cntr not only updates the counter, it also renders the counter! Unlike CGI which has to read values via QUERY_STRING and other environment variables, handler directly grabs configs from module and renders the image, resulting more efficiency in time and resources.
To use this feature, you have to enable handler that does.
This is what replaces cgi. From the document, all you have to do is you insert <img src=/server-cntr>. See "Using Webcouter" below for usage.
You can see what information gets passed to the handler using this handler. Click here to see what it does.
As explained above, WebCounter dynamically renders digit graphics from GIF files. In WebCounter 1.1, path to this file is can only be set compile-time. You can now do it with configuration directive CounterFaceDir so you can put it anywhere AS LONG AS IT IS READ-ACCESSBLE by httpd (normally user nobody).
Here is a directory hierarchy for seed files;
ServerCounterFacedir/ default/ Where default face files are stored 0.gif 1.gif ... 9.gif tiny/ 0.gif 1.gif ... 9.gif
WebCounetr comes with two digit faces, default and tiny. they are in digits directory so just copy them to whatever directory you spacified with the directive. If you don't know, just put it directly under DocumentRoot (that' sthe default). To specify which face to use, you give face=name query string. As you have correctly guessed, directory named name under CounterFaceDir will be used.
To see what faces are available, you can use show-digits.cgi perl script. No external library is used.
WebCounter-2.0 also comes with renamegif.pl perl script to convert digit files available at http://www.digitimania.com/ so you can add your favorite digit face.
Unlike WebCouter-1.1 whose data are stored in text format, WebCounter-2.0 uses a fixed-width binary format for better performance and storage efficiency. In other words, 2.0 counter file is incompatible with 1.1.
Don't worry, though. I have added updatedbm.pl perl script to update counter file to 2.0 format. To do so, just
updatedbm.pl <path-to-dbm-file>
And it's done. Old counter file will be backed up as counter.old.dbmsuffix.
Once installed, WebCounter is really easy to use.
All you have to do is insert the tag below in the document
Indented part is an option that you can omit.
<img src="/server-cntr/path/info?face=facename?ndigit=n?fcount=n?trans>
When server-cntr handler is called, it checks the referer and lookup appropriate uri. when it is a directory URI, it uses DirectoryIndex value to complete the URI (it snatches the setting of mod_dir.c. Though mod_cntr.c does work without it, I strongly suggest you link with it. Just leave it as the default and it will be included).
Though almost perfect, this might fail if the browser does not set Referer header. To compromise this, you can give additional path followed by /server-cntr (called path-info) and server-cntr will check it.
Tag | Description | Result |
---|---|---|
<img src=/server-cntr> | Count of this page | |
<img src=/server-cntr/index.html> | Count of /index.html |
This query specifies the alternate digit face for use. here, facename is a name of directory under CounterFaceDir directory where GIF files named 1.gif, 2.gif... are stored. When this directory is not found, the handler uses default face and logs the warning.
Tag | Result |
---|---|
<img src=/server-cntr> | |
<img src=/server-cntr?face=tiny> |
By default, server-cntr does not zero-fill the digit. With this set to non-zero, it forcibily renders this number of digits, with approprate numbers of zeroes.
Tag | Result |
---|---|
<img src=/server-cntr?face=tiny&ndigit=10> |
You can spoof the count with this. fcount is short for faked counter. Give it any number.
Tag | Result |
---|---|
<img src=/server-cntr?fcount=1234567890> |
A little nifty featue. When set (exists--you don't need to asign value with =value)The color of topleft (0,0) becomes transparent.
Tag | Result |
---|---|
<img src=/server-cntr?face=tiny&trans> |
WebCounter sets environment variables below that you can use in SSI. These values are also helpful if you want to access counter via CGI. I have included perl version of count.cgi. that does the same as server-cntr handler. It requires GD.pm and URI::URL (comes with libwww) to run.
variable | Description | Example | Result |
---|---|---|---|
URL_COUNT | Access Count to the file | <!--#echo var="URL_COUNT"--> |
|
URL_COUNT_RESET | When Access Count has started | <!--#echo var="URL_COUNT_RESET"--> |
|
URL_COUNT_DB | Path to counter database. | <!--#echo var="URL_COUNT_DB"--> |
|
URL_COUNT_TIMEFMT | Time format for URL_COUNT_RESET | <!--#echo var="URL_COUNT_TIMEFMT"--> |
|
URL_COUNT_FACEDIR | Path to counter face files . | <!--#echo var="URL_COUNT_FACEDIR"--> |
|
URL_COUNT_DINDEX | File names for directory index. | <!--#echo var="URL_COUNT_DINDEX"--> |
|
The script countctl.pl may be used to manipulate, reset, add, delete or view the counter logs. Make sure you have perl around. The countctl script is written assuming perl is located in /usr/local/bin/perl. If its in a different place, edit the first line to point to where your perl executable lies. Copy the script to either /usr/local/bin or where you plan to keep your counter log files. The script requires at least one argument, the hash or log filename. Certain options require the URL being processed.
The synopsis is as follows:
countctl.pl [ -cdrv URL ] filename -c create URL -d delete URL -r reset counter -v view counter (and reset date)If no option is supplied, it essentially dumps the contents of the file. The output is in no particular order. The format of the output is:
URL count reset_date
If you compiled mod_cntr with GDBM, countctl may not work. countctl.pl uses perl
and there are cases where perl is not compiled with GDBM enabled. That was the case
for most RedHat-based linux. Sigh....
I think I have done all the homework but if you dare me give me more (more platform support, DB_BTREE and DB_RECNO supports, missing Japanese support once existed in ver. 1.1 you name'em), I am welcome to listen to your ideas.
The following changes have been made since release 1.0:
This code allows easy transparent use of web page counters.
By Dan Kogai (dankogai@dan.co.jp)with help of Sander Steffann (steffann@nederland.net). Originally by Braian Kolaci but at last virtually none of his codes are left. Original GD codes are done by Thomas Bourtell (boutell@boutell.com) and Lincoln D. Stein.
Not a few people have given me suggestions and some have even sent me codes ever since I took over WebCounter from Brian Kolaci. I would like to thank them all but namely;