Skip to main content.
home | support | download

Back to List Archive

Re: Writing log files (was: Almost)

From: Bill Moseley <moseley(at)>
Date: Tue Jul 20 2004 - 15:24:58 GMT
Here's a few comments:

I assume the reason people are placing the logging in the template
module is that's where you can get at both the request and the
results.  But, it gives me the willies to do that in a module designed
for output.

I suppose what would be nice is a callback function you can place in
the config file (.swishcgi.conf by default) -- there's one to get at
the request but not one to see results.   Then the logging code could
be in the config file.

Unfortunately, swish.cgi is so old and hacked that the interface isn't
very clean (i.e. there's not nice request and response objects).

Or, another way you might do it that would be cleaner than hacking the
template modules would be to create a new template module that does
the logging and set it as the "package" in the template config option.
Then have that module do the logging and then call the real
(unmodified) template output module.

BTW, here's a few comments on your Perl -- I can never resist. ;)

>  my $message = sprintf("%s\t%-
> 30s\t%6d\t%s\t%s\t%s\t%s\t%s\n",$bigf,$query,$hits,$date,$search_time,$run_t
> ime,$browser,$query_complex);

That's fine, but a more "perl" way might be to place your data into a
hash and have all your field names in an array:

   $message = join "\t", @hash_of_logs_data{ @field_names };

Now, locking is normally unnecessary -- the OS will do atomic writes,
even with buffering enabled.  Plus, under something like mod_perl you
would likely want to keep the file open between requests (compare
stat(LOG) with stat($file) to see when it's been rotated and needs
to be reopened).

>   use Fcntl qw(:DEFAULT :flock);
>   unless (flock(LOG, LOCK_EX)) {
>   $| = 1;

I think you just asked STDOUT to be non-buffered, not LOG.  You need
to select() the file handle first.

>   print STDERR "Waiting for $logfile lock $date...";
>   flock(FH, LOCK_EX)  or exit "can't lock filename: $!";
>   }

Typically (and especially in a interactive script) you would wrap the
flock() in an eval{} with an alarm() to timeout the lock.

>  }
>    print LOG "$message";
>    $fh ? () : flock(LOG,LOCK_UN);
>    close LOG;

If you unlock and then close and the OS is buffering then you risk a
write from another process.  In other words, don't unlock -- just
close which flushes and then unlocks.

Under mod_perl you would might use pnotes to store your request and
results objects and use an apache log handler to write the logs.  That
allows logging (which might delay) after the request has been served.

Bill Moseley
Received on Tue Jul 20 08:25:10 2004