File Coverage

blib/lib/Log/Log4perl/Tiny.pm
Criterion Covered Total %
statement 373 400 93.2
branch 157 224 70.0
condition 21 38 55.2
subroutine 38 40 95.0
pod 20 20 100.0
total 609 722 84.3


line stmt bran cond sub pod time code
1             package Log::Log4perl::Tiny;
2              
3 26     26   1507449 use strict;
  26         238  
  26         599  
4 26     26   100 use warnings;
  26         38  
  26         912  
5             { our $VERSION = '1.6.4'; }
6              
7 26     26   105 use Carp;
  26         39  
  26         1036  
8 26     26   9967 use POSIX ();
  26         144089  
  26         2108  
9              
10             our ($TRACE, $DEBUG, $INFO, $WARN, $ERROR, $FATAL, $OFF, $DEAD);
11             my ($_instance, %name_of, %format_for, %id_for);
12             my $LOGDIE_MESSAGE_ON_STDERR = 1;
13              
14             sub import {
15 32     32   10586 my ($exporter, @list) = @_;
16 32         112 my ($caller, $file, $line) = caller();
17 26     26   164 no strict 'refs';
  26         55  
  26         78828  
18              
19 32 50       75 if (grep { $_ eq ':full_or_fake' } @list) {
  50         190  
20 0         0 @list = grep { $_ ne ':full_or_fake' } @list;
  0         0  
21 0         0 my $sue = 'use Log::Log4perl (@list)';
22 0 0       0 eval "
23             package $caller;
24             $sue;
25             1;
26             " and return;
27 0         0 unshift @list, ':fake';
28             } ## end if (grep { $_ eq ':full_or_fake'...})
29              
30 32         59 my (%done, $level_set);
31             ITEM:
32 32         67 for my $item (@list) {
33 299 100       491 next ITEM if $done{$item};
34 290         383 $done{$item} = 1;
35 290 100       745 if ($item =~ /^[a-zA-Z]/mxs) {
    100          
    100          
    100          
    100          
    100          
    50          
36 218         204 *{$caller . '::' . $item} = \&{$exporter . '::' . $item};
  218         2268  
  218         401  
37             }
38             elsif ($item eq ':levels') {
39 25         56 for my $level (qw( TRACE DEBUG INFO WARN ERROR FATAL OFF DEAD )) {
40 200         207 *{$caller . '::' . $level} = \${$exporter . '::' . $level};
  200         511  
  200         366  
41             }
42             }
43             elsif ($item eq ':subs') {
44 14         67 push @list, qw(
45             ALWAYS TRACE DEBUG INFO WARN ERROR FATAL
46             LOGWARN LOGDIE LOGEXIT LOGCARP LOGCLUCK LOGCROAK LOGCONFESS
47             get_logger
48             );
49             } ## end elsif ($item eq ':subs')
50             elsif ($item =~ /\A : (mimic | mask | fake) \z/mxs) {
51              
52             # module name as a string below to trick Module::ScanDeps
53 14 100       125 if (!'Log::Log4perl'->can('easy_init')) {
54 12         32 $INC{'Log/Log4perl.pm'} = __FILE__;
55 12     2   45 *Log::Log4perl::import = sub { };
56             *Log::Log4perl::easy_init = sub {
57 11     11   8792 my ($pack, $conf) = @_;
58 11 100       47 if (ref $conf) {
    100          
59 8         60 $_instance = __PACKAGE__->new($conf);
60             $_instance->level($conf->{level})
61 8 50       48 if exists $conf->{level};
62             $_instance->format($conf->{format})
63 8 50       55 if exists $conf->{format};
64             $_instance->format($conf->{layout})
65 8 50       81 if exists $conf->{layout};
66             } ## end if (ref $conf)
67             elsif (defined $conf) {
68 2         5 $_instance->level($conf);
69             }
70 12         49 };
71             } ## end if (!'Log::Log4perl'->...)
72             } ## end elsif ($item =~ /\A : (mimic | mask | fake) \z/mxs)
73             elsif ($item eq ':easy') {
74 13         41 push @list, qw( :levels :subs :fake );
75             }
76             elsif (lc($item) eq ':dead_if_first') {
77 5         16 get_logger()->_set_level_if_first($DEAD);
78 5         11 $level_set = 1;
79             }
80             elsif (lc($item) eq ':no_extra_logdie_message') {
81 1         1 $LOGDIE_MESSAGE_ON_STDERR = 0;
82             }
83             } ## end ITEM: for my $item (@list)
84              
85 32 100       90 if (!$level_set) {
86 27         96 my $logger = get_logger();
87 27         114 $logger->_set_level_if_first($INFO);
88 27         56 $logger->level($logger->level());
89             }
90              
91 32         8921 return;
92             } ## end sub import
93              
94             sub new {
95 37     37 1 1406 my $package = shift;
96 37 100       151 my %args = ref($_[0]) ? %{$_[0]} : @_;
  8         34  
97              
98 37 50       126 $args{format} = $args{layout} if exists $args{layout};
99              
100 37         131 my $channels_input = [fh => \*STDERR];
101 37 100       108 if (exists $args{channels}) {
102 1         3 $channels_input = $args{channels};
103             }
104             else {
105 36         88 for my $key (qw< file_append file_create file_insecure file fh >) {
106 173 100       290 next unless exists $args{$key};
107 4         11 $channels_input = [$key => $args{$key}];
108 4         11 last;
109             }
110             } ## end else [ if (exists $args{channels...})]
111 37         114 my $channels = build_channels($channels_input);
112 37 100       134 $channels = $channels->[0] if @$channels == 1; # remove outer shell
113              
114 37         140 my $self = bless {
115             fh => $channels,
116             level => $INFO,
117             }, $package;
118              
119 37         82 for my $accessor (qw( level fh format )) {
120 111 100       207 next unless defined $args{$accessor};
121 18         68 $self->$accessor($args{$accessor});
122             }
123              
124 37 100       294 $self->format('[%d] [%5p] %m%n') unless exists $self->{format};
125              
126 37 100       95 if (exists $args{loglocal}) {
127 1         2 my $local = $args{loglocal};
128 1         4 $self->loglocal($_, $local->{$_}) for keys %$local;
129             }
130              
131 37         1088 return $self;
132             } ## end sub new
133              
134             sub build_channels {
135 37 50 33 37 1 239 my @pairs = (@_ && ref($_[0])) ? @{$_[0]} : @_;
  37         436  
136 37         78 my @channels;
137 37         92 while (@pairs) {
138 40         106 my ($key, $value) = splice @pairs, 0, 2;
139              
140             # some initial validation
141 40 50       104 croak "build_channels(): undefined key in list"
142             unless defined $key;
143 40 50       79 croak "build_channels(): undefined value for key $key"
144             unless defined $value;
145              
146             # analyze the key-value pair and set the channel accordingly
147 40         62 my ($channel, $set_autoflush);
148 40 100       213 if ($key =~ m{\A(?: fh | sub | code | channel )\z}mxs) {
    100          
    50          
    0          
149 36         52 $channel = $value;
150             }
151             elsif ($key eq 'file_append') {
152 2 50       71 open $channel, '>>', $value
153             or croak "open('$value') for appending: $!";
154 2         7 $set_autoflush = 1;
155             }
156             elsif ($key eq 'file_create') {
157 2 50       188 open $channel, '>', $value
158             or croak "open('$value') for creating: $!";
159 2         8 $set_autoflush = 1;
160             }
161             elsif ($key =~ m{\A file (?: _insecure )? \z}mxs) {
162 0 0       0 open $channel, $value
163             or croak "open('$value'): $!";
164 0         0 $set_autoflush = 1;
165             }
166             else {
167 0         0 croak "unsupported channel key '$key'";
168             }
169              
170             # autoflush new filehandle if applicable
171 40 100       124 if ($set_autoflush) {
172 4         18 my $previous = select($channel);
173 4         14 $|++;
174 4         15 select($previous);
175             }
176              
177             # record the channel, on to the next
178 40         112 push @channels, $channel;
179             } ## end while (@pairs)
180 37         78 return \@channels;
181             } ## end sub build_channels
182              
183 87   66 87 1 11278 sub get_logger { return $_instance ||= __PACKAGE__->new(); }
184 2     2 1 63 sub LOGLEVEL { return get_logger()->level(@_); }
185              
186             sub LEVELID_FOR {
187 7     7 1 837 my $level = shift;
188 7 50       29 return $id_for{$level} if exists $id_for{$level};
189 0         0 return;
190             } ## end sub LEVELID_FOR
191              
192             sub LEVELNAME_FOR {
193 7     7 1 3381 my $id = shift;
194 7 50       28 return $name_of{$id} if exists $name_of{$id};
195 0 0       0 return $id if exists $id_for{$id};
196 0         0 return;
197             } ## end sub LEVELNAME_FOR
198              
199             sub loglocal {
200 11     11 1 1462 my $self = shift;
201 11         15 my $key = shift;
202 11         18 my $retval = delete $self->{loglocal}{$key};
203 11 100       25 $self->{loglocal}{$key} = shift if @_;
204 11         23 return $retval;
205             } ## end sub loglocal
206 4     4 1 2277 sub LOGLOCAL { return get_logger->loglocal(@_) }
207              
208             sub format {
209 93     93 1 21157 my $self = shift;
210              
211 93 50       190 if (@_) {
212 93         189 $self->{format} = shift;
213 93         211 $self->{args} = \my @args;
214             my $replace = sub {
215 210 100   210   420 if (defined $_[2]) { # op with options
216 7         19 my ($num, $opts, $op) = @_[0 .. 2];
217 7         15 push @args, [$op, $opts];
218 7         46 return "%$num$format_for{$op}[0]";
219             }
220 203 100       346 if (defined $_[4]) { # op without options
221 199         534 my ($num, $op) = @_[3, 4];
222 199         368 push @args, [$op];
223 199         1253 return "%$num$format_for{$op}[0]";
224             }
225              
226             # not an op
227 4 100 100     15 my $char = ((!defined($_[5])) || ($_[5] eq '%')) ? '' : $_[5];
228 4         27 return '%%' . $char; # keep the percent AND the char, if any
229 93         535 };
230              
231             # transform into real format
232 93         223 my ($with_options, $standalone) = ('', '');
233 93         376 for my $key (keys %format_for) {
234 1581   100     2732 my $type = $format_for{$key}[2] || '';
235 1581 100       1842 $with_options .= $key if $type;
236 1581 100       2214 $standalone .= $key if $type ne 'required';
237             }
238              
239             # quotemeta or land on impossible character class if empty
240             $_ = length($_) ? quotemeta($_) : '^\\w\\W'
241 93 50       389 for ($with_options, $standalone);
242 93         1754 $self->{format} =~ s<
243             % # format marker
244             (?:
245             (?: # something with options
246             ( -? \d* (?:\.\d+)? ) # number
247             ( (?:\{ .*? \}) ) # options
248             ([$with_options]) # specifier
249             )
250             | (?:
251             ( -? \d* (?:\.\d+)? ) # number
252             ([$standalone]) # specifier
253             )
254             | (.) # just any char
255             | \z # just the end of it!
256             )
257             >
258 210         457 {
259             $replace->($1, $2, $3, $4, $5, $6);
260             }gsmex;
261 93         206 } ## end if (@_)
262             return $self->{format};
263             } ## end sub format
264              
265             *layout = \&format;
266              
267 108     108 1 171 sub emit_log {
268 108         175 my ($self, $message) = @_;
269 108 100       257 my $fh = $self->{fh};
270             for my $channel ((ref($fh) eq 'ARRAY') ? (@$fh) : ($fh)) {
271             (ref($channel) eq 'CODE')
272 111 100       222 ? $channel->($message, $self)
  91         408  
273             : print {$channel} $message;
274 108         333 }
275             return $message;
276             } ## end sub emit_log
277              
278 133     133 1 211 sub log {
279 133 100       252 my $self = shift;
280             return if $self->{level} == $DEAD;
281 131         157  
282 131 100       245 my $level = shift;
283             return if $level > $self->{level};
284              
285             my %data_for = (
286             level => $level,
287 108 100       334 message => \@_,
288             (exists($self->{loglocal}) ? (loglocal => $self->{loglocal}) : ()),
289             );
290 108         154 my $message = sprintf $self->{format},
  236         512  
  108         195  
291             map { $format_for{$_->[0]}[1]->(\%data_for, @$_); } @{$self->{args}};
292 108         272  
293             return $self->emit_log($message);
294             } ## end sub log
295 2     2 1 10  
296             sub ALWAYS { return $_instance->log($OFF, @_); }
297              
298 0   0 0   0 sub _exit {
299 0 0       0 my $self = shift || $_instance;
300 0 0       0 exit $self->{logexit_code} if defined $self->{logexit_code};
301             exit $Log::Log4perl::LOGEXIT_CODE
302 0         0 if defined $Log::Log4perl::LOGEXIT_CODE;
303             exit 1;
304             } ## end sub _exit
305              
306 4     4 1 11 sub logwarn {
307             my $self = shift;
308 4         6  
309 4 50 33     7 my @message;
310             @message = __expand_message_list({message => \@_})
311             if $self->is_warn() || $LOGDIE_MESSAGE_ON_STDERR;
312 4         35  
313             $self->warn(@message);
314 4 50       16  
315             if ($LOGDIE_MESSAGE_ON_STDERR) {
316 4 50       8 # default warning when nothing is passed to warn
317             push @message, "Warning: something's wrong" unless @message;
318              
319 4         19 # add 'at line ' unless argument ends in "\n";
320 4 50       20 my (undef, $file, $line) = caller(1);
321             push @message, sprintf " at %s line %d.\n", $file, $line
322             if substr($message[-1], -1, 1) ne "\n";
323              
324 4         31 # go for it!
325             CORE::warn(@message);
326             }
327              
328 4         21 return
329             } ## end sub logwarn
330              
331 1     1 1 8 sub logdie {
332             my $self = shift;
333 1         2  
334 1 50 33     3 my @message;
335             @message = __expand_message_list({message => \@_})
336             if $self->is_fatal() || $LOGDIE_MESSAGE_ON_STDERR;
337 1         7  
338             $self->fatal(@message);
339 1 50       2  
340             if ($LOGDIE_MESSAGE_ON_STDERR) {
341 1 50       3 # default die message when nothing is passed to die
342             push @message, "Died" unless @message;
343              
344 1         5 # add 'at line ' unless argument ends in "\n";
345 1 50       7 my (undef, $file, $line) = caller(1);
346             push @message, sprintf " at %s line %d.\n", $file, $line
347             if substr($message[-1], -1, 1) ne "\n";
348              
349 1         5 # go for it!
350             CORE::die(@message);
351             }
352 0         0  
353             $self->_exit();
354             } ## end sub logdie
355              
356 0     0 1 0 sub logexit {
357 0         0 my $self = shift;
358 0         0 $self->fatal(@_);
359             $self->_exit();
360             }
361              
362 10     10   13 sub _carpstuff {
363 10         13 my $self = shift;
364 10         15 my $renderer = shift;
365 10         10 my $emitter = shift;
366             my $log_level = shift;
367 10         57  
368             my $emit_log = $self->can("is_$log_level")->($self);
369 10         43  
370 10         25 require Carp;
371 10         14 local $Carp::Internal{'' . __PACKAGE__} = 1;
372             local $Carp::CarpLevel = $Carp::CarpLevel + 2;
373 10         12  
374 10 50 33     40 my @message;
375             @message = __expand_message_list({message => \@_})
376             if $emit_log || $LOGDIE_MESSAGE_ON_STDERR;
377 10 50       58  
378 10         1481 if ($emit_log) { # avoid unless we're allowed to emit
379 10         278 my $message = Carp->can($renderer)->(@message);
380 10         50 my $method = $self->can($log_level);
381             $self->$method($_) for split m{\n}mxs, $message;
382 10 100       20 }
383 8         818 if ($LOGDIE_MESSAGE_ON_STDERR) {
384             Carp->can($emitter)->(@message);
385             }
386 7         204  
387             return;
388             }
389              
390 4     4 1 13 sub logcarp {
391 4         15 my $self = shift;
392             return $self->_carpstuff(qw< shortmess carp warn >, @_);
393             } ## end sub logcarp
394              
395 2     2 1 7 sub logcluck {
396 2         6 my $self = shift;
397             return $self->_carpstuff(qw< longmess cluck warn >, @_);
398             } ## end sub logcluck
399              
400 3     3 1 6 sub logcroak {
401 3         15 my $self = shift;
402 1         3 $self->_carpstuff(qw< shortmess croak fatal >, @_);
403             $self->_exit();
404             } ## end sub logcroak
405              
406 1     1 1 14 sub logconfess {
407 1         4 my $self = shift;
408 0         0 $self->_carpstuff(qw< longmess confess fatal >, @_);
409             $self->_exit();
410             } ## end sub logconfess
411              
412 125     125 1 15882 sub level {
413 125 50       247 my $self = shift;
414 125 100       238 $self = $_instance unless ref $self;
415 87         116 if (@_) {
416 87 50       197 my $level = shift;
417 87         162 return unless exists $id_for{$level};
418 87         135 $self->{level} = $id_for{$level};
419             $self->{_count}++;
420 125         222 } ## end if (@_)
421             return $self->{level};
422             } ## end sub level
423              
424 32     32   78 sub _set_level_if_first {
425 32 100       94 my ($self, $level) = @_;
426 27         77 if (!$self->{_count}) {
427 27         45 $self->level($level);
428             delete $self->{_count};
429 32         43 }
430             return;
431             } ## end sub _set_level_if_first
432              
433             sub __expand_message_list {
434             join(
435 81 50   81   172 (defined $, ? $, : ''),
  88 100       293  
  81         140  
436             map { ref($_) eq 'CODE' ? $_->() : $_; } @{shift->{message}}
437             );
438             }
439              
440             BEGIN {
441              
442             # Time tracking's start time. Used to be tied to $^T but Log::Log4perl
443 26     26   90 # does differently and uses Time::HiRes if available
444 26         103 my $has_time_hires;
  0         0  
445 26         68 my $gtod = sub { return (time(), 0) };
446 26         11534 eval {
447 26         27355 require Time::HiRes;
448 26         125 $has_time_hires = 1;
449             $gtod = \&Time::HiRes::gettimeofday;
450             };
451 26         179  
452             my $start_time = [$gtod->()];
453              
454 26         48 # For supporting %R
455             my $last_log = $start_time;
456              
457 26         2469 # Timezones are... differently supported somewhere
458             my $strftime_has_tz_offset =
459 26 50       138 POSIX::strftime('%z', localtime()) =~ m<\A [-+] \d{4} \z>mxs;
460 0         0 if (! $strftime_has_tz_offset) {
461             require Time::Local;
462             }
463              
464 26     26   197 { # alias to the one in Log::Log4perl, for easier switching towards that
  26         56  
  26         31842  
  26         46  
465 26         73 no strict 'refs';
466             *caller_depth = *Log::Log4perl::caller_depth;
467 26         43 }
468 26   50     179 our $caller_depth;
469             $caller_depth ||= 0;
470              
471             # %format_for idea from Log::Tiny by J. M. Adler
472 1         4 %format_for = ( # specifiers according to Log::Log4perl
473             c => [s => sub { 'main' }],
474             C => [
475 5         37 s => sub {
476 5         11 my ($internal_package) = caller 0;
477 5         21 my $max_i = 5;
478 5         10 my $i = 1;
479 5         13 my $package;
480 13         38 while ($i <= $max_i) {
481 13 50       26 ($package) = caller $i;
482 13 100       22 return '*undef*' unless defined $package;
483 8         13 last if $package ne $internal_package;
484             ++$i;
485 5 50       30 } ## end while ($i <= 4)
486 5 100       17 return '*undef' if $i > $max_i;
487 5         17 ($package) = caller($i += $caller_depth) if $caller_depth;
488             return $package;
489             },
490             ],
491             d => [
492 24   50     28 s => sub {
  24         131  
493 24         966 my ($epoch) = @{shift->{tod} ||= [$gtod->()]};
494             return POSIX::strftime('%Y/%m/%d %H:%M:%S', localtime($epoch));
495             },
496             ],
497             D => [
498 6         12 s => sub {
499 6 100       12 my ($data, $op, $options) = @_;
500 6         9 $options = '{}' unless defined $options;
501 6         18 $options = substr $options, 1, length($options) - 2;
  4         10  
502 6   100     11 my %flag_for = map { $_ => 1 } split /\s*,\s*/, lc($options);
  6         25  
503 6         14 my ($s, $u) = @{$data->{tod} ||= [$gtod->()]};
504             $u = substr "000000$u", -6, 6; # padding left with 0
505 6 100       66 return POSIX::strftime("%Y-%m-%d %H:%M:%S.$u+0000", gmtime $s)
506             if $flag_for{utc};
507 4         69  
508 4 50       105 my @localtime = localtime $s;
509             return POSIX::strftime("%Y-%m-%d %H:%M:%S.$u%z", @localtime)
510             if $strftime_has_tz_offset;
511 0         0  
512 0         0 my $sign = '+';
513 0 0       0 my $offset = Time::Local::timegm(@localtime) - $s;
514 0         0 ($sign, $offset) = ('-', -$offset) if $offset < 0;
515             my $z = sprintf '%s%02d%02d',
516             $sign, # sign
517             int($offset / 3600), # hours
518 0         0 (int($offset / 60) % 60); # minutes
519             return POSIX::strftime("%Y-%m-%d %H:%M:%S.$u$z", @localtime);
520             },
521             'optional'
522             ],
523             e => [
524 3         6 s => sub {
525 3   50     16 my ($data, $op, $options) = @_;
526 3 50       9 $data->{tod} ||= [$gtod->()]; # guarantee consistency here
527 3         7 my $local = $data->{loglocal} or return '';
528 3 50       6 my $key = substr $options, 1, length($options) - 2;
529 3         4 return '' unless exists $local->{$key};
530 3 50       7 my $target = $local->{$key};
531 3 100       11 return '' unless defined $target;
532 2 50       6 my $reft = ref $target or return $target;
533 2         4 return '' unless $reft eq 'CODE';
534             return $target->($data, $op, $options);
535             },
536             'required',
537             ],
538             F => [
539 5         33 s => sub {
540 5         9 my ($internal_package) = caller 0;
541 5         9 my $i = 1;
542 5         13 my ($package, $file);
543 13         34 while ($i <= 4) {
544 13 50       26 ($package, $file) = caller $i;
545 13 100       20 return '*undef*' unless defined $package;
546 8         11 last if $package ne $internal_package;
547             ++$i;
548 5 50       13 } ## end while ($i <= 4)
549 5 100       10 return '*undef' if $i > 4;
550 5         13 (undef, $file) = caller($i += $caller_depth) if $caller_depth;
551             return $file;
552             },
553             ],
554             H => [
555 1 50       1 s => sub {
  1         5  
  1         3  
556             eval { require Sys::Hostname; Sys::Hostname::hostname() }
557             || '';
558             },
559             ],
560             l => [
561 3         14 s => sub {
562 3         7 my ($internal_package) = caller 0;
563 3         6 my $i = 1;
564 3         8 my ($package, $filename, $line);
565 6         17 while ($i <= 4) {
566 6 50       12 ($package, $filename, $line) = caller $i;
567 6 100       13 return '*undef*' unless defined $package;
568 3         5 last if $package ne $internal_package;
569             ++$i;
570 3 50       7 } ## end while ($i <= 4)
571 3 100       7 return '*undef' if $i > 4;
572             (undef, $filename, $line) = caller($i += $caller_depth)
573 3         10 if $caller_depth;
574 3 50       8 my (undef, undef, undef, $subroutine) = caller($i + 1);
575 3         17 $subroutine = "main::" unless defined $subroutine;
576             return sprintf '%s %s (%d)', $subroutine, $filename, $line;
577             },
578             ],
579             L => [
580 5         20 d => sub {
581 5         9 my ($internal_package) = caller 0;
582 5         7 my $i = 1;
583 5         14 my ($package, $line);
584 13         34 while ($i <= 4) {
585 13 50       31 ($package, undef, $line) = caller $i;
586 13 100       24 return -1 unless defined $package;
587 8         10 last if $package ne $internal_package;
588             ++$i;
589 5 50       21 } ## end while ($i <= 4)
590 5 100       12 return -1 if $i > 4;
591             (undef, undef, $line) = caller($i += $caller_depth)
592 5         18 if $caller_depth;
593             return $line;
594             },
595             ],
596             m => [s => \&__expand_message_list,],
597             M => [
598 16         51 s => sub {
599 16         23 my ($internal_package) = caller 0;
600 16         19 my $max_i = 5;
601 16         29 my $i = 1;
602 68         148 while ($i <= $max_i) {
603 68 50       103 my ($package) = caller $i;
604 68 100       105 return '*undef*' unless defined $package;
605 52         65 last if $package ne $internal_package;
606             ++$i;
607 16 50       26 } ## end while ($i <= 4)
608 16 100       23 return '*undef' if $i > $max_i;
609 16         41 $i += $caller_depth if $caller_depth;
610 16 50       31 my (undef, undef, undef, $subroutine) = caller($i + 1);
611 16         31 $subroutine = "main::" unless defined $subroutine;
612             return $subroutine;
613             },
614 54         177 ],
615 37         94 n => [s => sub { "\n" },],
616 1         4 p => [s => sub { $name_of{shift->{level}} },],
617             P => [d => sub { $$ },],
618             r => [
619 3   50     6 d => sub {
  3         23  
620 3         7 my ($s, $u) = @{shift->{tod} ||= [$gtod->()]};
621 3         10 $s -= $start_time->[0];
622 3 50       7 my $m = int(($u - $start_time->[1]) / 1000);
623 3         10 ($s, $m) = ($s - 1, $m + 1000) if $m < 0;
624             return $m + 1000 * $s;
625             },
626             ],
627             R => [
628 3   100     4 d => sub {
  3         16  
629 3         6 my ($sx, $ux) = @{shift->{tod} ||= [$gtod->()]};
630 3         6 my $s = $sx - $last_log->[0];
631 3 50       9 my $m = int(($ux - $last_log->[1]) / 1000);
632 3         6 ($s, $m) = ($s - 1, $m + 1000) if $m < 0;
633 3         14 $last_log = [$sx, $ux];
634             return $m + 1000 * $s;
635             },
636             ],
637             T => [
638 3         14 s => sub {
639 3         8 my ($internal_package) = caller 0;
640 3         8 my $level = 1;
641 6         16 while ($level <= 4) {
642 6 50       15 my ($package) = caller $level;
643 6 100       10 return '*undef*' unless defined $package;
644 3         6 last if $package ne $internal_package;
645             ++$level;
646 3 50       7 } ## end while ($level <= 4)
647             return '*undef' if $level > 4;
648              
649             # usage of Carp::longmess() and substitutions is mostly copied
650             # from Log::Log4perl for better alignment and easier
651 3         6 # transition to the "bigger" module
652             local $Carp::CarpLevel =
653 3         266 $Carp::CarpLevel + $level + $caller_depth;
654 3         478 chomp(my $longmess = Carp::longmess());
655 3         10 $longmess =~ s{(?:\A\s*at.*?\n|^\s*)}{}mxsg;
656 3         11 $longmess =~ s{\n}{, }g;
657             return $longmess;
658 26         1222 },
659             ],
660             );
661              
662 26     26   181 # From now on we're going to play with GLOBs...
  26         41  
  26         7556  
663             no strict 'refs';
664 26         104  
665             for my $name (qw( FATAL ERROR WARN INFO DEBUG TRACE )) {
666              
667 156         511 # create the ->level methods
668 131     131   1287 *{__PACKAGE__ . '::' . lc($name)} = sub {
669 131         366 my $self = shift;
670 156         344 return $self->log($$name, @_);
671             };
672              
673 156         585 # create ->is_level and ->isLevelEnabled methods as well
674 156         530 *{__PACKAGE__ . '::is' . ucfirst(lc($name)) . 'Enabled'} =
675 87 100 66 87   14188 *{__PACKAGE__ . '::is_' . lc($name)} = sub {
676 57         161 return 0 if $_[0]->{level} == $DEAD || $$name > $_[0]->{level};
677 156         337 return 1;
678             };
679             } ## end for my $name (qw( FATAL ERROR WARN INFO DEBUG TRACE ))
680 26         73  
681             for my $name (
682             qw(
683             FATAL ERROR WARN INFO DEBUG TRACE
684             LOGWARN LOGDIE LOGEXIT
685             LOGCARP LOGCLUCK LOGCROAK LOGCONFESS
686             )
687             )
688 338         985 {
689 18     18   2366 *{__PACKAGE__ . '::' . $name} = sub {
690 338         875 $_instance->can(lc $name)->($_instance, @_);
691             };
692             } ## end for my $name (qw( FATAL ERROR WARN INFO DEBUG TRACE...))
693 26         60  
694 52         216 for my $accessor (qw( fh logexit_code )) {
695 107     107   3022133 *{__PACKAGE__ . '::' . $accessor} = sub {
696 107 50       237 my $self = shift;
697 107 100       502 $self = $_instance unless ref $self;
698 107         187 $self->{$accessor} = shift if @_;
699 52         404 return $self->{$accessor};
700             };
701             } ## end for my $accessor (qw( fh logexit_code ))
702 26         62  
703 26         51 my $index = -1;
704 208         553 for my $name (qw( DEAD OFF FATAL ERROR WARN INFO DEBUG TRACE )) {
705 208         285 $name_of{$$name = $index} = $name;
706 208         328 $id_for{$name} = $index;
707 208         296 $id_for{$index} = $index;
708             ++$index;
709             } ## end for my $name (qw( DEAD OFF FATAL ERROR WARN INFO DEBUG TRACE ))
710 26         98  
711             get_logger(); # initialises $_instance;
712             } ## end BEGIN
713              
714             1; # Magic true value required at end of module