File Coverage

blib/lib/Log/Contextual.pm
Criterion Covered Total %
statement 121 131 92.3
branch 34 48 70.8
condition 19 27 70.3
subroutine 34 36 94.4
pod 0 9 0.0
total 208 251 82.8


line stmt bran cond sub pod time code
1             package Log::Contextual;
2             $Log::Contextual::VERSION = '0.008000';
3             # ABSTRACT: Simple logging interface with a contextual log
4              
5 21     21   682144 use strict;
  21         185  
  21         737  
6 21     21   170 use warnings;
  21         163  
  21         1275  
7              
8             my @levels = qw(debug trace warn info error fatal);
9              
10 21     21   8766 use Exporter::Declare;
  21         584580  
  21         123  
11 21     21   53931 use Exporter::Declare::Export::Generator;
  21         71  
  21         942  
12 21     21   9423 use Data::Dumper::Concise;
  21         218127  
  21         3355  
13 21     21   221 use Scalar::Util 'blessed';
  21         61  
  21         1249  
14              
15 21     21   165 use B qw(svref_2object);
  21         60  
  21         7053  
16              
17             sub stash_name {
18 0     0 0 0 my ($coderef) = @_;
19 0 0       0 ref $coderef or return;
20 0         0 my $cv = B::svref_2object($coderef);
21 0 0       0 $cv->isa('B::CV') or return;
22              
23             # bail out if GV is undefined
24 0 0       0 $cv->GV->isa('B::SPECIAL') and return;
25              
26 0         0 return $cv->GV->STASH->NAME;
27             }
28              
29             my @dlog = ((map "Dlog_$_", @levels), (map "DlogS_$_", @levels));
30              
31             my @log = ((map "log_$_", @levels), (map "logS_$_", @levels));
32              
33             sub _maybe_export {
34 806     806   25280 my ($spec, $target, $name, $new_code) = @_;
35              
36 21     21   182 no strict 'refs';
  21         59  
  21         43012  
37 806 50       1789 if (defined &{"${target}::${name}"}) {
  806         5034  
38 0         0 my $code = \&{"${target}::${name}"};
  0         0  
39              
40             # this will warn
41 0 0       0 $spec->add_export("&$name", $new_code)
42             unless (stash_name($code) eq __PACKAGE__);
43             } else {
44 806         3191 $spec->add_export("&$name", $new_code)
45             }
46             }
47              
48             eval {
49             require Log::Log4perl;
50             die if $Log::Log4perl::VERSION < 1.29;
51             Log::Log4perl->wrapper_register(__PACKAGE__)
52             };
53              
54             # ____ is because tags must have at least one export and we don't want to
55             # export anything but the levels selected
56       0     sub ____ { }
57              
58             exports('____', @dlog, @log, qw( set_logger with_logger has_logger ));
59              
60             export_tag dlog => ('____');
61             export_tag log => ('____');
62             import_arguments qw(logger package_logger default_logger);
63              
64             sub router {
65 63   66 63 0 531 our $Router_Instance ||= do {
66 20         13075 require Log::Contextual::Router;
67 20         176 Log::Contextual::Router->new
68             }
69             }
70              
71             sub default_import {
72 3     3 0 35 my ($class) = shift;
73              
74 3         52 die 'Log::Contextual does not have a default import list';
75              
76             ()
77 0         0 }
78              
79 29     29 0 194 sub arg_logger { $_[1] }
80 30 100   30 0 623 sub arg_levels { $_[1] || [qw(debug trace warn info error fatal)] }
81 30     30 0 212 sub arg_package_logger { $_[1] }
82 30     30 0 24536 sub arg_default_logger { $_[1] }
83              
84             sub before_import {
85 35     35 0 44404 my ($class, $importer, $spec) = @_;
86 35         196 my $router = $class->router;
87 35         1860 my $exports = $spec->exports;
88 35         315 my %router_args = (
89             exporter => $class,
90             target => $importer,
91             arguments => $spec->argument_info
92             );
93              
94             my @tags = $class->default_import($spec)
95 35 100       2630 if $spec->config->{default};
96              
97 32         330 for (@tags) {
98 5 50       43 die "only tags are supported for defaults at this time"
99             unless $_ =~ /^:(.*)$/;
100              
101 5         22 $spec->config->{$1} = 1;
102             }
103              
104 32         265 $router->before_import(%router_args);
105              
106 32 100       184 if ($exports->{'&set_logger'}) {
107 18 50       127 die ref($router) . " does not support set_logger()"
108             unless $router->does('Log::Contextual::Role::Router::SetLogger');
109              
110             _maybe_export($spec, $importer, 'set_logger',
111 12     12   2933 sub { $router->set_logger(@_) },
112 18         1174 );
113             }
114              
115 32 100       1270 if ($exports->{'&with_logger'}) {
116 10 50       63 die ref($router) . " does not support with_logger()"
117             unless $router->does('Log::Contextual::Role::Router::WithLogger');
118              
119             _maybe_export($spec, $importer, 'with_logger',
120 4     4   1868 sub { $router->with_logger(@_) },
121 10         305 );
122             }
123              
124 32 100       509 if ($exports->{'&has_logger'}) {
125 1 50       8 die ref($router) . " does not support has_logger()"
126             unless $router->does('Log::Contextual::Role::Router::HasLogger');
127              
128             _maybe_export($spec, $importer, 'has_logger',
129 2     2   20 sub { $router->has_logger(@_) },
130 1         37 );
131             }
132              
133 32         137 my @levels = @{$class->arg_levels($spec->config->{levels})};
  32         159  
134 32         203 for my $level (@levels) {
135 181         5994 my %base =
136             (exporter => $class, caller_level => 1, message_level => $level);
137 181         429 my %exports;
138 181 100 100     596 if ($spec->config->{log} || $exports->{"&log_$level"}) {
139             $exports{log_} = sub (&@) {
140 97     97   64743 my ($code, @args) = @_;
141 97         883 $router->handle_log_request(
142             %base,
143             caller_package => scalar(caller),
144             message_sub => $code,
145             message_args => \@args,
146             );
147 94         780 return @args;
148 158         1781 };
149             }
150 181 100 66     819 if ($spec->config->{log} || $exports->{"&slog_$level"}) {
151             $exports{slog_} = sub {
152 9     9   5584 my ($text, @args) = @_;
153 9         48 $router->handle_log_request(
154             %base,
155             caller_package => scalar(caller),
156             message_text => $text,
157             message_args => \@args,
158             );
159 9         50 return @args;
160 157         1508 };
161             }
162 181 100 66     812 if ($spec->config->{log} || $exports->{"&logS_$level"}) {
163             $exports{logS_} = sub (&@) {
164 38     38   42299 my ($code, @args) = @_;
165 38         300 $router->handle_log_request(
166             %base,
167             caller_package => scalar(caller),
168             message_sub => $code,
169             message_args => \@args,
170             );
171 38         425 return $args[0];
172 157         1541 };
173             }
174 181 100 66     808 if ($spec->config->{log} || $exports->{"&slogS_$level"}) {
175             $exports{slogS_} = sub {
176 3     3   2501 my ($text, @args) = @_;
177 3         17 $router->handle_log_request(
178             %base,
179             caller_package => scalar(caller),
180             message_text => $text,
181             message_args => \@args,
182             );
183 3         17 return $args[0];
184 157         1362 };
185             }
186 181 100 66     739 if ($spec->config->{dlog} || $exports->{"&Dlog_$level"}) {
187             $exports{Dlog_} = sub (&@) {
188 30     30   29055 my ($code, @args) = @_;
189             my $wrapped = sub {
190 25 100   25   147 local $_ = (@_ ? Data::Dumper::Concise::Dumper @_ : '()');
191 25         2814 &$code;
192 30         216 };
193 30         267 $router->handle_log_request(
194             %base,
195             caller_package => scalar(caller),
196             message_sub => $wrapped,
197             message_args => \@args,
198             );
199 30         408 return @args;
200 37         358 };
201             }
202 181 100 66     1468 if ($spec->config->{dlog} || $exports->{"&Dslog_$level"}) {
203             $exports{Dslog_} = sub {
204 6     6   10051 my ($text, @args) = @_;
205             my $wrapped = sub {
206 6 50   6   37 $text . (@_ ? Data::Dumper::Concise::Dumper @_ : '()');
207 6         43 };
208 6         56 $router->handle_log_request(
209             %base,
210             caller_package => scalar(caller),
211             message_sub => $wrapped,
212             message_args => \@args,
213             );
214 6         86 return @args;
215 37         374 };
216             }
217 181 100 66     1319 if ($spec->config->{dlog} || $exports->{"&DlogS_$level"}) {
218             $exports{DlogS_} = sub (&$) {
219 21     21   15183 my ($code, $ref) = @_;
220             my $wrapped = sub {
221 16     16   72 local $_ = Data::Dumper::Concise::Dumper($_[0]);
222 16         2088 &$code;
223 21         108 };
224 21         180 $router->handle_log_request(
225             %base,
226             caller_package => scalar(caller),
227             message_sub => $wrapped,
228             message_args => [$ref],
229             );
230 21         278 return $ref;
231 37         368 };
232             }
233 181 100 66     1310 if ($spec->config->{dlog} || $exports->{"&DslogS_$level"}) {
234             $exports{DslogS_} = sub {
235 6     6   8736 my ($text, $ref) = @_;
236             my $wrapped = sub {
237 6     6   29 $text . Data::Dumper::Concise::Dumper($_[0]);
238 6         39 };
239 6         56 $router->handle_log_request(
240             %base,
241             caller_package => scalar(caller),
242             message_sub => $wrapped,
243             message_args => [$ref],
244             );
245 6         83 return $ref;
246 37         380 };
247             }
248             _maybe_export($spec, $importer, $_ . $level, $exports{$_})
249 181         1823 for keys %exports;
250             }
251             }
252              
253             sub after_import {
254 32     32 0 32768 my ($class, $importer, $spec) = @_;
255 32         195 my %router_args = (
256             exporter => $class,
257             target => $importer,
258             arguments => $spec->argument_info
259             );
260 32         1933 $class->router->after_import(%router_args);
261             }
262              
263             for (qw(set with)) {
264 21     21   226 no strict 'refs';
  21         63  
  21         2878  
265             my $sub = "${_}_logger";
266             *{"Log::Contextual::$sub"} = sub {
267 2     2   1733 die "$sub is no longer a direct sub in Log::Contextual. "
268             . 'Note that this feature was never tested nor documented. '
269             . "Please fix your code to import $sub instead of trying to use it directly"
270             }
271             }
272              
273             1;
274              
275             __END__