File Coverage

blib/lib/POE/XUL/Logging.pm
Criterion Covered Total %
statement 128 141 90.7
branch 52 70 74.2
condition 29 42 69.0
subroutine 19 20 95.0
pod 4 12 33.3
total 232 285 81.4


line stmt bran cond sub pod time code
1             package POE::XUL::Logging;
2             # $Id: Logging.pm 1566 2010-11-03 03:13:32Z fil $
3             # Copyright Philip Gwyn 2007-2010. All rights reserved.
4             #
5             # Handle logging features for the application
6             #
7              
8 20     20   316 use 5.008;
  20         52  
9 20     20   69 use strict;
  20         25  
  20         317  
10 20     20   60 use warnings;
  20         20  
  20         415  
11              
12 20     20   62 use Carp;
  20         22  
  20         1032  
13 20     20   77 use Scalar::Util qw( reftype blessed openhandle );
  20         28  
  20         1433  
14              
15 20     20   80 use constant DEBUG => 0;
  20         197  
  20         27296  
16              
17             our $VERSION = '0.0601';
18              
19             require Exporter;
20             our @ISA = qw( Exporter );
21              
22             our @EXPORT_OK = qw( xwarn xlog xdebug xcarp xcarp2 );
23             our @EXPORT = @EXPORT_OK;
24              
25             our $SINGLETON;
26              
27             # To interface with log4perl
28             my %type2level = (
29             DEBUG => 10000,
30             LOG => 20000,
31             REQ => 20000,
32             WARN => 30000,
33             SETUP => 42000
34             );
35              
36             ############################################################
37             sub new
38             {
39 6     6 0 9 my( $package, $args, $log_root ) = @_;
40              
41 6         36 my $rt = reftype $args;
42 6 50       20 if( $args ) {
43 6 100 66     65 if( !$rt or $rt eq 'CODE' or $rt eq 'HASH' or blessed $args ) {
    50 100        
      100        
44             # ok
45             }
46             elsif( $rt eq 'ARRAY' ) {
47 1 50       5 if( 2 > @$args ) {
48 0         0 croak "logging parameter must have at least 2 elements";
49             }
50             }
51             else {
52 0         0 croak "logging parameter must be a CODE ref, ARRAY ref, scalar or a log4perl object";
53             }
54             }
55              
56 6         23 my $self = $SINGLETON =
57             bless { logger=>$args, log_root=>$log_root }, $package;
58              
59 6 100 100     32 if( $rt and $rt eq 'HASH' ) {
60 3         10 $self->{logger} = $args->{logger};
61 3         4 $self->{access_log} = $args->{access_log};
62 3         5 $self->{error_log} = $args->{error_log};
63 3         7 $self->__init_apps( $args->{apps} );
64             }
65              
66 6         18 return $SINGLETON;
67             }
68              
69             sub __init_apps
70             {
71 3     3   6 my( $self, $apps ) = @_;
72 3 100       6 unless( $apps ) {
73 2         4 $self->{apps} = [];
74 2         4 return;
75             }
76 1 50       4 unless( ref $apps ) {
    50          
77 0         0 $apps = { $apps=>$apps };
78             }
79             elsif( 'ARRAY' eq ref $apps ) {
80 0         0 my %A;
81 0         0 @A{@$apps} = @$apps;
82 0         0 $apps = \%A;
83             }
84 1         2 $self->{apps} = [];
85 1         4 while( my( $app, $def ) = each %$apps ) {
86 2         5 push @{ $self->{apps} }, $app;
  2         3  
87 2         3 foreach my $t ( qw( access error ) ) {
88 4         24 my $log = "${t}_log";
89 4         2 my $file;
90 4 100       8 unless( ref $def ) {
    100          
91 2         9 $file = File::Spec->catfile( $def, $log );
92             }
93             elsif( $def->{$log} ) {
94 1         2 $file = $def->{$log};
95             }
96             else {
97 1         4 $file = File::Spec->catfile( $app, $log );
98             }
99 4         15 $self->{"$app-$t-log"} = $file;
100             }
101             }
102 1         2 return;
103             }
104              
105             ############################################################
106             sub setup
107             {
108 5     5 0 6 my( $self ) = @_;
109              
110 5   100     20 $self->{logger} ||= \&default_sub;
111             $self->dispatch( { type => 'SETUP',
112             directory => $self->{log_root}
113 5         21 } );
114             }
115              
116             ############################################################
117             # Dispatch the exception
118             sub dispatch
119             {
120 31     31 0 34 my( $self, $exception ) = @_;
121 31 50       85 $self = $SINGLETON unless blessed $self;
122              
123 31 50       54 $exception = { message => $exception, type => 'LOG' }
124             unless ref $exception;
125              
126 31         59 my $rt = reftype $self->{logger};
127 31 100       98 if( blessed $self->{logger} ) {
    100          
    100          
    50          
128 6 100       15 return if $exception->{type} eq 'SETUP';
129 5         6 my $lvl = $type2level{ $exception->{type} };
130 5   66     11 $lvl ||= $type2level{ 'LOG' };
131 5         9 $self->{logger}->log( $lvl, $exception->{message} );
132             }
133             elsif( not $rt ) {
134 5         13 $POE::Kernel::poe_kernel->call( $self->{logger}, 'log', $exception );
135             }
136             elsif( $rt eq 'ARRAY' ) {
137             # warn "POE logger @{ $self->{logger} }";
138 5         4 $POE::Kernel::poe_kernel->call( @{ $self->{logger} }, $exception );
  5         18  
139             }
140             elsif( $rt eq 'CODE' ) {
141 15         21 $self->{logger}->( $exception );
142             }
143             }
144              
145             ############################################################
146             sub default_sub
147             {
148 9     9 0 7 my( $ex ) = @_;
149 9   50     11 $ex->{type} ||= '';
150              
151 9 100       26 if( $ex->{type} eq 'SETUP' ) {
152 1         2 $SINGLETON->default_setup;
153 1         2 return;
154             }
155              
156 8 100 66     27 if( $ex->{type} and $ex->{type} ne 'REQ' ) {
157 6         10 $ex->{message} = "$ex->{type} $ex->{message}";
158             }
159 8         14 $SINGLETON->default( @_ )
160             }
161              
162              
163             ############################################################
164             sub default_setup
165             {
166 1     1 0 2 my( $self ) = @_;
167 1 50       3 $self = $SINGLETON unless blessed $self;
168              
169 1         3 $self->{stderr_fh} = $self->open_file( qw( error_log error_log ) );
170 1         2 $self->{error_fh} = $self->{stderr_fh};
171 1         2 $self->{log_fh} = $self->open_file( qw( access_log access_log ) );
172 1         2 $self->{access_fh} = $self->{log_fh};
173 1         2 foreach my $app ( @{ $self->{apps} } ) {
  1         3  
174 2         3 foreach my $t ( qw( error access ) ) {
175 4 50       9 if( $self->{"$app-$t-log"} ) {
176 4         14 $self->{"$app-$t-fh"} =
177             $self->open_file( "$app-$t-log", "$app/${t}_log" );
178             }
179             else {
180 0         0 $self->{"$app-$t-fh"} = $self->{"${t}_fh"};
181             }
182             }
183             }
184             }
185              
186             ############################################################
187             sub open_file
188             {
189 6     6 0 7 my( $self, $key, $name ) = @_;
190              
191 6         7 my $file = $self->{$key};
192 6   33     9 $file ||= File::Spec->catfile( $self->{log_root}, $name );
193 6 100       36 unless( File::Spec->file_name_is_absolute( $file ) ) {
194 4         25 $file = File::Spec->catfile( $self->{log_root}, $file );
195 4         8 $self->{$key} = $file;
196             }
197              
198 6         51 my( $vol, $dir, $f ) = File::Spec->splitpath( $file );
199              
200 6 100 66     109 if( $dir and not -d $dir ) {
201 3         371 File::Path::mkpath( [ $dir ], 0, 0750 );
202             }
203              
204 6         28 my $fh = IO::File->new;
205 6 50       136 unless( $fh->open(">> $file") ) {
206 0         0 warn "AUGH $file: $!";
207 0         0 die "Unable to create log file $file: $!";
208             }
209 6         356 $fh->autoflush(1);
210 6         160 return $fh;
211             }
212              
213              
214              
215             ############################################################
216             sub default
217             {
218 8     8 0 6 my( $self, $exception ) = @_;
219 8 50       17 $self = $SINGLETON unless blessed $self;
220              
221 8   50     13 my $type = $exception->{type}||'';
222 8         6 my $msg = $exception->{message};
223 8 50       11 $msg = '' unless defined $msg;
224 8 100       15 $msg =~ s/\n+$// if $exception->{location};
225 8 100       15 if( $msg !~ /\n$/ ) {
226             $msg .= " at $exception->{caller}[1] line $exception->{caller}[2]"
227 6 50       20 if $exception->{caller};
228 6         6 $msg .= "\n";
229             }
230            
231 8   100     16 my $app = $self->{app}||'THERE-IS-NO-APP';
232 8 100       12 my $t = $type eq 'REQ' ? 'access' : 'error';
233 8   33     38 my $fh = $self->{"$app-$t-fh"} || $self->{"${t}_fh"} || $self->{stderr_fh};
234 8 50       9 if( $fh ) {
235 8         21 $fh->print( $msg );
236             }
237             else {
238 0         0 print STDERR $msg;
239             }
240             }
241              
242              
243              
244             ############################################################
245             sub __mk_exception
246             {
247 22     22   37 my( $package, $type, $level, @msg ) = @_;
248              
249 22         23 local $, = $,;
250 22 50       46 $, = '' unless defined $,;
251             return {
252             type => $type,
253 22         32 message => join( $,, grep {defined} @msg),
  22         206  
254             caller => [ caller( $level ) ]
255             };
256             }
257              
258             sub xdebug
259             {
260 5 50   5 1 4976 return carp join( '' , @_ ) unless $SINGLETON;
261 5         15 $SINGLETON->dispatch( $SINGLETON->__mk_exception( 'DEBUG', 1, @_ ) );
262             }
263              
264             sub xwarn
265             {
266 7 50   7 1 8197 return carp join( '' , @_ ) unless $SINGLETON;
267 7         25 $SINGLETON->dispatch( $SINGLETON->__mk_exception( 'WARN', 1, @_ ) );
268             }
269              
270             sub xcarp
271             {
272 5     5 1 4852 my $ex = $SINGLETON->__mk_exception( 'WARN', 2, @_ );
273 5         11 $ex->{location} = 1;
274 5         16 $SINGLETON->dispatch( $ex );
275             }
276              
277             sub xcarp2
278             {
279 0     0 0 0 my $ex = $SINGLETON->__mk_exception( 'WARN', 3, @_ );
280 0         0 $ex->{location} = 1;
281 0         0 $SINGLETON->dispatch( $ex );
282             }
283              
284             sub xlog
285             {
286 9     9 1 5914 my $ex;
287 9 100 66     52 if( 1==@_ and 'HASH' eq ref $_[0] ) {
288 4         5 $ex = $_[0];
289 4   50     14 $ex->{type} ||= 'LOG';
290 4   50     33 $ex->{caller} ||= [ caller( 0 ) ];
291             }
292             else {
293 5         14 $ex = $SINGLETON->__mk_exception( 'LOG', 1, @_ );
294             }
295 9         23 $SINGLETON->dispatch( $ex );
296             }
297              
298              
299              
300              
301             1;
302              
303             __DATA__