File Coverage

blib/lib/Log/Defer.pm
Criterion Covered Total %
statement 88 89 98.8
branch 24 38 63.1
condition 11 15 73.3
subroutine 16 16 100.0
pod 0 10 0.0
total 139 168 82.7


line stmt bran cond sub pod time code
1             package Log::Defer;
2              
3 4     4   51950 use strict;
  4         6  
  4         134  
4              
5             our $VERSION = '0.312';
6              
7 4     4   1817 use Time::HiRes;
  4         3848  
  4         12  
8 4     4   283 use Carp qw/croak/;
  4         7  
  4         219  
9              
10 4     4   1519 use Guard;
  4         1340  
  4         2905  
11              
12              
13             sub new {
14 4     4 0 51 my ($class, $cb, $opts) = @_;
15              
16 4 50       11 if ($cb) {
17 4 100       17 if (ref $cb eq 'CODE') {
    50          
18 2   50     10 $opts ||= {};
19 2 50       8 croak "two callbacks provided" if $opts->{cb};
20             } elsif (ref $cb eq 'HASH') {
21 2         2 $opts = $cb;
22 2         4 $cb = $opts->{cb};
23             } else {
24 0         0 croak "first arg to new must be a coderef or hashref";
25             }
26             }
27              
28 4         5 my $self = $opts;
29 4         6 bless $self, $class;
30              
31 4 50 33     26 croak "must provide callback to Log::Defer" unless $cb && ref $cb eq 'CODE';
32              
33 4         21 my $msg = {
34             start => format_time(Time::HiRes::time),
35             };
36              
37 4         16 $self->{msg} = $msg;
38              
39             $self->{guard} = guard {
40 4     4   439 my $end_time = format_time(Time::HiRes::time());
41 4         13 my $duration = format_time($end_time - $msg->{start});
42 4         9 $msg->{end} = $duration;
43              
44 4 100       30 if (exists $msg->{timers}) {
45 2         2 foreach my $timer_entry (@{$msg->{timers}}) {
  2         7  
46 5 100       12 push @$timer_entry, $duration
47             if @$timer_entry == 2;
48             }
49             }
50              
51 4         13 $cb->($msg);
52 4         32 };
53              
54 4         16 return $self;
55             }
56              
57              
58             sub error {
59 2     2 0 10 my ($self, @logs) = @_;
60              
61 2         8 $self->add_log(10, @logs);
62             }
63              
64             sub warn {
65 2     2 0 13 my ($self, @logs) = @_;
66              
67 2         7 $self->add_log(20, @logs);
68             }
69              
70             sub info {
71 5     5 0 29 my ($self, @logs) = @_;
72              
73 5         16 $self->add_log(30, @logs);
74             }
75              
76             sub debug {
77 2     2 0 14 my ($self, @logs) = @_;
78              
79 2         7 $self->add_log(40, @logs);
80             }
81              
82             sub add_log {
83 13     13 0 23 my ($self, $verbosity, @logs) = @_;
84              
85 13 100 100     58 if (!exists $self->{verbosity} || $verbosity <= $self->{verbosity}) {
86 10         29 my $time = format_time(Time::HiRes::time() - $self->{msg}->{start});
87              
88 10 100 66     52 @logs = $logs[0]->() if $logs[0] && ref $logs[0] eq 'CODE';
89              
90 10         13 push @{$self->{msg}->{logs}}, [$time, $verbosity, @logs];
  10         41  
91             }
92             }
93              
94              
95             sub timer {
96 4     4 0 100226 my ($self, $name) = @_;
97              
98             ##croak "timer $name already registered" if defined $self->{msg}->{timers}->{$name};
99              
100 4         19 my $timer_start = format_time(Time::HiRes::time() - $self->{msg}->{start});
101              
102             ##$self->{msg}->{timers}->{$name} = [ $timer_start, ];
103              
104 4         8 my $msg = $self->{msg};
105              
106 4         8 my $timer_entry = [ $name, $timer_start, ];
107              
108 4   100     20 $msg->{timers} ||= [];
109              
110 4         4 push @{$msg->{timers}}, $timer_entry;
  4         11  
111              
112             return guard {
113 4     4   205335 my $timer_end = format_time(Time::HiRes::time() - $msg->{start});
114              
115 4         88 push @$timer_entry, $timer_end;
116             }
117 4         37 }
118              
119             sub data {
120 3     3 0 11 my ($self) = @_;
121              
122 3   100     11 $self->{msg}->{data} ||= {};
123              
124 3         7 return $self->{msg}->{data};
125             }
126              
127              
128              
129             sub merge {
130 1     1 0 4 my ($self, $msg) = @_;
131              
132 1         4 my $time_offset = $msg->{start} - $self->{msg}->{start};
133              
134             ## Merge logs
135              
136             my @logs = (
137 1 50       6 @{ $self->{msg}->{logs} || [] },
138 1 50       1 (map { [ $_->[0] + $time_offset, @$_[1..(@$_-1)] ] } @{ $msg->{logs} || [] })
  3         13  
  1         4  
139             );
140              
141 1         5 $self->{msg}->{logs} = [ sort { $a->[0] <=> $b->[0] } @logs ];
  9         11  
142              
143             ## Merge timers
144              
145 1 50       1 my $timers = [ @{ $msg->{timers} || [] } ];
  1         26  
146              
147 1         3 foreach my $timer_entry (@$timers) {
148 1         2 $timer_entry->[1] += $time_offset;
149 1         2 $timer_entry->[2] += $time_offset;
150             }
151              
152 1 50       1 $self->{msg}->{timers} = [ @{ $self->{msg}->{timers} || [] }, @$timers, ];
  1         4  
153              
154             ## Merge data
155              
156             ## FIXME: This needs to do something like Hash::Merge but I don't want to add a dependency...
157              
158 1 50       2 $self->{msg}->{data} = { %{ $self->{msg}->{data} || {} }, %{ $msg->{data} || {} } };
  1 50       6  
  1         4  
159              
160              
161 1 50       3 delete $self->{msg}->{logs} unless @{ $self->{msg}->{logs} };
  1         4  
162 1 50       2 delete $self->{msg}->{timers} unless @{ $self->{msg}->{timers} };
  1         4  
163 1 50       1 delete $self->{msg}->{data} unless keys %{ $self->{msg}->{data} };
  1         7  
164             }
165              
166              
167              
168              
169             #### INTERNAL ####
170              
171             sub format_time {
172 30     30 0 36 my $time = shift;
173              
174 30 50       68 $time = 0 if $time < 0;
175              
176 30         226 return 0.0 + sprintf("%.6f", $time);
177             }
178              
179              
180             1;
181              
182              
183              
184              
185             __END__