File Coverage

blib/lib/App/ArduinoBuilder/Logger.pm
Criterion Covered Total %
statement 40 57 70.1
branch 15 34 44.1
condition 0 3 0.0
subroutine 11 18 61.1
pod 0 10 0.0
total 66 122 54.1


line stmt bran cond sub pod time code
1             package App::ArduinoBuilder::Logger;
2              
3 3     3   244417 use strict;
  3         15  
  3         85  
4 3     3   13 use warnings;
  3         12  
  3         76  
5 3     3   13 use utf8;
  3         7  
  3         15  
6              
7 3     3   104 use Carp qw(confess);
  3         7  
  3         134  
8 3     3   16 use Exporter 'import';
  3         6  
  3         2957  
9              
10             our @EXPORT = qw(fatal error warning info debug full_debug);
11             our @EXPORT_OK = (@EXPORT, qw(log_cmd set_log_level set_prefix print_stack_on_fatal_error));
12             our %EXPORT_TAGS = (all => [@EXPORT_OK], all_logger => [@EXPORT, 'log_cmd']);
13              
14             my $LEVEL_FATAL = 0; # Fatal errors, abort the program.
15             my $LEVEL_ERROR = 1; # Recoverable errors (almost unused).
16             my $LEVEL_WARN = 2; # Warnings about possible mis-configuration.
17             my $LEVEL_INFO = 3; # Info about the main steps of the program.
18             my $LEVEL_DEBUG = 4; # Any possibly lengthy debugging information.
19             my $LEVEL_CMD = 5; # Command lines being executed (log method not exported by default).
20             my $LEVEL_FULL_DEBUG = 6; # Any possibly very-lengthy debugging information.
21              
22             my $default_level = $LEVEL_INFO;
23             my $current_level = $default_level;
24             my $prefix = '';
25             my $die_with_stack_trace = 0;
26              
27             sub _level_to_prefix {
28 2     2   5 my ($level) = @_;
29 2 50       11 return 'FATAL: ' if $level == $LEVEL_FATAL;
30 2 50       5 return 'ERROR: ' if $level == $LEVEL_ERROR;
31 2 100       10 return 'WARNING: ' if $level == $LEVEL_WARN;
32 1 50       3 return 'INFO: ' if $level == $LEVEL_INFO;
33 1 50       7 return 'DEBUG: ' if $level == $LEVEL_DEBUG;
34 0 0 0     0 return '' if $level == $LEVEL_CMD || $level == $LEVEL_FULL_DEBUG;
35 0         0 error("Unknown log level: ${level}");
36 0         0 return 'UNKNOWN';
37             }
38              
39             sub _log {
40 3     3   9 my ($level, $message, @args) = @_;
41 3 100       10 return if $level > $current_level;
42 2 50       6 @args = map { ref eq 'CODE' ? $_->() : $_ } @args;
  1         18  
43 2         10 my $msg = sprintf "%s%s${message}\n", _level_to_prefix($level), $prefix, @args;
44 2 50       6 if ($level == $LEVEL_FATAL) {
45 0 0       0 if ($die_with_stack_trace) {
46 0         0 confess $msg.'Died'; # Will print "message\nDied at foo.pm line 45\n..."
47             } else {
48 0         0 die $msg;
49             }
50             } else {
51 2         19 warn $msg;
52             }
53 2         15 return;
54             }
55              
56             # printf style method, you can also pass code reference they will be called
57             # and their return value used in the print command (useful to avoid expensive)
58             # method calls when not printing them.
59 0     0 0 0 sub fatal { _log($LEVEL_FATAL, @_) }
60 0     0 0 0 sub fatal_trace { _log($LEVEL_FATAL, @_) }
61 0     0 0 0 sub error { _log($LEVEL_ERROR, @_) }
62 1     1 0 106 sub warning { _log($LEVEL_WARN, @_) }
63 0     0 0 0 sub info { _log($LEVEL_INFO, @_) }
64 2     2 0 6647 sub debug { _log($LEVEL_DEBUG, @_) }
65 0     0 0 0 sub log_cmd { _log($LEVEL_CMD, @_) }
66 0     0 0 0 sub full_debug { _log($LEVEL_FULL_DEBUG, @_) }
67              
68             sub _string_to_level {
69 1     1   3 my ($level) = @_;
70 1 50       6 return $LEVEL_FATAL if $level =~ m/^FATAL$/i;
71 1 50       6 return $LEVEL_ERROR if $level =~ m/^ERR(?:OR)?$/i;
72 1 50       5 return $LEVEL_WARN if $level =~ m/^WARN(:?ING)?$/i;
73 1 50       5 return $LEVEL_INFO if $level =~ m/^INFO?$/i;
74 1 50       8 return $LEVEL_DEBUG if $level =~ m/^(?:DBG|DEBUG)$/i;
75 0 0       0 return $LEVEL_CMD if $level =~ m/^(?:CMD|COMMAND)S?$/i;
76 0 0       0 return $LEVEL_FULL_DEBUG if $level =~ m/^FULL(:?_?(?:DBG|DEBUG))?$/i;
77 0         0 error "Unknown log level: ${level}";
78 0         0 return $default_level;
79             }
80              
81             sub set_log_level {
82 1     1 0 247 my ($level) = @_;
83 1         4 $current_level = _string_to_level($level);
84 1         3 return;
85             }
86              
87             sub print_stack_on_fatal_error {
88 0     0 0   $die_with_stack_trace = $_[0];
89             }
90              
91             1;