File Coverage

blib/lib/Log/Log4perl/Tiny.pm
Criterion Covered Total %
statement 379 406 93.3
branch 164 230 71.3
condition 21 38 55.2
subroutine 40 42 95.2
pod 22 22 100.0
total 626 738 84.8


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