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   412244 use 5.016;
  7         26  
  7         264  
4 7     7   42 use strict;
  7         12  
  7         303  
5 7     7   610 use Smart::Comments;
  7         41371  
  7         48  
6 7     7   35938 use Log::Log4perl qw(get_logger :levels);
  7         370199  
  7         59  
7 7     7   987 use Scalar::Util qw(openhandle);
  7         14  
  7         5848  
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.00
16              
17             =cut
18              
19             our $VERSION = '1.00';
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   7 my ($level, @args) = @_;
83 3         5 local $LOG_LEVEL = $level;
84 3         4 $args[1] = q{};
85 3         8 _l4p_Dump(@args);
86             }
87              
88             sub _prep_logging
89             {
90 22     22   31 my ($package) = @_;
91 22 100       125 if (!Log::Log4perl->initialized())
92             {
93 6 100       42 if ($CONFIG_FILE)
94             {
95 5         45 Log::Log4perl->init($CONFIG_FILE);
96             }
97             else
98             {
99 1         10 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         7 Log::Log4perl->init( \%options );
105             }
106             }
107 22         17685 $LOG_HANDLE = get_logger($package);
108 22         2675 return;
109             }
110              
111             sub _l4p_Dump
112             {
113 31     31   6803 my ($package) = caller;
114 31 100 66     227 if (@_ > 1 && exists $ADDITIONAL_SMART_COMMENT_KEYWORDS{lc $_[1]})
115             {
116 9         33 $ADDITIONAL_SMART_COMMENT_KEYWORDS{lc $_[1]}->(@_);
117 9         20 return;
118             }
119 22         50 _prep_logging($package);
120 22         57 local *STDERR = *L4P_OVERRIDE_STDERR;
121 22         73 _orig_Dump(@_);
122 22         112 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   48 use base qw;
  7         18  
  7         5303  
170 7     7   16814 use Symbol qw;
  7         19  
  7         2203  
171              
172             *L4P_ORIGINAL_STDERR = *STDERR;
173              
174 7     7   35 sub TIEHANDLE { return bless geniosym, __PACKAGE__ }
175              
176             sub TELL
177             {
178 44     44   3041 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   3654 shift;
192 44         89 local *STDERR = *L4P_ORIGINAL_STDERR;
193 44 50       132 return unless exists $LOGGER_DISPATCH{$LOG_LEVEL};
194 44         96 return $LOGGER_DISPATCH{$LOG_LEVEL}->(@_);
195             }
196              
197             =head1 AUTHOR
198              
199             Tracy Beck, C<< >>
200              
201             =head1 BUGS
202              
203             Please report any bugs or feature requests to C, or through
204             the web interface at L. I will be notified, and then you'll
205             automatically be notified of progress on your bug as I make changes.
206              
207              
208              
209              
210             =head1 SUPPORT
211              
212             You can find documentation for this module with the perldoc command.
213              
214             perldoc Smart::Comments::Log4perl
215              
216              
217             You can also look for information at:
218              
219             =over 4
220              
221             =item * RT: CPAN's request tracker (report bugs here)
222              
223             L
224              
225             =item * AnnoCPAN: Annotated CPAN documentation
226              
227             L
228              
229             =item * CPAN Ratings
230              
231             L
232              
233             =item * Search CPAN
234              
235             L
236              
237             =back
238              
239              
240             =head1 ACKNOWLEDGEMENTS
241              
242              
243             =head1 LICENSE AND COPYRIGHT
244              
245             Copyright 2015 Tracy Beck.
246              
247             This program is free software; you can redistribute it and/or modify it
248             under the terms of the the Artistic License (2.0). You may obtain a
249             copy of the full license at:
250              
251             L
252              
253             Any use, modification, and distribution of the Standard or Modified
254             Versions is governed by this Artistic License. By using, modifying or
255             distributing the Package, you accept this license. Do not use, modify,
256             or distribute the Package, if you do not accept this license.
257              
258             If your Modified Version has been derived from a Modified Version made
259             by someone other than you, you are nevertheless required to ensure that
260             your Modified Version complies with the requirements of this license.
261              
262             This license does not grant you the right to use any trademark, service
263             mark, tradename, or logo of the Copyright Holder.
264              
265             This license includes the non-exclusive, worldwide, free-of-charge
266             patent license to make, have made, use, offer to sell, sell, import and
267             otherwise transfer the Package with respect to any patent claims
268             licensable by the Copyright Holder that are necessarily infringed by the
269             Package. If you institute patent litigation (including a cross-claim or
270             counterclaim) against any party alleging that the Package constitutes
271             direct or contributory patent infringement, then this Artistic License
272             to you shall terminate on the date that such litigation is filed.
273              
274             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
275             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
276             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
277             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
278             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
279             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
280             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
281             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
282              
283              
284             =cut
285              
286             1; # End of Smart::Comments::Log4perl