File Coverage

blib/lib/MojoX/Log/Rotate.pm
Criterion Covered Total %
statement 54 54 100.0
branch 9 14 64.2
condition 3 7 42.8
subroutine 5 5 100.0
pod 1 4 25.0
total 72 84 85.7


line stmt bran cond sub pod time code
1             package MojoX::Log::Rotate;
2             $MojoX::Log::Rotate::VERSION = '1.222630';
3             # ABSTRACT: Makes mojolicious log file rotation easy
4 2     2   180640 use Mojo::Base 'Mojo::Log', -signatures;
  2         333278  
  2         14  
5              
6             has 'need_rotate_cb';
7             has 'rotate_cb';
8             has last_rotate => sub ($s) { $s->path && -f $s->path ? (stat $s->path)[10] : time() };
9             has frequency => 60 * 60 * 24; #every day
10              
11 1     1 1 121 sub new ($class, %params) {
  1         3  
  1         4  
  1         3  
12 1         5 my %p = map { $_ => delete $params{$_} }
13 1         3 grep { exists $params{$_} }
  3         8  
14             qw(frequency how when);
15 1         14 my $self = $class->SUPER::new(%params);
16              
17 1 50       54 $self->frequency($p{frequency}) if exists $p{frequency};
18 1   50     17 $self->rotate_cb($p{how} // \&default_rotation_cb);
19 1   50     14 $self->need_rotate_cb($p{when} // \&default_need_rotation_cb);
20              
21             #inject our message subscrition on the top
22 1         12 my $subscribers = $self->subscribers('message');
23 1         10 $self->unsubscribe('message');
24 1         11 $self->on(message => \&on_message_handler);
25 1         8 $self->on(message => $_) for @$subscribers;
26              
27 1         7 $self;
28             }
29              
30 4     4 0 6003838 sub on_message_handler ($self, $level, @args) {
  4         14  
  4         9  
  4         16  
  4         10  
31 4         25 my $cb_when = $self->need_rotate_cb;
32 4         39 my $cb_how = $self->rotate_cb;
33 4 50 33     52 if($cb_when && $cb_how) {
34 4 100       20 if(my $when_res = $cb_when->($self)) {
35 2         14 $self->last_rotate( time() );
36 2         22 my $how_res = $cb_how->($self, $when_res);
37 2         18 $self->emit('rotate' => { how => $how_res, when => $when_res });
38             }
39             }
40             }
41              
42             # must returns a false value when there is no need to rotate, or a true value.
43             # the returns value will be passed to the rotate_cb so that you can share data between callback.
44 4     4 0 9 sub default_need_rotation_cb ($self) {
  4         12  
  4         15  
45 4 50       23 return unless $self->path;
46 4 100       43 if(time - $self->last_rotate > $self->frequency ) {
47 2         38 my $last_rotate = $self->last_rotate;
48 2         38 return { last_rotate => $last_rotate };
49             }
50 2         53 return;
51             }
52              
53 2     2 0 6 sub default_rotation_cb ($self, $when_res) {
  2         6  
  2         6  
  2         4  
54 2         43 require File::Copy;
55 2         12 close $self->handle;
56 2         141 my $res = { }; #nothing to rotate
57 2 50       7 if(-f $self->path) {
58 2         214 my ($y, $m, $d, $h, $mi, $s) = (localtime)[5, 4, 3, 2, 1, 0];
59 2         40 my $suffix = sprintf("_%04d%02d%02d_%02d%02d%02d", $y+1900, $m+1, $d, $h, $mi, $s);
60 2         9 my $new_name = $self->path =~ s/(\.[^.]+)$/$suffix$1/r;
61 2 50       79 File::Copy::move $self->path => $new_name
62             or die "MojoX::Log::Rotation failed to move " . $self->path . " into $new_name : $!";
63 2         307 $res = { rotated_file => $new_name };
64             }
65 2         11 $self->handle(Mojo::File->new($self->path)->open('>>'));
66 2         654 return $res;
67             }
68              
69             1;
70              
71             __END__