File Coverage

blib/lib/Log/Contextual.pm
Criterion Covered Total %
statement 93 101 92.0
branch 25 38 65.7
condition 11 15 73.3
subroutine 27 29 93.1
pod 0 9 0.0
total 156 192 81.2


line stmt bran cond sub pod time code
1             package Log::Contextual;
2             $Log::Contextual::VERSION = '0.007001';
3             # ABSTRACT: Simple logging interface with a contextual log
4              
5 20     20   116825 use strict;
  20         65  
  20         522  
6 20     20   112 use warnings;
  20         39  
  20         738  
7              
8             my @levels = qw(debug trace warn info error fatal);
9              
10 20     20   8749 use Exporter::Declare;
  20         400813  
  20         94  
11 20     20   34321 use Exporter::Declare::Export::Generator;
  20         88  
  20         386  
12 20     20   9257 use Data::Dumper::Concise;
  20         167355  
  20         4942  
13 20     20   187 use Scalar::Util 'blessed';
  20         50  
  20         910  
14              
15 20     20   133 use B qw(svref_2object);
  20         60  
  20         27829  
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 393     393   6520 my ($spec, $target, $name, $new_code) = @_;
35              
36 393 50       2139 if (my $code = $target->can($name)) {
37              
38             # this will warn
39 0 0       0 $spec->add_export("&$name", $new_code)
40             unless (stash_name($code) eq __PACKAGE__);
41             } else {
42 393         1172 $spec->add_export("&$name", $new_code)
43             }
44             }
45              
46             eval {
47             require Log::Log4perl;
48             die if $Log::Log4perl::VERSION < 1.29;
49             Log::Log4perl->wrapper_register(__PACKAGE__)
50             };
51              
52             # ____ is because tags must have at least one export and we don't want to
53             # export anything but the levels selected
54       0     sub ____ { }
55              
56             exports('____', @dlog, @log, qw( set_logger with_logger has_logger ));
57              
58             export_tag dlog => ('____');
59             export_tag log => ('____');
60             import_arguments qw(logger package_logger default_logger);
61              
62             sub router {
63 57   66 57 0 326 our $Router_Instance ||= do {
64 19         7941 require Log::Contextual::Router;
65 19         135 Log::Contextual::Router->new
66             }
67             }
68              
69             sub default_import {
70 3     3 0 28 my ($class) = shift;
71              
72 3         44 die 'Log::Contextual does not have a default import list';
73              
74             ()
75 0         0 }
76              
77 26     26 0 134 sub arg_logger { $_[1] }
78 27 100   27 0 399 sub arg_levels { $_[1] || [qw(debug trace warn info error fatal)] }
79 27     27 0 136 sub arg_package_logger { $_[1] }
80 27     27 0 14619 sub arg_default_logger { $_[1] }
81              
82             sub before_import {
83 32     32 0 22919 my ($class, $importer, $spec) = @_;
84 32         125 my $router = $class->router;
85 32         1192 my $exports = $spec->exports;
86 32         235 my %router_args = (
87             exporter => $class,
88             target => $importer,
89             arguments => $spec->argument_info
90             );
91              
92             my @tags = $class->default_import($spec)
93 32 100       1733 if $spec->config->{default};
94              
95 29         282 for (@tags) {
96 5 50       37 die "only tags are supported for defaults at this time"
97             unless $_ =~ /^:(.*)$/;
98              
99 5         15 $spec->config->{$1} = 1;
100             }
101              
102 29         207 $router->before_import(%router_args);
103              
104 29 100       141 if ($exports->{'&set_logger'}) {
105 17 50       100 die ref($router) . " does not support set_logger()"
106             unless $router->does('Log::Contextual::Role::Router::SetLogger');
107              
108             _maybe_export($spec, $importer, 'set_logger',
109 11     11   1720 sub { $router->set_logger(@_) },
110 17         788 );
111             }
112              
113 29 100       913 if ($exports->{'&with_logger'}) {
114 10 50       41 die ref($router) . " does not support with_logger()"
115             unless $router->does('Log::Contextual::Role::Router::WithLogger');
116              
117             _maybe_export($spec, $importer, 'with_logger',
118 4     4   1312 sub { $router->with_logger(@_) },
119 10         194 );
120             }
121              
122 29 100       358 if ($exports->{'&has_logger'}) {
123 1 50       4 die ref($router) . " does not support has_logger()"
124             unless $router->does('Log::Contextual::Role::Router::HasLogger');
125              
126             _maybe_export($spec, $importer, 'has_logger',
127 2     2   17 sub { $router->has_logger(@_) },
128 1         19 );
129             }
130              
131 29         86 my @levels = @{$class->arg_levels($spec->config->{levels})};
  29         114  
132 29         154 for my $level (@levels) {
133 163         3582 my %base =
134             (exporter => $class, caller_level => 1, message_level => $level);
135 163         261 my %exports;
136 163 100 100     386 if ($spec->config->{log} || $exports->{"&log_$level"}) {
137             $exports{log_} = sub (&@) {
138 96     96   33464 my ($code, @args) = @_;
139 96         678 $router->handle_log_request(
140             %base,
141             caller_package => scalar(caller),
142             message_sub => $code,
143             message_args => \@args,
144             );
145 93         624 return @args;
146 146         1108 };
147             }
148 163 100 66     522 if ($spec->config->{log} || $exports->{"&logS_$level"}) {
149             $exports{logS_} = sub (&@) {
150 38     38   18894 my ($code, @args) = @_;
151 38         209 $router->handle_log_request(
152             %base,
153             caller_package => scalar(caller),
154             message_sub => $code,
155             message_args => \@args,
156             );
157 38         304 return $args[0];
158 145         1039 };
159             }
160 163 100 66     512 if ($spec->config->{dlog} || $exports->{"&Dlog_$level"}) {
161             $exports{Dlog_} = sub (&@) {
162 30     30   20505 my ($code, @args) = @_;
163             my $wrapped = sub {
164 25 100   25   133 local $_ = (@_ ? Data::Dumper::Concise::Dumper @_ : '()');
165 25         5658 &$code;
166 30         125 };
167 30         194 $router->handle_log_request(
168             %base,
169             caller_package => scalar(caller),
170             message_sub => $wrapped,
171             message_args => \@args,
172             );
173 30         282 return @args;
174 37         279 };
175             }
176 163 100 66     1025 if ($spec->config->{dlog} || $exports->{"&DlogS_$level"}) {
177             $exports{DlogS_} = sub (&$) {
178 21     21   11130 my ($code, $ref) = @_;
179             my $wrapped = sub {
180 16     16   54 local $_ = Data::Dumper::Concise::Dumper($_[0]);
181 16         4657 &$code;
182 21         78 };
183 21         128 $router->handle_log_request(
184             %base,
185             caller_package => scalar(caller),
186             message_sub => $wrapped,
187             message_args => [$ref],
188             );
189 21         210 return $ref;
190 37         240 };
191             }
192             _maybe_export($spec, $importer, $_ . $level, $exports{$_})
193 163         1378 for keys %exports;
194             }
195             }
196              
197             sub after_import {
198 29     29 0 11589 my ($class, $importer, $spec) = @_;
199 29         131 my %router_args = (
200             exporter => $class,
201             target => $importer,
202             arguments => $spec->argument_info
203             );
204 29         1294 $class->router->after_import(%router_args);
205             }
206              
207             for (qw(set with)) {
208 20     20   172 no strict 'refs';
  20         53  
  20         2228  
209             my $sub = "${_}_logger";
210             *{"Log::Contextual::$sub"} = sub {
211 2     2   1055 die "$sub is no longer a direct sub in Log::Contextual. "
212             . 'Note that this feature was never tested nor documented. '
213             . "Please fix your code to import $sub instead of trying to use it directly"
214             }
215             }
216              
217             1;
218              
219             __END__