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.008001';
3             # ABSTRACT: Simple logging interface with a contextual log
4              
5 21     21   451185 use strict;
  21         93  
  21         471  
6 21     21   101 use warnings;
  21         43  
  21         706  
7              
8             my @levels = qw(debug trace warn info error fatal);
9              
10 21     21   8325 use Exporter::Declare;
  21         382076  
  21         67  
11 21     21   28426 use Exporter::Declare::Export::Generator;
  21         40  
  21         347  
12 21     21   7981 use Data::Dumper::Concise;
  21         141215  
  21         2538  
13 21     21   133 use Scalar::Util 'blessed';
  21         47  
  21         875  
14              
15 21     21   111 use B qw(svref_2object);
  21         38  
  21         4004  
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 = (
30             (map "Dlog_$_", @levels),
31             (map "DlogS_$_", @levels),
32             (map "Dslog_$_", @levels),
33             (map "DslogS_$_", @levels));
34              
35             my @log = (
36             (map "log_$_", @levels),
37             (map "logS_$_", @levels),
38             (map "slog_$_", @levels),
39             (map "slogS_$_", @levels));
40              
41             sub _maybe_export {
42 806     806   15019 my ($spec, $target, $name, $new_code) = @_;
43              
44 21     21   129 no strict 'refs';
  21         35  
  21         28022  
45 806 50       844 if (defined &{"${target}::${name}"}) {
  806         2865  
46 0         0 my $code = \&{"${target}::${name}"};
  0         0  
47              
48             # this will warn
49 0 0       0 $spec->add_export("&$name", $new_code)
50             unless (stash_name($code) eq __PACKAGE__);
51             } else {
52 806         1793 $spec->add_export("&$name", $new_code)
53             }
54             }
55              
56             eval {
57             require Log::Log4perl;
58             die if $Log::Log4perl::VERSION < 1.29;
59             Log::Log4perl->wrapper_register(__PACKAGE__)
60             };
61              
62             # ____ is because tags must have at least one export and we don't want to
63             # export anything but the levels selected
64       0     sub ____ { }
65              
66             exports('____', @dlog, @log, qw( set_logger with_logger has_logger ));
67              
68             export_tag dlog => ('____');
69             export_tag log => ('____');
70             import_arguments qw(logger package_logger default_logger);
71              
72             sub router {
73 63   66 63 0 291 our $Router_Instance ||= do {
74 20         7309 require Log::Contextual::Router;
75 20         115 Log::Contextual::Router->new
76             }
77             }
78              
79             sub default_import {
80 3     3 0 23 my ($class) = shift;
81              
82 3         33 die 'Log::Contextual does not have a default import list';
83              
84             ()
85 0         0 }
86              
87 29     29 0 125 sub arg_logger { $_[1] }
88 30 100   30 0 373 sub arg_levels { $_[1] || [qw(debug trace warn info error fatal)] }
89 30     30 0 128 sub arg_package_logger { $_[1] }
90 30     30 0 18447 sub arg_default_logger { $_[1] }
91              
92             sub before_import {
93 35     35 0 19781 my ($class, $importer, $spec) = @_;
94 35         92 my $router = $class->router;
95 35         1014 my $exports = $spec->exports;
96 35         206 my %router_args = (
97             exporter => $class,
98             target => $importer,
99             arguments => $spec->argument_info
100             );
101              
102             my @tags = $class->default_import($spec)
103 35 100       1506 if $spec->config->{default};
104              
105 32         198 for (@tags) {
106 5 50       25 die "only tags are supported for defaults at this time"
107             unless $_ =~ /^:(.*)$/;
108              
109 5         11 $spec->config->{$1} = 1;
110             }
111              
112 32         144 $router->before_import(%router_args);
113              
114 32 100       107 if ($exports->{'&set_logger'}) {
115 18 50       62 die ref($router) . " does not support set_logger()"
116             unless $router->does('Log::Contextual::Role::Router::SetLogger');
117              
118             _maybe_export($spec, $importer, 'set_logger',
119 12     12   1693 sub { $router->set_logger(@_) },
120 18         631 );
121             }
122              
123 32 100       734 if ($exports->{'&with_logger'}) {
124 10 50       31 die ref($router) . " does not support with_logger()"
125             unless $router->does('Log::Contextual::Role::Router::WithLogger');
126              
127             _maybe_export($spec, $importer, 'with_logger',
128 4     4   1370 sub { $router->with_logger(@_) },
129 10         148 );
130             }
131              
132 32 100       360 if ($exports->{'&has_logger'}) {
133 1 50       4 die ref($router) . " does not support has_logger()"
134             unless $router->does('Log::Contextual::Role::Router::HasLogger');
135              
136             _maybe_export($spec, $importer, 'has_logger',
137 2     2   10 sub { $router->has_logger(@_) },
138 1         16 );
139             }
140              
141 32         77 my @levels = @{$class->arg_levels($spec->config->{levels})};
  32         85  
142 32         142 for my $level (@levels) {
143 181         3417 my %base =
144             (exporter => $class, caller_level => 1, message_level => $level);
145 181         531 my %exports;
146 181 100 100     329 if ($spec->config->{log} || $exports->{"&log_$level"}) {
147             $exports{log_} = sub (&@) {
148 97     97   30131 my ($code, @args) = @_;
149 97         518 $router->handle_log_request(
150             %base,
151             caller_package => scalar(caller),
152             message_sub => $code,
153             message_args => \@args,
154             );
155 94         462 return @args;
156 158         1152 };
157             }
158 181 100 66     497 if ($spec->config->{log} || $exports->{"&slog_$level"}) {
159             $exports{slog_} = sub {
160 9     9   5076 my ($text, @args) = @_;
161 9         41 $router->handle_log_request(
162             %base,
163             caller_package => scalar(caller),
164             message_text => $text,
165             message_args => \@args,
166             );
167 9         44 return @args;
168 157         993 };
169             }
170 181 100 66     471 if ($spec->config->{log} || $exports->{"&logS_$level"}) {
171             $exports{logS_} = sub (&@) {
172 38     38   14936 my ($code, @args) = @_;
173 38         162 $router->handle_log_request(
174             %base,
175             caller_package => scalar(caller),
176             message_sub => $code,
177             message_args => \@args,
178             );
179 38         235 return $args[0];
180 157         1004 };
181             }
182 181 100 66     486 if ($spec->config->{log} || $exports->{"&slogS_$level"}) {
183             $exports{slogS_} = sub {
184 3     3   2412 my ($text, @args) = @_;
185 3         17 $router->handle_log_request(
186             %base,
187             caller_package => scalar(caller),
188             message_text => $text,
189             message_args => \@args,
190             );
191 3         16 return $args[0];
192 157         830 };
193             }
194 181 100 66     442 if ($spec->config->{dlog} || $exports->{"&Dlog_$level"}) {
195             $exports{Dlog_} = sub (&@) {
196 30     30   16065 my ($code, @args) = @_;
197             my $wrapped = sub {
198 25 100   25   86 local $_ = (@_ ? Data::Dumper::Concise::Dumper @_ : '()');
199 25         1625 &$code;
200 30         91 };
201 30         136 $router->handle_log_request(
202             %base,
203             caller_package => scalar(caller),
204             message_sub => $wrapped,
205             message_args => \@args,
206             );
207 30         225 return @args;
208 37         240 };
209             }
210 181 100 66     933 if ($spec->config->{dlog} || $exports->{"&Dslog_$level"}) {
211             $exports{Dslog_} = sub {
212 6     6   5007 my ($text, @args) = @_;
213             my $wrapped = sub {
214 6 50   6   20 $text . (@_ ? Data::Dumper::Concise::Dumper @_ : '()');
215 6         24 };
216 6         26 $router->handle_log_request(
217             %base,
218             caller_package => scalar(caller),
219             message_sub => $wrapped,
220             message_args => \@args,
221             );
222 6         49 return @args;
223 37         250 };
224             }
225 181 100 66     870 if ($spec->config->{dlog} || $exports->{"&DlogS_$level"}) {
226             $exports{DlogS_} = sub (&$) {
227 21     21   8341 my ($code, $ref) = @_;
228             my $wrapped = sub {
229 16     16   38 local $_ = Data::Dumper::Concise::Dumper($_[0]);
230 16         1212 &$code;
231 21         59 };
232 21         97 $router->handle_log_request(
233             %base,
234             caller_package => scalar(caller),
235             message_sub => $wrapped,
236             message_args => [$ref],
237             );
238 21         148 return $ref;
239 37         287 };
240             }
241 181 100 66     794 if ($spec->config->{dlog} || $exports->{"&DslogS_$level"}) {
242             $exports{DslogS_} = sub {
243 6     6   4463 my ($text, $ref) = @_;
244             my $wrapped = sub {
245 6     6   14 $text . Data::Dumper::Concise::Dumper($_[0]);
246 6         29 };
247 6         30 $router->handle_log_request(
248             %base,
249             caller_package => scalar(caller),
250             message_sub => $wrapped,
251             message_args => [$ref],
252             );
253 6         48 return $ref;
254 37         295 };
255             }
256             _maybe_export($spec, $importer, $_ . $level, $exports{$_})
257 181         1231 for keys %exports;
258             }
259             }
260              
261             sub after_import {
262 32     32 0 18773 my ($class, $importer, $spec) = @_;
263 32         101 my %router_args = (
264             exporter => $class,
265             target => $importer,
266             arguments => $spec->argument_info
267             );
268 32         1088 $class->router->after_import(%router_args);
269             }
270              
271             for (qw(set with)) {
272 21     21   149 no strict 'refs';
  21         45  
  21         2417  
273             my $sub = "${_}_logger";
274             *{"Log::Contextual::$sub"} = sub {
275 2     2   1184 die "$sub is no longer a direct sub in Log::Contextual. "
276             . 'Note that this feature was never tested nor documented. '
277             . "Please fix your code to import $sub instead of trying to use it directly"
278             }
279             }
280              
281             1;
282              
283             __END__