File Coverage

blib/lib/Object/Remote/Logging/Logger.pm
Criterion Covered Total %
statement 70 75 93.3
branch 14 18 77.7
condition 2 3 66.6
subroutine 16 19 84.2
pod 0 1 0.0
total 102 116 87.9


line stmt bran cond sub pod time code
1             package Object::Remote::Logging::Logger;
2              
3 18     18   2777 use Moo;
  18         35  
  18         102  
4 18     18   6229 use Carp qw(croak);
  18         52  
  18         4789  
5              
6             #TODO sigh invoking a logger with a log level name the same
7             #as an attribute could happen - restrict attributes to _ prefix
8             #and restrict log levels to not start with out that prefix?
9             has format => ( is => 'ro', required => 1, default => sub { '%l: %s' } );
10             has level_names => ( is => 'ro', required => 1 );
11             has min_level => ( is => 'ro', required => 1, default => sub { 'info' } );
12             has max_level => ( is => 'lazy', required => 1 );
13             has _level_active => ( is => 'lazy' );
14              
15             #just a stub so it doesn't get to AUTOLOAD
16       18 0   sub BUILD { }
17       0     sub DESTROY { }
18              
19             sub AUTOLOAD {
20 8     8   49 my $self = shift;
21 8         68 (my $method) = (our $AUTOLOAD =~ /([^:]+)$/);
22              
23 18     18   139 no strict 'refs';
  18         36  
  18         21471  
24              
25 8 50       31 if ($method =~ m/^_/) {
26 0         0 croak "invalid method name $method for " . ref($self);
27             }
28              
29 8 100       41 if ($method =~ m/^is_(.+)/) {
30 4         10 my $level_name = $1;
31 4         9 my $is_method = "is_$level_name";
32 4     60   39 *{$is_method} = sub { shift(@_)->_level_active->{$level_name} };
  4         26  
  60         1575  
33 4         18 return $self->$is_method;
34             }
35              
36 4         36 my $level_name = $method;
37 4         90 *{$level_name} = sub {
38 60     60   81 my $self = shift;
        0      
39 60 50       1086 unless(exists($self->_level_active->{$level_name})) {
40 0         0 croak "$level_name is not a valid log level name";
41             }
42              
43 60         430 $self->_log($level_name, @_);
44 4         22 };
45              
46 4         21 return $self->$level_name(@_);
47             }
48              
49             sub _build_max_level {
50 18     18   1066 my ($self) = @_;
51 18         95 return $self->level_names->[-1];
52             }
53              
54             sub _build__level_active {
55 18     18   206 my ($self) = @_;
56 18         36 my $should_log = 0;
57 18         72 my $min_level = $self->min_level;
58 18         420 my $max_level = $self->max_level;
59 18         46 my %active;
60              
61 18         38 foreach my $level (@{$self->level_names}) {
  18         52  
62 117 100       283 if($level eq $min_level) {
63 18         35 $should_log = 1;
64             }
65              
66 117         253 $active{$level} = $should_log;
67              
68 117 100 66     390 if (defined $max_level && $level eq $max_level) {
69 18         40 $should_log = 0;
70             }
71             }
72              
73 18         163 return \%active;
74             }
75              
76             sub _log {
77 60     60   443 my ($self, $level, $content, $metadata_in) = @_;
78 60         303 my %metadata = %$metadata_in;
79 60         174 my $rendered = $self->_render($level, \%metadata, @$content);
80 60         170 $self->_output($rendered);
81             }
82              
83             sub _create_format_lookup {
84 60     60   91 my ($self, $level, $metadata, $content) = @_;
85 60         87 my $method = $metadata->{method};
86              
87 60 100       100 $method = '(none)' unless defined $method;
88              
89             return {
90             '%' => '%', 'n' => "\n",
91             t => $self->_render_time($metadata->{timestamp}),
92             r => $self->_render_remote($metadata->{object_remote}),
93             s => $self->_render_log(@$content), l => $level,
94             c => $metadata->{exporter}, p => $metadata->{caller_package}, m => $method,
95             f => $metadata->{filename}, i => $metadata->{line},
96             h => $metadata->{hostname}, P => $metadata->{pid},
97 60         125 };
98             }
99              
100             sub _get_format_var_value {
101 64     64   186 my ($self, $name, $data) = @_;
102 64         107 my $val = $data->{$name};
103 64 50       209 return $val if defined $val;
104 0         0 return '(undefined)';
105             }
106              
107             sub _render_time {
108 60     60   129 my ($self, $time) = @_;
109 60         1424 return scalar(localtime($time));
110             }
111              
112             sub _render_remote {
113 60     60   141 my ($self, $remote) = @_;
114 60 100       179 return 'local' unless defined $remote;
115 2         4 my $conn_id = $remote->{connection_id};
116 2 50       5 $conn_id = '(uninit)' unless defined $conn_id;
117 2         7 return "remote #$conn_id";
118             }
119              
120             sub _render_log {
121 60     60   104 my ($self, @content) = @_;
122 60         575 return join('', @content);
123             }
124             sub _render {
125 60     60   111 my ($self, $level, $metadata, @content) = @_;
126 60         137 my $var_table = $self->_create_format_lookup($level, $metadata, [@content]);
127 60         165 my $template = $self->format;
128              
129 60         273 $template =~ s/%([\w%])/$self->_get_format_var_value($1, $var_table)/ge;
  64         138  
130              
131 60         99 chomp($template);
132 60         99 $template =~ s/\n/\n /g;
133 60         94 $template .= "\n";
134 60         246 return $template;
135             }
136              
137             sub _output {
138 0     0   0 my ($self, $content) = @_;
139 0         0 print STDERR $content;
140             }
141              
142             1;
143              
144             __END__