File Coverage

blib/lib/Log/Any/Adapter/Daemontools.pm
Criterion Covered Total %
statement 98 105 93.3
branch 16 24 66.6
condition 11 15 73.3
subroutine 29 31 93.5
pod 4 8 50.0
total 158 183 86.3


line stmt bran cond sub pod time code
1             package Log::Any::Adapter::Daemontools;
2 24     24   88021 use 5.008; # need weak reference support
  24         53  
3 24     24   1600 our @ISA; BEGIN { require Log::Any::Adapter::Base; @ISA= 'Log::Any::Adapter::Base' };
  24         2115  
4 24     24   71 use strict;
  24         32  
  24         455  
5 24     24   67 use warnings;
  24         25  
  24         537  
6 24     24   83 use Log::Any::Adapter::Util 'numeric_level';
  24         30  
  24         1252  
7 24     24   83 use Log::Any 1.03;
  24         325  
  24         101  
8 24     24   10914 use Log::Any::Adapter::Daemontools::Config;
  24         34  
  24         9799  
9              
10             our $VERSION= '0.101';
11              
12             # ABSTRACT: Logging adapter suitable for use in a Daemontools-style logging chain
13              
14              
15             our $global_config;
16             sub global_config {
17 27   66 27 1 417 $global_config ||= shift->new_config;
18             }
19              
20             sub new_config {
21 26     26 1 1543 my $class= shift;
22 26   66     94 $class= ref($class) || $class;
23 26         121 my $cfg= "${class}::Config"->new(@_);
24 26         141 return $cfg;
25             }
26              
27              
28 6     6 1 47 sub category { shift->{category} }
29 117     117 1 371 sub config { shift->{config} }
30              
31              
32             # Special carp/croak that ignore Log::Any infrastructure
33 3     3 0 5 sub carp { Log::Any::Adapter::Daemontools::Config::carp(@_) }
34 0     0 0 0 sub croak { Log::Any::Adapter::Daemontools::Config::croak(@_) }
35              
36             # Log::Any::Adapter constructor, also named 'init'
37             sub init {
38 28     28 0 9918 my $self= shift;
39            
40 28   66     209 $self->{config} ||= $self->global_config;
41            
42             # Warn about unsupported/deprecated features from 0.002
43 28 100       70 carp "filter is deprecated. Use config->log_level" if exists $self->{filter};
44 28 50       59 carp "dumper is unsupported. See Log::Any::Proxy" if exists $self->{dumper};
45            
46            
47             # This constructor gets called for each Adapter instance, so we need
48             # to track whether we applied the -init to the config yet.
49 28 100 100     123 if ($self->{'-init'} && !$self->{config}{_adapter_init_applied}) {
50 17         30 ++$self->{config}{_adapter_init_applied};
51 17         51 $self->{config}->init( $self->{'-init'} );
52             }
53              
54             # Set up our lazy caching system (re-blesses current object)
55 28         108 $self->_uncache_config;
56             }
57              
58              
59 28 50   28   151 sub _squelch_base_class { ref($_[0]) || $_[0] }
60              
61             # Create per-squelch-level subclasses of a given package
62             # This is an optimization for minimizing overhead when using disabled levels
63             sub _build_squelch_subclasses {
64 24     24   37 my $class= shift;
65 24         59 my %numeric_levels= ( map { $_ => 1 } -1, map { numeric_level($_) } Log::Any->logging_methods() );
  240         374  
  216         883  
66 24         67 my %subclass;
67 24         74 foreach my $level_num (keys %numeric_levels) {
68 240         880 my $package= $class.'::Squelch'.($level_num+1);
69 240     16   672 $subclass{$package}{_squelch_base_class}= sub { $class };
  16         54  
70 240         397 foreach my $method (Log::Any->logging_methods(), 'fatal') {
71 2400 100       5957 if ($level_num < numeric_level($method)) {
72 1152     1   5712 $subclass{$package}{$method}= sub {};
73 1152     19   2932 $subclass{$package}{"is_$method"}= sub { 0 };
  19         134  
74             }
75             }
76             }
77 24     39   171 $subclass{"${class}::Lazy"}{_squelch_base_class}= sub { $class };
  39         126  
78 24         79 foreach my $method (Log::Any->logging_and_detection_methods(), 'fatal', 'is_fatal') {
79             # Trampoline code that lazily re-caches an adaptor the first time it is used
80             $subclass{"${class}::Lazy"}{$method}= sub {
81 39     39   12328 $_[0]->_cache_config;
82 39         267 goto $_[0]->can($method)
83 480         1220 };
84             }
85            
86             # Create subclasses and install methods
87 24         74 for my $pkg (keys %subclass) {
88 24     24   124 no strict 'refs';
  24         27  
  24         3457  
89 264         185 @{$pkg.'::ISA'}= ( $class );
  264         2090  
90 264         207 for my $method (keys %{ $subclass{$pkg} }) {
  264         670  
91 3048         2044 *{$pkg.'::'.$method}= $subclass{$pkg}{$method};
  3048         8263  
92             }
93             }
94 24         9452 1;
95             }
96              
97             # The set of adapters which have been "squelch-cached"
98             # (i.e. blessed into a subclass)
99             our %_squelch_cached_adapters;
100              
101             BEGIN {
102 24     24   135 foreach my $method ( Log::Any->logging_methods() ) {
103 216     31   560 my $m= sub { my $self= shift; $self->{_writer}->($self, $method, @_); };
  31         5263  
  31         664  
104 24     24   91 no strict 'refs';
  24         23  
  24         1437  
105 216         169 *{__PACKAGE__ . "::$method"}= $m;
  216         889  
106 216     18   327 *{__PACKAGE__ . "::is_$method"}= sub { 1 };
  216         693  
  18         410  
107             }
108 24         118 __PACKAGE__->_build_squelch_subclasses();
109             }
110              
111             # Cache the ->config settings into this adapter, which also
112             # re-blesses it based on the current log level.
113             sub _cache_config {
114 39     39   49 my $self= shift;
115 39         101 $self->{_writer}= $self->config->compiled_writer;
116 39         250 my $lev= $self->config->log_level_num;
117             # Backward compatibility with version 0.002
118 39 100       109 if (exists $self->{filter}) {
119 3         6 $lev= Log::Any::Adapter::Util::NOTICE - _coerce_filter_level($self->{filter});
120             }
121 39         70 bless $self, $self->_squelch_base_class.'::Squelch'.($lev+1);
122 39         118 $self->config->_register_cached_adapter($self);
123             }
124              
125             # Re-bless adapter back to its "Lazy" config cacher class
126             sub _uncache_config {
127 44     44   88 bless $_[0], $_[0]->_squelch_base_class . '::Lazy';
128             }
129              
130             #-------------------------------------------------------------------
131             # Backward compatibility with version 0.002. Do not use in new code.
132              
133             sub write_msg {
134 0     0 0 0 my ($self, $level, $message)= @_;
135             # Don't bother optimizing and caching
136 0         0 $self->config->compiled_writer->($self, $level, $message);
137             }
138              
139             sub _default_dumper {
140 1     1   5 require Data::Dumper;
141 1         1 my $val= shift;
142 1         1 local $@;
143 1         1 my $dump= eval { Data::Dumper->new([$val])->Indent(0)->Terse(1)->Useqq(1)->Quotekeys(0)->Maxdepth(4)->Sortkeys(1)->Dump };
  1         8  
144 1 50       115 if (!defined $dump) {
145 0         0 my $x= "$@";
146 0         0 $x =~ s/\n//;
147 0 0       0 substr($x, 50)= '...' if length $x >= 50;
148 0         0 $dump= "";
149             };
150 1         4 return $dump;
151             }
152              
153             sub _coerce_filter_level {
154 3     3   2 my $val= shift;
155 3         9 my %level_map= (
156             trace => -2,
157             debug => -1,
158             info => 0,
159             notice => 1,
160             warning => 2,
161             error => 3,
162             critical => 4,
163             fatal => 4,
164             );
165             return (!defined $val || $val eq 'none')? $level_map{trace}-1
166             : Scalar::Util::looks_like_number($val)? $val
167             : exists $level_map{$val}? $level_map{$val}
168 3 0 66     22 : ($val =~ /^debug-(\d+)$/)? $level_map{debug} - $1
    50          
    100          
    100          
169             : croak "unknown log level '$val'";
170             }
171              
172             1;
173              
174             __END__