File Coverage

lib/Catalyst/Log/Log4perl.pm
Criterion Covered Total %
statement 25 116 21.5
branch 0 22 0.0
condition 0 7 0.0
subroutine 9 24 37.5
pod 5 5 100.0
total 39 174 22.4


line stmt bran cond sub pod time code
1             package Catalyst::Log::Log4perl;
2              
3             =head1 NAME
4              
5             Catalyst::Log::Log4perl - DEPRECATED (see Log::Log4perl::Catalyst)
6              
7             =head1 SYNOPSIS
8              
9             In MyApp.pm:
10              
11             use Catalyst::Log::Log4perl;
12              
13             # then we create a custom logger object for catalyst to use.
14             # If we don't supply any arguments to new, it will work almost
15             # like the default catalyst-logger.
16            
17             __PACKAGE__->log(Catalyst::Log::Log4perl->new());
18              
19             # But the real power of Log4perl lies in the configuration, so
20             # lets try that. example.conf is included in the distribution,
21             # alongside the README and Changes.
22            
23             __PACKAGE__->log(Catalyst::Log::Log4perl->new('example.conf'));
24            
25             And later...
26              
27             $c->log->debug("This is using log4perl!");
28              
29             =head1 DESCRIPTION
30              
31             This module provides a L<Catalyst::Log> implementation that uses
32             L<Log::Log4perl> as the underlying log mechanism. It provides all
33             the methods listed in L<Catalyst::Log>, with the exception of:
34              
35             levels
36             enable
37             disable
38              
39             These methods simply return 0 and do nothing, as similar functionality
40             is already provided by L<Log::Log4perl>.
41              
42             These methods will all instantiate a logger with the component set to
43             the package who called it. For example, if you were in the
44             MyApp::C::Main package, the following:
45              
46             package MyApp::C::Main;
47              
48             sub default : Private {
49             my ( $self, $c ) = @_;
50             my $logger = $c->log;
51             $logger->debug("Woot!");
52             }
53              
54             Would send a message to the Myapp.C.Main L<Log::Log4perl> component.
55              
56             See L<Log::Log4perl> for more information on how to configure different
57             logging mechanisms based on the component.
58              
59             =head1 METHODS
60              
61             =over 4
62              
63             =cut
64              
65 1     1   32075 use strict;
  1         2  
  1         33  
66 1     1   1558 use Log::Log4perl;
  1         71021  
  1         8  
67 1     1   46 use Log::Log4perl::Layout;
  1         8  
  1         20  
68 1     1   4 use Log::Log4perl::Level;
  1         2  
  1         4  
69 1     1   1076 use Params::Validate;
  1         11477  
  1         70  
70 1     1   997 use Data::Dump;
  1         9848  
  1         79  
71 1     1   8 use Carp 'carp';
  1         2  
  1         99  
72              
73             our $VERSION = '1.06';
74              
75             BEGIN {
76 1     1   446 carp 'Catalyst::Log::Log4perl is DEPRECATED, update your app to use Log::Log4perl::Catalyst';
77             }
78              
79             {
80             my @levels = qw[ debug info warn error fatal ];
81              
82             for ( my $i = 0; $i < @levels; $i++ ) {
83              
84             my $name = $levels[$i];
85             my $level = 1 << $i;
86              
87 1     1   7 no strict 'refs';
  1         2  
  1         1322  
88             *{$name} = sub {
89 0     0     my ( $self, @message ) = @_;
90 0           my ( $package, $filename, $line ) = caller;
91 0           my $depth = $Log::Log4perl::caller_depth;
92 0 0         unless ( $depth > 0 ) {
93 0           $depth = 1;
94             }
95 0           my @info = ( $package, $name, $depth, \@message );
96 0 0         if ( $self->{override_cspecs} ) {
97 0           my %caller;
98 0           @caller{qw/package filename line/} = caller;
99              
100             # I really have no idea why the correct subroutine
101             # is on a different call stack
102 0           $caller{subroutine} = ( caller(1) )[3]; #wtf?
103              
104 0           push @info, \%caller;
105             }
106 0           $self->_log( \@info );
107 0           return 1;
108             };
109              
110             *{"is_$name"} = sub {
111 0     0     my ( $self, @message ) = @_;
112 0           my ( $package, $filename, $line ) = caller;
113 0           my $logger = Log::Log4perl->get_logger($package);
114 0           my $func = "is_" . $name;
115 0           return $logger->$func;
116             };
117             }
118             }
119              
120             sub _log {
121 0     0     my $self = shift;
122 0           push @{ $self->{log4perl_stack} }, @_;
  0            
123             }
124              
125             sub _dump {
126 0     0     my $self = shift;
127 0           $self->debug( Data::Dump::dump(@_) );
128             }
129              
130             =item new($config, [%options])
131              
132             This builds a new L<Catalyst::Log::Log4perl> object. If you provide an argument
133             to new(), it will be passed directly to Log::Log4perl::init.
134              
135             The second (optional) parameter is a hash with extra options. Currently
136             three additional parameters are defined:
137              
138             'autoflush' - Set it to a true value to disable abort(1) support.
139             'watch_delay' - Set it to a true value to use L<Log::Log4perl>'s init_and_watch
140              
141             'override_cspecs' - EXPERIMENTAL
142             Set it to a true value to locally override some parts of
143             L<Log::Log4perl::Layout::PatternLayout>. See L<OVERRIDING CSPECS> below
144              
145             Without any arguments, new() will initialize a root logger with a single appender,
146             L<Log::Log4perl::Appender::Screen>, configured to have an identical layout to
147             the default L<Catalyst::Log> object.
148              
149             =cut
150              
151             sub new {
152 0     0 1   my $self = shift;
153 0           my $config = shift;
154 0           my %options = @_;
155              
156 0           my %foo;
157 0           my $ref = \%foo;
158              
159 0           my $watch_delay = 0;
160 0 0         if ( exists( $options{'watch_delay'} ) ) {
161 0 0         if ( $options{'watch_delay'} ) {
162 0           $watch_delay = $options{'watch_delay'};
163             }
164             }
165 0 0         unless ( Log::Log4perl->initialized ) {
166 0 0         if ( defined($config) ) {
167 0 0         if ($watch_delay) {
168 0           Log::Log4perl::init_and_watch( $config, $watch_delay );
169             } else {
170 0           Log::Log4perl::init($config);
171             }
172             } else {
173 0           my $log = Log::Log4perl->get_logger("");
174 0           my $layout =
175             Log::Log4perl::Layout::PatternLayout->new(
176             "[%d] [catalyst] [%p] %m%n");
177 0           my $appender = Log::Log4perl::Appender->new(
178             "Log::Log4perl::Appender::Screen",
179             'name' => 'screenlog',
180             'stderr' => 1,
181             );
182 0           $appender->layout($layout);
183 0           $log->add_appender($appender);
184 0           $log->level($DEBUG);
185             }
186             }
187              
188 0   0       $ref->{autoflush} = $options{autoflush} || 0;
189              
190 0   0       $ref->{override_cspecs} = $options{override_cspecs} || 0;
191              
192 0 0         if ( $ref->{override_cspecs} ) {
193 0           @{ $ref->{local_cspecs} }{qw/L F C M l/} = (
194 0     0     sub { $ref->{context}->{line} },
195 0     0     sub { $ref->{context}->{filename} },
196 0     0     sub { $ref->{context}->{package} },
197 0     0     sub { $ref->{context}->{subroutine} },
198             sub {
199 0           sprintf '%s %s (%d)',
200 0     0     @{ $ref->{context} }{qw/subroutine filename line/};
201             }
202 0           );
203             }
204              
205 0           $ref->{abort} = 0;
206 0           $ref->{log4perl_stack} = [];
207              
208 0           bless $ref, $self;
209              
210 0           return $ref;
211             }
212              
213             =item _flush()
214              
215             Flushes the cache. Much like the way Catalyst::Log does it.
216              
217             =cut
218              
219             sub _flush {
220 0     0     my ($self) = @_;
221              
222 0           local $SIG{CHLD} = 'DEFAULT'; # Some log backends spawn processes, and
223             # don't play nicely unless we do this.
224              
225 0           my @stack = @{ $self->{log4perl_stack} };
  0            
226 0           $self->{log4perl_stack} = [];
227 0 0 0       if ( !$self->{autoflush} and $self->{abort} ) {
228 0           $self->{abort} = 0;
229 0           return 0;
230             }
231              
232 0           foreach my $logmsg (@stack) {
233 0           my ( $package, $type, $depth, $message ) = @{$logmsg}[ 0 .. 3 ];
  0            
234 0 0         $self->{context} = $logmsg->[-1] if $self->{override_cspecs};
235              
236             # fetch all instances of pattern layouts
237 0           my @patterns;
238 0 0         if ( $self->{override_cspecs} ) {
239 0           @patterns =
240 0           grep { $_->isa('Log::Log4perl::Layout::PatternLayout') }
241 0           map { $_->layout } values %{ Log::Log4perl->appenders() };
  0            
242             }
243              
244             # localize the cspecs so we don't disturb modules that
245             # directly operate on Log4perl
246 0           local $_->{USER_DEFINED_CSPECS} for @patterns;
247              
248 0           for my $layout (@patterns) {
249 0           while ( my ( $cspec, $subref ) = each %{ $self->{local_cspecs} } )
  0            
250             {
251              
252             # overriding USER_DEFINED_CSPECS relies on an missing internal
253             # check in Log4perl: cspecs that collide with a predefined one
254             # can't be added via the API but are executed nonetheless
255             # and override the originals. This behaviour is only verified
256             # with version 1.08 of Log::Log4perl
257 0           $layout->{USER_DEFINED_CSPECS}->{$cspec} = $subref;
258             }
259             }
260              
261 0           local $Log::Log4perl::caller_depth = $depth;
262              
263 0           my $logger = Log::Log4perl->get_logger($package);
264 0           $logger->$type(@$message);
265             }
266             }
267              
268             =item abort($abort)
269              
270             Causes the current log-object to not log anything, effectivly shutting
271             up this request, making it disapear from the logs.
272              
273             =cut
274              
275             sub abort {
276 0     0 1   my $self = shift;
277 0           my $abort = shift;
278 0           $self->{abort} = $abort;
279 0           return $self->{abort};
280             }
281              
282             =item debug($message)
283              
284             Passes it's arguments to $logger->debug.
285              
286             =item info($message)
287              
288             Passes it's arguments to $logger->info.
289              
290             =item warn($message)
291              
292             Passes it's arguments to $logger->warn.
293              
294             =item error($message)
295              
296             Passes it's arguments to $logger->error.
297              
298             =item fatal($message)
299              
300             Passes it's arguments to $logger->fatal.
301              
302             =item is_debug()
303              
304             Calls $logger->is_debug.
305              
306             =item is_info()
307              
308             Calls $logger->is_info.
309              
310             =item is_warn()
311              
312             Calls $logger->is_warn.
313              
314             =item is_error()
315              
316             Calls $logger->is_error.
317              
318             =item is_fatal()
319              
320             Calls $logger->is_fatal.
321              
322             =item levels()
323              
324             This method does nothing but return "0". You should use L<Log::Log4perl>'s
325             built in mechanisms for setting up log levels.
326              
327             =cut
328              
329             sub levels {
330 0     0 1   return 0;
331             }
332              
333             =item enable()
334              
335             This method does nothing but return "0". You should use L<Log::Log4perl>'s
336             built in mechanisms for enabling log levels.
337              
338             =cut
339              
340             sub enable {
341 0     0 1   return 0;
342             }
343              
344             =item disable()
345              
346             This method does nothing but return "0". You should use L<Log::Log4perl>'s
347             built in mechanisms for disabling log levels.
348              
349             =cut
350              
351             sub disable {
352 0     0 1   return 0;
353             }
354              
355             1;
356              
357             __END__
358              
359             =back
360              
361             =head1 OVERRIDING CSPECS
362              
363             Due to some fundamental design incompatibilities of L<Log::Log4perl>
364             and L<Catalyst::Log> all cspecs of L<Log::Log4perl::Layout::PatternLayout>
365             that rely on call stack information fail to work as expected. Affected
366             are the format strings %L, %F, %C, %M, %l and %T. You can instruct
367             B<Catalyst::Log::Log4perl> to try to hijack these patterns which seems to
368             work reasonable well, but be advised that this feature is HIGHLY EXPERIMENTAL
369             and relies on a few internals of L<Log::Log4perl> that might change in later
370             versions of this library. Additionally, this feature is currently only tested
371             with L<Log::Log4perl> version 1.08 allthough the underlying internals of
372             L<Log::Log4perl> seem to be stable since at least version 0.47.
373              
374             =head1 BUGS AND LIMITATIONS
375              
376             The %T cspec of L<Log::Log4perl::Layout::PatternLayout> is currently
377             unimplemented. The implementation to get %M defies any logical approach
378             but seems to work perfectly.
379              
380             =head1 SEE ALSO
381              
382             L<Log::Log4perl>, L<Catalyst::Log>, L<Catalyst>.
383              
384             =head1 AUTHORS
385              
386             Adam Jacob, C<adam@stalecoffee.org>
387              
388             Andreas Marienborg, C<omega@palle.net>
389              
390             Gavin Henry, C<ghenry@suretecsystems.com> (Typos)
391              
392             Sebastian Willert (Overriding CSPECS)
393              
394             J. Shirley C<jshirley@gmail.com> (Adding _dump)
395              
396             Tomas Doran (t0m) C<bobtfish@bobtfish.net> (Current maintainer)
397              
398             Wallace Reis (wreis) C<wreis@cpan.org>
399              
400             =head1 COPYRIGHT
401              
402             Copyright (c) 2005 - 2009
403             the Catalyst::Log::Log4perl L</AUTHORS>
404             as listed above.
405              
406             =head1 LICENSE
407              
408             This library is free software. You can redistribute it and/or modify it under
409             the same terms as perl itself.
410              
411             =cut