File Coverage

blib/lib/Log/Contextual.pm
Criterion Covered Total %
statement 137 145 94.4
branch 30 52 57.6
condition 5 8 62.5
subroutine 40 41 97.5
pod 0 6 0.0
total 212 252 84.1


line stmt bran cond sub pod time code
1             package Log::Contextual;
2 23     23   1030275 use strict;
  23         57  
  23         1045  
3 23     23   121 use warnings;
  23         105  
  23         1678  
4              
5             our $VERSION = '0.009001';
6              
7 23     23   11650 use Data::Dumper::Concise;
  23         265754  
  23         2738  
8              
9 23     23   219 use B qw(svref_2object);
  23         74  
  23         32083  
10              
11             sub _stash_name {
12 0     0   0 my ($coderef) = @_;
13 0 0       0 ref $coderef or return;
14 0         0 my $cv = B::svref_2object($coderef);
15 0 0       0 $cv->isa('B::CV') or return;
16              
17             # bail out if GV is undefined
18 0 0       0 $cv->GV->isa('B::SPECIAL') and return;
19              
20 0         0 return $cv->GV->STASH->NAME;
21             }
22              
23             eval { ## no critic (ErrorHandling::RequireCheckingReturnValueOfEval)
24             require Log::Log4perl;
25             die if $Log::Log4perl::VERSION < 1.29;
26             Log::Log4perl->wrapper_register(__PACKAGE__)
27             };
28              
29             sub router {
30 29   66 29 0 161 our $Router_Instance ||= do {
31 18         10453 require Log::Contextual::Router;
32 18         146 Log::Contextual::Router->new
33             }
34             }
35              
36             sub default_import {
37 3     3 0 10 my ($class) = shift;
38              
39 3         46 die 'Log::Contextual does not have a default import list';
40             }
41              
42             my @all_levels = qw(debug trace warn info error fatal);
43              
44 28     28 0 144 sub arg_logger { $_[1] }
45 29 100   29 0 297 sub arg_levels { $_[1] || [@all_levels] }
46 29     29 0 123 sub arg_package_logger { $_[1] }
47 29     29 0 22028 sub arg_default_logger { $_[1] }
48              
49             my %exports;
50             for my $level (@all_levels) {
51             $exports{$_.'_'.$level} = { type => $_, level => $level }
52             for qw(Dlog DlogS Dslog DslogS);
53             $exports{$_.'_'.$level} = { type => $_, level => $level }
54             for qw(log logS slog slogS);
55             }
56              
57             $exports{$_} = {}
58             for qw( set_logger with_logger has_logger );
59             my %import_arguments = map +($_ => $_), qw(logger package_logger default_logger levels);
60             my %allowed_tags = map +($_ => $_), qw(log dlog);
61              
62             sub import {
63 34     34   11930 my ($class, @args) = @_;
64 34         108 my $target = caller;
65 34         112 my %options;
66             my @tags;
67 34         0 my @imports;
68              
69 34 100       141 @args = qw(:default)
70             if !@args;
71              
72 34         115 while (@args) {
73 83         160 my $arg = shift @args;
74 83 100       428 if ($arg =~ /\A[-:](.*)/s) {
75 54         222 my $name = $1;
76 54 100       273 if ($import_arguments{$name}) {
    100          
    50          
77 14         27 my $option_args = shift @args;
78 14         53 $options{$name} = $option_args;
79             }
80             elsif ($name eq 'default') {
81 6 50       30 my @tag_args = ref $args[0] ? shift @args : ();
82 6         34 push @args, map +($_ => @tag_args), $class->default_import;
83             }
84             elsif (defined $allowed_tags{$name}) {
85 34 50       115 my $tag_args = ref $args[0] ? shift @args : undef;
86 34         235 push @tags, { tag => $name, args => $tag_args };
87             }
88             else {
89 0         0 die "Invalid argument $arg!";
90             }
91             }
92             else {
93 29         77 $arg =~ s/\A&//;
94 29 50       98 my $export_config = $exports{$arg}
95             or die "Invalid import $arg!";
96              
97 29 50       101 my $import_args = ref $args[0] ? shift @args : undef;
98 29         164 push @imports, { import => $arg, args => $import_args, %$export_config };
99             }
100             }
101              
102 31         134 my @levels = @{$class->arg_levels($options{levels})};
  31         215  
103              
104 31         134 for my $tag (@tags) {
105             my @want
106             = $tag->{tag} eq 'log' ? qw(log logS slog slogS)
107 34 50       187 : $tag->{tag} eq 'dlog' ? qw(Dlog DlogS Dslog DslogS)
    100          
108             : die "Invalid tag $tag->{tag}";
109              
110 34         67 for my $want (@want) {
111             push @imports, map +{
112             import => "${want}_$_",
113             args => $tag->{args},
114 136         2006 type => $want,
115             level => $_
116             }, @levels;
117             }
118             }
119              
120 31         174 my %router_args = (
121             exporter => $class,
122             target => $target,
123             arguments => \%options,
124             );
125 31         143 my $router = $class->router;
126             # wrapped in an extra sub so that caller levels match what they were when
127             # using Exporter::Declare
128 31     31   1800 sub { $router->before_import(%router_args) }->();
  31         189  
129              
130 31         155 for my $import (@imports) {
131 781         1554 $class->_maybe_export($target, $import, $router);
132             }
133              
134 31     31   289 sub { $router->after_import(%router_args) }->();
  31         206  
135             }
136              
137             sub _maybe_export {
138 781     781   1351 my ($class, $target, $import, $router) = @_;
139              
140 781         1266 my $name = $import->{import};
141 781   50     2198 my $import_args = $import->{args} || {};
142              
143 781         1105 my $as = $import_args->{-as};
144 781         1077 my $prefix = $import_args->{-prefix};
145 781         1000 my $suffix = $import_args->{-suffix};
146              
147 781 50       1901 my $target_name = defined $as ? $as : (
    50          
    50          
148             (defined $prefix ? $prefix : '')
149             . $name
150             . (defined $suffix ? $suffix : '')
151             );
152 781         1174 my $full_target = "${target}::${target_name}";
153              
154 781   66     1599 my $method = '_gen_' . ($import->{type} || $name);
155 781         1210 my $level = $import->{level};
156              
157 781 100       2203 my $sub = $class->$method($router, defined $level ? $level : ());
158              
159 23     23   257 no strict 'refs';
  23         55  
  23         32413  
160 781 50       3408 if (defined &$full_target) {
161             return
162 0 0       0 if _stash_name(\&full_target) eq __PACKAGE__;
163              
164             # reexport will warn
165             }
166 781         2727 *$full_target = $sub;
167             }
168              
169             sub _gen_set_logger { ## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
170 17     17   50 my ($class, $router) = @_;
171 17 50       116 die ref($router) . " does not support set_logger()"
172             unless $router->does('Log::Contextual::Role::Router::SetLogger');
173              
174 12     12   381818 sub { $router->set_logger(@_) },
175 17         647 }
176              
177             sub _gen_with_logger { ## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
178 10     10   29 my ($class, $router) = @_;
179 10 50       51 die ref($router) . " does not support with_logger()"
180             unless $router->does('Log::Contextual::Role::Router::WithLogger');
181              
182 4     4   2750 sub { $router->with_logger(@_) },
183 10         396 }
184              
185             sub _gen_has_logger { ## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
186 1     1   5 my ($class, $router) = @_;
187 1 50       4 die ref($router) . " does not support has_logger()"
188             unless $router->does('Log::Contextual::Role::Router::HasLogger');
189              
190 2     2   20 sub { $router->has_logger(@_) },
191 1         17 }
192              
193             sub _gen_log { ## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
194 152     152   331 my ($class, $router, $level) = @_;
195              
196             sub (&@) {
197 97     97   1711434 my ($code, @args) = @_;
198 97         650 $router->handle_log_request(
199             exporter => $class,
200             caller_level => 1,
201             message_level => $level,
202             caller_package => scalar(caller),
203             message_sub => $code,
204             message_args => \@args,
205             );
206 94         728 return @args;
207 152         847 };
208             }
209              
210             sub _gen_slog { ## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
211 151     151   347 my ($class, $router, $level) = @_;
212             sub {
213 9     9   6943 my ($text, @args) = @_;
214 9         43 $router->handle_log_request(
215             exporter => $class,
216             caller_level => 1,
217             message_level => $level,
218             caller_package => scalar(caller),
219             message_text => $text,
220             message_args => \@args,
221             );
222 9         48 return @args;
223 151         798 };
224             }
225              
226             sub _gen_logS { ## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
227 151     151   286 my ($class, $router, $level) = @_;
228             sub (&@) {
229 38     38   31390 my ($code, @args) = @_;
230 38         274 $router->handle_log_request(
231             exporter => $class,
232             caller_level => 1,
233             message_level => $level,
234             caller_package => scalar(caller),
235             message_sub => $code,
236             message_args => \@args,
237             );
238 38         451 return $args[0];
239 151         713 };
240             }
241              
242             sub _gen_slogS { ## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
243 151     151   287 my ($class, $router, $level) = @_;
244             sub {
245 3     3   3852 my ($text, @args) = @_;
246 3         16 $router->handle_log_request(
247             exporter => $class,
248             caller_level => 1,
249             message_level => $level,
250             caller_package => scalar(caller),
251             message_text => $text,
252             message_args => \@args,
253             );
254 3         18 return $args[0];
255 151         741 };
256             }
257              
258              
259             sub _gen_Dlog { ## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
260 37     37   65 my ($class, $router, $level) = @_;
261             sub (&@) {
262 30     30   188211 my ($code, @args) = @_;
263             my $wrapped = sub {
264 25 100   25   112 local $_ = (@_ ? Data::Dumper::Concise::Dumper @_ : '()');
265 25         2585 &$code;
266 30         200 };
267 30         182 $router->handle_log_request(
268             exporter => $class,
269             caller_level => 1,
270             message_level => $level,
271             caller_package => scalar(caller),
272             message_sub => $wrapped,
273             message_args => \@args,
274             );
275 30         356 return @args;
276 37         208 };
277             }
278              
279             sub _gen_Dslog { ## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
280 37     37   68 my ($class, $router, $level) = @_;
281             sub {
282 6     6   11156 my ($text, @args) = @_;
283             my $wrapped = sub {
284 6 50       19 $text . (@_ ? Data::Dumper::Concise::Dumper @_ : '()');
285 6         33 };
286 6         42 $router->handle_log_request(
287             exporter => $class,
288             caller_level => 1,
289             message_level => $level,
290             caller_package => scalar(caller),
291             message_sub => $wrapped,
292             message_args => \@args,
293             );
294 6         61 return @args;
295 37         169 };
296             }
297              
298             sub _gen_DlogS { ## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
299 37     43   63 my ($class, $router, $level) = @_;
300             sub (&$) {
301 21     21   18027 my ($code, $ref) = @_;
302             my $wrapped = sub {
303 16         59 local $_ = Data::Dumper::Concise::Dumper($_[0]);
304 16         2116 &$code;
305 21         94 };
306 21         133 $router->handle_log_request(
307             exporter => $class,
308             caller_level => 1,
309             message_level => $level,
310             caller_package => scalar(caller),
311             message_sub => $wrapped,
312             message_args => [$ref],
313             );
314 21         268 return $ref;
315 37         253 };
316             }
317              
318             sub _gen_DslogS { ## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
319 37     53   76 my ($class, $router, $level) = @_;
320             sub {
321 6     6   6955 my ($text, $ref) = @_;
322             my $wrapped = sub {
323 6         16 $text . Data::Dumper::Concise::Dumper($_[0]);
324 6         32 };
325 6         34 $router->handle_log_request(
326             exporter => $class,
327             caller_level => 1,
328             message_level => $level,
329             caller_package => scalar(caller),
330             message_sub => $wrapped,
331             message_args => [$ref],
332             );
333 6         68 return $ref;
334 37         148 };
335             }
336              
337             for (qw(set with)) {
338 23     23   213 no strict 'refs';
  23         69  
  23         4146  
339             my $sub = "${_}_logger";
340             *{"Log::Contextual::$sub"} = sub {
341 2     8   174226 die "$sub is no longer a direct sub in Log::Contextual. "
342             . 'Note that this feature was never tested nor documented. '
343             . "Please fix your code to import $sub instead of trying to use it directly";
344             }
345             }
346              
347             1;
348              
349             __END__