#======================================================================== # # Badger::Log::File # # DESCRIPTION # Subclass of Badger::Log for logging messages to a file. # # AUTHOR # Andy Wardley # #======================================================================== package Badger::Log::File; use Badger::Class version => 0.01, base => 'Badger::Log', filesystem => 'FS', config => [ 'filesystem|method:FS', 'filename|class:FILENAME', 'keep_open|class:KEEP_OPEN=0', ], messages => { no_filename => 'No filename specified for log file', started => 'Started logging', }; sub init { my ($self, $config) = @_; $self->init_log($config); $self->init_file($config); return $self; } sub init_file { my ($self, $config) = @_; # init_log() has already called configured() which will copy the filename # parameter into $self. We don't make the filename parameter mandatory # in the config schema because that will report missing parameters # using error_msg() which has been redefined in Badger::Log. So we # check for it here and use our "backdoor" _error_msg() method. my $filename = $self->{ filename }; return $self->_error_msg('no_filename') unless defined $filename; $self->{ file } = $self->{ filesystem }->file($filename); $self->info_msg('started'); } sub acquire { my $self = shift; # Badger::Filesystem::File::append() method returns file handle open for append return $self->{ handle } ||= $self->{ file }->append; } sub release { my $self = shift; my $fh = delete $self->{ handle } || return; $fh->close() # TODO: does IO::File throw an error on close fail? # || return $self->base_error_msg( bad_close => $self->{ filename }, $! ); } sub log { my ($self, $level, $message) = @_; my $handle = $self->{ handle } || $self->acquire; my $output = sprintf($self->format($level, $message)); $output =~ s/\n+$//; $handle->printflush($output, "\n"); $self->release unless $self->{ keep_open }; } sub DESTROY { shift->release; } 1; __END__ =head1 NAME Badger::Log::File - writes log messages to a log file =head1 SYNOPSIS use Badger::Log::File; my $log = Badger::Log::File->new({ filename => '/var/log/badger.log', keep_open => 1, }); $log->log('a debug message'); $log->info('an info message'); $log->warn('a warning message'); $log->error('an error message'); $log->fatal('a fatal error message'); =head1 DESCRIPTION This module is a subclass of L that implements a simple mechanism for logging messages to a file. It uses L for all the underlying file operations. =head1 CONFIGURATION OPTIONS The following configuration options are available in addition to those inherited form the L base class. =head2 filename The name of the log file which you want messages appended to. This parameter is mandatory. =head2 filesystem An optional reference to a L object, or the name of a filesystem class having a L method similar to that in L. This defaults to the L class. =head2 keep_open A flag indicating if the log file should be kept open between calls to logging methods. The default value is C<0> meaning that the file will be opened for each message and closed again afterwards. Set it to any true value to have the file kept open. =head1 METHODS The following methods are implemented in addition to those inherited from L and its base classes. =head2 log($level,$message) This method redefines the L method in L to write logging messages to the log file. =head2 INTERNAL METHODS =head2 init(\%config) Custom initialiser method which calls the base class L method followed by the L method. =head2 init_file(\%config) Custom initialiser method which handles the configuration and initialisation of the file-specific parts of the logger. =head2 acquire() This method acquires a file handle (an L object) for the specified L, opened ready for appending log messages. =head2 release() The method releases a previously acquired file handle. i.e. it closes the log file. =head1 AUTHOR Andy Wardley L =head1 COPYRIGHT Copyright (C) 2005-2009 Andy Wardley. All Rights Reserved. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO L =cut # Local Variables: # mode: perl # perl-indent-level: 4 # indent-tabs-mode: nil # End: # # vim: expandtab shiftwidth=4: