Dancer-Logger-File-PerRequest
view release on metacpan or search on metacpan
lib/Dancer/Logger/File/PerRequest.pm view on Meta::CPAN
package Dancer::Logger::File::PerRequest;
use strict;
use warnings;
use 5.008_005;
our $VERSION = '0.03';
use Carp;
use base 'Dancer::Logger::Abstract';
use Dancer::FileUtils qw(open_file);
use Dancer::Config 'setting';
use Dancer::Hook;
use Dancer::Factory::Hook;
use Dancer::SharedData;
use IO::File;
use Fcntl qw(:flock SEEK_END);
use Scalar::Util ();
Dancer::Factory::Hook->instance->install_hooks(
qw/before_file_per_request_close after_file_per_request_close/
);
sub init {
my $self = shift;
$self->SUPER::init(@_);
my $logdir = logdir();
return unless ($logdir);
mkdir($logdir) unless -d $logdir;
my $logfile_callback = setting('logfile_callback') || sub {
## timestamp + pid + request->id
my @d = localtime();
my $file = sprintf('%04d%02d%02d%02d%02d%02d', $d[5] + 1900, $d[4] + 1, $d[3], $d[2], $d[1], $d[0]);
my $request_id = Dancer::SharedData->request ? Dancer::SharedData->request->id : '';
return $file . '-' . $$ . '-' . $request_id . '.log';
};
$self->{logfile_callback} = $logfile_callback;
# per request
Scalar::Util::weaken $self;
my $on_end = sub {
return unless $self->{fh};
Dancer::Factory::Hook->execute_hooks('before_file_per_request_close', $self->{fh}, $self->{logfile});
close($self->{fh}); # close
undef $self->{fh};
Dancer::Factory::Hook->execute_hooks('after_file_per_request_close', $self->{logfile}, Dancer::SharedData->response);
undef $self->{logfile};
};
Dancer::Hook->new('after' => $on_end);
if (setting('serializer')) { # when serializer, on error, it's not call 'after' hook
Dancer::Hook->new('after_error_render' => $on_end);
}
}
sub _log {
my ($self, $level, $message) = @_;
my $fh = $self->{fh};
unless ($fh) {
my $logfile = $self->{logfile_callback}->();
my $logdir = logdir() or return;
$logfile = File::Spec->catfile($logdir, $logfile);
unless($fh = open_file('>>', $logfile)) {
carp "unable to create or append to $logfile";
return;
}
# looks like older perls don't auto-convert to IO::File
# and can't autoflush
# see https://github.com/PerlDancer/Dancer/issues/954
eval { $fh->autoflush };
$self->{fh} = $fh;
$self->{logfile} = $logfile;
}
return unless(ref $fh && $fh->opened);
flock($fh, LOCK_EX)
or carp "locking logfile $self->{logfile} failed";
seek($fh, 0, SEEK_END)
or carp "seeking to logfile $self->{logfile} end failed";
$fh->print($self->format_message($level => $message))
or carp "writing to logfile $self->{logfile} failed";
flock($fh, LOCK_UN)
or carp "unlocking logfile $self->{logfile} failed";
}
# Copied from Dancer::Logger::File
sub logdir {
if ( my $altpath = setting('log_path') ) {
return $altpath;
}
my $logroot = setting('appdir');
if ( $logroot and ! -d $logroot and ! mkdir $logroot ) {
carp "app directory '$logroot' doesn't exist, am unable to create it";
( run in 1.031 second using v1.01-cache-2.11-cpan-39bf76dae61 )