File Coverage

blib/lib/Algorithm/Genetic/Diploid/Logger.pm
Criterion Covered Total %
statement 24 57 42.1
branch 6 28 21.4
condition 0 3 0.0
subroutine 5 11 45.4
pod 3 3 100.0
total 38 102 37.2


line stmt bran cond sub pod time code
1             package Algorithm::Genetic::Diploid::Logger;
2 2     2   11 use strict;
  2         4  
  2         68  
3 2     2   15 use Exporter;
  2         5  
  2         103  
4 2     2   12 use base 'Exporter';
  2         4  
  2         2689  
5              
6             our $AUTOLOAD;
7             our @EXPORT_OK = qw(DEBUG INFO WARN ERROR FATAL);
8             our %EXPORT_TAGS = ( 'levels' => [@EXPORT_OK] );
9             our $VERBOSE = 2; # i.e. WARN, default
10             our %VERBOSE;
11             my $formatter = \&_simple_formatter;
12              
13             =head1 NAME
14              
15             Algorithm::Genetic::Diploid::Logger - reports on progress of the experiment
16              
17             =head1 METHODS
18              
19             =over
20              
21             =item new
22              
23             This singleton constructor always returns reference to same object
24              
25             =cut
26              
27             my $SINGLETON;
28             sub new {
29 2     2 1 6 my $class = shift;
30 2 50       11 if ( not $SINGLETON ) {
31 2         18 $SINGLETON = bless \$class, $class;
32             }
33 2 50       11 $SINGLETON->level(@_) if @_;
34 2         6 return $SINGLETON;
35             }
36              
37             =item level
38              
39             Alters log level. Takes named arguments: C provides a scalar or array of fully
40             qualified method names whose verbosity to alter. C provides a scalar or array of
41             package names whose verbosity to alter. C sets the verbosity to one of the levels
42             described below.
43              
44             =cut
45              
46             sub level {
47 0     0 1 0 my $self = shift;
48 0         0 my %args = @_;
49            
50             # set verbosity at the level of methods
51 0 0       0 if ( $args{'method'} ) {
    0          
52 0 0       0 if ( ref $args{'method'} eq 'ARRAY' ) {
53 0         0 $VERBOSE{$_} = $args{'level'} for @{ $args{'method'} };
  0         0  
54             }
55             else {
56 0         0 $VERBOSE{$args{'method'}} = $args{'level'};
57             }
58             }
59            
60             # set verbosity at the level of classes
61             elsif ( $args{'class'} ) {
62 0 0       0 if ( ref $args{'class'} eq 'ARRAY' ) {
63 0         0 $VERBOSE{$_} = $args{'level'} for @{ $args{'class'} };
  0         0  
64             }
65             else {
66 0         0 $VERBOSE{$args{'class'}} = $args{'level'};
67             }
68             }
69            
70             # set verbosity globally
71             else {
72 0         0 $VERBOSE = $args{'level'};
73             }
74 0         0 return $self;
75             }
76              
77             =item formatter
78              
79             Alters log string formatter. When argument is 'simple' the log string is just
80             the logging level and message, when argument is 'verbose', the log string has
81             the calling subroutine name and location in it. 'medium' omits the file location.
82             When the argument is a code reference, this reference is executed for every
83             log message, with the following named arguments:
84              
85             'level' => (DEBUG|INFO|WARN|ERROR|FATAL)
86             'sub' => fully qualified name of the calling subroutine
87             'file' => path to the calling file
88             'line' => line number from whence the call was made
89             'msg' => the log message
90              
91             =cut
92              
93             sub formatter {
94 0     0 1 0 my ( $self, $arg ) = @_;
95 0 0 0     0 if ( ref $arg and ref $arg eq 'CODE' ) {
96 0         0 $formatter = $arg;
97             }
98             else {
99 0 0       0 if ( 'simple' eq lc $arg ) {
    0          
    0          
100 0         0 $formatter = \&_simple_formatter;
101             }
102             elsif ( 'medium' eq lc $arg ) {
103 0         0 $formatter = \&_medium_formatter;
104             }
105             elsif ( 'verbose' eq lc $arg ) {
106 0         0 $formatter = \&_verbose_formatter;
107             }
108             }
109             }
110              
111             # destructor does nothing
112 0     0   0 sub DESTROY {}
113              
114             =back
115              
116             =head1 VERBOSITY LEVELS
117              
118             The following constants are available when using this package with the use qualifier
119             ':levels', i.e. C. They represent
120             different verbosity levels that can be set globally, and/or at package level, and/or
121             at method level.
122              
123             =over
124              
125             =item FATAL
126              
127             Only most severe messages are transmitted.
128              
129             =cut
130              
131             sub FATAL () { 0 }
132              
133             =item ERROR
134              
135             Possibly unrecoverable errors are transmitted.
136              
137             =cut
138              
139             sub ERROR () { 1 }
140              
141             =item WARN
142              
143             Warnings are transmitted. This is the default.
144              
145             =cut
146              
147             sub WARN () { 2 }
148              
149             =item INFO
150              
151             Informational messages are transmitted.
152              
153             =cut
154              
155             sub INFO () { 3 }
156              
157             =item DEBUG
158              
159             Everything is transmitted, including debugging messages.
160              
161             =cut
162              
163             sub DEBUG () { 4 }
164              
165             # constants mapped to string for AUTOLOAD
166             my %levels = (
167             'fatal' => FATAL,
168             'error' => ERROR,
169             'warn' => WARN,
170             'info' => INFO,
171             'debug' => DEBUG,
172             );
173              
174             sub _simple_formatter {
175 0     0   0 my %args = @_;
176 0         0 my ( $level, $sub, $file, $line, $msg ) = @args{('level','sub','file','line','msg')};
177 0         0 return sprintf "%s %s\n", $level, $msg;
178             }
179              
180             sub _verbose_formatter {
181 0     0   0 my %args = @_;
182 0         0 my ( $level, $sub, $file, $line, $msg ) = @args{('level','sub','file','line','msg')};
183 0         0 return sprintf "%s %s [%s, %s] - %s\n", $level, $sub, $file, $line, $msg;
184             }
185              
186             sub _medium_formatter {
187 0     0   0 my %args = @_;
188 0         0 my ( $level, $sub, $file, $line, $msg ) = @args{('level','sub','file','line','msg')};
189 0         0 return sprintf "%s %s [%s] - %s\n", $level, $sub, $line, $msg;
190             }
191              
192             # this is where methods such as $log->info ultimately are routed to
193             sub AUTOLOAD {
194 28455     28455   49847 my ( $self, $msg ) = @_;
195 28455         53565 my $method = $AUTOLOAD;
196 28455         109435 $method =~ s/.+://;
197            
198             # only proceed if method was one of fatal..debug
199 28455 50       102501 if ( exists $levels{$method} ) {
200 28455         169200 my ( $package, $file1up, $line1up, $subroutine ) = caller( 1 );
201 28455         129073 my ( $pack0up, $filename, $line, $sub0up ) = caller( 0 );
202            
203             # calculate what the verbosity is for the current context
204             # (either at sub, package or global level)
205 28455         49533 my $verbosity;
206 28455 50       97934 if ( exists $VERBOSE{$subroutine} ) {
    50          
207 0         0 $verbosity = $VERBOSE{$subroutine};
208             }
209             elsif ( exists $VERBOSE{$pack0up} ) {
210 0         0 $verbosity = $VERBOSE{$pack0up};
211             }
212             else {
213 28455         38769 $verbosity = $VERBOSE;
214             }
215            
216             # we need to do something with the message
217 28455 50       143614 if ( $verbosity >= $levels{$method} ) {
218 0           printf STDERR $formatter->(
219             'level' => uc $method,
220             'sub' => $subroutine,
221             'file' => $filename,
222             'line' => $line,
223             'msg' => $msg,
224             );
225             }
226             }
227             }
228              
229             =back
230              
231             =cut
232              
233             1;