Filename | /var/www/foswikidev/core/lib/Foswiki/Logger/PlainFile.pm |
Statements | Executed 110 statements in 2.24ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 1.20ms | 1.38ms | BEGIN@36 | Foswiki::Logger::PlainFile::
1 | 1 | 1 | 371µs | 448µs | BEGIN@38 | Foswiki::Logger::PlainFile::
1 | 1 | 1 | 282µs | 362µs | BEGIN@37 | Foswiki::Logger::PlainFile::
1 | 1 | 1 | 118µs | 496µs | log | Foswiki::Logger::PlainFile::
1 | 1 | 1 | 36µs | 133µs | _rotate | Foswiki::Logger::PlainFile::
2 | 2 | 1 | 31µs | 31µs | _time2month | Foswiki::Logger::PlainFile::
1 | 1 | 1 | 18µs | 46µs | BEGIN@5 | Foswiki::Logger::PlainFile::EventIterator::
1 | 1 | 1 | 14µs | 14µs | _lock | Foswiki::Logger::PlainFile::
1 | 1 | 1 | 13µs | 26µs | BEGIN@3 | Foswiki::Logger::PlainFile::EventIterator::
1 | 1 | 1 | 12µs | 26µs | _getLogsForLevel | Foswiki::Logger::PlainFile::
1 | 1 | 1 | 11µs | 11µs | BEGIN@39 | Foswiki::Logger::PlainFile::
1 | 1 | 1 | 11µs | 16µs | BEGIN@62 | Foswiki::Logger::PlainFile::
1 | 1 | 1 | 10µs | 119µs | BEGIN@7 | Foswiki::Logger::PlainFile::EventIterator::
1 | 1 | 1 | 10µs | 14µs | BEGIN@4 | Foswiki::Logger::PlainFile::EventIterator::
1 | 1 | 1 | 9µs | 33µs | BEGIN@33 | Foswiki::Logger::PlainFile::
1 | 1 | 1 | 9µs | 38µs | BEGIN@64 | Foswiki::Logger::PlainFile::
1 | 1 | 1 | 9µs | 16µs | BEGIN@32 | Foswiki::Logger::PlainFile::
1 | 1 | 1 | 9µs | 21µs | BEGIN@31 | Foswiki::Logger::PlainFile::
1 | 1 | 1 | 9µs | 9µs | new | Foswiki::Logger::PlainFile::
1 | 1 | 1 | 8µs | 91µs | BEGIN@40 | Foswiki::Logger::PlainFile::
1 | 1 | 1 | 5µs | 5µs | BEGIN@35 | Foswiki::Logger::PlainFile::
1 | 1 | 1 | 5µs | 5µs | BEGIN@9 | Foswiki::Logger::PlainFile::EventIterator::
1 | 1 | 1 | 4µs | 4µs | _time | Foswiki::Logger::PlainFile::
1 | 1 | 1 | 3µs | 3µs | _stat | Foswiki::Logger::PlainFile::
0 | 0 | 0 | 0s | 0s | DESTROY | Foswiki::Logger::PlainFile::EventIterator::
0 | 0 | 0 | 0s | 0s | eachEventSince | Foswiki::Logger::PlainFile::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | # See bottom of file for license and copyright information | ||||
2 | package Foswiki::Logger::PlainFile::EventIterator; | ||||
3 | 2 | 30µs | 2 | 39µs | # spent 26µs (13+13) within Foswiki::Logger::PlainFile::EventIterator::BEGIN@3 which was called:
# once (13µs+13µs) by Foswiki::logger at line 3 # spent 26µs making 1 call to Foswiki::Logger::PlainFile::EventIterator::BEGIN@3
# spent 13µs making 1 call to strict::import |
4 | 2 | 24µs | 2 | 18µs | # spent 14µs (10+4) within Foswiki::Logger::PlainFile::EventIterator::BEGIN@4 which was called:
# once (10µs+4µs) by Foswiki::logger at line 4 # spent 14µs making 1 call to Foswiki::Logger::PlainFile::EventIterator::BEGIN@4
# spent 4µs making 1 call to warnings::import |
5 | 2 | 30µs | 2 | 74µs | # spent 46µs (18+28) within Foswiki::Logger::PlainFile::EventIterator::BEGIN@5 which was called:
# once (18µs+28µs) by Foswiki::logger at line 5 # spent 46µs making 1 call to Foswiki::Logger::PlainFile::EventIterator::BEGIN@5
# spent 28µs making 1 call to Exporter::import |
6 | |||||
7 | 2 | 54µs | 2 | 227µs | # spent 119µs (10+108) within Foswiki::Logger::PlainFile::EventIterator::BEGIN@7 which was called:
# once (10µs+108µs) by Foswiki::logger at line 7 # spent 119µs making 1 call to Foswiki::Logger::PlainFile::EventIterator::BEGIN@7
# spent 108µs making 1 call to Exporter::import |
8 | |||||
9 | # spent 5µs within Foswiki::Logger::PlainFile::EventIterator::BEGIN@9 which was called:
# once (5µs+0s) by Foswiki::logger at line 14 | ||||
10 | 1 | 4µs | if ( $Foswiki::cfg{UseLocale} ) { | ||
11 | require locale; | ||||
12 | import locale(); | ||||
13 | } | ||||
14 | 1 | 88µs | 1 | 5µs | } # spent 5µs making 1 call to Foswiki::Logger::PlainFile::EventIterator::BEGIN@9 |
15 | |||||
16 | # Internal class for Logfile iterators. | ||||
17 | # So we don't break encapsulation of file handles. Open / Close in same file. | ||||
18 | 1 | 9µs | our @ISA = qw/Foswiki::Iterator::EventIterator/; | ||
19 | |||||
20 | # # Object destruction | ||||
21 | # # Release locks and file | ||||
22 | sub DESTROY { | ||||
23 | my $this = shift; | ||||
24 | flock( $this->{handle}, LOCK_UN ) | ||||
25 | if ( defined $this->{logLocked} ); | ||||
26 | close( delete $this->{handle} ) if ( defined $this->{handle} ); | ||||
27 | } | ||||
28 | |||||
29 | package Foswiki::Logger::PlainFile; | ||||
30 | |||||
31 | 2 | 26µs | 2 | 34µs | # spent 21µs (9+12) within Foswiki::Logger::PlainFile::BEGIN@31 which was called:
# once (9µs+12µs) by Foswiki::logger at line 31 # spent 21µs making 1 call to Foswiki::Logger::PlainFile::BEGIN@31
# spent 12µs making 1 call to strict::import |
32 | 2 | 23µs | 2 | 22µs | # spent 16µs (9+7) within Foswiki::Logger::PlainFile::BEGIN@32 which was called:
# once (9µs+7µs) by Foswiki::logger at line 32 # spent 16µs making 1 call to Foswiki::Logger::PlainFile::BEGIN@32
# spent 7µs making 1 call to warnings::import |
33 | 2 | 27µs | 2 | 56µs | # spent 33µs (9+23) within Foswiki::Logger::PlainFile::BEGIN@33 which was called:
# once (9µs+23µs) by Foswiki::logger at line 33 # spent 33µs making 1 call to Foswiki::Logger::PlainFile::BEGIN@33
# spent 24µs making 1 call to Exporter::import |
34 | |||||
35 | 2 | 21µs | 1 | 5µs | # spent 5µs within Foswiki::Logger::PlainFile::BEGIN@35 which was called:
# once (5µs+0s) by Foswiki::logger at line 35 # spent 5µs making 1 call to Foswiki::Logger::PlainFile::BEGIN@35 |
36 | 2 | 91µs | 1 | 1.38ms | # spent 1.38ms (1.20+178µs) within Foswiki::Logger::PlainFile::BEGIN@36 which was called:
# once (1.20ms+178µs) by Foswiki::logger at line 36 # spent 1.38ms making 1 call to Foswiki::Logger::PlainFile::BEGIN@36 |
37 | 2 | 83µs | 1 | 362µs | # spent 362µs (282+80) within Foswiki::Logger::PlainFile::BEGIN@37 which was called:
# once (282µs+80µs) by Foswiki::logger at line 37 # spent 362µs making 1 call to Foswiki::Logger::PlainFile::BEGIN@37 |
38 | 2 | 87µs | 1 | 448µs | # spent 448µs (371+77) within Foswiki::Logger::PlainFile::BEGIN@38 which was called:
# once (371µs+77µs) by Foswiki::logger at line 38 # spent 448µs making 1 call to Foswiki::Logger::PlainFile::BEGIN@38 |
39 | 2 | 30µs | 1 | 11µs | # spent 11µs within Foswiki::Logger::PlainFile::BEGIN@39 which was called:
# once (11µs+0s) by Foswiki::logger at line 39 # spent 11µs making 1 call to Foswiki::Logger::PlainFile::BEGIN@39 |
40 | 2 | 54µs | 2 | 174µs | # spent 91µs (8+83) within Foswiki::Logger::PlainFile::BEGIN@40 which was called:
# once (8µs+83µs) by Foswiki::logger at line 40 # spent 91µs making 1 call to Foswiki::Logger::PlainFile::BEGIN@40
# spent 83µs making 1 call to Exporter::import |
41 | 1 | 5µs | our @ISA = ('Foswiki::Logger'); | ||
42 | |||||
43 | =begin TML | ||||
44 | |||||
45 | ---+ package Foswiki::Logger::PlainFile | ||||
46 | |||||
47 | Plain file implementation of the Foswiki Logger interface. Mostly | ||||
48 | compatible with TWiki (and Foswiki 1.0.0) log files, except that dates | ||||
49 | are recorded using ISO format, and include the time, and it dies when | ||||
50 | a log can't be written (rather than printing a warning). | ||||
51 | |||||
52 | This logger implementation maps groups of levels to a single logfile, viz. | ||||
53 | * =debug= messages are output to $Foswiki::cfg{Log}{Dir}/debug.log | ||||
54 | * =info= messages are output to $Foswiki::cfg{Log}{Dir}/events.log | ||||
55 | * =warning=, =error=, =critical=, =alert=, =emergency= messages are | ||||
56 | output to $Foswiki::cfg{Log}{Dir}/error.log. | ||||
57 | * =error=, =critical=, =alert=, and =emergency= messages are also | ||||
58 | written to standard error (the webserver log file, usually) | ||||
59 | |||||
60 | =cut | ||||
61 | |||||
62 | 2 | 28µs | 2 | 20µs | # spent 16µs (11+5) within Foswiki::Logger::PlainFile::BEGIN@62 which was called:
# once (11µs+5µs) by Foswiki::logger at line 62 # spent 16µs making 1 call to Foswiki::Logger::PlainFile::BEGIN@62
# spent 5µs making 1 call to Foswiki::Time::import |
63 | |||||
64 | 2 | 1.29ms | 2 | 68µs | # spent 38µs (9+29) within Foswiki::Logger::PlainFile::BEGIN@64 which was called:
# once (9µs+29µs) by Foswiki::logger at line 64 # spent 38µs making 1 call to Foswiki::Logger::PlainFile::BEGIN@64
# spent 29µs making 1 call to constant::import |
65 | |||||
66 | # Map from a log level to the root of a log file name | ||||
67 | 1 | 5µs | our %LEVEL2LOG = ( | ||
68 | debug => 'debug', | ||||
69 | info => 'events', | ||||
70 | notice => 'configure', | ||||
71 | warning => 'error', | ||||
72 | error => 'error', | ||||
73 | critical => 'error', | ||||
74 | alert => 'error', | ||||
75 | emergency => 'error' | ||||
76 | ); | ||||
77 | |||||
78 | 1 | 2µs | our %nextCheckDue = ( | ||
79 | configure => 0, | ||||
80 | debug => 0, | ||||
81 | events => 0, | ||||
82 | error => 0, | ||||
83 | ); | ||||
84 | |||||
85 | # Symbols used so we can override during unit testing | ||||
86 | 1 | 200ns | our $dontRotate = 0; | ||
87 | 1 | 6µs | # spent 4µs within Foswiki::Logger::PlainFile::_time which was called:
# once (4µs+0s) by Foswiki::Logger::PlainFile::log at line 117 | ||
88 | 1 | 6µs | # spent 3µs within Foswiki::Logger::PlainFile::_stat which was called:
# once (3µs+0s) by Foswiki::Logger::PlainFile::_rotate at line 319 | ||
89 | |||||
90 | # spent 9µs within Foswiki::Logger::PlainFile::new which was called:
# once (9µs+0s) by Foswiki::logger at line 2385 of /var/www/foswikidev/core/lib/Foswiki.pm | ||||
91 | 1 | 600ns | my $class = shift; | ||
92 | 1 | 12µs | return bless( { acceptsHash => 1 }, $class ); | ||
93 | } | ||||
94 | |||||
95 | =begin TML | ||||
96 | |||||
97 | ---++ ObjectMethod log($level, @fields) | ||||
98 | |||||
99 | See Foswiki::Logger for the interface. | ||||
100 | |||||
101 | =cut | ||||
102 | |||||
103 | # spent 496µs (118+378) within Foswiki::Logger::PlainFile::log which was called:
# once (118µs+378µs) by Foswiki::UI::View::view at line 256 of /var/www/foswikidev/core/lib/Foswiki/UI/View.pm | ||||
104 | 1 | 300ns | my $this = shift; | ||
105 | 1 | 100ns | my $level; | ||
106 | 1 | 200ns | my @fields; | ||
107 | |||||
108 | # Native interface: Convert the hash back to list format | ||||
109 | 1 | 900ns | if ( ref( $_[0] ) eq 'HASH' ) { | ||
110 | 1 | 7µs | 1 | 86µs | ( $level, @fields ) = Foswiki::Logger::getOldCall(@_); # spent 86µs making 1 call to Foswiki::Logger::getOldCall |
111 | 1 | 400ns | return unless defined $level; | ||
112 | } | ||||
113 | else { | ||||
114 | ( $level, @fields ) = @_; | ||||
115 | } | ||||
116 | |||||
117 | 1 | 1µs | 1 | 4µs | my $now = _time(); # spent 4µs making 1 call to Foswiki::Logger::PlainFile::_time |
118 | 1 | 2µs | 1 | 26µs | my @logs = _getLogsForLevel( [$level] ); # spent 26µs making 1 call to Foswiki::Logger::PlainFile::_getLogsForLevel |
119 | 1 | 500ns | my $log = shift @logs; | ||
120 | 1 | 2µs | 1 | 133µs | _rotate( $LEVEL2LOG{$level}, $log, $now ); # spent 133µs making 1 call to Foswiki::Logger::PlainFile::_rotate |
121 | 1 | 3µs | 1 | 85µs | my $time = Foswiki::Time::formatTime( $now, 'iso', 'servertime' ); # spent 85µs making 1 call to Foswiki::Time::formatTime |
122 | |||||
123 | # Unfortunate compatibility requirement; need the level, but the old | ||||
124 | # logfile format doesn't allow us to add fields. Since we are changing | ||||
125 | # the date format anyway, the least pain is to concatenate the level | ||||
126 | # to the date; Foswiki::Time::ParseTime can handle it, and it looks | ||||
127 | # OK too. | ||||
128 | 1 | 2µs | unshift( @fields, "$time $level" ); | ||
129 | 6 | 1µs | my $message = | ||
130 | 7 | 6µs | '| ' . join( ' | ', map { s/\|/&vbar;/g; $_ } @fields ) . ' |'; | ||
131 | |||||
132 | 1 | 100ns | my $file; | ||
133 | 1 | 300ns | my $mode = '>>'; | ||
134 | |||||
135 | 1 | 18µs | if ( open( $file, $mode, $log ) ) { | ||
136 | 1 | 13µs | 3 | 26µs | binmode $file, ":encoding(utf-8)"; # spent 17µs making 1 call to Encode::find_encoding
# spent 9µs making 1 call to Encode::Encoding::renew
# spent 700ns making 1 call to Encode::Encoding::needs_lines |
137 | 1 | 1µs | 1 | 14µs | _lock($file); # spent 14µs making 1 call to Foswiki::Logger::PlainFile::_lock |
138 | 1 | 4µs | print $file "$message\n"; | ||
139 | 1 | 37µs | 1 | 3µs | close($file); # spent 3µs making 1 call to Encode::utf8::encode_xs |
140 | } | ||||
141 | elsif ( $Foswiki::cfg{isVALID} ) { | ||||
142 | |||||
143 | # Only whine if there is a known good configuration (in which case | ||||
144 | # $Foswiki::cfg{Log}{Dir} will be set sensibly) | ||||
145 | if ( !-w $log ) { | ||||
146 | die | ||||
147 | "ERROR: Could not open logfile $log for write. Your admin should 'configure' now and fix the errors!\n"; | ||||
148 | } | ||||
149 | |||||
150 | # die to force the admin to get permissions correct | ||||
151 | die 'ERROR: Could not write ' . $message . ' to ' . "$log: $!\n"; | ||||
152 | } | ||||
153 | 1 | 8µs | if ( $level =~ m/^(error|critical|alert|emergency)$/ ) { | ||
154 | print STDERR "$message\n"; | ||||
155 | } | ||||
156 | } | ||||
157 | |||||
158 | # spent 14µs within Foswiki::Logger::PlainFile::_lock which was called:
# once (14µs+0s) by Foswiki::Logger::PlainFile::log at line 137 | ||||
159 | 1 | 400ns | my $fh = shift; | ||
160 | 2 | 10µs | eval { flock( $fh, LOCK_EX ) }; # Ignore lock errors, not all platforms support flock | ||
161 | # Make sure we are at the EOF | ||||
162 | 1 | 2µs | seek( $fh, 0, 2 ); | ||
163 | 1 | 4µs | return 1; | ||
164 | } | ||||
165 | |||||
166 | =begin TML | ||||
167 | |||||
168 | ---++ ObjectMethod eachEventSince($time, \@levels, $version) -> $iterator | ||||
169 | * =$time= - a time in the past | ||||
170 | * =\@levels= - log levels to return events for. Individual level or array reference. | ||||
171 | * =$version= - Version 1 of API returns a hash instead of an array. | ||||
172 | |||||
173 | See Foswiki::Logger for the interface. | ||||
174 | |||||
175 | =cut | ||||
176 | |||||
177 | sub eachEventSince { | ||||
178 | my ( $this, $time, $level, $version ) = @_; | ||||
179 | |||||
180 | $level = ref $level ? $level : [$level]; | ||||
181 | |||||
182 | my @log4level = _getLogsForLevel($level); | ||||
183 | |||||
184 | # Find the year-month for the current time | ||||
185 | my $now = _time(); | ||||
186 | my $nowLogYear = Foswiki::Time::formatTime( $now, '$year', 'servertime' ); | ||||
187 | my $nowLogMonth = Foswiki::Time::formatTime( $now, '$mo', 'servertime' ); | ||||
188 | |||||
189 | # Find the year-month for the first time in the range | ||||
190 | my $logYear = Foswiki::Time::formatTime( $time, '$year', 'servertime' ); | ||||
191 | my $logMonth = Foswiki::Time::formatTime( $time, '$mo', 'servertime' ); | ||||
192 | |||||
193 | print STDERR "Scanning $logYear:$logMonth thru $nowLogYear:$nowLogMonth\n" | ||||
194 | if (TRACE); | ||||
195 | |||||
196 | # Convert the requested level into a regular expression for the scan | ||||
197 | my $reqLevel = join( '|', @$level ); | ||||
198 | $reqLevel = "(?:$reqLevel)"; | ||||
199 | |||||
200 | my @mergeIterators; | ||||
201 | |||||
202 | foreach my $log (@log4level) { | ||||
203 | |||||
204 | # Get the names of all the logfiles in the time range | ||||
205 | my @logs; | ||||
206 | while ( !( $logMonth == $nowLogMonth && $logYear == $nowLogYear ) ) { | ||||
207 | my $logfile = $log; | ||||
208 | my $logTime = $logYear . sprintf( "%02d", $logMonth ); | ||||
209 | |||||
210 | $logfile =~ s/\.log$/.$logTime/g; | ||||
211 | push( @logs, $logfile ); | ||||
212 | $logMonth++; | ||||
213 | if ( $logMonth == 13 ) { | ||||
214 | $logMonth = 1; | ||||
215 | $logYear++; | ||||
216 | } | ||||
217 | } | ||||
218 | |||||
219 | # Finally the current log | ||||
220 | push( @logs, $log ); | ||||
221 | |||||
222 | my @iterators; | ||||
223 | foreach my $logfile (@logs) { | ||||
224 | next unless -r $logfile; | ||||
225 | |||||
226 | my $fh; | ||||
227 | if ( open( $fh, '<:encoding(utf-8)', $logfile ) ) { | ||||
228 | my $logIt = | ||||
229 | new Foswiki::Logger::PlainFile::EventIterator( $fh, $time, | ||||
230 | $reqLevel, $version, $logfile ); | ||||
231 | $logIt->{logLocked} = | ||||
232 | eval { flock( $fh, LOCK_SH ) }; # No error in case on non-flockable FS; eval in case flock not supported. | ||||
233 | # print STDERR " pushed iterator for $reqLevel \n"; | ||||
234 | push( @iterators, $logIt ); | ||||
235 | } | ||||
236 | else { | ||||
237 | |||||
238 | # Would be nice to report this, but it's chicken and egg and | ||||
239 | # besides, empty logfiles can happen. | ||||
240 | print STDERR "Failed to open $logfile: $!" if (TRACE); | ||||
241 | } | ||||
242 | } | ||||
243 | |||||
244 | push @mergeIterators, | ||||
245 | new Foswiki::Iterator::AggregateEventIterator( \@iterators ); | ||||
246 | } | ||||
247 | |||||
248 | if (TRACE) { | ||||
249 | require Data::Dumper; | ||||
250 | print STDERR "Merge built for \@mergeIterators " | ||||
251 | . Data::Dumper::Dumper( \@mergeIterators ); | ||||
252 | } | ||||
253 | |||||
254 | return new Foswiki::Iterator::MergeEventIterator( \@mergeIterators ); | ||||
255 | } | ||||
256 | |||||
257 | # Get the name of the log for a given reporting level | ||||
258 | # spent 26µs (12+14) within Foswiki::Logger::PlainFile::_getLogsForLevel which was called:
# once (12µs+14µs) by Foswiki::Logger::PlainFile::log at line 118 | ||||
259 | 1 | 300ns | my $level = shift; | ||
260 | 1 | 200ns | my %logs; | ||
261 | |||||
262 | 1 | 700ns | foreach my $lvl (@$level) { | ||
263 | ASSERT( defined $LEVEL2LOG{$lvl} ) if DEBUG; | ||||
264 | 1 | 2µs | my $log = $Foswiki::cfg{Log}{Dir} . '/' . $LEVEL2LOG{$lvl} . '.log'; | ||
265 | |||||
266 | # SMELL: Expand should not be needed, except if bin/configure tries | ||||
267 | # to log to locations relative to $Foswiki::cfg{WorkingDir}, DataDir, etc. | ||||
268 | # Windows seemed to be the most difficult to fix - this was the only thing | ||||
269 | # that I could find that worked all the time. | ||||
270 | 1 | 2µs | 1 | 14µs | Foswiki::Configure::Load::expandValue($log); # spent 14µs making 1 call to Foswiki::Configure::Load::expandValue |
271 | 1 | 2µs | $logs{$log} = 1; | ||
272 | } | ||||
273 | |||||
274 | 1 | 5µs | return ( keys %logs ); | ||
275 | } | ||||
276 | |||||
277 | sub _time2month { | ||||
278 | 2 | 500ns | my $time = shift; | ||
279 | 2 | 300ns | return undef unless ( defined $time ); | ||
280 | 2 | 23µs | my @t = localtime($time); | ||
281 | 2 | 1µs | $t[5] += 1900; | ||
282 | 2 | 12µs | return sprintf( '%0.4d%0.2d', $t[5], $t[4] + 1 ); | ||
283 | } | ||||
284 | |||||
285 | # See if the log needs to be rotated. If the log was last modified | ||||
286 | # last month, we need to rotate it. | ||||
287 | # spent 133µs (36+97) within Foswiki::Logger::PlainFile::_rotate which was called:
# once (36µs+97µs) by Foswiki::Logger::PlainFile::log at line 120 | ||||
288 | 1 | 700ns | my ( $level, $log, $now ) = @_; | ||
289 | |||||
290 | 1 | 100ns | return if $dontRotate; | ||
291 | 1 | 100ns | return unless $level; | ||
292 | |||||
293 | # Don't bother checking if we have checked in this process already | ||||
294 | 1 | 400ns | return if ( $now < $nextCheckDue{$level} ); | ||
295 | |||||
296 | # Work out the current month | ||||
297 | 1 | 1µs | 1 | 21µs | my $curMonth = _time2month($now); # spent 21µs making 1 call to Foswiki::Logger::PlainFile::_time2month |
298 | print STDERR "Current MONTH = $curMonth\n" if (TRACE); | ||||
299 | |||||
300 | # After this check, don't check again for a month. | ||||
301 | 1 | 3µs | $curMonth =~ m/(\d{4})(\d{2})/; | ||
302 | 1 | 3µs | my ( $y, $m ) = ( $1, $2 + 1 ); | ||
303 | 1 | 700ns | if ( $m > 12 ) { | ||
304 | $m = '01'; | ||||
305 | $y++; | ||||
306 | } | ||||
307 | else { | ||||
308 | 1 | 1µs | $m = sprintf( '%0.2d', $m ); | ||
309 | } | ||||
310 | 1 | 3µs | 1 | 63µs | $nextCheckDue{$level} = Foswiki::Time::parseTime("$y-$m-01"); # spent 63µs making 1 call to Foswiki::Time::parseTime |
311 | print STDERR "Next log check due $nextCheckDue{$level} for $level\n" | ||||
312 | if (TRACE); | ||||
313 | |||||
314 | # If there's no existing log, there's nothing to rotate | ||||
315 | 1 | 5µs | return unless -e $log; | ||
316 | |||||
317 | # Check when the log was last modified. If it was in the previous | ||||
318 | # month, if may need to be rotated. | ||||
319 | 1 | 3µs | 1 | 3µs | my @stat = _stat($log); # spent 3µs making 1 call to Foswiki::Logger::PlainFile::_stat |
320 | 1 | 2µs | 1 | 10µs | my $modMonth = _time2month( $stat[9] ); # spent 10µs making 1 call to Foswiki::Logger::PlainFile::_time2month |
321 | print STDERR "compare $modMonth, $curMonth\n" if (TRACE); | ||||
322 | 1 | 4µs | return if ( $modMonth == $curMonth ); | ||
323 | |||||
324 | my $lockfile; | ||||
325 | unless ( open( $lockfile, '>', $log . 'LOCK' ) ) { | ||||
326 | print STDERR "ERROR: PlainFile Logger could not open $log.LOCK: $! \n"; | ||||
327 | return; | ||||
328 | } | ||||
329 | flock( $lockfile, LOCK_EX ); | ||||
330 | |||||
331 | my $newname = $log; | ||||
332 | $newname =~ s/log$/$modMonth/; | ||||
333 | print STDERR "Renaming from $log to $newname \n" if (TRACE); | ||||
334 | |||||
335 | unless ( -e $newname ) { | ||||
336 | open( my $lf, '>>', $log ); | ||||
337 | _lock($lf); | ||||
338 | rename $log, $newname; | ||||
339 | close($lf); | ||||
340 | unlink $log . 'LOCK'; | ||||
341 | } | ||||
342 | else { | ||||
343 | print STDERR "ROTATE SKIPPED - prior log ($log) exists\n"; | ||||
344 | unlink $log . 'LOCK'; | ||||
345 | } | ||||
346 | |||||
347 | } | ||||
348 | |||||
349 | 1 | 6µs | 1; | ||
350 | __END__ |