line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Log::Any::App; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
our $DATE = '2016-01-19'; # DATE |
4
|
|
|
|
|
|
|
our $VERSION = '0.52'; # VERSION |
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
# i need this to run on centos 5.x. otherwise all my other servers are debian |
7
|
|
|
|
|
|
|
# 5.x and 6.x+ (perl 5.010). |
8
|
2
|
|
|
2
|
|
47984
|
use 5.008000; |
|
2
|
|
|
|
|
6
|
|
9
|
2
|
|
|
2
|
|
10
|
use strict; |
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
41
|
|
10
|
2
|
|
|
2
|
|
9
|
use warnings; |
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
74
|
|
11
|
|
|
|
|
|
|
|
12
|
2
|
|
|
2
|
|
8
|
use File::Path qw(make_path); |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
115
|
|
13
|
2
|
|
|
2
|
|
9
|
use File::Spec; |
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
47
|
|
14
|
2
|
|
|
2
|
|
2372
|
use Log::Any::IfLOG; |
|
2
|
|
|
|
|
26
|
|
|
2
|
|
|
|
|
11
|
|
15
|
2
|
|
|
2
|
|
1444
|
use Log::Any::Adapter; |
|
2
|
|
|
|
|
31460
|
|
|
2
|
|
|
|
|
16
|
|
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
|
18
|
2
|
|
|
2
|
|
73
|
use vars qw($dbg_ctx); |
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
17823
|
|
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
our %PATTERN_STYLES = ( |
21
|
|
|
|
|
|
|
plain => '%m', |
22
|
|
|
|
|
|
|
plain_nl => '%m%n', |
23
|
|
|
|
|
|
|
script_short => '[%r] %m%n', |
24
|
|
|
|
|
|
|
script_long => '[%d] %m%n', |
25
|
|
|
|
|
|
|
daemon => '[pid %P] [%d] %m%n', |
26
|
|
|
|
|
|
|
syslog => '[pid %p] %m', |
27
|
|
|
|
|
|
|
); |
28
|
|
|
|
|
|
|
for (keys %PATTERN_STYLES) { |
29
|
|
|
|
|
|
|
$PATTERN_STYLES{"cat_$_"} = "[cat %c]$PATTERN_STYLES{$_}"; |
30
|
|
|
|
|
|
|
$PATTERN_STYLES{"loc_$_"} = "[loc %l]$PATTERN_STYLES{$_}"; |
31
|
|
|
|
|
|
|
} |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
my $init_args; |
34
|
|
|
|
|
|
|
our $init_called; |
35
|
|
|
|
|
|
|
my $is_daemon; |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
# poor man's version of 5.10's // |
38
|
|
|
|
|
|
|
sub _ifdef { |
39
|
3482
|
|
|
3482
|
|
4831
|
my $def = pop @_; |
40
|
3482
|
|
|
|
|
5840
|
for (@_) { |
41
|
3482
|
100
|
|
|
|
9349
|
return $_ if defined($_); |
42
|
|
|
|
|
|
|
} |
43
|
3378
|
|
|
|
|
9838
|
$def; |
44
|
|
|
|
|
|
|
} |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
# j=as json (except the last default) |
47
|
|
|
|
|
|
|
sub _ifdefj { |
48
|
144
|
|
|
144
|
|
697
|
require JSON; |
49
|
|
|
|
|
|
|
|
50
|
144
|
|
|
|
|
286
|
my $def = pop @_; |
51
|
144
|
|
|
|
|
274
|
for (@_) { |
52
|
239
|
50
|
|
|
|
789
|
return JSON::decode_json($_) if defined($_); |
53
|
|
|
|
|
|
|
} |
54
|
144
|
|
|
|
|
657
|
$def; |
55
|
|
|
|
|
|
|
} |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
sub init { |
58
|
49
|
50
|
|
49
|
1
|
82357
|
return if $init_called++; |
59
|
|
|
|
|
|
|
|
60
|
49
|
|
|
|
|
91
|
$is_daemon = undef; |
61
|
|
|
|
|
|
|
|
62
|
49
|
|
|
|
|
97
|
my ($args, $caller) = @_; |
63
|
49
|
|
66
|
|
|
264
|
$caller ||= caller(); |
64
|
|
|
|
|
|
|
|
65
|
49
|
|
|
|
|
126
|
my $spec = _parse_opts($args, $caller); |
66
|
49
|
100
|
33
|
|
|
206
|
if ($spec->{log} && $spec->{init}) { |
67
|
1
|
|
|
|
|
5
|
_init_log4perl($spec); |
68
|
1
|
50
|
|
|
|
3490
|
if ($ENV{LOG_ENV}) { |
69
|
0
|
|
|
|
|
0
|
my $log_main = Log::Any->get_logger(category => 'main'); |
70
|
0
|
|
|
|
|
0
|
$log_main->tracef("Environment variables: %s", \%ENV); |
71
|
|
|
|
|
|
|
} |
72
|
|
|
|
|
|
|
} |
73
|
49
|
|
|
|
|
131
|
$spec; |
74
|
|
|
|
|
|
|
} |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
sub _gen_appender_config { |
77
|
6
|
|
|
6
|
|
11
|
my ($ospec, $apd_name, $filter) = @_; |
78
|
|
|
|
|
|
|
|
79
|
6
|
|
|
|
|
11
|
my $name = $ospec->{name}; |
80
|
6
|
|
|
|
|
7
|
my $class; |
81
|
6
|
|
|
|
|
8
|
my $params = {}; |
82
|
6
|
50
|
|
|
|
36
|
if ($name =~ /^dir/i) { |
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
83
|
0
|
|
|
|
|
0
|
$class = "Log::Dispatch::Dir"; |
84
|
0
|
|
|
|
|
0
|
$params->{dirname} = $ospec->{path}; |
85
|
0
|
|
|
|
|
0
|
$params->{filename_pattern} = $ospec->{filename_pattern}; |
86
|
0
|
0
|
|
|
|
0
|
$params->{max_size} = $ospec->{max_size} if $ospec->{max_size}; |
87
|
0
|
0
|
|
|
|
0
|
$params->{max_files} = $ospec->{histories}+1 if $ospec->{histories}; |
88
|
0
|
0
|
|
|
|
0
|
$params->{max_age} = $ospec->{max_age} if $ospec->{max_age}; |
89
|
|
|
|
|
|
|
} elsif ($name =~ /^file/i) { |
90
|
6
|
|
|
|
|
7
|
$class = "Log::Dispatch::FileWriteRotate"; |
91
|
6
|
|
|
|
|
28
|
my ($dir, $prefix) = $ospec->{path} =~ m!(.+)/(.+)!; |
92
|
6
|
|
50
|
|
|
19
|
$dir ||= "."; $prefix ||= $ospec->{path}; |
|
6
|
|
33
|
|
|
12
|
|
93
|
6
|
|
|
|
|
14
|
$params->{dir} = $dir; |
94
|
6
|
|
|
|
|
8
|
$params->{prefix} = $prefix; |
95
|
6
|
|
|
|
|
10
|
$params->{suffix} = $ospec->{suffix}; |
96
|
6
|
|
|
|
|
10
|
$params->{size} = $ospec->{max_size}; |
97
|
6
|
|
|
|
|
9
|
$params->{period} = $ospec->{period}; |
98
|
6
|
|
|
|
|
9
|
$params->{histories} = $ospec->{histories}; |
99
|
6
|
|
|
|
|
17
|
$params->{buffer_size} = $ospec->{buffer_size}; |
100
|
|
|
|
|
|
|
} elsif ($name =~ /^screen/i) { |
101
|
|
|
|
|
|
|
$class = "Log::Log4perl::Appender::" . |
102
|
0
|
0
|
|
|
|
0
|
($ospec->{color} ? "ScreenColoredLevels" : "Screen"); |
103
|
0
|
0
|
|
|
|
0
|
$params->{stderr} = $ospec->{stderr} ? 1:0; |
104
|
0
|
|
|
|
|
0
|
$params->{"color.WARN"} = "bold blue"; # blue on black is so unreadable |
105
|
|
|
|
|
|
|
} elsif ($name =~ /^syslog/i) { |
106
|
0
|
|
|
|
|
0
|
$class = "Log::Dispatch::Syslog"; |
107
|
0
|
|
|
|
|
0
|
$params->{mode} = 'append'; |
108
|
0
|
|
|
|
|
0
|
$params->{ident} = $ospec->{ident}; |
109
|
0
|
|
|
|
|
0
|
$params->{facility} = $ospec->{facility}; |
110
|
|
|
|
|
|
|
} elsif ($name =~ /^unixsock/i) { |
111
|
0
|
|
|
|
|
0
|
$class = "Log::Log4perl::Appender::Socket::UNIX"; |
112
|
0
|
|
|
|
|
0
|
$params->{Socket} = $ospec->{path}; |
113
|
|
|
|
|
|
|
} elsif ($name =~ /^array/i) { |
114
|
0
|
|
|
|
|
0
|
$class = "Log::Dispatch::ArrayWithLimits"; |
115
|
0
|
|
|
|
|
0
|
$params->{array} = $ospec->{array}; |
116
|
0
|
|
|
|
|
0
|
$params->{max_elems} = $ospec->{max_elems}; |
117
|
|
|
|
|
|
|
} else { |
118
|
0
|
|
|
|
|
0
|
die "BUG: Unknown appender type: $name"; |
119
|
|
|
|
|
|
|
} |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
join( |
122
|
|
|
|
|
|
|
"", |
123
|
|
|
|
|
|
|
"log4perl.appender.$apd_name = $class\n", |
124
|
12
|
|
|
|
|
78
|
(map { "log4perl.appender.$apd_name.$_ = $params->{$_}\n" } |
125
|
6
|
50
|
|
|
|
23
|
grep {defined $params->{$_}} keys %$params), |
|
42
|
|
|
|
|
74
|
|
126
|
|
|
|
|
|
|
"log4perl.appender.$apd_name.layout = PatternLayout\n", |
127
|
|
|
|
|
|
|
"log4perl.appender.$apd_name.layout.ConversionPattern = $ospec->{pattern}\n", |
128
|
|
|
|
|
|
|
($filter ? "log4perl.appender.$apd_name.Filter = $filter\n" : ""), |
129
|
|
|
|
|
|
|
); |
130
|
|
|
|
|
|
|
} |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
sub _lit { |
133
|
0
|
|
|
0
|
|
0
|
require Data::Dump; |
134
|
0
|
|
|
|
|
0
|
Data::Dump::dump(shift); |
135
|
|
|
|
|
|
|
} |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
sub _gen_l4p_config { |
138
|
1
|
|
|
1
|
|
2
|
my ($spec) = @_; |
139
|
|
|
|
|
|
|
|
140
|
1
|
|
|
|
|
5
|
my @otypes = qw(file dir screen syslog unixsock array); |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
# we use a custom perl code to implement filter_* specs. |
143
|
1
|
|
|
|
|
3
|
my @fccode; |
144
|
1
|
|
|
|
|
3
|
push @fccode, 'my %p = @_'; |
145
|
1
|
|
|
|
|
2
|
push @fccode, 'my $str'; |
146
|
1
|
|
|
|
|
3
|
for my $ospec (map { @{ $spec->{$_} } } @otypes) { |
|
6
|
|
|
|
|
8
|
|
|
6
|
|
|
|
|
16
|
|
147
|
2
|
50
|
|
|
|
8
|
if (defined $ospec->{filter_text}) { |
148
|
0
|
|
|
|
|
0
|
push @fccode, '$str = '._lit($ospec->{filter_text}); |
149
|
0
|
|
|
|
|
0
|
push @fccode, 'return 0 if $p{name} eq '._lit($ospec->{name}). |
150
|
|
|
|
|
|
|
' && index($_, $str) == -1'; |
151
|
|
|
|
|
|
|
} |
152
|
2
|
50
|
|
|
|
8
|
if (defined $ospec->{filter_no_text}) { |
153
|
0
|
|
|
|
|
0
|
push @fccode, '$str = '._lit($ospec->{filter_no_text}); |
154
|
0
|
|
|
|
|
0
|
push @fccode, 'return 0 if $p{name} eq '._lit($ospec->{name}). |
155
|
|
|
|
|
|
|
' && index($_, $str) > -1'; |
156
|
|
|
|
|
|
|
} |
157
|
2
|
50
|
|
|
|
7
|
if (defined $ospec->{filter_citext}) { |
158
|
0
|
|
|
|
|
0
|
push @fccode, '$str = '._lit($ospec->{filter_citext}); |
159
|
0
|
|
|
|
|
0
|
push @fccode, 'return 0 if $p{name} eq '._lit($ospec->{name}). |
160
|
|
|
|
|
|
|
' && !/\Q$str/io'; |
161
|
|
|
|
|
|
|
} |
162
|
2
|
50
|
|
|
|
7
|
if (defined $ospec->{filter_no_citext}) { |
163
|
0
|
|
|
|
|
0
|
push @fccode, '$str = '._lit($ospec->{filter_no_citext}); |
164
|
0
|
|
|
|
|
0
|
push @fccode, 'return 0 if $p{name} eq '._lit($ospec->{name}). |
165
|
|
|
|
|
|
|
' && /\Q$str/io'; |
166
|
|
|
|
|
|
|
} |
167
|
2
|
50
|
|
|
|
8
|
if (defined $ospec->{filter_re}) { |
168
|
0
|
|
|
|
|
0
|
push @fccode, '$str = '._lit($ospec->{filter_re}); |
169
|
|
|
|
|
|
|
push @fccode, 'return 0 if $p{name} eq '._lit($ospec->{name}). |
170
|
0
|
0
|
|
|
|
0
|
' && $_ !~ ' . (ref($ospec->{filter_re}) eq 'Regexp' ? '$str' : 'qr/$str/o'); |
171
|
|
|
|
|
|
|
} |
172
|
2
|
50
|
|
|
|
6
|
if (defined $ospec->{filter_no_re}) { |
173
|
0
|
|
|
|
|
0
|
push @fccode, '$str = '._lit($ospec->{filter_no_re}); |
174
|
|
|
|
|
|
|
push @fccode, 'return 0 if $p{name} eq '._lit($ospec->{name}). |
175
|
0
|
0
|
|
|
|
0
|
' && $_ =~ ' . (ref($ospec->{filter_re}) eq 'Regexp' ? '$str' : 'qr/$str/o'); |
176
|
|
|
|
|
|
|
} |
177
|
|
|
|
|
|
|
} |
178
|
1
|
|
|
|
|
3
|
push @fccode, "1"; |
179
|
1
|
|
|
|
|
4
|
my $fccode = join "; ", @fccode; |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
my $filters_str = join( |
182
|
|
|
|
|
|
|
"", |
183
|
|
|
|
|
|
|
"log4perl.filter.FilterCustom = sub { $fccode }\n", |
184
|
|
|
|
|
|
|
"\n", |
185
|
|
|
|
|
|
|
"log4perl.filter.FilterOFF0 = Log::Log4perl::Filter::LevelRange\n", |
186
|
|
|
|
|
|
|
"log4perl.filter.FilterOFF0.LevelMin = TRACE\n", |
187
|
|
|
|
|
|
|
"log4perl.filter.FilterOFF0.LevelMax = FATAL\n", |
188
|
|
|
|
|
|
|
"log4perl.filter.FilterOFF0.AcceptOnMatch = false\n", |
189
|
|
|
|
|
|
|
"\n", |
190
|
|
|
|
|
|
|
"log4perl.filter.FilterOFF = Log::Log4perl::Filter::Boolean\n", |
191
|
|
|
|
|
|
|
"log4perl.filter.FilterOFF.logic = FilterOFF0 && FilterCustom\n", |
192
|
1
|
|
|
|
|
5
|
map {join( |
|
5
|
|
|
|
|
39
|
|
193
|
|
|
|
|
|
|
"", |
194
|
|
|
|
|
|
|
"log4perl.filter.Filter${_}0 = Log::Log4perl::Filter::LevelRange\n", |
195
|
|
|
|
|
|
|
"log4perl.filter.Filter${_}0.LevelMin = $_\n", |
196
|
|
|
|
|
|
|
"log4perl.filter.Filter${_}0.LevelMax = FATAL\n", |
197
|
|
|
|
|
|
|
"log4perl.filter.Filter${_}0.AcceptOnMatch = true\n", |
198
|
|
|
|
|
|
|
"\n", |
199
|
|
|
|
|
|
|
"log4perl.filter.Filter$_ = Log::Log4perl::Filter::Boolean\n", |
200
|
|
|
|
|
|
|
"log4perl.filter.Filter$_.logic = Filter${_}0 && FilterCustom\n", |
201
|
|
|
|
|
|
|
"\n", |
202
|
|
|
|
|
|
|
)} qw(FATAL ERROR WARN INFO DEBUG), # TRACE |
203
|
|
|
|
|
|
|
); |
204
|
|
|
|
|
|
|
|
205
|
1
|
|
|
|
|
3
|
my %levels; # key = output name; value = { cat => level, ... } |
206
|
|
|
|
|
|
|
my %cats; # list of categories |
207
|
0
|
|
|
|
|
0
|
my %ospecs; # key = oname; this is just a shortcut to get ospec |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
# 1. list all levels for each category and output |
210
|
1
|
|
|
|
|
3
|
for my $ospec (map { @{ $spec->{$_} } } @otypes) { |
|
6
|
|
|
|
|
7
|
|
|
6
|
|
|
|
|
12
|
|
211
|
2
|
|
|
|
|
6
|
my $oname = $ospec->{name}; |
212
|
2
|
|
|
|
|
6
|
$ospecs{$oname} = $ospec; |
213
|
2
|
|
|
|
|
5
|
$levels{$oname} = {}; |
214
|
2
|
|
|
|
|
3
|
my %seen_cats; |
215
|
2
|
50
|
|
|
|
7
|
if ($ospec->{category_level}) { |
216
|
2
|
|
|
|
|
3
|
while (my ($cat0, $level) = each %{ $ospec->{category_level} }) { |
|
6
|
|
|
|
|
27
|
|
217
|
4
|
|
|
|
|
11
|
my @cat = _extract_category($ospec, $cat0); |
218
|
4
|
|
|
|
|
8
|
for my $cat (@cat) { |
219
|
4
|
50
|
|
|
|
12
|
next if $seen_cats{$cat}++; |
220
|
4
|
|
|
|
|
7
|
$cats{$cat}++; |
221
|
4
|
|
|
|
|
17
|
$levels{$oname}{$cat} = $level; |
222
|
|
|
|
|
|
|
} |
223
|
|
|
|
|
|
|
} |
224
|
|
|
|
|
|
|
} |
225
|
2
|
50
|
|
|
|
9
|
if ($spec->{category_level}) { |
226
|
2
|
|
|
|
|
3
|
while (my ($cat0, $level) = each %{ $spec->{category_level} }) { |
|
4
|
|
|
|
|
16
|
|
227
|
2
|
|
|
|
|
5
|
my @cat = _extract_category($ospec, $cat0); |
228
|
2
|
|
|
|
|
9
|
for my $cat (@cat) { |
229
|
4
|
50
|
|
|
|
14
|
next if $seen_cats{$cat}++; |
230
|
4
|
|
|
|
|
7
|
$cats{$cat}++; |
231
|
4
|
|
|
|
|
14
|
$levels{$oname}{$cat} = $level; |
232
|
|
|
|
|
|
|
} |
233
|
|
|
|
|
|
|
} |
234
|
|
|
|
|
|
|
} |
235
|
2
|
|
|
|
|
5
|
my @cat = _extract_category($ospec); |
236
|
2
|
|
|
|
|
5
|
for my $cat (@cat) { |
237
|
2
|
50
|
|
|
|
6
|
next if $seen_cats{$cat}++; |
238
|
2
|
|
|
|
|
3
|
$cats{$cat}++; |
239
|
2
|
|
|
|
|
9
|
$levels{$oname}{$cat} = $ospec->{level}; |
240
|
|
|
|
|
|
|
} |
241
|
|
|
|
|
|
|
} |
242
|
|
|
|
|
|
|
#print Dumper \%levels; exit; |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
my $find_olevel = sub { |
245
|
40
|
|
|
40
|
|
58
|
my ($oname, $cat) = @_; |
246
|
40
|
|
|
|
|
63
|
my $olevel = $levels{$oname}{''}; |
247
|
40
|
|
|
|
|
80
|
my @c = split /\./, $cat; |
248
|
40
|
|
|
|
|
106
|
for (my $i=0; $i<@c; $i++) { |
249
|
64
|
|
|
|
|
114
|
my $c = join(".", @c[0..$i]); |
250
|
64
|
100
|
|
|
|
190
|
if ($levels{$oname}{$c}) { |
251
|
42
|
|
|
|
|
128
|
$olevel = $levels{$oname}{$c}; |
252
|
|
|
|
|
|
|
} |
253
|
|
|
|
|
|
|
} |
254
|
40
|
|
|
|
|
104
|
$olevel; |
255
|
1
|
|
|
|
|
7
|
}; |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
# 2. determine level for each category (which is the minimum level of all |
258
|
|
|
|
|
|
|
# appenders for that category) |
259
|
1
|
|
|
|
|
3
|
my %cat_configs; # key = cat, value = [catlevel, apdname, ...] |
260
|
1
|
|
|
|
|
2
|
my $add_str = ''; |
261
|
1
|
|
|
|
|
2
|
my $apd_str = ''; |
262
|
1
|
|
|
|
|
8
|
for my $cat0 (sort {$a cmp $b} keys %cats) { |
|
13
|
|
|
|
|
20
|
|
263
|
7
|
100
|
|
|
|
33
|
$add_str .= "log4perl.additivity.$cat0 = 0\n" unless $cat0 eq ''; |
264
|
7
|
|
|
|
|
12
|
my @cats = ($cat0); |
265
|
|
|
|
|
|
|
# since we don't use additivity, we need to add supercategories ourselves |
266
|
7
|
|
|
|
|
30
|
while ($cat0 =~ s/\.[^.]+$//) { push @cats, $cat0 } |
|
6
|
|
|
|
|
25
|
|
267
|
7
|
|
|
|
|
9
|
for my $cat (@cats) { |
268
|
13
|
|
|
|
|
15
|
my $cat_level; |
269
|
13
|
|
|
|
|
23
|
for my $oname (keys %levels) { |
270
|
26
|
|
|
|
|
48
|
my $olevel = $find_olevel->($oname, $cat); |
271
|
26
|
50
|
|
|
|
56
|
next unless $olevel; |
272
|
26
|
|
|
|
|
45
|
$cat_level = _ifdef($cat_level, $olevel); |
273
|
26
|
|
|
|
|
51
|
$cat_level = _min_level($cat_level, $olevel); |
274
|
|
|
|
|
|
|
} |
275
|
13
|
|
|
|
|
51
|
$cat_configs{$cat} = [uc($cat_level)]; |
276
|
|
|
|
|
|
|
#next if $cat_level eq 'off'; |
277
|
|
|
|
|
|
|
} |
278
|
|
|
|
|
|
|
} |
279
|
|
|
|
|
|
|
#print Dumper \%cat_configs; exit; |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
# 3. add appenders for each category |
282
|
1
|
|
|
|
|
4
|
my %generated_appenders; # key = apdname, just a memory hash |
283
|
1
|
|
|
|
|
5
|
for my $cat (keys %cat_configs) { |
284
|
7
|
|
|
|
|
12
|
my $cat_level = $cat_configs{$cat}[0]; |
285
|
7
|
|
|
|
|
15
|
for my $oname (keys %levels) { |
286
|
14
|
|
|
|
|
21
|
my $ospec = $ospecs{$oname}; |
287
|
14
|
|
|
|
|
23
|
my $olevel = $find_olevel->($oname, $cat); |
288
|
|
|
|
|
|
|
#print "D:oname=$oname, cat=$cat, olevel=$olevel, cat_level=$cat_level\n"; |
289
|
14
|
|
|
|
|
22
|
my $apd_name; |
290
|
|
|
|
|
|
|
my $filter; |
291
|
14
|
100
|
66
|
|
|
46
|
if ($olevel ne $cat_level && |
292
|
|
|
|
|
|
|
_min_level($olevel, $cat_level) eq $cat_level) { |
293
|
|
|
|
|
|
|
# we need to filter the appender, since the category level is |
294
|
|
|
|
|
|
|
# lower than the output level |
295
|
5
|
|
|
|
|
9
|
$apd_name = $oname . "_" . uc($olevel); |
296
|
5
|
|
|
|
|
9
|
$filter = "Filter".uc($olevel); |
297
|
|
|
|
|
|
|
} else { |
298
|
9
|
|
|
|
|
14
|
$apd_name = $oname; |
299
|
9
|
|
|
|
|
11
|
$filter = "FilterCustom"; |
300
|
|
|
|
|
|
|
} |
301
|
14
|
100
|
|
|
|
43
|
unless ($generated_appenders{$apd_name}++) { |
302
|
6
|
|
|
|
|
13
|
$apd_str .= _gen_appender_config($ospec, $apd_name, $filter). |
303
|
|
|
|
|
|
|
"\n"; |
304
|
|
|
|
|
|
|
} |
305
|
14
|
|
|
|
|
20
|
push @{ $cat_configs{$cat} }, $apd_name; |
|
14
|
|
|
|
|
43
|
|
306
|
|
|
|
|
|
|
} |
307
|
|
|
|
|
|
|
} |
308
|
|
|
|
|
|
|
#print Dumper \%cat_configs; exit; |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
# 4. write out log4perl category line |
311
|
1
|
|
|
|
|
4
|
my $cat_str = ''; |
312
|
1
|
|
|
|
|
5
|
for my $cat (sort {$a cmp $b} keys %cat_configs) { |
|
13
|
|
|
|
|
20
|
|
313
|
7
|
100
|
|
|
|
21
|
my $l = $cat eq '' ? '' : ".$cat"; |
314
|
7
|
|
|
|
|
19
|
$cat_str .= "log4perl.logger$l = ".join(", ", @{ $cat_configs{$cat} })."\n"; |
|
7
|
|
|
|
|
31
|
|
315
|
|
|
|
|
|
|
} |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
join( |
318
|
1
|
|
|
|
|
26
|
"", |
319
|
|
|
|
|
|
|
"# filters\n", $filters_str, |
320
|
|
|
|
|
|
|
"# categories\n", $cat_str, $add_str, "\n", |
321
|
|
|
|
|
|
|
"# appenders\n", $apd_str, |
322
|
|
|
|
|
|
|
); |
323
|
|
|
|
|
|
|
} |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
sub _init_log4perl { |
326
|
1
|
|
|
1
|
|
1289
|
require Log::Log4perl; |
327
|
|
|
|
|
|
|
|
328
|
1
|
|
|
|
|
55839
|
my ($spec) = @_; |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
# create intermediate directories for dir |
331
|
1
|
|
|
|
|
2
|
for (@{ $spec->{dir} }) { |
|
1
|
|
|
|
|
6
|
|
332
|
0
|
|
|
|
|
0
|
my $dir = _dirname($_->{path}); |
333
|
0
|
0
|
0
|
|
|
0
|
make_path($dir) if length($dir) && !(-d $dir); |
334
|
|
|
|
|
|
|
} |
335
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
# create intermediate directories for file |
337
|
1
|
|
|
|
|
4
|
for (@{ $spec->{file} }) { |
|
1
|
|
|
|
|
4
|
|
338
|
2
|
|
|
|
|
10
|
my $dir = _dirname($_->{path}); |
339
|
2
|
50
|
33
|
|
|
53
|
make_path($dir) if length($dir) && !(-d $dir); |
340
|
|
|
|
|
|
|
} |
341
|
|
|
|
|
|
|
|
342
|
1
|
|
|
|
|
6
|
my $config_str = _gen_l4p_config($spec); |
343
|
1
|
50
|
|
|
|
6
|
if ($spec->{dump}) { |
344
|
0
|
|
|
|
|
0
|
require Data::Dump; |
345
|
0
|
|
|
|
|
0
|
print "Log::Any::App configuration:\n", |
346
|
|
|
|
|
|
|
Data::Dump::dump($spec); |
347
|
0
|
|
|
|
|
0
|
print "Log4perl configuration: <
|
348
|
|
|
|
|
|
|
} |
349
|
|
|
|
|
|
|
|
350
|
1
|
|
|
|
|
6
|
Log::Log4perl->init(\$config_str); |
351
|
1
|
|
|
|
|
123904
|
Log::Any::Adapter->set('Log4perl'); |
352
|
|
|
|
|
|
|
} |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
sub _basename { |
355
|
49
|
|
|
49
|
|
95
|
my $path = shift; |
356
|
49
|
|
|
|
|
690
|
my ($vol, $dir, $file) = File::Spec->splitpath($path); |
357
|
49
|
|
|
|
|
169
|
$file; |
358
|
|
|
|
|
|
|
} |
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
sub _dirname { |
361
|
2
|
|
|
2
|
|
4
|
my $path = shift; |
362
|
2
|
|
|
|
|
35
|
my ($vol, $dir, $file) = File::Spec->splitpath($path); |
363
|
2
|
|
|
|
|
7
|
$dir; |
364
|
|
|
|
|
|
|
} |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
# we separate args and opts, because we need to export logger early |
367
|
|
|
|
|
|
|
# (BEGIN), but configure logger in INIT (to be able to detect |
368
|
|
|
|
|
|
|
# existence of other modules). |
369
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
sub _parse_args { |
371
|
2
|
|
|
2
|
|
5
|
my ($args, $caller) = @_; |
372
|
2
|
|
|
|
|
8
|
$args = _ifdef($args, []); # if we don't import(), we never get args |
373
|
|
|
|
|
|
|
|
374
|
2
|
|
|
|
|
5
|
my $i = 0; |
375
|
2
|
|
|
|
|
9
|
while ($i < @$args) { |
376
|
10
|
|
|
|
|
15
|
my $arg = $args->[$i]; |
377
|
10
|
100
|
|
|
|
45
|
do { $i+=2; next } if $arg =~ /^-(\w+)$/; |
|
9
|
|
|
|
|
12
|
|
|
9
|
|
|
|
|
32
|
|
378
|
1
|
50
|
|
|
|
7
|
if ($arg eq '$log') { |
379
|
1
|
|
|
|
|
3
|
_export_logger($caller); |
380
|
|
|
|
|
|
|
} else { |
381
|
0
|
|
|
|
|
0
|
die "Unknown arg '$arg', valid arg is '\$log' or -OPTS"; |
382
|
|
|
|
|
|
|
} |
383
|
1
|
|
|
|
|
6
|
$i++; |
384
|
|
|
|
|
|
|
} |
385
|
|
|
|
|
|
|
} |
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
sub _parse_opts { |
388
|
49
|
|
|
49
|
|
3699
|
require File::HomeDir; |
389
|
|
|
|
|
|
|
|
390
|
49
|
|
|
|
|
15234
|
my ($args, $caller) = @_; |
391
|
49
|
|
|
|
|
134
|
$args = _ifdef($args, []); # if we don't import(), we never get args |
392
|
49
|
|
|
|
|
306
|
_debug("parse_opts: args = [".join(", ", @$args)."]"); |
393
|
|
|
|
|
|
|
|
394
|
49
|
|
|
|
|
95
|
my $i = 0; |
395
|
49
|
|
|
|
|
69
|
my %opts; |
396
|
49
|
|
|
|
|
165
|
while ($i < @$args) { |
397
|
73
|
|
|
|
|
124
|
my $arg = $args->[$i]; |
398
|
73
|
100
|
|
|
|
380
|
do { $i++; next } unless $arg =~ /^-(\w+)$/; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
3
|
|
399
|
72
|
|
|
|
|
151
|
my $opt = $1; |
400
|
72
|
50
|
|
|
|
190
|
die "Missing argument for option $opt" unless $i++ < @$args-1; |
401
|
72
|
|
|
|
|
125
|
$arg = $args->[$i]; |
402
|
72
|
|
|
|
|
171
|
$opts{$opt} = $arg; |
403
|
72
|
|
|
|
|
192
|
$i++; |
404
|
|
|
|
|
|
|
} |
405
|
|
|
|
|
|
|
|
406
|
49
|
|
|
|
|
85
|
my $spec = {}; |
407
|
|
|
|
|
|
|
|
408
|
49
|
|
|
|
|
195
|
$spec->{log} = _ifdef($ENV{LOG}, 1); |
409
|
49
|
50
|
|
|
|
166
|
if (defined $opts{log}) { |
410
|
0
|
|
|
|
|
0
|
$spec->{log} = $opts{log}; |
411
|
0
|
|
|
|
|
0
|
delete $opts{log}; |
412
|
|
|
|
|
|
|
} |
413
|
|
|
|
|
|
|
# exit as early as possible if we are not doing any logging |
414
|
49
|
50
|
|
|
|
128
|
goto END_PARSE_OPTS unless $spec->{log}; |
415
|
|
|
|
|
|
|
|
416
|
49
|
|
|
|
|
115
|
$spec->{name} = _basename($0); |
417
|
49
|
100
|
|
|
|
133
|
if (defined $opts{name}) { |
418
|
6
|
|
|
|
|
14
|
$spec->{name} = $opts{name}; |
419
|
6
|
|
|
|
|
12
|
delete $opts{name}; |
420
|
|
|
|
|
|
|
} |
421
|
|
|
|
|
|
|
|
422
|
49
|
|
|
|
|
196
|
$spec->{level_flag_paths} = [File::HomeDir->my_home, "/etc"]; |
423
|
49
|
100
|
|
|
|
1956
|
if (defined $opts{level_flag_paths}) { |
424
|
4
|
|
|
|
|
8
|
$spec->{level_flag_paths} = $opts{level_flag_paths}; |
425
|
4
|
|
|
|
|
10
|
delete $opts{level_flag_paths}; |
426
|
|
|
|
|
|
|
} |
427
|
|
|
|
|
|
|
|
428
|
49
|
|
|
|
|
186
|
$spec->{level} = _set_level("", "", $spec); |
429
|
49
|
50
|
66
|
|
|
310
|
if (!$spec->{level} && defined($opts{level})) { |
|
|
100
|
|
|
|
|
|
430
|
0
|
|
|
|
|
0
|
$spec->{level} = _check_level($opts{level}, "-level"); |
431
|
0
|
|
|
|
|
0
|
_debug("Set general level to $spec->{level} (from -level)"); |
432
|
|
|
|
|
|
|
} elsif (!$spec->{level}) { |
433
|
31
|
|
|
|
|
59
|
$spec->{level} = "warn"; |
434
|
31
|
|
|
|
|
101
|
_debug("Set general level to $spec->{level} (default)"); |
435
|
|
|
|
|
|
|
} |
436
|
49
|
|
|
|
|
85
|
delete $opts{level}; |
437
|
|
|
|
|
|
|
|
438
|
49
|
|
|
|
|
181
|
$spec->{category_alias} = _ifdefj($ENV{LOG_CATEGORY_ALIAS}, {}); |
439
|
49
|
100
|
|
|
|
162
|
if (defined $opts{category_alias}) { |
440
|
|
|
|
|
|
|
die "category_alias must be a hashref" |
441
|
1
|
50
|
|
|
|
6
|
unless ref($opts{category_alias}) eq 'HASH'; |
442
|
1
|
|
|
|
|
3
|
$spec->{category_alias} = $opts{category_alias}; |
443
|
1
|
|
|
|
|
2
|
delete $opts{category_alias}; |
444
|
|
|
|
|
|
|
} |
445
|
|
|
|
|
|
|
|
446
|
49
|
100
|
|
|
|
109
|
if (defined $opts{category_level}) { |
447
|
|
|
|
|
|
|
die "category_level must be a hashref" |
448
|
1
|
50
|
|
|
|
5
|
unless ref($opts{category_level}) eq 'HASH'; |
449
|
1
|
|
|
|
|
2
|
$spec->{category_level} = {}; |
450
|
1
|
|
|
|
|
2
|
for (keys %{ $opts{category_level} }) { |
|
1
|
|
|
|
|
5
|
|
451
|
|
|
|
|
|
|
$spec->{category_level}{$_} = |
452
|
1
|
|
|
|
|
7
|
_check_level($opts{category_level}{$_}, "-category_level{$_}"); |
453
|
|
|
|
|
|
|
} |
454
|
1
|
|
|
|
|
2
|
delete $opts{category_level}; |
455
|
|
|
|
|
|
|
} |
456
|
|
|
|
|
|
|
|
457
|
49
|
|
|
|
|
93
|
$spec->{init} = 1; |
458
|
49
|
100
|
|
|
|
116
|
if (defined $opts{init}) { |
459
|
48
|
|
|
|
|
99
|
$spec->{init} = $opts{init}; |
460
|
48
|
|
|
|
|
150
|
delete $opts{init}; |
461
|
|
|
|
|
|
|
} |
462
|
|
|
|
|
|
|
|
463
|
49
|
|
|
|
|
89
|
$spec->{daemon} = 0; |
464
|
49
|
100
|
|
|
|
105
|
if (defined $opts{daemon}) { |
465
|
2
|
|
|
|
|
5
|
$spec->{daemon} = $opts{daemon}; |
466
|
2
|
|
|
|
|
7
|
_debug("setting is_daemon=$opts{daemon} (from daemon option)"); |
467
|
2
|
|
|
|
|
3
|
$is_daemon = $opts{daemon}; |
468
|
2
|
|
|
|
|
5
|
delete $opts{daemon}; |
469
|
|
|
|
|
|
|
} |
470
|
|
|
|
|
|
|
|
471
|
49
|
|
|
|
|
167
|
$spec->{dump} = $ENV{LOGANYAPP_DEBUG}; |
472
|
49
|
50
|
|
|
|
109
|
if (defined $opts{dump}) { |
473
|
0
|
|
|
|
|
0
|
$spec->{dump} = 1; |
474
|
0
|
|
|
|
|
0
|
delete $opts{dump}; |
475
|
|
|
|
|
|
|
} |
476
|
|
|
|
|
|
|
|
477
|
49
|
|
|
|
|
96
|
$spec->{filter_text} = $ENV{LOG_FILTER_TEXT}; |
478
|
49
|
50
|
|
|
|
115
|
if (defined $opts{filter_text}) { |
479
|
0
|
|
|
|
|
0
|
$spec->{filter_text} = $opts{filter_text}; |
480
|
0
|
|
|
|
|
0
|
delete $opts{filter_text}; |
481
|
|
|
|
|
|
|
} |
482
|
49
|
|
|
|
|
93
|
$spec->{filter_no_text} = $ENV{LOG_FILTER_NO_TEXT}; |
483
|
49
|
50
|
|
|
|
120
|
if (defined $opts{filter_no_text}) { |
484
|
0
|
|
|
|
|
0
|
$spec->{filter_no_text} = $opts{filter_no_text}; |
485
|
0
|
|
|
|
|
0
|
delete $opts{filter_no_text}; |
486
|
|
|
|
|
|
|
} |
487
|
49
|
|
|
|
|
93
|
$spec->{filter_citext} = $ENV{LOG_FILTER_CITEXT}; |
488
|
49
|
50
|
|
|
|
105
|
if (defined $opts{filter_citext}) { |
489
|
0
|
|
|
|
|
0
|
$spec->{filter_citext} = $opts{filter_citext}; |
490
|
0
|
|
|
|
|
0
|
delete $opts{filter_citext}; |
491
|
|
|
|
|
|
|
} |
492
|
49
|
|
|
|
|
92
|
$spec->{filter_no_citext} = $ENV{LOG_FILTER_NO_CITEXT}; |
493
|
49
|
50
|
|
|
|
101
|
if (defined $opts{filter_no_citext}) { |
494
|
0
|
|
|
|
|
0
|
$spec->{filter_no_citext} = $opts{filter_no_citext}; |
495
|
0
|
|
|
|
|
0
|
delete $opts{filter_no_citext}; |
496
|
|
|
|
|
|
|
} |
497
|
49
|
|
|
|
|
83
|
$spec->{filter_re} = $ENV{LOG_FILTER_RE}; |
498
|
49
|
50
|
|
|
|
130
|
if (defined $opts{filter_re}) { |
499
|
0
|
|
|
|
|
0
|
$spec->{filter_re} = $opts{filter_re}; |
500
|
0
|
|
|
|
|
0
|
delete $opts{filter_re}; |
501
|
|
|
|
|
|
|
} |
502
|
49
|
|
|
|
|
103
|
$spec->{filter_no_re} = $ENV{LOG_FILTER_NO_RE}; |
503
|
49
|
50
|
|
|
|
101
|
if (defined $opts{filter_no_re}) { |
504
|
0
|
|
|
|
|
0
|
$spec->{filter_no_re} = $opts{filter_no_re}; |
505
|
0
|
|
|
|
|
0
|
delete $opts{filter_no_re}; |
506
|
|
|
|
|
|
|
} |
507
|
|
|
|
|
|
|
|
508
|
49
|
|
|
|
|
108
|
$spec->{file} = []; |
509
|
49
|
100
|
|
|
|
227
|
_parse_opt_file($spec, _ifdef($opts{file}, ($0 ne '-e' ? 1:0))); |
510
|
49
|
|
|
|
|
333
|
delete $opts{file}; |
511
|
|
|
|
|
|
|
|
512
|
49
|
|
|
|
|
182
|
$spec->{dir} = []; |
513
|
49
|
|
|
|
|
160
|
_parse_opt_dir($spec, _ifdef($opts{dir}, 0)); |
514
|
49
|
|
|
|
|
94
|
delete $opts{dir}; |
515
|
|
|
|
|
|
|
|
516
|
49
|
|
|
|
|
106
|
$spec->{screen} = []; |
517
|
49
|
|
|
|
|
149
|
_parse_opt_screen($spec, _ifdef($opts{screen}, !_is_daemon())); |
518
|
49
|
|
|
|
|
104
|
delete $opts{screen}; |
519
|
|
|
|
|
|
|
|
520
|
49
|
|
|
|
|
103
|
$spec->{syslog} = []; |
521
|
49
|
|
|
|
|
158
|
_parse_opt_syslog($spec, _ifdef($opts{syslog}, _is_daemon())); |
522
|
49
|
|
|
|
|
103
|
delete $opts{syslog}; |
523
|
|
|
|
|
|
|
|
524
|
49
|
|
|
|
|
93
|
$spec->{unixsock} = []; |
525
|
49
|
|
|
|
|
145
|
_parse_opt_unixsock($spec, _ifdef($opts{unixsock}, 0)); |
526
|
49
|
|
|
|
|
299
|
delete $opts{unixsock}; |
527
|
|
|
|
|
|
|
|
528
|
49
|
|
|
|
|
104
|
$spec->{array} = []; |
529
|
49
|
|
|
|
|
152
|
_parse_opt_array($spec, _ifdef($opts{array}, 0)); |
530
|
49
|
|
|
|
|
98
|
delete $opts{array}; |
531
|
|
|
|
|
|
|
|
532
|
49
|
50
|
|
|
|
122
|
if (keys %opts) { |
533
|
0
|
|
|
|
|
0
|
die "Unknown option(s) ".join(", ", keys %opts)." Known opts are: ". |
534
|
|
|
|
|
|
|
"log, name, level, category_level, category_alias, dump, init, ". |
535
|
|
|
|
|
|
|
"filter_{,no_}{text,citext,re}, file, dir, screen, syslog, ". |
536
|
|
|
|
|
|
|
"unixsock, array"; |
537
|
|
|
|
|
|
|
} |
538
|
|
|
|
|
|
|
|
539
|
|
|
|
|
|
|
END_PARSE_OPTS: |
540
|
|
|
|
|
|
|
#use Data::Dump; dd $spec; |
541
|
49
|
|
|
|
|
134
|
$spec; |
542
|
|
|
|
|
|
|
} |
543
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
sub _is_daemon { |
545
|
98
|
100
|
|
98
|
|
236
|
if (defined $is_daemon) { return $is_daemon } |
|
51
|
|
|
|
|
120
|
|
546
|
47
|
100
|
|
|
|
98
|
if (defined $main::IS_DAEMON) { |
547
|
1
|
|
|
|
|
2
|
$is_daemon = $main::IS_DAEMON; |
548
|
1
|
|
|
|
|
5
|
_debug("Setting is_daemon=$main::IS_DAEMON (from \$main::IS_DAEMON)"); |
549
|
1
|
|
|
|
|
3
|
return $main::IS_DAEMON; |
550
|
|
|
|
|
|
|
} |
551
|
|
|
|
|
|
|
|
552
|
46
|
|
|
|
|
116
|
for ( |
553
|
|
|
|
|
|
|
"App/Daemon.pm", |
554
|
|
|
|
|
|
|
"Daemon/Easy.pm", |
555
|
|
|
|
|
|
|
"Daemon/Daemonize.pm", |
556
|
|
|
|
|
|
|
"Daemon/Generic.pm", |
557
|
|
|
|
|
|
|
"Daemonise.pm", |
558
|
|
|
|
|
|
|
"Daemon/Simple.pm", |
559
|
|
|
|
|
|
|
"HTTP/Daemon.pm", |
560
|
|
|
|
|
|
|
"IO/Socket/INET/Daemon.pm", |
561
|
|
|
|
|
|
|
#"Mojo/Server/Daemon.pm", # simply loading Mojo::UserAgent will load this too |
562
|
|
|
|
|
|
|
"MooseX/Daemonize.pm", |
563
|
|
|
|
|
|
|
"Net/Daemon.pm", |
564
|
|
|
|
|
|
|
"Net/Server.pm", |
565
|
|
|
|
|
|
|
"Proc/Daemon.pm", |
566
|
|
|
|
|
|
|
"Proc/PID/File.pm", |
567
|
|
|
|
|
|
|
"Win32/Daemon/Simple.pm") { |
568
|
636
|
100
|
|
|
|
1640
|
if ($INC{$_}) { |
569
|
2
|
|
|
|
|
9
|
_debug("setting is_daemon=1 (from existence of module $_)"); |
570
|
2
|
|
|
|
|
3
|
$is_daemon = 1; |
571
|
2
|
|
|
|
|
6
|
return 1; |
572
|
|
|
|
|
|
|
} |
573
|
|
|
|
|
|
|
} |
574
|
44
|
|
|
|
|
94
|
_debug("setting is_daemon=0 (no indication that we are a daemon)"); |
575
|
44
|
|
|
|
|
62
|
$is_daemon = 0; |
576
|
44
|
|
|
|
|
97
|
0; |
577
|
|
|
|
|
|
|
} |
578
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
sub _parse_opt_OUTPUT { |
580
|
296
|
|
|
296
|
|
1211
|
my (%args) = @_; |
581
|
296
|
|
|
|
|
462
|
my $kind = $args{kind}; |
582
|
296
|
|
|
|
|
392
|
my $default_sub = $args{default_sub}; |
583
|
296
|
|
|
|
|
389
|
my $postprocess = $args{postprocess}; |
584
|
296
|
|
|
|
|
423
|
my $spec = $args{spec}; |
585
|
296
|
|
|
|
|
385
|
my $arg = $args{arg}; |
586
|
|
|
|
|
|
|
|
587
|
296
|
100
|
|
|
|
899
|
return unless $arg; |
588
|
|
|
|
|
|
|
|
589
|
96
|
100
|
100
|
|
|
322
|
if (!ref($arg) || ref($arg) eq 'HASH') { |
|
|
50
|
|
|
|
|
|
590
|
95
|
|
|
|
|
133
|
my $name = uc($kind).(@{ $spec->{$kind} }+0); |
|
95
|
|
|
|
|
284
|
|
591
|
95
|
|
|
|
|
167
|
local $dbg_ctx = $name; |
592
|
95
|
|
|
|
|
102
|
push @{ $spec->{$kind} }, $default_sub->($spec); |
|
95
|
|
|
|
|
257
|
|
593
|
95
|
|
|
|
|
507
|
$spec->{$kind}[-1]{name} = $name; |
594
|
95
|
100
|
|
|
|
279
|
if (!ref($arg)) { |
595
|
|
|
|
|
|
|
# leave every output parameter as is |
596
|
|
|
|
|
|
|
} else { |
597
|
6
|
|
|
|
|
20
|
for my $k (keys %$arg) { |
598
|
12
|
|
|
|
|
26
|
for ($spec->{$kind}[-1]) { |
599
|
12
|
50
|
|
|
|
29
|
exists($_->{$k}) or die "Invalid $kind argument: $k, please". |
600
|
|
|
|
|
|
|
" only specify one of: " . join(", ", sort keys %$_); |
601
|
|
|
|
|
|
|
$_->{$k} = $k eq 'level' ? |
602
|
12
|
100
|
|
|
|
38
|
_check_level($arg->{$k}, "-$kind") : $arg->{$k}; |
603
|
12
|
100
|
|
|
|
73
|
_debug("Set level of $kind to $_->{$k} (spec)") |
604
|
|
|
|
|
|
|
if $k eq 'level'; |
605
|
|
|
|
|
|
|
} |
606
|
|
|
|
|
|
|
} |
607
|
|
|
|
|
|
|
} |
608
|
95
|
|
|
|
|
181
|
$spec->{$kind}[-1]{main_spec} = $spec; |
609
|
95
|
|
|
|
|
228
|
_set_pattern($spec->{$kind}[-1], $kind); |
610
|
95
|
100
|
|
|
|
400
|
$postprocess->(spec => $spec, ospec => $spec->{$kind}[-1]) |
611
|
|
|
|
|
|
|
if $postprocess; |
612
|
|
|
|
|
|
|
} elsif (ref($arg) eq 'ARRAY') { |
613
|
1
|
|
|
|
|
3
|
for (@$arg) { |
614
|
2
|
|
|
|
|
11
|
_parse_opt_OUTPUT(%args, arg => $_); |
615
|
|
|
|
|
|
|
} |
616
|
|
|
|
|
|
|
} else { |
617
|
0
|
|
|
|
|
0
|
die "Invalid argument for -$kind, ". |
618
|
|
|
|
|
|
|
"must be a boolean or hashref or arrayref"; |
619
|
|
|
|
|
|
|
} |
620
|
|
|
|
|
|
|
} |
621
|
|
|
|
|
|
|
|
622
|
|
|
|
|
|
|
sub _set_pattern_style { |
623
|
95
|
|
|
95
|
|
159
|
my ($x) = @_; |
624
|
|
|
|
|
|
|
($ENV{LOG_SHOW_LOCATION} ? 'loc_': |
625
|
95
|
50
|
|
|
|
568
|
$ENV{LOG_SHOW_CATEGORY} ? 'cat_':'') . $x; |
|
|
50
|
|
|
|
|
|
626
|
|
|
|
|
|
|
} |
627
|
|
|
|
|
|
|
|
628
|
|
|
|
|
|
|
sub _default_file { |
629
|
48
|
|
|
48
|
|
288
|
require File::HomeDir; |
630
|
|
|
|
|
|
|
|
631
|
48
|
|
|
|
|
75
|
my ($spec) = @_; |
632
|
48
|
|
|
|
|
98
|
my $level = _set_level("file", "file", $spec); |
633
|
48
|
100
|
|
|
|
122
|
if (!$level) { |
634
|
39
|
|
|
|
|
72
|
$level = $spec->{level}; |
635
|
39
|
|
|
|
|
106
|
_debug("Set level of file to $level (general level)"); |
636
|
|
|
|
|
|
|
} |
637
|
|
|
|
|
|
|
return { |
638
|
|
|
|
|
|
|
level => $level, |
639
|
|
|
|
|
|
|
category_level => _ifdefj($ENV{FILE_LOG_CATEGORY_LEVEL}, |
640
|
|
|
|
|
|
|
$ENV{LOG_CATEGORY_LEVEL}, |
641
|
|
|
|
|
|
|
$spec->{category_level}), |
642
|
|
|
|
|
|
|
path => $> ? File::Spec->catfile(File::HomeDir->my_home, "$spec->{name}.log") : |
643
|
|
|
|
|
|
|
"/var/log/$spec->{name}.log", # XXX and on Windows? |
644
|
|
|
|
|
|
|
max_size => undef, |
645
|
|
|
|
|
|
|
histories => undef, |
646
|
|
|
|
|
|
|
period => undef, |
647
|
|
|
|
|
|
|
buffer_size => undef, |
648
|
|
|
|
|
|
|
category => '', |
649
|
|
|
|
|
|
|
pattern_style => _set_pattern_style('daemon'), |
650
|
|
|
|
|
|
|
pattern => undef, |
651
|
|
|
|
|
|
|
|
652
|
|
|
|
|
|
|
filter_text => _ifdef($ENV{FILE_LOG_FILTER_TEXT}, $spec->{filter_text}), |
653
|
|
|
|
|
|
|
filter_no_text => _ifdef($ENV{FILE_LOG_FILTER_NO_TEXT}, $spec->{filter_no_text}), |
654
|
|
|
|
|
|
|
filter_citext => _ifdef($ENV{FILE_LOG_FILTER_CITEXT}, $spec->{filter_citext}), |
655
|
|
|
|
|
|
|
filter_no_citext => _ifdef($ENV{FILE_LOG_FILTER_NO_CITEXT}, $spec->{filter_no_citext}), |
656
|
|
|
|
|
|
|
filter_re => _ifdef($ENV{FILE_LOG_FILTER_RE}, $spec->{filter_re}), |
657
|
48
|
50
|
|
|
|
243
|
filter_no_re => _ifdef($ENV{FILE_LOG_FILTER_NO_RE}, $spec->{filter_no_re}), |
658
|
|
|
|
|
|
|
}; |
659
|
|
|
|
|
|
|
} |
660
|
|
|
|
|
|
|
|
661
|
|
|
|
|
|
|
sub _parse_opt_file { |
662
|
49
|
|
|
49
|
|
87
|
my ($spec, $arg) = @_; |
663
|
|
|
|
|
|
|
|
664
|
49
|
100
|
100
|
|
|
538
|
if (!ref($arg) && $arg && $arg !~ /^(1|yes|true)$/i) { |
|
|
|
100
|
|
|
|
|
665
|
2
|
|
|
|
|
6
|
$arg = {path => $arg}; |
666
|
|
|
|
|
|
|
} |
667
|
|
|
|
|
|
|
|
668
|
|
|
|
|
|
|
_parse_opt_OUTPUT( |
669
|
|
|
|
|
|
|
kind => 'file', default_sub => \&_default_file, |
670
|
|
|
|
|
|
|
spec => $spec, arg => $arg, |
671
|
|
|
|
|
|
|
postprocess => sub { |
672
|
48
|
|
|
48
|
|
156
|
my (%args) = @_; |
673
|
48
|
|
|
|
|
86
|
my $spec = $args{spec}; |
674
|
48
|
|
|
|
|
66
|
my $ospec = $args{ospec}; |
675
|
48
|
100
|
|
|
|
312
|
if ($ospec->{path} =~ m!/$!) { |
676
|
2
|
|
|
|
|
5
|
my $p = $ospec->{path}; |
677
|
2
|
|
|
|
|
5
|
$p .= "$spec->{name}.log"; |
678
|
2
|
|
|
|
|
9
|
_debug("File path ends with /, assumed to be dir, ". |
679
|
|
|
|
|
|
|
"final path becomes $p"); |
680
|
2
|
|
|
|
|
10
|
$ospec->{path} = $p; |
681
|
|
|
|
|
|
|
} |
682
|
|
|
|
|
|
|
}, |
683
|
49
|
|
|
|
|
356
|
); |
684
|
|
|
|
|
|
|
} |
685
|
|
|
|
|
|
|
|
686
|
|
|
|
|
|
|
sub _default_dir { |
687
|
0
|
|
|
0
|
|
0
|
require File::HomeDir; |
688
|
|
|
|
|
|
|
|
689
|
0
|
|
|
|
|
0
|
my ($spec) = @_; |
690
|
0
|
|
|
|
|
0
|
my $level = _set_level("dir", "dir", $spec); |
691
|
0
|
0
|
|
|
|
0
|
if (!$level) { |
692
|
0
|
|
|
|
|
0
|
$level = $spec->{level}; |
693
|
0
|
|
|
|
|
0
|
_debug("Set level of dir to $level (general level)"); |
694
|
|
|
|
|
|
|
} |
695
|
|
|
|
|
|
|
return { |
696
|
|
|
|
|
|
|
level => $level, |
697
|
|
|
|
|
|
|
category_level => _ifdefj($ENV{DIR_LOG_CATEGORY_LEVEL}, |
698
|
|
|
|
|
|
|
$ENV{LOG_CATEGORY_LEVEL}, |
699
|
|
|
|
|
|
|
$spec->{category_level}), |
700
|
|
|
|
|
|
|
path => $> ? File::Spec->catfile(File::HomeDir->my_home, "log", $spec->{name}) : |
701
|
|
|
|
|
|
|
"/var/log/$spec->{name}", # XXX and on Windows? |
702
|
|
|
|
|
|
|
max_size => undef, |
703
|
|
|
|
|
|
|
max_age => undef, |
704
|
|
|
|
|
|
|
histories => undef, |
705
|
|
|
|
|
|
|
category => '', |
706
|
|
|
|
|
|
|
pattern_style => _set_pattern_style('plain'), |
707
|
|
|
|
|
|
|
pattern => undef, |
708
|
|
|
|
|
|
|
filename_pattern => undef, |
709
|
|
|
|
|
|
|
|
710
|
|
|
|
|
|
|
filter_text => _ifdef($ENV{DIR_LOG_FILTER_TEXT}, $spec->{filter_text}), |
711
|
|
|
|
|
|
|
filter_no_text => _ifdef($ENV{DIR_LOG_FILTER_NO_TEXT}, $spec->{filter_no_text}), |
712
|
|
|
|
|
|
|
filter_citext => _ifdef($ENV{DIR_LOG_FILTER_CITEXT}, $spec->{filter_citext}), |
713
|
|
|
|
|
|
|
filter_no_citext => _ifdef($ENV{DIR_LOG_FILTER_NO_CITEXT}, $spec->{filter_no_citext}), |
714
|
|
|
|
|
|
|
filter_re => _ifdef($ENV{DIR_LOG_FILTER_RE}, $spec->{filter_re}), |
715
|
0
|
0
|
|
|
|
0
|
filter_no_re => _ifdef($ENV{DIR_LOG_FILTER_NO_RE}, $spec->{filter_no_re}), |
716
|
|
|
|
|
|
|
}; |
717
|
|
|
|
|
|
|
} |
718
|
|
|
|
|
|
|
|
719
|
|
|
|
|
|
|
sub _parse_opt_dir { |
720
|
49
|
|
|
49
|
|
87
|
my ($spec, $arg) = @_; |
721
|
|
|
|
|
|
|
|
722
|
49
|
50
|
33
|
|
|
310
|
if (!ref($arg) && $arg && $arg !~ /^(1|yes|true)$/i) { |
|
|
|
33
|
|
|
|
|
723
|
0
|
|
|
|
|
0
|
$arg = {path => $arg}; |
724
|
|
|
|
|
|
|
} |
725
|
|
|
|
|
|
|
|
726
|
|
|
|
|
|
|
_parse_opt_OUTPUT( |
727
|
49
|
|
|
|
|
126
|
kind => 'dir', default_sub => \&_default_dir, |
728
|
|
|
|
|
|
|
spec => $spec, arg => $arg, |
729
|
|
|
|
|
|
|
); |
730
|
|
|
|
|
|
|
} |
731
|
|
|
|
|
|
|
|
732
|
|
|
|
|
|
|
sub _default_screen { |
733
|
43
|
|
|
43
|
|
64
|
my ($spec) = @_; |
734
|
43
|
|
|
|
|
87
|
my $level = _set_level("screen", "screen", $spec); |
735
|
43
|
100
|
|
|
|
108
|
if (!$level) { |
736
|
34
|
|
|
|
|
66
|
$level = $spec->{level}; |
737
|
34
|
|
|
|
|
179
|
_debug("Set level of screen to $level (general level)"); |
738
|
|
|
|
|
|
|
} |
739
|
|
|
|
|
|
|
return { |
740
|
|
|
|
|
|
|
color => _ifdef($ENV{COLOR}, (-t STDOUT)), |
741
|
|
|
|
|
|
|
stderr => 1, |
742
|
|
|
|
|
|
|
level => $level, |
743
|
|
|
|
|
|
|
category_level => _ifdefj($ENV{SCREEN_LOG_CATEGORY_LEVEL}, |
744
|
|
|
|
|
|
|
$ENV{LOG_CATEGORY_LEVEL}, |
745
|
|
|
|
|
|
|
$spec->{category_level}), |
746
|
|
|
|
|
|
|
category => '', |
747
|
|
|
|
|
|
|
pattern_style => _set_pattern_style( |
748
|
|
|
|
|
|
|
$ENV{LOG_ELAPSED_TIME_IN_SCREEN} ? 'script_short' : 'plain_nl'), |
749
|
|
|
|
|
|
|
pattern => undef, |
750
|
|
|
|
|
|
|
|
751
|
|
|
|
|
|
|
filter_text => _ifdef($ENV{SCREEN_LOG_FILTER_TEXT}, $spec->{filter_text}), |
752
|
|
|
|
|
|
|
filter_no_text => _ifdef($ENV{SCREEN_FILTER_NO_TEXT}, $spec->{filter_no_text}), |
753
|
|
|
|
|
|
|
filter_citext => _ifdef($ENV{SCREEN_FILTER_CITEXT}, $spec->{filter_citext}), |
754
|
|
|
|
|
|
|
filter_no_citext => _ifdef($ENV{SCREEN_FILTER_NO_CITEXT}, $spec->{filter_no_citext}), |
755
|
|
|
|
|
|
|
filter_re => _ifdef($ENV{SCREEN_FILTER_RE}, $spec->{filter_re}), |
756
|
43
|
50
|
|
|
|
225
|
filter_no_re => _ifdef($ENV{SCREEN_FILTER_NO_RE}, $spec->{filter_no_re}), |
757
|
|
|
|
|
|
|
}; |
758
|
|
|
|
|
|
|
} |
759
|
|
|
|
|
|
|
|
760
|
|
|
|
|
|
|
sub _parse_opt_screen { |
761
|
49
|
|
|
49
|
|
86
|
my ($spec, $arg) = @_; |
762
|
49
|
|
|
|
|
127
|
_parse_opt_OUTPUT( |
763
|
|
|
|
|
|
|
kind => 'screen', default_sub => \&_default_screen, |
764
|
|
|
|
|
|
|
spec => $spec, arg => $arg, |
765
|
|
|
|
|
|
|
); |
766
|
|
|
|
|
|
|
} |
767
|
|
|
|
|
|
|
|
768
|
|
|
|
|
|
|
sub _default_syslog { |
769
|
4
|
|
|
4
|
|
6
|
my ($spec) = @_; |
770
|
4
|
|
|
|
|
9
|
my $level = _set_level("syslog", "syslog", $spec); |
771
|
4
|
50
|
|
|
|
13
|
if (!$level) { |
772
|
4
|
|
|
|
|
6
|
$level = $spec->{level}; |
773
|
4
|
|
|
|
|
11
|
_debug("Set level of syslog to $level (general level)"); |
774
|
|
|
|
|
|
|
} |
775
|
|
|
|
|
|
|
return { |
776
|
|
|
|
|
|
|
level => $level, |
777
|
|
|
|
|
|
|
category_level => _ifdefj($ENV{SYSLOG_LOG_CATEGORY_LEVEL}, |
778
|
|
|
|
|
|
|
$ENV{LOG_CATEGORY_LEVEL}, |
779
|
|
|
|
|
|
|
$spec->{category_level}), |
780
|
|
|
|
|
|
|
ident => $spec->{name}, |
781
|
|
|
|
|
|
|
facility => 'daemon', |
782
|
|
|
|
|
|
|
pattern_style => _set_pattern_style('syslog'), |
783
|
|
|
|
|
|
|
pattern => undef, |
784
|
|
|
|
|
|
|
category => '', |
785
|
|
|
|
|
|
|
|
786
|
|
|
|
|
|
|
filter_text => _ifdef($ENV{SYSLOG_LOG_FILTER_TEXT}, $spec->{filter_text}), |
787
|
|
|
|
|
|
|
filter_no_text => _ifdef($ENV{SYSLOG_FILTER_NO_TEXT}, $spec->{filter_no_text}), |
788
|
|
|
|
|
|
|
filter_citext => _ifdef($ENV{SYSLOG_FILTER_CITEXT}, $spec->{filter_citext}), |
789
|
|
|
|
|
|
|
filter_no_citext => _ifdef($ENV{SYSLOG_FILTER_NO_CITEXT}, $spec->{filter_no_citext}), |
790
|
|
|
|
|
|
|
filter_re => _ifdef($ENV{SYSLOG_FILTER_RE}, $spec->{filter_re}), |
791
|
4
|
|
|
|
|
18
|
filter_no_re => _ifdef($ENV{SYSLOG_FILTER_NO_RE}, $spec->{filter_no_re}), |
792
|
|
|
|
|
|
|
}; |
793
|
|
|
|
|
|
|
} |
794
|
|
|
|
|
|
|
|
795
|
|
|
|
|
|
|
sub _parse_opt_syslog { |
796
|
49
|
|
|
49
|
|
84
|
my ($spec, $arg) = @_; |
797
|
49
|
|
|
|
|
132
|
_parse_opt_OUTPUT( |
798
|
|
|
|
|
|
|
kind => 'syslog', default_sub => \&_default_syslog, |
799
|
|
|
|
|
|
|
spec => $spec, arg => $arg, |
800
|
|
|
|
|
|
|
); |
801
|
|
|
|
|
|
|
} |
802
|
|
|
|
|
|
|
|
803
|
|
|
|
|
|
|
sub _default_unixsock { |
804
|
0
|
|
|
0
|
|
0
|
require File::HomeDir; |
805
|
|
|
|
|
|
|
|
806
|
0
|
|
|
|
|
0
|
my ($spec) = @_; |
807
|
0
|
|
|
|
|
0
|
my $level = _set_level("unixsock", "unixsock", $spec); |
808
|
0
|
0
|
|
|
|
0
|
if (!$level) { |
809
|
0
|
|
|
|
|
0
|
$level = $spec->{level}; |
810
|
0
|
|
|
|
|
0
|
_debug("Set level of unixsock to $level (general level)"); |
811
|
|
|
|
|
|
|
} |
812
|
|
|
|
|
|
|
return { |
813
|
|
|
|
|
|
|
level => $level, |
814
|
|
|
|
|
|
|
category_level => _ifdefj($ENV{UNIXSOCK_LOG_CATEGORY_LEVEL}, |
815
|
|
|
|
|
|
|
$ENV{LOG_CATEGORY_LEVEL}, |
816
|
|
|
|
|
|
|
$spec->{category_level}), |
817
|
|
|
|
|
|
|
path => $> ? File::Spec->catfile(File::HomeDir->my_home, "$spec->{name}-log.sock") : |
818
|
|
|
|
|
|
|
"/var/run/$spec->{name}-log.sock", # XXX and on Windows? |
819
|
|
|
|
|
|
|
category => '', |
820
|
|
|
|
|
|
|
pattern_style => _set_pattern_style('daemon'), |
821
|
|
|
|
|
|
|
pattern => undef, |
822
|
|
|
|
|
|
|
|
823
|
|
|
|
|
|
|
filter_text => _ifdef($ENV{UNIXSOCK_LOG_FILTER_TEXT}, $spec->{filter_text}), |
824
|
|
|
|
|
|
|
filter_no_text => _ifdef($ENV{UNIXSOCK_LOG_FILTER_NO_TEXT}, $spec->{filter_no_text}), |
825
|
|
|
|
|
|
|
filter_citext => _ifdef($ENV{UNIXSOCK_LOG_FILTER_CITEXT}, $spec->{filter_citext}), |
826
|
|
|
|
|
|
|
filter_no_citext => _ifdef($ENV{UNIXSOCK_LOG_FILTER_NO_CITEXT}, $spec->{filter_no_citext}), |
827
|
|
|
|
|
|
|
filter_re => _ifdef($ENV{UNIXSOCK_LOG_FILTER_RE}, $spec->{filter_re}), |
828
|
0
|
0
|
|
|
|
0
|
filter_no_re => _ifdef($ENV{UNIXSOCK_LOG_FILTER_NO_RE}, $spec->{filter_no_re}), |
829
|
|
|
|
|
|
|
}; |
830
|
|
|
|
|
|
|
} |
831
|
|
|
|
|
|
|
|
832
|
|
|
|
|
|
|
sub _parse_opt_unixsock { |
833
|
49
|
|
|
49
|
|
81
|
my ($spec, $arg) = @_; |
834
|
|
|
|
|
|
|
|
835
|
49
|
50
|
33
|
|
|
266
|
if (!ref($arg) && $arg && $arg !~ /^(1|yes|true)$/i) { |
|
|
|
33
|
|
|
|
|
836
|
0
|
|
|
|
|
0
|
$arg = {path => $arg}; |
837
|
|
|
|
|
|
|
} |
838
|
|
|
|
|
|
|
|
839
|
|
|
|
|
|
|
_parse_opt_OUTPUT( |
840
|
|
|
|
|
|
|
kind => 'unixsock', default_sub => \&_default_unixsock, |
841
|
|
|
|
|
|
|
spec => $spec, arg => $arg, |
842
|
|
|
|
|
|
|
postprocess => sub { |
843
|
0
|
|
|
0
|
|
0
|
my (%args) = @_; |
844
|
0
|
|
|
|
|
0
|
my $spec = $args{spec}; |
845
|
0
|
|
|
|
|
0
|
my $ospec = $args{ospec}; |
846
|
0
|
0
|
|
|
|
0
|
if ($ospec->{path} =~ m!/$!) { |
847
|
0
|
|
|
|
|
0
|
my $p = $ospec->{path}; |
848
|
0
|
|
|
|
|
0
|
$p .= "$spec->{name}-log.sock"; |
849
|
0
|
|
|
|
|
0
|
_debug("Unix socket path ends with /, assumed to be dir, ". |
850
|
|
|
|
|
|
|
"final path becomes $p"); |
851
|
0
|
|
|
|
|
0
|
$ospec->{path} = $p; |
852
|
|
|
|
|
|
|
} |
853
|
|
|
|
|
|
|
|
854
|
|
|
|
|
|
|
# currently Log::Log4perl::Appender::Socket::UNIX *connects to an |
855
|
|
|
|
|
|
|
# existing and listening* Unix socket and prints log to it. we are |
856
|
|
|
|
|
|
|
# *not* creating a listening unix socket where clients can connect |
857
|
|
|
|
|
|
|
# and see logs. to do that, we'll need a separate thread/process |
858
|
|
|
|
|
|
|
# that listens to unix socket and stores (some) log entries and |
859
|
|
|
|
|
|
|
# display it to users when they connect and request them. |
860
|
|
|
|
|
|
|
# |
861
|
|
|
|
|
|
|
#if ($ospec->{create} && !(-e $ospec->{path})) { |
862
|
|
|
|
|
|
|
# _debug("Creating Unix socket $ospec->{path} ..."); |
863
|
|
|
|
|
|
|
# require IO::Socket::UNIX::Util; |
864
|
|
|
|
|
|
|
# IO::Socket::UNIX::Util::create_unix_socket( |
865
|
|
|
|
|
|
|
# $ospec->{path}); |
866
|
|
|
|
|
|
|
#} |
867
|
|
|
|
|
|
|
}, |
868
|
49
|
|
|
|
|
280
|
); |
869
|
|
|
|
|
|
|
} |
870
|
|
|
|
|
|
|
|
871
|
|
|
|
|
|
|
sub _default_array { |
872
|
0
|
|
|
0
|
|
0
|
my ($spec) = @_; |
873
|
0
|
|
|
|
|
0
|
my $level = _set_level("array", "array", $spec); |
874
|
0
|
0
|
|
|
|
0
|
if (!$level) { |
875
|
0
|
|
|
|
|
0
|
$level = $spec->{level}; |
876
|
0
|
|
|
|
|
0
|
_debug("Set level of array to $level (general level)"); |
877
|
|
|
|
|
|
|
} |
878
|
|
|
|
|
|
|
return { |
879
|
|
|
|
|
|
|
level => $level, |
880
|
|
|
|
|
|
|
category_level => _ifdefj($ENV{ARRAY_LOG_CATEGORY_LEVEL}, |
881
|
|
|
|
|
|
|
$ENV{LOG_CATEGORY_LEVEL}, |
882
|
|
|
|
|
|
|
$spec->{category_level}), |
883
|
|
|
|
|
|
|
array => [], |
884
|
|
|
|
|
|
|
max_elems => undef, |
885
|
|
|
|
|
|
|
category => '', |
886
|
|
|
|
|
|
|
pattern_style => _set_pattern_style('script_long'), |
887
|
|
|
|
|
|
|
pattern => undef, |
888
|
|
|
|
|
|
|
|
889
|
|
|
|
|
|
|
filter_text => _ifdef($ENV{ARRAY_LOG_FILTER_TEXT}, $spec->{filter_text}), |
890
|
|
|
|
|
|
|
filter_no_text => _ifdef($ENV{ARRAY_LOG_FILTER_NO_TEXT}, $spec->{filter_no_text}), |
891
|
|
|
|
|
|
|
filter_citext => _ifdef($ENV{ARRAY_LOG_FILTER_CITEXT}, $spec->{filter_citext}), |
892
|
|
|
|
|
|
|
filter_no_citext => _ifdef($ENV{ARRAY_LOG_FILTER_NO_CITEXT}, $spec->{filter_no_citext}), |
893
|
|
|
|
|
|
|
filter_re => _ifdef($ENV{ARRAY_LOG_FILTER_RE}, $spec->{filter_re}), |
894
|
0
|
|
|
|
|
0
|
filter_no_re => _ifdef($ENV{ARRAY_LOG_FILTER_NO_RE}, $spec->{filter_no_re}), |
895
|
|
|
|
|
|
|
}; |
896
|
|
|
|
|
|
|
} |
897
|
|
|
|
|
|
|
|
898
|
|
|
|
|
|
|
sub _parse_opt_array { |
899
|
49
|
|
|
49
|
|
87
|
my ($spec, $arg) = @_; |
900
|
|
|
|
|
|
|
|
901
|
49
|
|
|
|
|
121
|
_parse_opt_OUTPUT( |
902
|
|
|
|
|
|
|
kind => 'array', default_sub => \&_default_array, |
903
|
|
|
|
|
|
|
spec => $spec, arg => $arg, |
904
|
|
|
|
|
|
|
); |
905
|
|
|
|
|
|
|
} |
906
|
|
|
|
|
|
|
|
907
|
|
|
|
|
|
|
sub _set_pattern { |
908
|
95
|
|
|
95
|
|
155
|
my ($s, $name) = @_; |
909
|
95
|
|
|
|
|
240
|
_debug("Setting $name pattern ..."); |
910
|
95
|
50
|
|
|
|
281
|
unless (defined($s->{pattern})) { |
911
|
|
|
|
|
|
|
die "BUG: neither pattern nor pattern_style is defined ($name)" |
912
|
95
|
50
|
|
|
|
231
|
unless defined($s->{pattern_style}); |
913
|
|
|
|
|
|
|
die "Unknown pattern style for $name `$s->{pattern_style}`, ". |
914
|
|
|
|
|
|
|
"use one of: ".join(", ", keys %PATTERN_STYLES) |
915
|
95
|
50
|
|
|
|
276
|
unless defined($PATTERN_STYLES{ $s->{pattern_style} }); |
916
|
95
|
|
|
|
|
187
|
$s->{pattern} = $PATTERN_STYLES{ $s->{pattern_style} }; |
917
|
95
|
|
|
|
|
350
|
_debug("Set $name pattern to `$s->{pattern}` ". |
918
|
|
|
|
|
|
|
"(from style `$s->{pattern_style}`)"); |
919
|
|
|
|
|
|
|
} |
920
|
|
|
|
|
|
|
} |
921
|
|
|
|
|
|
|
|
922
|
|
|
|
|
|
|
sub _extract_category { |
923
|
8
|
|
|
8
|
|
13
|
my ($ospec, $c) = @_; |
924
|
8
|
|
|
|
|
18
|
my $c0 = _ifdef($c, $ospec->{category}); |
925
|
8
|
|
|
|
|
13
|
my @res; |
926
|
8
|
50
|
|
|
|
18
|
if (ref($c0) eq 'ARRAY') { @res = @$c0 } else { @res = ($c0) } |
|
0
|
|
|
|
|
0
|
|
|
8
|
|
|
|
|
16
|
|
927
|
|
|
|
|
|
|
# replace alias with real value |
928
|
8
|
|
|
|
|
22
|
for (my $i=0; $i<@res; $i++) { |
929
|
8
|
|
|
|
|
12
|
my $c1 = $res[$i]; |
930
|
8
|
|
|
|
|
18
|
my $a = $ospec->{main_spec}{category_alias}{$c1}; |
931
|
8
|
100
|
|
|
|
27
|
next unless defined($a); |
932
|
2
|
50
|
|
|
|
7
|
if (ref($a) eq 'ARRAY') { |
933
|
2
|
|
|
|
|
6
|
splice @res, $i, 1, @$a; |
934
|
2
|
|
|
|
|
8
|
$i += (@$a-1); |
935
|
|
|
|
|
|
|
} else { |
936
|
0
|
|
|
|
|
0
|
$res[$i] = $a; |
937
|
|
|
|
|
|
|
} |
938
|
|
|
|
|
|
|
} |
939
|
8
|
|
|
|
|
16
|
for (@res) { |
940
|
10
|
|
|
|
|
24
|
s/::/./g; |
941
|
|
|
|
|
|
|
# $_ = lc; # XXX do we need this? |
942
|
|
|
|
|
|
|
} |
943
|
8
|
|
|
|
|
24
|
@res; |
944
|
|
|
|
|
|
|
} |
945
|
|
|
|
|
|
|
|
946
|
|
|
|
|
|
|
sub _cat2apd { |
947
|
0
|
|
|
0
|
|
0
|
my $cat = shift; |
948
|
0
|
|
|
|
|
0
|
$cat =~ s/[^A-Za-z0-9_]+/_/g; |
949
|
0
|
|
|
|
|
0
|
$cat; |
950
|
|
|
|
|
|
|
} |
951
|
|
|
|
|
|
|
|
952
|
|
|
|
|
|
|
sub _check_level { |
953
|
25
|
|
|
25
|
|
54
|
my ($level, $from) = @_; |
954
|
25
|
50
|
|
|
|
147
|
$level =~ /^(off|fatal|error|warn|info|debug|trace)$/i |
955
|
|
|
|
|
|
|
or die "Unknown level (from $from): $level"; |
956
|
25
|
|
|
|
|
94
|
lc($1); |
957
|
|
|
|
|
|
|
} |
958
|
|
|
|
|
|
|
|
959
|
|
|
|
|
|
|
sub _set_level { |
960
|
144
|
|
|
144
|
|
258
|
my ($prefix, $which, $spec) = @_; |
961
|
|
|
|
|
|
|
#use Data::Dump; dd $spec; |
962
|
144
|
100
|
|
|
|
394
|
my $p_ = $prefix ? "${prefix}_" : ""; |
963
|
144
|
100
|
|
|
|
295
|
my $P_ = $prefix ? uc("${prefix}_") : ""; |
964
|
144
|
100
|
|
|
|
277
|
my $F_ = $prefix ? ucfirst("${prefix}_") : ""; |
965
|
144
|
100
|
|
|
|
268
|
my $pd = $prefix ? "${prefix}-" : ""; |
966
|
144
|
100
|
|
|
|
2473
|
my $pr = $prefix ? qr/$prefix(_|-)/ : qr//; |
967
|
144
|
|
|
|
|
235
|
my ($level, $from); |
968
|
|
|
|
|
|
|
|
969
|
144
|
|
|
|
|
629
|
my @label2level =([trace=>"trace"], [debug=>"debug"], |
970
|
|
|
|
|
|
|
[verbose=>"info"], [quiet=>"error"]); |
971
|
|
|
|
|
|
|
|
972
|
144
|
100
|
|
|
|
463
|
_debug("Setting ", ($which ? "level of $which" : "general level"), " ..."); |
973
|
|
|
|
|
|
|
SET: |
974
|
|
|
|
|
|
|
{ |
975
|
144
|
50
|
|
|
|
207
|
if ($INC{"App/Options.pm"}) { |
|
144
|
|
|
|
|
313
|
|
976
|
0
|
|
|
|
|
0
|
my $key; |
977
|
0
|
|
|
|
|
0
|
for (qw/log_level loglevel/) { |
978
|
0
|
|
|
|
|
0
|
$key = $p_ . $_; |
979
|
0
|
|
|
|
|
0
|
_debug("Checking \$App::options{$key}: ", _ifdef($App::options{$key}, "(undef)")); |
980
|
0
|
0
|
|
|
|
0
|
if ($App::options{$key}) { |
981
|
0
|
|
|
|
|
0
|
$level = _check_level($App::options{$key}, "\$App::options{$key}"); |
982
|
0
|
|
|
|
|
0
|
$from = "\$App::options{$key}"; |
983
|
0
|
|
|
|
|
0
|
last SET; |
984
|
|
|
|
|
|
|
} |
985
|
|
|
|
|
|
|
} |
986
|
0
|
|
|
|
|
0
|
for (@label2level) { |
987
|
0
|
|
|
|
|
0
|
$key = $p_ . $_->[0]; |
988
|
0
|
|
|
|
|
0
|
_debug("Checking \$App::options{$key}: ", _ifdef($App::options{$key}, "(undef)")); |
989
|
0
|
0
|
|
|
|
0
|
if ($App::options{$key}) { |
990
|
0
|
|
|
|
|
0
|
$level = $_->[1]; |
991
|
0
|
|
|
|
|
0
|
$from = "\$App::options{$key}"; |
992
|
0
|
|
|
|
|
0
|
last SET; |
993
|
|
|
|
|
|
|
} |
994
|
|
|
|
|
|
|
} |
995
|
|
|
|
|
|
|
} |
996
|
|
|
|
|
|
|
|
997
|
144
|
|
|
|
|
177
|
my $i = 0; |
998
|
144
|
|
|
|
|
243
|
_debug("Checking \@ARGV ..."); |
999
|
144
|
|
|
|
|
368
|
while ($i < @ARGV) { |
1000
|
36
|
|
|
|
|
51
|
my $arg = $ARGV[$i]; |
1001
|
36
|
|
|
|
|
54
|
$from = "cmdline arg $arg"; |
1002
|
36
|
50
|
|
|
|
638
|
if ($arg =~ /^--${pr}log[_-]?level=(.+)/) { |
1003
|
0
|
|
|
|
|
0
|
_debug("\$ARGV[$i] looks like an option to specify level: $arg"); |
1004
|
0
|
|
|
|
|
0
|
$level = _check_level($1, "ARGV $arg"); |
1005
|
0
|
|
|
|
|
0
|
last SET; |
1006
|
|
|
|
|
|
|
} |
1007
|
36
|
100
|
66
|
|
|
549
|
if ($arg =~ /^--${pr}log[_-]?level$/ and $i < @ARGV-1) { |
1008
|
6
|
|
|
|
|
13
|
_debug("\$ARGV[$i] and \$ARGV[${\($i+1)}] looks like an option to specify level: $arg ", $ARGV[$i+1]); |
|
6
|
|
|
|
|
30
|
|
1009
|
6
|
|
|
|
|
25
|
$level = _check_level($ARGV[$i+1], "ARGV $arg ".$ARGV[$i+1]); |
1010
|
6
|
|
|
|
|
18
|
last SET; |
1011
|
|
|
|
|
|
|
} |
1012
|
30
|
|
|
|
|
63
|
for (@label2level) { |
1013
|
120
|
100
|
|
|
|
3613
|
if ($arg =~ /^--${pr}$_->[0](=(1|yes|true))?$/i) { |
1014
|
2
|
|
|
|
|
9
|
_debug("\$ARGV[$i] looks like an option to specify level: $arg"); |
1015
|
2
|
|
|
|
|
4
|
$level = $_->[1]; |
1016
|
2
|
|
|
|
|
8
|
last SET; |
1017
|
|
|
|
|
|
|
} |
1018
|
|
|
|
|
|
|
} |
1019
|
28
|
|
|
|
|
92
|
$i++; |
1020
|
|
|
|
|
|
|
} |
1021
|
|
|
|
|
|
|
|
1022
|
136
|
|
|
|
|
248
|
for (qw/LOG_LEVEL LOGLEVEL/) { |
1023
|
270
|
|
|
|
|
451
|
my $key = $P_ . $_; |
1024
|
270
|
|
|
|
|
946
|
_debug("Checking environment variable $key: ", _ifdef($ENV{$key}, "(undef)")); |
1025
|
270
|
100
|
|
|
|
1005
|
if ($ENV{$key}) { |
1026
|
2
|
|
|
|
|
8
|
$level = _check_level($ENV{$key}, "ENV $key"); |
1027
|
2
|
|
|
|
|
6
|
$from = "\$ENV{$key}"; |
1028
|
2
|
|
|
|
|
6
|
last SET; |
1029
|
|
|
|
|
|
|
} |
1030
|
|
|
|
|
|
|
} |
1031
|
134
|
|
|
|
|
244
|
for (@label2level) { |
1032
|
533
|
|
|
|
|
1095
|
my $key = $P_ . uc($_->[0]); |
1033
|
533
|
|
|
|
|
1589
|
_debug("Checking environment variable $key: ", _ifdef($ENV{$key}, "(undef)")); |
1034
|
533
|
100
|
|
|
|
1831
|
if ($ENV{$key}) { |
1035
|
2
|
|
|
|
|
4
|
$level = $_->[1]; |
1036
|
2
|
|
|
|
|
6
|
$from = "\$ENV{$key}"; |
1037
|
2
|
|
|
|
|
7
|
last SET; |
1038
|
|
|
|
|
|
|
} |
1039
|
|
|
|
|
|
|
} |
1040
|
|
|
|
|
|
|
|
1041
|
132
|
|
|
|
|
161
|
for my $dir (@{$spec->{level_flag_paths}}) { |
|
132
|
|
|
|
|
323
|
|
1042
|
252
|
|
|
|
|
436
|
for (@label2level) { |
1043
|
999
|
|
|
|
|
2296
|
my $filename = "$dir/$spec->{name}." . $P_ . "log_level"; |
1044
|
999
|
|
|
|
|
13547
|
my $exists = -f $filename; |
1045
|
999
|
|
|
|
|
1137
|
my $content; |
1046
|
999
|
100
|
|
|
|
1825
|
if ($exists) { |
1047
|
2
|
|
|
|
|
68
|
open my($f), $filename; |
1048
|
2
|
|
|
|
|
47
|
$content = <$f>; |
1049
|
2
|
50
|
|
|
|
15
|
chomp($content) if defined($content); |
1050
|
2
|
|
|
|
|
19
|
close $f; |
1051
|
|
|
|
|
|
|
} |
1052
|
999
|
100
|
|
|
|
3037
|
_debug("Checking level flag file content $filename: ", |
1053
|
|
|
|
|
|
|
(defined($content) ? $content : "(undef)")); |
1054
|
999
|
100
|
|
|
|
2325
|
if (defined $content) { |
1055
|
2
|
|
|
|
|
7
|
$level = _check_level($content, |
1056
|
|
|
|
|
|
|
"level flag file $filename"); |
1057
|
2
|
|
|
|
|
4
|
$from = $filename; |
1058
|
2
|
|
|
|
|
6
|
last SET; |
1059
|
|
|
|
|
|
|
} |
1060
|
|
|
|
|
|
|
|
1061
|
997
|
|
|
|
|
2500
|
$filename = "$dir/$spec->{name}." . $P_ . uc($_->[0]); |
1062
|
997
|
|
|
|
|
12093
|
$exists = -e $filename; |
1063
|
997
|
100
|
|
|
|
3218
|
_debug("Checking level flag file $filename: ", |
1064
|
|
|
|
|
|
|
($exists ? "EXISTS" : 0)); |
1065
|
997
|
100
|
|
|
|
2892
|
if ($exists) { |
1066
|
2
|
|
|
|
|
5
|
$level = $_->[1]; |
1067
|
2
|
|
|
|
|
3
|
$from = $filename; |
1068
|
2
|
|
|
|
|
6
|
last SET; |
1069
|
|
|
|
|
|
|
} |
1070
|
|
|
|
|
|
|
} |
1071
|
|
|
|
|
|
|
} |
1072
|
|
|
|
|
|
|
|
1073
|
2
|
|
|
2
|
|
18
|
no strict 'refs'; |
|
2
|
|
|
|
|
9
|
|
|
2
|
|
|
|
|
1124
|
|
1074
|
128
|
|
|
|
|
451
|
for ("${F_}Log_Level", "${P_}LOG_LEVEL", "${p_}log_level", |
1075
|
|
|
|
|
|
|
"${F_}LogLevel", "${P_}LOGLEVEL", "${p_}loglevel") { |
1076
|
738
|
|
|
|
|
1126
|
my $varname = "main::$_"; |
1077
|
738
|
|
|
|
|
2256
|
_debug("Checking variable \$$varname: ", _ifdef($$varname, "(undef)")); |
1078
|
738
|
100
|
|
|
|
2846
|
if ($$varname) { |
1079
|
12
|
|
|
|
|
22
|
$from = "\$$varname"; |
1080
|
12
|
|
|
|
|
48
|
$level = _check_level($$varname, "\$$varname"); |
1081
|
12
|
|
|
|
|
38
|
last SET; |
1082
|
|
|
|
|
|
|
} |
1083
|
|
|
|
|
|
|
} |
1084
|
116
|
|
|
|
|
225
|
for (@label2level) { |
1085
|
452
|
|
|
|
|
1494
|
for my $varname ( |
1086
|
|
|
|
|
|
|
"main::$F_" . ucfirst($_->[0]), |
1087
|
|
|
|
|
|
|
"main::$P_" . uc($_->[0])) { |
1088
|
900
|
|
|
|
|
2540
|
_debug("Checking variable \$$varname: ", _ifdef($$varname, "(undef)")); |
1089
|
900
|
100
|
|
|
|
3309
|
if ($$varname) { |
1090
|
8
|
|
|
|
|
18
|
$from = "\$$varname"; |
1091
|
8
|
|
|
|
|
13
|
$level = $_->[1]; |
1092
|
8
|
|
|
|
|
23
|
last SET; |
1093
|
|
|
|
|
|
|
} |
1094
|
|
|
|
|
|
|
} |
1095
|
|
|
|
|
|
|
} |
1096
|
|
|
|
|
|
|
} |
1097
|
|
|
|
|
|
|
|
1098
|
144
|
100
|
|
|
|
457
|
_debug("Set ", ($which ? "level of $which" : "general level"), " to $level (from $from)") if $level; |
|
|
100
|
|
|
|
|
|
1099
|
144
|
|
|
|
|
755
|
return $level; |
1100
|
|
|
|
|
|
|
} |
1101
|
|
|
|
|
|
|
|
1102
|
|
|
|
|
|
|
# return the lower level (e.g. _min_level("debug", "INFO") -> INFO |
1103
|
|
|
|
|
|
|
sub _min_level { |
1104
|
40
|
|
|
40
|
|
62
|
my ($l1, $l2) = @_; |
1105
|
40
|
|
|
|
|
161
|
my %vals = (OFF=>99, |
1106
|
|
|
|
|
|
|
FATAL=>6, ERROR=>5, WARN=>4, INFO=>3, DEBUG=>2, TRACE=>1); |
1107
|
40
|
100
|
|
|
|
187
|
$vals{uc($l1)} > $vals{uc($l2)} ? $l2 : $l1; |
1108
|
|
|
|
|
|
|
} |
1109
|
|
|
|
|
|
|
|
1110
|
|
|
|
|
|
|
sub _export_logger { |
1111
|
1
|
|
|
1
|
|
2
|
my ($caller) = @_; |
1112
|
1
|
|
|
|
|
6
|
my $log_for_caller = Log::Any->get_logger(category => $caller); |
1113
|
1
|
|
|
|
|
9383
|
my $varname = "$caller\::log"; |
1114
|
2
|
|
|
2
|
|
35
|
no strict 'refs'; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
285
|
|
1115
|
1
|
|
|
|
|
5
|
*$varname = \$log_for_caller; |
1116
|
|
|
|
|
|
|
} |
1117
|
|
|
|
|
|
|
|
1118
|
|
|
|
|
|
|
sub _debug { |
1119
|
5169
|
50
|
|
5169
|
|
12463
|
return unless $ENV{LOGANYAPP_DEBUG}; |
1120
|
0
|
0
|
|
|
|
0
|
print $dbg_ctx, ": " if $dbg_ctx; |
1121
|
0
|
|
|
|
|
0
|
print @_, "\n"; |
1122
|
|
|
|
|
|
|
} |
1123
|
|
|
|
|
|
|
|
1124
|
|
|
|
|
|
|
sub import { |
1125
|
2
|
|
|
2
|
|
44
|
my ($self, @args) = @_; |
1126
|
2
|
|
|
|
|
6
|
my $caller = caller(); |
1127
|
2
|
|
|
|
|
7
|
_parse_args(\@args, $caller); |
1128
|
2
|
|
|
|
|
67
|
$init_args = \@args; |
1129
|
|
|
|
|
|
|
} |
1130
|
|
|
|
|
|
|
|
1131
|
|
|
|
|
|
|
{ |
1132
|
2
|
|
|
2
|
|
10
|
no warnings; |
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
216
|
|
1133
|
|
|
|
|
|
|
# if we are loaded at run-time, it's too late to run INIT blocks, so user |
1134
|
|
|
|
|
|
|
# must call init() manually. but sometimes this is what the user wants. so |
1135
|
|
|
|
|
|
|
# shut up perl warning. |
1136
|
|
|
|
|
|
|
INIT { |
1137
|
2
|
|
|
2
|
|
56
|
my $caller = caller(); |
1138
|
2
|
|
|
|
|
12
|
init($init_args, $caller); |
1139
|
|
|
|
|
|
|
} |
1140
|
|
|
|
|
|
|
} |
1141
|
|
|
|
|
|
|
|
1142
|
|
|
|
|
|
|
1; |
1143
|
|
|
|
|
|
|
# ABSTRACT: An easy way to use Log::Any in applications |
1144
|
|
|
|
|
|
|
|
1145
|
|
|
|
|
|
|
__END__ |