File Coverage

blib/lib/Log/Dispatchouli/Proxy.pm
Criterion Covered Total %
statement 149 202 73.7
branch 25 34 73.5
condition 7 11 63.6
subroutine 29 41 70.7
pod 0 30 0.0
total 210 318 66.0


line stmt bran cond sub pod time code
1 7     7   96 use v5.20;
  7         28  
2 7     7   45 use warnings;
  7         12  
  7         622  
3             package Log::Dispatchouli::Proxy 3.013;
4             # ABSTRACT: a simple wrapper around Log::Dispatch
5              
6             # Not dangerous. Accepted without change.
7 7     7   39 use experimental 'postderef', 'signatures';
  7         16  
  7         52  
8              
9 7     7   1540 use Log::Fmt ();
  7         38  
  7         292  
10 7     7   39 use Params::Util qw(_ARRAY0 _HASH0);
  7         22  
  7         18440  
11              
12             #pod =head1 DESCRIPTION
13             #pod
14             #pod A Log::Dispatchouli::Proxy object is the child of a L<Log::Dispatchouli> logger
15             #pod (or another proxy) and relays log messages to its parent. It behaves almost
16             #pod identically to a Log::Dispatchouli logger, and you should refer there for more
17             #pod of its documentation.
18             #pod
19             #pod Here are the differences:
20             #pod
21             #pod =begin :list
22             #pod
23             #pod * You can't create a proxy with C<< ->new >>, only by calling C<< ->proxy >> on an existing logger or proxy.
24             #pod
25             #pod * C<set_debug> will set a value for the proxy; if none is set, C<get_debug> will check the parent's setting; C<clear_debug> will clear any set value on this proxy
26             #pod
27             #pod * C<log_debug> messages will be redispatched to C<log> (to the 'debug' logging level) to prevent parent loggers from dropping them due to C<debug> setting differences
28             #pod
29             #pod =end :list
30             #pod
31             #pod =cut
32              
33 21     21   34 sub _new ($class, $arg) {
  21         34  
  21         27  
  21         28  
34             my $guts = {
35             parent => $arg->{parent},
36             logger => $arg->{logger},
37             debug => $arg->{debug},
38             proxy_prefix => $arg->{proxy_prefix},
39             proxy_ctx => $arg->{proxy_ctx},
40 21         75 };
41              
42 21         73 bless $guts => $class;
43             }
44              
45 10     10 0 62 sub proxy ($self, $arg = undef) {
  10         17  
  10         16  
  10         13  
46 10   50     69 $arg ||= {};
47              
48 10         20 my @proxy_ctx;
49              
50 10 100       30 if (my $ctx = $arg->{proxy_ctx}) {
51             @proxy_ctx = _ARRAY0($ctx)
52             ? (@proxy_ctx, @$ctx)
53 8 100       38 : (@proxy_ctx, $ctx->%{ sort keys %$ctx });
54             }
55              
56             my $prox = (ref $self)->_new({
57             parent => $self,
58             logger => $self->logger,
59             debug => $arg->{debug},
60             muted => $arg->{muted},
61             proxy_prefix => $arg->{proxy_prefix},
62 10         33 proxy_ctx => \@proxy_ctx,
63             });
64             }
65              
66 51     51 0 74 sub parent ($self) { $self->{parent} }
  51         78  
  51         131  
  51         209  
67 19     19 0 26 sub logger ($self) { $self->{logger} }
  19         26  
  19         26  
  19         105  
68              
69 1     1 0 7 sub ident ($self) { $self->{logger}->ident }
  1         2  
  1         2  
  1         34  
70 0     0 0 0 sub config_id ($self) { $self->{logger}->config_id }
  0         0  
  0         0  
  0         0  
71              
72 27     27 0 45 sub get_prefix ($self) { $self->{prefix} }
  27         61  
  27         41  
  27         184  
73 4     4 0 14 sub set_prefix ($self, $prefix) { $self->{prefix} = $prefix }
  4         7  
  4         6  
  4         4  
  4         12  
74 0     0 0 0 sub clear_prefix ($self) { undef $self->{prefix} }
  0         0  
  0         0  
  0         0  
75 0     0 0 0 sub unset_prefix ($self) { $self->clear_prefix }
  0         0  
  0         0  
  0         0  
76              
77 4 100   4 0 1605 sub set_debug ($self, $bool) { $self->{debug} = $bool ? 1 : 0 }
  4         7  
  4         72  
  4         5  
  4         19  
78 0     0 0 0 sub clear_debug ($self) { undef $self->{debug} }
  0         0  
  0         0  
  0         0  
79              
80 13     13 0 20 sub get_debug ($self) {
  13         33  
  13         16  
81 13 100       45 return $self->{debug} if defined $self->{debug};
82 5         13 return $self->parent->get_debug;
83             }
84              
85 0     0 0 0 sub is_debug ($self) { $self->get_debug }
  0         0  
  0         0  
  0         0  
86 0     0 0 0 sub is_info ($) { 1 }
  0         0  
  0         0  
87 0     0 0 0 sub is_fatal ($) { 1 }
  0         0  
  0         0  
88              
89 3     3 0 12 sub mute ($self) { $self->{muted} = 1 }
  3         4  
  3         5  
  3         6  
90 1     1 0 4 sub unmute ($self) { $self->{muted} = 0 }
  1         1  
  1         2  
  1         3  
91              
92 0 0   0 0 0 sub set_muted ($self, $bool) { $self->{muted} = $bool ? 1 : 0 }
  0         0  
  0         0  
  0         0  
  0         0  
93 6     6 0 2015 sub clear_muted ($self) { undef $self->{muted} }
  6         12  
  6         6  
  6         18  
94              
95 26     26   39 sub _get_local_muted ($self) { $self->{muted} }
  26         60  
  26         34  
  26         145  
96              
97 11     11 0 16 sub get_muted ($self) {
  11         14  
  11         14  
98 11 50       27 return $self->{muted} if defined $self->{muted};
99 11         19 return $self->parent->get_muted;
100             }
101              
102 27     27   43 sub _get_all_prefix ($self, $arg) {
  27         42  
  27         42  
  27         60  
103             return [
104             $self->{proxy_prefix},
105             $self->get_prefix,
106 6         23 _ARRAY0($arg->{prefix}) ? @{ $arg->{prefix} } : $arg->{prefix}
107 27 100       79 ];
108             }
109              
110 6     6 0 14 sub flog_messages ($self, @rest) {
  6         10  
  6         13  
  6         9  
111 6 100       22 my $arg = _HASH0($rest[0]) ? shift(@rest) : {};
112 6         15 local $arg->{prefix} = $self->_get_all_prefix($arg);
113              
114 6         16 $self->parent->flog_messages($arg, @rest);
115             }
116              
117 26     26 0 89 sub log ($self, @rest) {
  26         43  
  26         51  
  26         40  
118 26 100       84 my $arg = _HASH0($rest[0]) ? shift(@rest) : {};
119              
120 26 100 66     65 return if $self->_get_local_muted and ! $arg->{fatal};
121              
122 21         52 local $arg->{prefix} = $self->_get_all_prefix($arg);
123              
124 21         67 $self->parent->log($arg, @rest);
125             }
126              
127 0     0 0 0 sub log_fatal ($self, @rest) {
  0         0  
  0         0  
  0         0  
128 0 0       0 my $arg = _HASH0($rest[0]) ? shift(@rest) : {};
129 0         0 local $arg->{fatal} = 1;
130              
131 0         0 $self->log($arg, @rest);
132             }
133              
134 6     6 0 30 sub log_debug ($self, @rest) {
  6         13  
  6         12  
  6         8  
135 6         15 my $debug = $self->get_debug;
136 6 100 66     37 return if defined $debug and ! $debug;
137              
138 3 50       15 my $arg = _HASH0($rest[0]) ? shift(@rest) : {};
139 3         10 local $arg->{level} = 'debug';
140              
141 3         54 $self->log($arg, @rest);
142             }
143              
144 10     10   13 sub _compute_proxy_ctx_kvstr_aref ($self) {
  10         14  
  10         9  
145 10   66     63 return $self->{proxy_ctx_kvstr} //= do {
146 6         13 my @kvstr = $self->parent->_compute_proxy_ctx_kvstr_aref->@*;
147              
148 6 50       16 if ($self->{proxy_ctx}) {
149 6         16 my $our_kv = Log::Fmt->_pairs_to_kvstr_aref($self->{proxy_ctx});
150 6         12 push @kvstr, @$our_kv;
151             }
152              
153 6         20 \@kvstr;
154             };
155             }
156              
157 7     7 0 11 sub fmt_event ($self, $type, $data) {
  7         9  
  7         8  
  7         8  
  7         11  
158             my $kv_aref = Log::Fmt->_pairs_to_kvstr_aref([
159             event => $type,
160 7 50       38 (_ARRAY0($data) ? @$data : $data->%{ sort keys %$data })
161             ]);
162              
163 7         25 splice @$kv_aref, 1, 0, $self->_compute_proxy_ctx_kvstr_aref->@*;
164              
165 7         30 return join q{ }, @$kv_aref;
166             }
167              
168 7     7 0 4869 sub log_event ($self, $event, $data) {
  7         31  
  7         10  
  7         9  
  7         9  
169 7 50       20 return if $self->get_muted;
170              
171 7         16 my $message = $self->fmt_event($event, $data);
172              
173 7         17 $self->logger->dispatcher->log(
174             level => 'info',
175             message => $message,
176             );
177             }
178              
179 4     4 0 141 sub log_debug_event ($self, $event, $data) {
  4         4  
  4         5  
  4         5  
  4         4  
180 4 100       6 return unless $self->get_debug;
181              
182 3         4 return $self->log_event($event, $data);
183             }
184              
185 0     0 0   sub info ($self, @rest) { $self->log(@rest); }
  0            
  0            
  0            
  0            
186 0     0 0   sub fatal ($self, @rest) { $self->log_fatal(@rest); }
  0            
  0            
  0            
  0            
187 0     0 0   sub debug ($self, @rest) { $self->log_debug(@rest); }
  0            
  0            
  0            
  0            
188              
189             use overload
190 1     1   4 '&{}' => sub { my ($self) = @_; sub { $self->log(@_) } },
  1         7  
  1         4  
191 7         81 fallback => 1,
192 7     7   65 ;
  7         16  
193              
194             1;
195              
196             __END__
197              
198             =pod
199              
200             =encoding UTF-8
201              
202             =head1 NAME
203              
204             Log::Dispatchouli::Proxy - a simple wrapper around Log::Dispatch
205              
206             =head1 VERSION
207              
208             version 3.013
209              
210             =head1 DESCRIPTION
211              
212             A Log::Dispatchouli::Proxy object is the child of a L<Log::Dispatchouli> logger
213             (or another proxy) and relays log messages to its parent. It behaves almost
214             identically to a Log::Dispatchouli logger, and you should refer there for more
215             of its documentation.
216              
217             Here are the differences:
218              
219             =over 4
220              
221             =item *
222              
223             You can't create a proxy with C<< ->new >>, only by calling C<< ->proxy >> on an existing logger or proxy.
224              
225             =item *
226              
227             C<set_debug> will set a value for the proxy; if none is set, C<get_debug> will check the parent's setting; C<clear_debug> will clear any set value on this proxy
228              
229             =item *
230              
231             C<log_debug> messages will be redispatched to C<log> (to the 'debug' logging level) to prevent parent loggers from dropping them due to C<debug> setting differences
232              
233             =back
234              
235             =head1 PERL VERSION
236              
237             This library should run on perls released even a long time ago. It should
238             work on any version of perl released in the last five years.
239              
240             Although it may work on older versions of perl, no guarantee is made that the
241             minimum required version will not be increased. The version may be increased
242             for any reason, and there is no promise that patches will be accepted to
243             lower the minimum required perl.
244              
245             =head1 AUTHOR
246              
247             Ricardo SIGNES <cpan@semiotic.systems>
248              
249             =head1 COPYRIGHT AND LICENSE
250              
251             This software is copyright (c) 2025 by Ricardo SIGNES.
252              
253             This is free software; you can redistribute it and/or modify it under
254             the same terms as the Perl 5 programming language system itself.
255              
256             =cut