File Coverage

blib/lib/Log/Fu.pm
Criterion Covered Total %
statement 160 171 93.5
branch 42 62 67.7
condition 12 20 60.0
subroutine 29 30 96.6
pod 4 4 100.0
total 247 287 86.0


line stmt bran cond sub pod time code
1             package Log::Fu;
2 5     5   1256228 use strict;
  5         11  
  5         188  
3 5     5   53 use warnings;
  5         11  
  5         216  
4 5     5   26 use base qw(Exporter);
  5         14  
  5         414  
5 5     5   617691 use Log::Fu::Common qw(:levels %Config LEVELS fu_term_is_ansi);
  5         13  
  5         1092  
6 5     5   43 use Log::Fu::Common;
  5         9  
  5         237  
7 5     5   3205 use Log::Fu::Color;
  5         11  
  5         264  
8 5     5   913741 use Log::Fu::Chomp;
  5         14  
  5         260  
9 5     5   31 use Carp qw(carp);
  5         7  
  5         232  
10 5     5   5736 use Sys::Syslog;
  5         149155  
  5         476  
11 5     5   52 use File::Basename qw(basename);
  5         12  
  5         510  
12              
13 5     5   34 use Constant::Generate [ map {"FLD_$_"} (qw(FH LVL FMT COLOR ISATTY CODE))];
  5         9  
  5         12  
  30         112  
14 5         34 use Constant::Generate [qw(
15             LOGFN_TYPE_LIST
16             LOGFN_TYPE_SUB_PLAIN
17             LOGFN_TYPE_SUB_FMT
18 5     5   1711 )], -start_at => 1;
  5         10  
19              
20             our @EXPORT = ( map { ("log_$_", "elog_$_" ) } (LEVELS) );
21             push @EXPORT, map "log_$_"."f", LEVELS;
22             push @EXPORT, map "elog_$_"."f", LEVELS;
23             our @EXPORT_OK = qw(set_log_level);
24              
25             our $VERSION = '0.31';
26              
27             our $SHUSH = 0;
28             our $LINE_PREFIX = "";
29             our $LINE_SUFFIX = "";
30              
31             our $TERM_ANSI = fu_term_is_ansi();
32             our $TERM_CLEAR_LINE= $TERM_ANSI;
33              
34             our $USE_WATCHDOG = $ENV{LOG_FU_WATCHDOG};
35             our $NO_STRIP = $ENV{LOG_FU_NO_STRIP};
36              
37             our $FORCE_COLOR = $ENV{LOG_FU_FORCE_COLOR};
38              
39             our $DISPLAY_SEVERITY = $ENV{LOG_FU_DISPLAY_SEVERITY};
40             $DISPLAY_SEVERITY ||= 0;
41              
42             my $ENABLE_SYSLOG;
43             my $SYSLOG_FACILITY;
44             my $SYSLOG_STDERR_ECHO = 0;
45              
46             my $CLEAR_LINE_ESC = "\033[0J";
47             #From 0.20
48             sub Configure {
49 3     3 1 2392 my %options = @_;
50            
51 3 50       12 if($USE_WATCHDOG) {
52 0         0 carp "Changing global logging options..";
53             }
54            
55 3         14 foreach my $k (keys %Config) {
56 21 100       45 if(exists $options{$k}) {
57 6         15 $Config{$k} = delete $options{$k};
58             }
59             }
60 3 50       15 if(%options) {
61 0         0 die "Unknown options: " . join(",", keys %options);
62             }
63             }
64              
65             #From 0.20
66             *AddHandler = *Log::Fu::Chomp::AddHandler;
67             *DelHandler = *Log::Fu::Chomp::DelHandler;
68              
69             my (%sources,$log_target);
70             $$log_target = *STDERR;
71             my $def_target_can_use_color = -t STDERR;
72              
73             sub _set_source_level {
74 11     11   28 my ($source,%params) = @_;
75 11         18 my @datum;
76 11         20 my $h = \%params;
77 11 100       42 $params{level} = LOG_INFO unless defined $params{level};
78 11 100       40 $params{target} = $log_target unless defined $params{target};
79 11         35 @datum[FLD_LVL, FLD_FH] = @params{qw(level target)};
80 11 100       100 if(ref $params{target} eq 'CODE') {
81 5         12 $datum[FLD_CODE] = $params{target};
82             } else {
83 6         38 $datum[FLD_COLOR] = -t $datum[FLD_FH];
84 6         87 $datum[FLD_ISATTY] = -t $datum[FLD_FH];
85             }
86 11         40 $sources{$source} = \@datum;
87             }
88              
89             my $defpkg_key = '__LOG_FU_DEFAULTS__';
90              
91             _set_source_level($defpkg_key);
92              
93              
94              
95             sub import {
96 6     6   614 my $h;
97             #check if we're passed an option hashref
98 6         32 foreach my $i (0..$#_) {
99 12 100       52 if(ref($_[$i]) eq "HASH") {
100 6         23 $h = delete $_[$i];
101             }
102             }
103             #get the filename of the code that's using us.
104 6         20 my $pkgname = caller();
105            
106 6         23 my($ulevel,$target,$subs,$prefix) =
107 6         11 delete @{$h}{qw(level target subs function_prefix)};
108            
109 6   100     31 $prefix ||= "";
110 6 100       20 $ulevel = "info" unless defined $ulevel;
111 6         386 my $level = eval("LOG_".uc($ulevel));
112 6 50       28 die "Unknown level $ulevel" unless defined $level;
113 6         21 _set_source_level($pkgname, level => $level, target => $target);
114 6 100       18 if($subs) {
115 1         3 _gen_subsubs($pkgname, $prefix);
116             } else {
117 5         16 _gen_listsubs($pkgname, $prefix);
118 5         21 _gen_subsubs($pkgname, $prefix."e");
119             }
120 6         4716 return 1;
121             }
122              
123             #Called to get stuff for per-package personalization
124             sub _get_pkg_params {
125             #clandestinely does level checking
126 25     25   36 my ($pkgname, $level) = @_;
127 25         46 my $ret = $sources{$pkgname};
128 25   33     64 $ret ||= $sources{$defpkg_key};
129 25 100       72 if($level < $ret->[FLD_LVL]) {
130 6         10 $ret = undef;
131             }
132 25         49 return $ret;
133             }
134              
135              
136             sub _logger {
137 25 50   25   72 return if $SHUSH; #no logging wanted!
138 25         58 my ($level_number, $level_name, $stack_offset, $type, @messages) = @_;
139            
140 25         174 my ($pkgname,$filename,$line) = caller(0+$stack_offset);
141 25         79 my $pparams = _get_pkg_params($pkgname, $level_number);
142 25 100       74 return if !defined $pparams;
143              
144 19         59 my (undef,undef,undef,$subroutine) = caller(1+$stack_offset);
145 19   100     76 $subroutine ||= "-";
146 19         29 my $outfile = $pparams->[FLD_FH];
147 19         669 my $basename = basename($filename);
148 19         42 my $level_str = "[$level_name] ";
149            
150 19         22 my $message;
151 19 100       46 if($type == LOGFN_TYPE_LIST) {
152 17         37 $message = join(" ", @messages);
153             } else {
154 2 50       39 my $sub = $messages[0]
155             or die "Sub-style logging requested but no sub provided";
156 2         8 @messages = $sub->();
157            
158 2 100       21 if($type == LOGFN_TYPE_SUB_PLAIN) {
    50          
159 1         4 $message = join(" ", @messages);
160             } elsif($type == LOGFN_TYPE_SUB_FMT) {
161 1         4 my $fmt_str = $messages[0];
162 1         8 $message = sprintf($fmt_str, @messages[1..$#messages]);
163             } else {
164 0         0 die("Unknown logging mode $type");
165             }
166             }
167              
168             #Color stuff...
169 19 50 33     149 if( ($Log::Fu::Color::USE_COLOR && $pparams->[FLD_COLOR]) || $FORCE_COLOR) {
    100 33        
170 0         0 $message = fu_colorize($level_number, $message);
171 0 0       0 if($DISPLAY_SEVERITY <= 0) {
172 0         0 $level_str = "";
173             }
174             } elsif($DISPLAY_SEVERITY == -1) {
175 1         4 $level_str = "";
176             }
177              
178 19         72 $subroutine = fu_chomp($subroutine);
179            
180 19         76 my $msg = "$level_str$basename:$line ($subroutine): $message\n";
181            
182 19 50       58 if ($LINE_PREFIX) {
183 0         0 $msg =~ s/^(.)/$LINE_PREFIX$1/mg;
184             }
185 19 50       41 if($LINE_SUFFIX) {
186 0         0 $msg =~ s/(.)$/$1$LINE_SUFFIX/mg;
187             }
188 19 0 33     43 if($pparams->[FLD_ISATTY] && $TERM_CLEAR_LINE) {
189 0         0 $msg =~ s/^(.)/$CLEAR_LINE_ESC$1/mg
190             #Clear the rest of the line, too:
191             }
192 19 50       60 if(ref $outfile eq 'CODE') {
193 19         62 $outfile->($msg);
194             } else {
195 0         0 print $outfile $msg;
196             }
197            
198 19 100       4375 if ($ENABLE_SYSLOG) {
199 2         11 syslog(syslog_level($level_number), $msg);
200             }
201             }
202              
203             foreach my $level (LEVELS) {
204             #Plain wrappers
205             my $fn_name = "log_$level";
206 5     5   18170 no strict "refs";
  5         12  
  5         6733  
207             my $const = &{uc("LOG_" . $level)};
208             #Offset wrappers
209             *{ $fn_name . "_with_offset" } = sub {
210 0     0   0 _logger($const, uc($level), 1 + shift, LOGFN_TYPE_LIST, @_);
211             };
212             }
213              
214             my %export_cache;
215              
216             sub _gen_listsubs {
217 10     10   18 my ($pkgname,$prefix) = @_;
218 10   100     75 $prefix ||= "";
219 10         29 foreach my $level (LEVELS) {
220 50         104 my $fn_name = $pkgname . "::$prefix" . "log_$level";
221 50 50       114 next if exists $export_cache{$fn_name};
222 50         116 $export_cache{$fn_name} = 1;
223 5     5   37 no strict 'refs';
  5         11  
  5         1504  
224 50         49 my $const = &{uc("LOG_$level")};
  50         132  
225 50         206 *{ $fn_name } = sub {
226 18     18   3906 @_ = ($const,uc($level),0,LOGFN_TYPE_LIST,@_);
227 18         67 goto &_logger;
228 50         207 };
229            
230 50         292 *{ $fn_name . "f" } = sub {
231 2     2   541 @_ = ($const,uc($level),0,LOGFN_TYPE_LIST,
232             sprintf($_[0], @_[1..$#_]));
233 2         7 goto &_logger;
234 50         195 };
235             }
236             }
237              
238             sub _gen_subsubs {
239 11     11   42 my ($pkgname,$prefix) = @_;
240 11   100     31 $prefix ||= "";
241 11         35 foreach my $level (LEVELS) {
242 55         141 my $fn_name = $pkgname . "::$prefix" . "log_$level";
243 55 50       132 next if exists $export_cache{$fn_name};
244 55         129 $export_cache{$fn_name} = 1;
245            
246 5     5   27 no strict 'refs';
  5         13  
  5         2133  
247 55         63 my $const = &{uc("LOG_".$level)};
  55         151  
248            
249 55         239 *{$fn_name} = sub (&) {
250 2     2   1325 @_ = ($const,uc($level), 0, LOGFN_TYPE_SUB_PLAIN, $_[0]);
251 2         13 goto &_logger;
252 55         197 };
253            
254 55         260 *{$fn_name . "f"} = sub (&) {
255 3     3   2342 @_ = ($const, uc($level), 0, LOGFN_TYPE_SUB_FMT, $_[0]);
256 3         11 goto &_logger;
257 55         219 };
258             }
259             }
260              
261             _gen_subsubs(__PACKAGE__, "e");
262             _gen_listsubs(__PACKAGE__, "");
263              
264             #From 0.03
265             sub set_log_level {
266 3     3 1 1111 my ($pkgname,$level) = @_;
267 3         162 $level = eval("LOG_".uc($level));
268 3 50       11 return if !defined $level;
269 3 50       7 return if !exists $sources{$pkgname};
270 3         5 $sources{$pkgname}->[FLD_LVL] = $level;
271 3         33 return 1;
272             }
273              
274             #From 0.04
275             sub start_syslog {
276             #Take standard openlog options,
277 1     1 1 530 my $ok = openlog(@_);
278 1 50       45 $ENABLE_SYSLOG = 1 if $ok;
279 1         4 return $ok;
280             }
281              
282             sub stop_syslog {
283 1     1 1 495 my $ok = closelog();
284 1 50       28 $ENABLE_SYSLOG = 0 if $ok;
285 1         6 return $ok;
286             }
287              
288             1;
289              
290             __END__