File Coverage

blib/lib/Log/Dispatch/Config.pm
Criterion Covered Total %
statement 99 103 96.1
branch 25 32 78.1
condition 7 12 58.3
subroutine 20 21 95.2
pod 0 9 0.0
total 151 177 85.3


line stmt bran cond sub pod time code
1             package Log::Dispatch::Config;
2              
3 16     16   447321 use strict;
  16         44  
  16         713  
4 16     16   83 use vars qw($VERSION);
  16         33  
  16         1200  
5             $VERSION = "1.04";
6              
7 16     16   19135 use Log::Dispatch 2.00;
  16         312280  
  16         537  
8 16     16   164 use base qw(Log::Dispatch);
  16         35  
  16         2403  
9              
10             # caller depth: can be changed from outside
11             $Log::Dispatch::Config::CallerDepth = 0;
12              
13 0     0   0 sub _croak { require Carp; Carp::croak(@_); }
  0         0  
14              
15             # accessor for symblic reference
16             sub __instance {
17 98     98   176 my $class = shift;
18 16     16   85 no strict 'refs';
  16         39  
  16         18672  
19 98         2871 my $instance = "$class\::_instance";
20 98 100       405 $$instance = shift if @_;
21 98         645 return $$instance;
22             }
23              
24             sub _configurator_for {
25 16     16   56 my($class, $stuff) = @_;
26 16 100       195 return $stuff if UNIVERSAL::isa($stuff, 'Log::Dispatch::Configurator');
27 13         17919 require Log::Dispatch::Configurator::AppConfig;
28 13         226 return Log::Dispatch::Configurator::AppConfig->new($stuff);
29             }
30              
31             sub configure {
32 16     16 0 28477 my($class, $stuff) = @_;
33 16 50       87 _croak "no config file or configurator supplied" unless $stuff;
34 16         102 my $config = $class->_configurator_for($stuff);
35 16         213 $config->myinit;
36 16         145 $class->__instance($config);
37             }
38              
39             sub configure_and_watch {
40 2     2 0 41563 my $class = shift;
41 2         12 $class->configure(@_);
42 2         7 $class->__instance->should_watch(1); # tells conf to watch config file
43             }
44              
45             # backward compatibility
46 2     2 0 770 sub Log::Dispatch::instance { __PACKAGE__->instance; }
47              
48             sub instance {
49 28     28 0 2017387 my $class = shift;
50              
51 28 50       99 my $instance = $class->__instance or _croak "configure not yet called.";
52 28 100       305 if ($instance->isa('Log::Dispatch::Config')) {
53             # reload singleton on the fly
54 12 100       61 $class->reload if $instance->needs_reload;
55             }
56             else {
57             # first time call: $_instance is L::D::Configurator::*
58 16         112 $class->__instance($class->create_instance($instance));
59             }
60 27         100 return $class->__instance;
61             }
62              
63             sub needs_reload {
64 12     12 0 29 my $self = shift;
65 12   100     144 return $self->{config}->should_watch && $self->{config}->needs_reload;
66             }
67              
68             sub reload {
69 5     5 0 1001666 my $proto = shift;
70 5   33     42 my $class = ref $proto || $proto;
71 5         19 my $instance = $class->__instance;
72 5         36 $instance->{config}->reload;
73 5         116 $class->__instance($class->create_instance($instance->{config}));
74             }
75              
76             sub create_instance {
77 21     21 0 52 my($class, $config) = @_;
78 21         204 $config->{LDC_ctime} = time; # creation time
79              
80 21         107 my $global = $config->get_attrs_global;
81 20         657 my $callback = $class->format_to_cb($global->{format}, 0);
82 20         38 my %dispatchers;
83 20         41 foreach my $disp (@{$global->{dispatchers}}) {
  20         64  
84 32         162 $dispatchers{$disp} = $class->config_dispatcher(
85             $disp, $config->get_attrs($disp),
86             );
87             }
88 20         45 my %args;
89 20 50       85 $args{callbacks} = $callback if defined $callback;
90 20         212 my $instance = $class->new(%args);
91              
92 20         1368 for my $dispname (keys %dispatchers) {
93 32         3952 my $logclass = delete $dispatchers{$dispname}->{class};
94 32         237 $instance->add(
95             $logclass->new(
96             name => $dispname,
97 32         61 %{$dispatchers{$dispname}},
98             ),
99             );
100             }
101              
102 20         5298 $instance->{config} = $config;
103 20         202 return $instance;
104             }
105              
106             sub config_dispatcher {
107 32     32 0 127 my($class, $disp, $var) = @_;
108              
109 32 50       119 my $dispclass = $var->{class} or _croak "class param missing for $disp";
110              
111 32         2379 eval qq{require $dispclass};
112 32 50 33     56278 _croak $@ if $@ && $@ !~ /locate/;
113              
114 32 100       131 if (exists $var->{format}) {
115 27         176 $var->{callbacks} = $class->format_to_cb(delete $var->{format}, 2);
116             }
117 32         162 return $var;
118             }
119              
120             sub format_to_cb {
121 47     47 0 114 my($class, $format, $stack) = @_;
122 47 100       173 return undef unless defined $format;
123              
124             # caller() called only when necessary
125 27         144 my $needs_caller = $format =~ /%[FLP]/;
126             return sub {
127 6     6   7977 my %p = @_;
128 6         20 $p{p} = delete $p{level};
129 6         17 $p{m} = delete $p{message};
130 6         109 $p{n} = "\n";
131 6         15 $p{'%'} = '%';
132              
133 6 100       23 if ($needs_caller) {
134 4         6 my $depth = 0;
135 4         66 $depth++ while caller($depth) =~ /^Log::Dispatch/;
136 4         8 $depth += $Log::Dispatch::Config::CallerDepth;
137 4         29 @p{qw(P F L)} = caller($depth);
138             }
139              
140 6         15 my $log = $format;
141 6         40 $log =~ s{
142             (%d(?:{(.*?)})?)| # $1: datetime $2: datetime fmt
143             (?:%([%pmFLPn])) # $3: others
144             }{
145 25 100 66     443 if ($1 && $2) {
    100          
    50          
146 1         7 _strftime($2);
147             }
148             elsif ($1) {
149 5         187 scalar localtime;
150             }
151             elsif ($3) {
152 19         154 $p{$3};
153             }
154             }egx;
155 6         50 return $log;
156 27         302 };
157             }
158              
159             {
160 16     16   106 use vars qw($HasTimePiece);
  16         34  
  16         1142  
161 16     16   59 BEGIN { eval { require Time::Piece; $HasTimePiece = 1 }; }
  16         25818  
  16         276903  
162              
163             sub _strftime {
164 1     1   4 my $fmt = shift;
165 1 50       5 if ($HasTimePiece) {
166 1         11 return Time::Piece->new->strftime($fmt);
167             } else {
168 0           require POSIX;
169 0           return POSIX::strftime($fmt, localtime);
170             }
171             }
172             }
173              
174             1;
175             __END__