File Coverage

blib/lib/Log/WarnDie.pm
Criterion Covered Total %
statement 45 63 71.4
branch 12 34 35.2
condition 4 12 33.3
subroutine 9 12 75.0
pod 1 1 100.0
total 71 122 58.2


line stmt bran cond sub pod time code
1             package Log::WarnDie;
2              
3 4     4   361742 use warnings;
  4         5  
  4         120  
4 4     4   14 use strict;
  4         4  
  4         64  
5              
6             # Make sure we have the modules that we need
7              
8 4     4   1829 use IO::Handle ();
  4         19495  
  4         84  
9 4     4   21 use Scalar::Util qw(blessed);
  4         6  
  4         2071  
10              
11             # The logging dispatcher that should be used
12             # The (original) error output handle
13             # Reference to the previous parameters sent
14              
15             our $DISPATCHER;
16             our $STDERR;
17             our $LAST;
18              
19             # Old settings of standard Perl logging mechanisms
20              
21             our $WARN;
22             our $DIE;
23              
24             =head1 NAME
25              
26             Log::WarnDie - Log standard Perl warnings and errors on a log handler
27              
28             =head1 VERSION
29              
30             Version 0.07
31              
32             =head1 SYNOPSIS
33              
34             use Log::WarnDie; # install to be used later
35              
36             my $dispatcher = Log::Dispatch->new; # can be any dispatcher!
37             $dispatcher->add( Log::Dispatch::Foo->new( # whatever output you like
38             name => 'foo',
39             min_level => 'info',
40             ) );
41              
42             use Log::WarnDie $dispatcher; # activate later
43              
44             Log::WarnDie->dispatcher( $dispatcher ); # same
45              
46             warn "This is a warning"; # now also dispatched
47             die "Sorry it didn't work out"; # now also dispatched
48              
49             no Log::WarnDie; # deactivate later
50              
51             Log::WarnDie->dispatcher( undef ); # same
52              
53             warn "This is a warning"; # no longer dispatched
54             die "Sorry it didn't work out"; # no longer dispatched
55              
56             =head1 DESCRIPTION
57              
58             The "Log::WarnDie" module offers a logging alternative for standard
59             Perl core functions. This allows you to use the features of e.g.
60             L<Log::Dispatch>, L<Log::Any> or L<Log::Log4perl> B<without> having to make extensive
61             changes to your source code.
62              
63             When loaded, it installs a __WARN__ and __DIE__ handler and intercepts any
64             output to STDERR. It also takes over the messaging functions of L<Carp>.
65             Without being further activated, the standard Perl logging functions continue
66             to be executed: e.g. if you expect warnings to appear on STDERR, they will.
67              
68             Then, when necessary, you can activate actual logging through e.g.
69             Log::Dispatch by installing a log dispatcher. From then on, any warn, die,
70             carp, croak, cluck, confess or print to the STDERR handle, will be logged
71             using the Log::Dispatch logging dispatcher. Logging can be disabled and
72             enabled at any time for critical sections of code.
73              
74             =cut
75              
76             our $VERSION = '0.07';
77              
78             =head1 SUBROUTINES/METHODS
79              
80             =cut
81              
82             #---------------------------------------------------------------------------
83              
84             # Tie subroutines need to be known at compile time, hence there here, near
85             # the start of code rather than near the end where these would normally live.
86              
87             #---------------------------------------------------------------------------
88             # TIEHANDLE
89             #
90             # Called whenever a dispatcher is activated
91             #
92             # IN: 1 class with which to bless
93             # OUT: 1 blessed object
94              
95 4     4   14 sub TIEHANDLE { bless \"$_[0]",$_[0] } #TIEHANDLE
96              
97             #---------------------------------------------------------------------------
98             # PRINT
99             #
100             # Called whenever something is printed on STDERR
101             #
102             # IN: 1 blessed object returned by TIEHANDLE
103             # 2..N whatever was needed to be printed
104              
105             sub PRINT {
106              
107             # Lose the object
108             # If there is a dispatcher
109             # Put it in the log handler if not the same as last time
110             # Reset the flag
111             # Make sure it appears on the original STDERR as well
112              
113 1     1   8 shift;
114 1 50       3 if ($DISPATCHER) {
115 1 0 33     8 $DISPATCHER->error( @_ )
      33        
116             unless $LAST and @$LAST == @_ and join( '',@$LAST ) eq join( '',@_ );
117 1         143 undef $LAST;
118             }
119 1 50       8 if($STDERR) {
120 1         14 print $STDERR @_;
121             }
122             } #PRINT
123              
124             #---------------------------------------------------------------------------
125             # PRINTF
126             #
127             # Called whenever something is printed on STDERR using printf
128             #
129             # IN: 1 blessed object returned by TIEHANDLE
130             # 2..N whatever was needed to be printed
131              
132             sub PRINTF {
133              
134             # Lose the object
135             # If there is a dispatcher
136             # Put it in the log handler if not the same as last time
137             # Reset the flag
138             # Make sure it appears on the original STDERR as well
139              
140 1     1   12 shift;
141 1 50       3 if ($DISPATCHER) {
142 1 0 33     6 $DISPATCHER->error( @_ )
      33        
143             unless $LAST and @$LAST == @_ and join( '',@$LAST ) eq join( '',@_ );
144 1         86 undef $LAST;
145             }
146 1 50       5 if($STDERR) {
147 1         36 printf $STDERR @_;
148             }
149             } #PRINTF
150              
151             #---------------------------------------------------------------------------
152             # CLOSE
153             #
154             # Called whenever something tries to close STDERR
155             #
156             # IN: 1 blessed object returned by TIEHANDLE
157             # 2..N whatever was needed to be printed
158              
159             sub CLOSE {
160              
161             # Lose the object
162             # If there is a dispatcher
163             # Put it in the log handler if not the same as last time
164             # Reset the flag
165             # Make sure it appears on the original STDERR as well
166              
167 0     0   0 my $keep = $STDERR;
168 0         0 $STDERR = undef;
169 0         0 close $keep; # So that the return status can be checked
170             } #CLOSE
171              
172             #---------------------------------------------------------------------------
173             # OPEN
174             #
175             # Called whenever something tries to (re)open STDERR
176             #
177             # IN: 1 blessed object returned by TIEHANDLE
178             # 2..N whatever was needed to be printed
179              
180             sub OPEN {
181              
182             # Lose the object
183             # If there is a dispatcher
184             # Put it in the log handler if not the same as last time
185             # Reset the flag
186             # Make sure it appears on the original STDERR as well
187              
188 0     0   0 shift;
189 0         0 my $arg1 = shift;
190 0         0 my $arg2 = shift;
191              
192 0         0 open($STDERR, $arg1, $arg2);
193             } #OPEN
194             #---------------------------------------------------------------------------
195             # At compile time
196             # Create new handle
197             # Make sure it's the same as the current STDERR
198             # Make sure the original STDERR is now handled by our sub
199              
200             BEGIN {
201 4     4   17 $STDERR = new IO::Handle;
202 4 50       72 $STDERR->fdopen( fileno( STDERR ),"w" )
203             or die "Could not open STDERR 2nd time: $!\n";
204 4         184 tie *STDERR,__PACKAGE__;
205              
206             # Save current __WARN__ setting
207             # Replace it with a sub that
208             # If there is a dispatcher
209             # Remembers the last parameters
210             # Dispatches a warning message
211             # Executes the standard system warn() or whatever was there before
212              
213 4         7 $WARN = $SIG{__WARN__};
214             $SIG{__WARN__} = sub {
215 0 0       0 if ($DISPATCHER) {
216 0         0 $LAST = \@_;
217 0 0       0 if(ref($DISPATCHER) =~ /^Log::Log4perl/) {
218 0         0 $DISPATCHER->warn( @_ );
219             } else {
220 0         0 $DISPATCHER->warning( @_ );
221             }
222             }
223 0 0       0 $WARN ? $WARN->( @_ ) : CORE::warn( @_ );
224 4         23 };
225              
226             # Save current __DIE__ setting
227             # Replace it with a sub that
228             # If there is a dispatcher
229             # Remembers the last parameters
230             # Dispatches a critical message
231             # Executes the standard system die() or whatever was there before
232              
233 4         15 $DIE = $SIG{__DIE__};
234             $SIG{__DIE__} = sub {
235 4 50       16 if ($DISPATCHER) {
236 0         0 $LAST = \@_;
237 0 0       0 if(ref($DISPATCHER) =~ /^Log::Log4perl/) {
238 0         0 $DISPATCHER->fatal( @_ );
239             } else {
240 0         0 $DISPATCHER->critical( @_ );
241             }
242             }
243 4 50       50 $DIE ? $DIE->( @_ ) : CORE::die( @_ );
244 4         15 };
245              
246             # Make sure we won't be listed ourselves by Carp::
247              
248 4         709 $Carp::Internal{__PACKAGE__} = 1;
249             } #BEGIN
250              
251             # Satisfy require
252              
253             1;
254              
255             #---------------------------------------------------------------------------
256              
257             # Class methods
258              
259             #---------------------------------------------------------------------------
260              
261             =head2 dispatcher
262              
263             Class method to set and/or return the current dispatcher
264              
265             IN: 1 class (ignored)
266             2 new dispatcher (optional)
267             OUT: 1 current dispatcher
268              
269             =cut
270              
271             sub dispatcher {
272              
273             # Return the current dispatcher if no changes needed
274             # Set the new dispatcher
275              
276 4 100   4 1 1630 return $DISPATCHER unless @_ > 1;
277 1         3 $DISPATCHER = $_[1];
278              
279             # If there is a dispatcher now
280             # If the dispatcher is a Log::Dispatch er
281             # Make sure all of standard Log::Dispatch stuff becomes invisible for Carp::
282             # If there are outputs already
283             # Make sure all of the output objects become invisible for Carp::
284              
285 1 50       4 if ($DISPATCHER) {
286 1 50       6 if ($DISPATCHER->isa( 'Log::Dispatch' )) {
287             $Carp::Internal{$_} = 1
288 1         5 foreach 'Log::Dispatch','Log::Dispatch::Output';
289 1 50       4 if (my $outputs = $DISPATCHER->{'outputs'}) {
290             $Carp::Internal{$_} = 1
291 1         2 foreach map {blessed $_} values %{$outputs};
  1         10  
  1         2  
292             }
293             }
294             }
295              
296             # Return the current dispatcher
297              
298 1         2 $DISPATCHER;
299             } #dispatcher
300              
301             #---------------------------------------------------------------------------
302              
303             # Perl standard features
304              
305             #---------------------------------------------------------------------------
306             # import
307             #
308             # Called whenever a -use- is done.
309             #
310             # IN: 1 class (ignored)
311             # 2 new dispatcher (optional)
312              
313             *import = \&dispatcher;
314              
315             #---------------------------------------------------------------------------
316             # unimport
317             #
318             # Called whenever a -use- is done.
319             #
320             # IN: 1 class (ignored)
321              
322 0     0     sub unimport { import( undef ) } #unimport
323              
324             #---------------------------------------------------------------------------
325              
326             __END__
327              
328             =head1 LOG LEVELS
329              
330             The following log levels are used:
331              
332             =head2 warning
333              
334             Any C<warn>, C<Carp::carp> or C<Carp::cluck> will generate a "warning" level
335             message.
336              
337             =head2 error
338              
339             Any direct output to STDERR will generate an "error" level message.
340              
341             =head2 critical
342              
343             Any C<die>, C<Carp::croak> or C<Carp::confess> will generate a "critical"
344             level message.
345              
346             =head1 REQUIRED MODULES
347              
348             Scalar::Util (1.08)
349              
350             =head1 CAVEATS
351              
352             The following caveats may apply to your situation.
353              
354             =head2 Associated modules
355              
356             Although a module such as L<Log::Dispatch> is B<not> listed as a prerequisite,
357             the real use of this module only comes into view when such a module B<is>
358             installed. Please note that for testing this module, you will need the
359             L<Log::Dispatch::Buffer> module to also be available.
360              
361             This module has been tested with
362             L<Log::Dispatch>, L<Log::Any> and L<Log::Log4perl> B<without>.
363             In principle any object which recognises C<warning>, C<error> and C<critical> should work.
364              
365             =head2 eval
366              
367             In the current implementation of Perl, a __DIE__ handler is B<also> called
368             inside an eval. Whereas a normal C<die> would just exit the eval, the __DIE__
369             handler _will_ get called inside the eval. Which may or may not be what you
370             want. To prevent the __DIE__ handler to be called inside eval's, add the
371             following line to the eval block or string being evaluated:
372              
373             local $SIG{__DIE__} = undef;
374              
375             This disables the __DIE__ handler within the evalled block or string, and
376             will automatically enable it again upon exit of the evalled block or string.
377             Unfortunately there is no automatic way to do that for you.
378              
379             =head1 AUTHOR
380              
381             Elizabeth Mattijsen, <liz@dijkmat.nl>
382              
383             Maintained by Nigel Horne, C<< <njh at bandsman.co.uk> >>
384              
385             =head1 BUGS
386              
387             Please report any bugs or feature requests to C<bug-log-warndie at rt.cpan.org>,
388             or through the web interface at
389             L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Log-WarnDie>.
390             I will be notified, and then you'll
391             automatically be notified of progress on your bug as I make changes.
392              
393             =head1 COPYRIGHT
394              
395             Copyright (c) 2004, 2007 Elizabeth Mattijsen <liz@dijkmat.nl>. All rights
396             reserved. This program is free software; you can redistribute it and/or
397             modify it under the same terms as Perl itself.
398              
399             Portions of versions 0.06 onwards, Copyright 2017 Nigel Horne
400              
401             =cut