File Coverage

blib/lib/Bio/Gonzales/Util/Log.pm
Criterion Covered Total %
statement 53 67 79.1
branch 11 30 36.6
condition 2 6 33.3
subroutine 14 28 50.0
pod 13 19 68.4
total 93 150 62.0


line stmt bran cond sub pod time code
1             package Bio::Gonzales::Util::Log;
2              
3             # shamelessly stolen from Mojo::Log, thanks to Sebastian Riedel & contributors for creating it.
4 14     14   169575 use Moo;
  14         156948  
  14         70  
5              
6 14     14   25238 use Carp qw(croak confess);
  14         42  
  14         788  
7 14     14   76 use Fcntl ':flock';
  14         28  
  14         1532  
8 14     14   110 use POSIX qw/strftime/;
  14         28  
  14         126  
9              
10 14     14   23798 use warnings;
  14         41  
  14         432  
11 14     14   73 use strict;
  14         29  
  14         386  
12              
13 14     14   242 use 5.010;
  14         56  
14              
15             our $VERSION = '0.083'; # VERSION
16              
17             # Supported log level
18             my $LEVEL = { debug => 1, info => 2, warn => 3, error => 4, fatal => 5 };
19             my $is_thread = eval '$threads::threads';
20              
21             has path => ( is => 'rw' );
22             has level => ( is => 'rw', default => sub { 'info' } );
23             has namespace => ( is => 'rw' );
24             has _fh => ( is => 'lazy' );
25             has tee_stderr => ( is => 'rw' );
26              
27             has append => ( is => 'rw', default => 1 );
28              
29             sub _build__fh {
30 2     2   40 my $self = shift;
31              
32             # File
33 2 100       12 if ( my $path = $self->path ) {
34 1 50       12 my $mode = $self->append ? '>>' : '>';
35              
36 1 50       91 croak qq{Can't open log file "$path": $!}
37             unless open( my $fh, $mode, $path );
38 1         17 return $fh;
39             }
40              
41             # STDERR
42 1         4 $self->tee_stderr(0);
43 1         6 return \*STDERR;
44             }
45              
46 1     1 1 3164 sub debug { shift->log( debug => @_ ) }
47 0     0 1 0 sub error { shift->log( error => @_ ) }
48 0     0 1 0 sub warn { shift->log( warn => @_ ) }
49 0     0 1 0 sub fatal { shift->log( fatal => @_ ) }
50              
51 0 0   0 0 0 sub fatal_confess { shift->log( fatal => @_ ) and confess(@_) }
52 0 0   0 0 0 sub fatal_die { shift->log( fatal => @_ ) and die(@_) }
53 0 0   0 0 0 sub fatal_croak { shift->log( fatal => @_ ) and croak(@_) }
54              
55 0 0   0 0 0 sub fatal_confess_silent { shift->log( fatal => @_ ) and confess }
56 0 0   0 0 0 sub fatal_die_silent { shift->log( fatal => @_ ) and die }
57 0 0   0 0 0 sub fatal_croak_silent { shift->log( fatal => @_ ) and croak }
58              
59             sub format {
60 3     3 1 9 my ( $self, $level, @lines ) = @_;
61              
62 3         9 @lines = map { split /\n/, $_ } @lines;
  3         17  
63              
64 3         220 my $txt = strftime( "[%d %b %H:%M:%S]", localtime ) . " [" . uc($level) . "]";
65 3 100       32 $txt .= " " . $self->namespace if ( $self->namespace );
66 3 50       12 $txt .= ' (t' . threads->tid() . ')' if ($is_thread);
67 3         6 $txt .= ": ";
68              
69 3         16 $txt .= join( ( "\n" . ( " " x length($txt) ) ), @lines );
70 3         7 $txt .= "\n";
71 3         8 return $txt;
72             }
73              
74 2     2 1 11 sub info { shift->log( info => @_ ) }
75              
76 0     0 1 0 sub is_debug { shift->is_level('debug') }
77 0     0 1 0 sub is_error { shift->is_level('error') }
78 0     0 1 0 sub is_fatal { shift->is_level('fatal') }
79 0     0 1 0 sub is_info { shift->is_level('info') }
80 0     0 1 0 sub is_warn { shift->is_level('warn') }
81              
82             sub is_level {
83 3     3 1 20 my ( $self, $level ) = @_;
84 3 50       10 croak "level not specified" unless ($level);
85 3   33     155 return $LEVEL->{ lc $level } >= $LEVEL->{ lc($ENV{GONZ_LOG_LEVEL} || $self->level) };
86             }
87              
88             sub log {
89 3     3 1 10 my ( $self, $level ) = ( shift, shift );
90              
91 3 50 33     10 return unless $self->is_level($level) && ( my $handle = $self->_fh );
92              
93 3         36 my $msg = $self->format( $level, @_ );
94              
95 3         12 _print( $handle, $msg );
96 3 50       28 _print( \*STDERR, $msg ) if ( $self->tee_stderr );
97 3         16 return $self;
98             }
99              
100             sub _print {
101 3     3   10 my ( $handle, $msg ) = ( shift, shift );
102              
103 3         38 flock $handle, LOCK_EX;
104 3 50       36 $handle->print($msg) or croak "Can't write to log: $!";
105 3         158 $handle->flush;
106 3         29 flock $handle, LOCK_UN;
107             }
108              
109             1;
110              
111             __END__
112              
113             =head1 NAME
114              
115             Bio::Gonzales::Util::Log - basic logging for Bio::Gonzales
116              
117             =head1 SYNOPSIS
118              
119             # logs to stderr by default
120             my $l = Bio::Gonzales::Util::Log->new();
121             $l->info("started application");
122              
123             =head1 DESCRIPTION
124              
125             First of all: Shamelessly stolen from Mojo::Log, thanks to Sebastian Riedel & contributors for creating it.
126              
127             =head1 METHODS
128              
129             =over 4
130              
131             =item B<< $log->path($file) >>
132              
133             Sets or gets the log file path. If not set, STDERR is used.
134              
135             =item B<< $log->level($level) >>
136              
137             Sets or gets the threshold level for logging. Everything lower than this level will not be logged. By default C<debug>.
138              
139             =item B<< $log->namespace($namespace) >>
140              
141             Sets or gets the namespace of the logger.
142              
143             =item B<< $log->tee_stderr($bool) >>
144              
145             Log to file and STDERR. If no path is set, setting this option has no effect.
146              
147             =item B<< $log->append($bool) >>
148              
149             If 1, the logger appends the log output to the log file.
150              
151             =item B<< $log->debug(@lines) >>
152              
153             Log debug message.
154              
155             =item B<< $log->error(@lines) >>
156              
157             Log error message.
158              
159             =item B<< $log->warn(@lines) >>
160              
161             Log warning message.
162              
163             =item B<< $log->fatal(@lines) >>
164              
165             Log fatal message.
166              
167             =item B<< $log->info(@lines) >>
168              
169             Log info message.
170              
171             =item B<< $log_text = $log->format($level, @lines) >>
172              
173             Format C<@lines> and return the formatted text.
174              
175             =item B<< $log->is_debug >>
176              
177             Return true if log level is debug.
178              
179             =item B<< $log->is_error >>
180              
181             Return true if log level is error.
182              
183             =item B<< $log->is_fatal >>
184              
185             Return true if log level is fatal.
186              
187             =item B<< $log->is_info >>
188              
189             Return true if log level is info.
190              
191             =item B<< $log->is_warn >>
192              
193             Return true if log level is warn.
194              
195             =item B<< $log->is_level($level) >>
196              
197             Return true if log level is C<$level>
198              
199             =item B<< $log->log($level, @lines) >>
200              
201             Logs C<$lines> with C<$level> to log destination.
202              
203             =back
204              
205             =head1 SEE ALSO
206              
207             L<Mojo::Log>
208              
209             =head1 AUTHOR
210              
211             jw bargsten, C<< <jwb at cpan dot org> >>
212              
213             =cut