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