File Coverage

blib/lib/Smart/Comments/Log4perl.pm
Criterion Covered Total %
statement 47 57 82.4
branch 7 8 87.5
condition 2 3 66.6
subroutine 13 15 86.6
pod n/a
total 69 83 83.1


line stmt bran cond sub pod time code
1             package Smart::Comments::Log4perl;
2              
3 7     7   317028 use 5.016;
  7         21  
4 7     7   29 use strict;
  7         8  
  7         140  
5 7     7   994 use Smart::Comments;
  7         46061  
  7         36  
6 7     7   28339 use Log::Log4perl qw(get_logger :levels);
  7         288064  
  7         75  
7 7     7   801 use Scalar::Util qw(openhandle);
  7         13  
  7         4889  
8              
9             =head1 NAME
10              
11             Smart::Comments::Log4perl - An extension of Smart::Comments to utilize Log::Log4perl for all output
12              
13             =head1 VERSION
14              
15             Version 1.002
16              
17             =cut
18              
19             our $VERSION = '1.002';
20             our $INITIALIZED;
21             our $LAYOUT;
22             our $CONFIG_FILE = $ENV{'SCL4P_CONFIG'};
23             our $LOG_LEVEL = 'info';
24              
25             my %ADDITIONAL_SMART_COMMENT_KEYWORDS = (
26             'l4p_config:' => sub { $CONFIG_FILE = $_[3][0]; },
27             'l4p_fatal:' => sub { _log_at_level('fatal', @_); },
28             'l4p_warn:' => sub { _log_at_level('warn', @_); },
29             'l4p_info:' => sub { _log_at_level('info', @_); },
30             'l4p_debug:' => sub { _log_at_level('debug', @_); },
31             'l4p_trace:' => sub { _log_at_level('trace', @_); },
32             'l4p_level:' => sub { $LOG_LEVEL = lc $_[3][0]; },
33             );
34              
35             my $LOG_HANDLE;
36              
37             =head1 SYNOPSIS
38              
39             Smart:Comments is a great module which allows debug to be completely ignored during normal execution, but have debug entries fire when
40             necessary. Log4perl turns logging up a notch, allowing easy logging to STDOUT/STDERR or file handles easily. This seeks to combine the
41             two in a useful manner.
42              
43             Here's a brief code snippet.
44              
45             use Smart::Comments::Log4perl;
46              
47             my $foo = {};
48             ### Log a variable: $foo;
49             ...
50              
51             =head1 CONFIGURATION
52              
53             Configuration of Log4Perl is very simple by default, with no additional decorations above Smart::Comments, with a to-screen logger that
54             logs at debug and above. Wholesale configuration may be done via a Log4perl configuration file, which can be loaded into the system by
55             either setting the SCL4P_CONFIG environment variable to the location of the file or by placing the following line:
56             ### l4p_config: 'config/location'
57             Variables may also be used in this configuration:
58             ### l4p_config: "/log_root/$log_file"
59              
60             Please note: Once a single line of logging has occurred, the ### l4p_config lines will be ignored, as there is no way to re-intialize
61             the Log4perl system at the moment.
62              
63             =head1 LOGGING
64              
65             All normal ### smart comments will, by default, be logged as INFO level logs. The level for regular smart comments may be changed by
66             calling the meta-command:
67             ### l4p_level: 'INFO'
68             (Other valid options are FATAL, WARN, DEBUG, and TRACE)
69             A single line of logging may be run at a different level by a matching meta-command per level:
70             ### l4p_trace: 'This is a TRACE level log'
71             Note that anything after the : must evaluate to a valid Perl string in order to log successfully. Analog meta-commands exist for all 5
72             available log levels
73              
74             =head1 EXPORT
75              
76             =head1 SUBROUTINES/METHODS
77              
78             =cut
79              
80             sub _log_at_level
81             {
82 3     3   9 my ($level, @args) = @_;
83 3         3 local $LOG_LEVEL = $level;
84 3         6 $args[1] = q{};
85 3         7 _l4p_Dump(@args);
86             }
87              
88             sub _prep_logging
89             {
90 22     22   36 my ($package) = @_;
91 22 100       126 if (!Log::Log4perl->initialized())
92             {
93 6 100       36 if ($CONFIG_FILE)
94             {
95 5         40 Log::Log4perl->init($CONFIG_FILE);
96             }
97             else
98             {
99 1         6 my %options = ( 'log4perl.rootLogger' => 'DEBUG, Screen',
100             'log4perl.appender.Screen' => 'Log::Log4perl::Appender::Screen',
101             'log4perl.appender.Screen.layout' => 'PatternLayout',
102             'log4perl.appender.Screen.layout.ConversionPattern' => '%m',
103             );
104 1         5 Log::Log4perl->init( \%options );
105             }
106             }
107 22         210249 $LOG_HANDLE = get_logger($package);
108 22         3415 return;
109             }
110              
111             sub _l4p_Dump
112             {
113 31     31   5696 my ($package) = caller;
114 31 100 66     230 if (@_ > 1 && exists $ADDITIONAL_SMART_COMMENT_KEYWORDS{lc $_[1]})
115             {
116 9         31 $ADDITIONAL_SMART_COMMENT_KEYWORDS{lc $_[1]}->(@_);
117 9         18 return;
118             }
119 22         54 _prep_logging($package);
120 22         73 local *STDERR = *L4P_OVERRIDE_STDERR;
121 22         82 _orig_Dump(@_);
122 22         120 return;
123             }
124              
125             sub _l4p_for_progress
126             {
127 0     0   0 my ($package) = caller;
128 0         0 _prep_logging($package);
129 0         0 local *STDERR = *L4P_OVERRIDE_STDERR;
130 0         0 _orig_for_progress(@_);
131 0         0 return;
132             }
133              
134             sub _while_progress
135             {
136 0     0   0 my ($package) = caller;
137 0         0 _prep_logging($package);
138 0         0 local *STDERR = *L4P_OVERRIDE_STDERR;
139 0         0 _orig_while_progress(@_);
140 0         0 return;
141             }
142              
143             # These are the nasty hacks to hijack Smart::Comments -- I'd love to have a better way to hook into that framework, but this was the
144             # most useful method I could come up with.
145              
146             unless ( $INITIALIZED )
147             {
148             # To avoid double re-defining causing an infinite loop, ensure this only runs once
149             *Smart::Comments::Log4perl::_orig_Dump = \&Smart::Comments::_Dump;
150             undef *Smart::Comments::_Dump;
151             *Smart::Comments::_Dump = \&_l4p_Dump;
152              
153             *Smart::Comments::Log4perl::_orig_for_progress = \&Smart::Comments::_for_progress;
154             undef *Smart::Comments::_for_progress;
155             *Smart::Comments::_for_progress = \&_l4p_for_progress;
156              
157             *Smart::Comments::Log4perl::_orig_while_progress = \&Smart::Comments::_while_progress;
158             undef *Smart::Comments::_while_progress;
159             *Smart::Comments::_while_progress = \&_l4p_while_progress;
160              
161             $INITIALIZED=1;
162             }
163              
164             tie *L4P_OVERRIDE_STDERR, 'Smart::Comments::Log4perl::IO';
165              
166             # A new package we can tie to STDERR temporarily to hijack Smart::Comment's output
167              
168             package Smart::Comments::Log4perl::IO;
169 7     7   40 use base qw;
  7         10  
  7         4733  
170 7     7   13072 use Symbol qw;
  7         12  
  7         1644  
171              
172             *L4P_ORIGINAL_STDERR = *STDERR;
173              
174 7     7   29 sub TIEHANDLE { return bless geniosym, __PACKAGE__ }
175              
176             sub TELL
177             {
178 44     44   3182 return tell L4P_ORIGINAL_STDERR;
179             }
180              
181             my %LOGGER_DISPATCH = (
182             'fatal' => sub { return $LOG_HANDLE->fatal(@_); },
183             'warn' => sub { return $LOG_HANDLE->warn(@_); },
184             'info' => sub { return $LOG_HANDLE->info(@_); },
185             'debug' => sub { return $LOG_HANDLE->debug(@_); },
186             'trace' => sub { return $LOG_HANDLE->trace(@_); },
187             );
188              
189             sub PRINT
190             {
191 44     44   3894 shift;
192 44         110 local *STDERR = *L4P_ORIGINAL_STDERR;
193             # Kind of a magic number, needed to step back out of these frames deep enough to find where the smart::comment was originally
194             # So, Smart::Comments::Dump, PRINT, LOGGER_DISPATCH, etc.
195 44         112 local $Log::Log4perl::caller_depth = 4;
196 44 50       118 return unless exists $LOGGER_DISPATCH{$LOG_LEVEL};
197 44         93 return $LOGGER_DISPATCH{$LOG_LEVEL}->(@_);
198             }
199              
200             =head1 AUTHOR
201              
202             Tracy Beck, C<< >>
203              
204             =head1 BUGS
205              
206             Please report any bugs or feature requests to C, or through
207             the web interface at L. I will be notified, and then you'll
208             automatically be notified of progress on your bug as I make changes.
209              
210              
211              
212              
213             =head1 SUPPORT
214              
215             You can find documentation for this module with the perldoc command.
216              
217             perldoc Smart::Comments::Log4perl
218              
219              
220             You can also look for information at:
221              
222             =over 4
223              
224             =item * RT: CPAN's request tracker (report bugs here)
225              
226             L
227              
228             =item * AnnoCPAN: Annotated CPAN documentation
229              
230             L
231              
232             =item * CPAN Ratings
233              
234             L
235              
236             =item * Search CPAN
237              
238             L
239              
240             =back
241              
242              
243             =head1 ACKNOWLEDGEMENTS
244              
245              
246             =head1 LICENSE AND COPYRIGHT
247              
248             Copyright 2015 Tracy Beck.
249              
250             This program is free software; you can redistribute it and/or modify it
251             under the terms of the the Artistic License (2.0). You may obtain a
252             copy of the full license at:
253              
254             L
255              
256             Any use, modification, and distribution of the Standard or Modified
257             Versions is governed by this Artistic License. By using, modifying or
258             distributing the Package, you accept this license. Do not use, modify,
259             or distribute the Package, if you do not accept this license.
260              
261             If your Modified Version has been derived from a Modified Version made
262             by someone other than you, you are nevertheless required to ensure that
263             your Modified Version complies with the requirements of this license.
264              
265             This license does not grant you the right to use any trademark, service
266             mark, tradename, or logo of the Copyright Holder.
267              
268             This license includes the non-exclusive, worldwide, free-of-charge
269             patent license to make, have made, use, offer to sell, sell, import and
270             otherwise transfer the Package with respect to any patent claims
271             licensable by the Copyright Holder that are necessarily infringed by the
272             Package. If you institute patent litigation (including a cross-claim or
273             counterclaim) against any party alleging that the Package constitutes
274             direct or contributory patent infringement, then this Artistic License
275             to you shall terminate on the date that such litigation is filed.
276              
277             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
278             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
279             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
280             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
281             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
282             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
283             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
284             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
285              
286              
287             =cut
288              
289             1; # End of Smart::Comments::Log4perl