package BigLogger; use strict; sub new { my ($type,%args) = @_; my ($filename,$debug,$statIndex) = @args{qw( fileName debug statIndex )}; if (!defined $filename) { $! = __PACKAGE__."- No statIndex arg passed to constructor"; return; } if (!defined $statIndex) { $! = __PACKAGE__."No statIndex passed to constructor"; return; } my $file = new IO::File(">>$filename"); return if !$file; $file->autoflush(1); my $statVal = (stat($file))[$statIndex]; print STDERR __PACKAGE__," new called - statVal=$statVal, statIndex=$statIndex file=$filename\n" if $debug; return bless [$file,$statVal,$statIndex,$debug,$filename],ref($type)||$type; } sub print { my ($self,@data) = @_; my ($file,$statVal,$statIndex,$debug,$filename) = @{ $self }; # # See if the stat data is different ?? # my $sv = (stat($file))[$statIndex]; if ($sv != $statVal) { # # OK - reopen the file.... # print STDERR __PACKAGE__," reopening $filename\n" if $debug; $file->close; $file = new IO::File(">>$filename"); if (!$file) { print STDERR __PACKAGE__," failed to open file: $!\n" if $debug; return; } $file->autoflush(1); # # Fetch the new stat value # $self->[2] = (stat($file))[$statIndex]; } $file->print(@data); } 1; __END__ =pod =head1 NAME BigLogger - Demonstration of a Perl implementation of a client logger which uses fstat on a filehandle to determine whether a logfile needs reopening. It can check a selected attribute from the stat results, such as owner, group or permissions. =head1 SYNOPSIS use BigLogger; my $Logger = BigLogger( debug => 1, fileName => '/var/log/biglog.log', statIndex => 4, # The uid is monitored ); while (1) { $Logger->print("Some data...\n"); } =head1 ABSTRACT This simple class opens the selected file for append and before each write, checks the file by stating it and checks the selected stat attribute to see if a rotation process has changed the permissions or group or user. This allows several clients to append to a log file easily, and a seperate process is able to rotate the files, this reduced IPC and server load (a problem seen with logrotate in apache). It should be noted that there is a short race condition between the fstat and write to the file where the rotate program could change the file state, to overcome this the rotator is recommended to do the following: Rename the file Chmod or Chown file Wait a second Process File This almost guarantees nothing will write to the file. =head1 METHODS Only two methods are provided:- =head2 new This is the constructor and takes two manditory argument, the filename as B and B which is the array index to the stat attribute which is to be monitored, (4-uid, 5-gid, 2-mode/perms). The optional B argument may be provided, and if true outputs information to STDERR. On error undef is returned with the error in $!. =head2 print Tests for file rotation, reopening if neccessary. Then prints the supplied content to the file returning true on success. If an error occurs undef is returned and $! will have the error status. =head1 IMPLEMENTATION The class is implemented as a blessed array to reduce the overhead of several hash lookups per log line. It appears a little messy for this reason. =head1 USE You may use this code, but the Bigmite offer no liability or guarantee.