Filename | /var/www/foswikidev/core/lib/Foswiki/Logger.pm |
Statements | Executed 44 statements in 965µs |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 27µs | 86µs | getOldCall | Foswiki::Logger::
1 | 1 | 1 | 24µs | 59µs | setCommonFields | Foswiki::Logger::
1 | 1 | 1 | 12µs | 26µs | BEGIN@4 | Foswiki::Logger::
1 | 1 | 1 | 12µs | 16µs | BEGIN@5 | Foswiki::Logger::
1 | 1 | 1 | 9µs | 33µs | BEGIN@7 | Foswiki::Logger::
1 | 1 | 1 | 4µs | 4µs | BEGIN@9 | Foswiki::Logger::
1 | 1 | 1 | 3µs | 3µs | finish | Foswiki::Logger::
0 | 0 | 0 | 0s | 0s | alert | Foswiki::Logger::
0 | 0 | 0 | 0s | 0s | critical | Foswiki::Logger::
0 | 0 | 0 | 0s | 0s | debug | Foswiki::Logger::
0 | 0 | 0 | 0s | 0s | eachEventSince | Foswiki::Logger::
0 | 0 | 0 | 0s | 0s | emergency | Foswiki::Logger::
0 | 0 | 0 | 0s | 0s | error | Foswiki::Logger::
0 | 0 | 0 | 0s | 0s | info | Foswiki::Logger::
0 | 0 | 0 | 0s | 0s | log | Foswiki::Logger::
0 | 0 | 0 | 0s | 0s | new | Foswiki::Logger::
0 | 0 | 0 | 0s | 0s | notice | Foswiki::Logger::
0 | 0 | 0 | 0s | 0s | warn | Foswiki::Logger::
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; | ||||
3 | |||||
4 | 2 | 26µs | 2 | 39µs | # spent 26µs (12+14) within Foswiki::Logger::BEGIN@4 which was called:
# once (12µs+14µs) by Foswiki::BEGIN@641 at line 4 # spent 26µs making 1 call to Foswiki::Logger::BEGIN@4
# spent 14µs making 1 call to strict::import |
5 | 2 | 25µs | 2 | 20µs | # spent 16µs (12+4) within Foswiki::Logger::BEGIN@5 which was called:
# once (12µs+4µs) by Foswiki::BEGIN@641 at line 5 # spent 16µs making 1 call to Foswiki::Logger::BEGIN@5
# spent 4µs making 1 call to warnings::import |
6 | |||||
7 | 2 | 44µs | 2 | 57µs | # spent 33µs (9+24) within Foswiki::Logger::BEGIN@7 which was called:
# once (9µs+24µs) by Foswiki::BEGIN@641 at line 7 # spent 33µs making 1 call to Foswiki::Logger::BEGIN@7
# spent 24µs making 1 call to Exporter::import |
8 | |||||
9 | # spent 4µs within Foswiki::Logger::BEGIN@9 which was called:
# once (4µs+0s) by Foswiki::BEGIN@641 at line 14 | ||||
10 | 1 | 4µs | if ( $Foswiki::cfg{UseLocale} ) { | ||
11 | require locale; | ||||
12 | import locale(); | ||||
13 | } | ||||
14 | 1 | 810µs | 1 | 4µs | } # spent 4µs making 1 call to Foswiki::Logger::BEGIN@9 |
15 | |||||
16 | =begin TML | ||||
17 | |||||
18 | ---+ package Foswiki::Logger | ||||
19 | |||||
20 | Object that interfaces to whatever records Foswiki log files. | ||||
21 | |||||
22 | This is a base class which will be subclassed by a class in the | ||||
23 | Logger subdirectory and selected by $Foswiki::cfg{Log}{Implementation} | ||||
24 | |||||
25 | Note that the implementation has to provide a way for the log to be replayed. | ||||
26 | Unfortunately this means that the simpler CPAN loggers are not suitable. | ||||
27 | |||||
28 | =cut | ||||
29 | |||||
30 | sub new { | ||||
31 | return bless( {}, shift ); | ||||
32 | } | ||||
33 | |||||
34 | =begin TML | ||||
35 | |||||
36 | ---++ ObjectMethod finish() | ||||
37 | Release memory. Subclasses must implement this if they use any fields | ||||
38 | in the object. | ||||
39 | |||||
40 | =cut | ||||
41 | |||||
42 | # spent 3µs within Foswiki::Logger::finish which was called:
# once (3µs+0s) by Foswiki::finish at line 2488 of /var/www/foswikidev/core/lib/Foswiki.pm | ||||
43 | 1 | 6µs | my $this = shift; | ||
44 | } | ||||
45 | |||||
46 | =begin TML | ||||
47 | |||||
48 | ---++ ObjectMethod =log($level, @fields)= or =log( { param => 'value', } )= | ||||
49 | |||||
50 | Adds a log message to a log. | ||||
51 | |||||
52 | ---+++ Compatibility interface: | ||||
53 | <verbatim> | ||||
54 | $this->logger->log( 'info', $user, $action, $webTopic, $message, $remoteAddr ); | ||||
55 | $this->logger->log( 'warning', $mess ); | ||||
56 | $this->logger->log( 'debug', $mess ); | ||||
57 | </verbatim> | ||||
58 | |||||
59 | ---+++ Native interface: | ||||
60 | <verbatim> | ||||
61 | $this->logger->log( { level => 'info', | ||||
62 | user => $user, | ||||
63 | action => $action, | ||||
64 | webTopic => $webTopic, | ||||
65 | extra => $message, | ||||
66 | remoteAddr => $remoteAddr } ); | ||||
67 | |||||
68 | $this->logger->log( { level => 'warning', | ||||
69 | caller => $caller, | ||||
70 | fields => \@fields } ); | ||||
71 | |||||
72 | $this->logger->log( { level => 'debug', | ||||
73 | fields => \@fields } ); | ||||
74 | </verbatim> | ||||
75 | |||||
76 | Fields recorded for info messages are generally fixed. Any levels other than info | ||||
77 | can be called with an array of additional fields to log. | ||||
78 | |||||
79 | * =$level= - level of the event - one of =debug=, =info=, | ||||
80 | =warning=, =error=, =critical=, =alert=, =emergency=. | ||||
81 | * =@fields= - an arbitrary list of fields to output to the log. | ||||
82 | These fields are recoverable when the log is enumerated using the | ||||
83 | =eachEventSince= method. | ||||
84 | |||||
85 | The levels are chosen to be compatible with Log::Dispatch. | ||||
86 | |||||
87 | =cut | ||||
88 | |||||
89 | # Default behaviour is a NOP | ||||
90 | sub log { | ||||
91 | } | ||||
92 | |||||
93 | =begin TML | ||||
94 | |||||
95 | ---++ StaticMethod eachEventSince($time, \@levels, $api) -> $iterator | ||||
96 | * =$time= - a time in the past | ||||
97 | * =\@levels= - log levels to return events for. | ||||
98 | * API version. If true, return hash name => value, otherwise return fixed list | ||||
99 | |||||
100 | Get an iterator over the list of all the events at the given level(s) | ||||
101 | between =$time= and now. | ||||
102 | |||||
103 | Events are returned in *oldest-first* order. | ||||
104 | |||||
105 | Each event is returned as a reference to an array. The first element | ||||
106 | of this array is always the date of the event (seconds since the epoch). | ||||
107 | Subsequent elements are the fields passed to =log=. | ||||
108 | |||||
109 | Note that a log implementation may choose to collapse several log levels | ||||
110 | into a single log. In this case, all messages in the same set as the | ||||
111 | requested level will be returned if any of the collapsed levels is selected. | ||||
112 | |||||
113 | =cut | ||||
114 | |||||
115 | # Default behaviour is an empty iteration | ||||
116 | sub eachEventSince { | ||||
117 | require Foswiki::ListIterator; | ||||
118 | return new Foswiki::ListIterator( [] ); | ||||
119 | } | ||||
120 | |||||
121 | =begin TML | ||||
122 | |||||
123 | ---++ ClassMethod setCommonFields( \%fhash ) | ||||
124 | * =%fhash= - Hashref of fields to be logged. | ||||
125 | |||||
126 | This routine assigns values to some common fields that are useful in logs. | ||||
127 | |||||
128 | In the older Logging API, these were only provided by the Foswiki::writeEvent() | ||||
129 | method for "info" level events. | ||||
130 | |||||
131 | | =$fhash->{agent}= | The user agent | | ||||
132 | | =$fhash->{timestamp}= | The time of the event | | ||||
133 | | =$fhash->{user}= | The logged in user, if any | | ||||
134 | | =$fhash->{webTopic}= | The current topic | | ||||
135 | | =$fhash->{remoteAddr}= | Remote IP Address | | ||||
136 | |||||
137 | =cut | ||||
138 | |||||
139 | # spent 59µs (24+34) within Foswiki::Logger::setCommonFields which was called:
# once (24µs+34µs) by Foswiki::Logger::getOldCall at line 218 | ||||
140 | |||||
141 | # my $fhash = shift | ||||
142 | 1 | 2µs | my $user = $_[0]->{user} || $Foswiki::Plugins::SESSION->{user}; | ||
143 | 1 | 500ns | my $users = $Foswiki::Plugins::SESSION->{users}; | ||
144 | 1 | 200ns | my $login; | ||
145 | 1 | 2µs | 1 | 3µs | $login = $users->getLoginName($user) if ($users); # spent 3µs making 1 call to Foswiki::Users::getLoginName |
146 | 1 | 900ns | $_[0]->{user} = $login if $login; | ||
147 | |||||
148 | 1 | 2µs | unless ( defined $_[0]->{agent} ) { | ||
149 | 1 | 500ns | my $agent = ''; | ||
150 | 1 | 300ns | my $cgiQuery = $Foswiki::Plugins::SESSION->{request}; | ||
151 | 1 | 400ns | if ($cgiQuery) { | ||
152 | 1 | 3µs | 1 | 28µs | my $agentStr = $cgiQuery->user_agent(); # spent 28µs making 1 call to Foswiki::Request::userAgent |
153 | 1 | 500ns | if ($agentStr) { | ||
154 | if ( $agentStr =~ | ||||
155 | m/(MSIE 6|MSIE 7|MSIE 8|MSI 9|Firefox|Opera|Konqueror|Chrome|Safari)/ | ||||
156 | ) | ||||
157 | { | ||||
158 | $_[0]->{agent} = $1; | ||||
159 | } | ||||
160 | else { | ||||
161 | $agentStr =~ m/([\w]+)/; | ||||
162 | $_[0]->{agent} = $1; | ||||
163 | } | ||||
164 | } | ||||
165 | } | ||||
166 | } | ||||
167 | |||||
168 | 1 | 6µs | 1 | 4µs | unless ( defined $_[0]->{remoteAddr} ) { # spent 4µs making 1 call to Foswiki::Request::remoteAddress |
169 | $_[0]->{remoteAddr} = | ||||
170 | $Foswiki::Plugins::SESSION->{request}->remoteAddress() || '' | ||||
171 | if ( defined $Foswiki::Plugins::SESSION->{request} ); | ||||
172 | } | ||||
173 | |||||
174 | 1 | 800ns | unless ( defined $_[0]->{webTopic} ) { | ||
175 | my $webTopic = $Foswiki::Plugins::SESSION->{webName} || ''; | ||||
176 | $webTopic .= '.' if ($webTopic); | ||||
177 | $webTopic .= $Foswiki::Plugins::SESSION->{topicName} || ''; | ||||
178 | $_[0]->{webTopic} = $webTopic || ''; | ||||
179 | } | ||||
180 | |||||
181 | 1 | 4µs | return; | ||
182 | |||||
183 | } | ||||
184 | |||||
185 | =begin TML | ||||
186 | |||||
187 | ---++ ClassMethod getOldCall( \%fhash ) | ||||
188 | * =%fhash= - Hashref of fields to be logged. | ||||
189 | |||||
190 | This utility routine converts the new style hash calling convention into | ||||
191 | the older parameter list calling convention. Use it in an old logger | ||||
192 | to work with the new style calls in Foswiki 2. | ||||
193 | |||||
194 | In Foswiki 1.1 and earlier, event logs were "filtered" by the core. With Foswiki 2, | ||||
195 | the logger is responsible for filtering. This routine implements the 1.1 filter and | ||||
196 | returns undef if the record should not be logged. | ||||
197 | |||||
198 | <verbatim> | ||||
199 | my $level; | ||||
200 | my @fields; | ||||
201 | |||||
202 | # Native interface: Convert the hash back to list format | ||||
203 | if ( ref( $_[0] ) eq 'HASH' ) { | ||||
204 | ($level, @fields) = Foswiki::Logger::getOldCall(@_); | ||||
205 | return unless defined $level; | ||||
206 | } | ||||
207 | else { | ||||
208 | ( $level, @fields ) = @_; | ||||
209 | } | ||||
210 | </verbatim> | ||||
211 | |||||
212 | =cut | ||||
213 | |||||
214 | # spent 86µs (27+59) within Foswiki::Logger::getOldCall which was called:
# once (27µs+59µs) by Foswiki::Logger::PlainFile::log at line 110 of /var/www/foswikidev/core/lib/Foswiki/Logger/PlainFile.pm | ||||
215 | 1 | 800ns | my $fhash = shift; | ||
216 | 1 | 200ns | my @fields; | ||
217 | |||||
218 | 1 | 2µs | 1 | 59µs | Foswiki::Logger::setCommonFields($fhash); # spent 59µs making 1 call to Foswiki::Logger::setCommonFields |
219 | 1 | 800ns | my $level = $fhash->{level}; | ||
220 | 1 | 1µs | delete $fhash->{level}; | ||
221 | 1 | 700ns | if ( $level eq 'info' ) { | ||
222 | |||||
223 | # Implement the core event filter | ||||
224 | return undef | ||||
225 | 1 | 3µs | if ( defined $fhash->{action} | ||
226 | && defined $Foswiki::cfg{Log}{Action}{ $fhash->{action} } | ||||
227 | && !$Foswiki::cfg{Log}{Action}{ $fhash->{action} } ); | ||||
228 | |||||
229 | 1 | 2µs | foreach my $key (qw( user action webTopic )) { | ||
230 | 3 | 2µs | push( @fields, $fhash->{$key} || '' ); | ||
231 | 3 | 2µs | delete $fhash->{$key}; | ||
232 | } | ||||
233 | |||||
234 | # The original writeEvent appended the agent to the extra field | ||||
235 | # New version will append agent and any other unaccounted for fields | ||||
236 | 1 | 1µs | my $extra = $fhash->{extra} || ''; | ||
237 | 1 | 600ns | delete $fhash->{extra}; | ||
238 | 1 | 4µs | foreach my $key ( sort keys %$fhash ) { | ||
239 | 1 | 1µs | next if $key eq 'remoteAddr'; | ||
240 | $extra .= " $fhash->{$key}"; | ||||
241 | } | ||||
242 | 1 | 600ns | push( @fields, $extra ); | ||
243 | 1 | 900ns | push( @fields, $fhash->{remoteAddr} || '' ); | ||
244 | } | ||||
245 | elsif ( $level eq 'notice' ) { # Configuration changes logged as notice | ||||
246 | foreach my $key (qw( user remoteAddr setting oldvalue newvalue)) { | ||||
247 | push( @fields, $fhash->{$key} || '' ); | ||||
248 | delete $fhash->{$key}; | ||||
249 | } | ||||
250 | } | ||||
251 | else { | ||||
252 | push( @fields, $fhash->{caller} ) if defined $fhash->{caller}; | ||||
253 | push( @fields, @{ $fhash->{extra} } ) if defined $fhash->{extra}; | ||||
254 | } | ||||
255 | |||||
256 | 1 | 5µs | return ( $level, @fields ); | ||
257 | } | ||||
258 | |||||
259 | =begin TML | ||||
260 | |||||
261 | ---++ Log4Perl compatibility methods | ||||
262 | |||||
263 | These methods implement the simple Log4Perl methods, for example | ||||
264 | =$this->logger->error('Some failure'); | ||||
265 | |||||
266 | ---+++ ObjectMethod debug( $message ) | ||||
267 | |||||
268 | Equivalent to log( 'debug', $message ) | ||||
269 | |||||
270 | =cut | ||||
271 | |||||
272 | sub debug { | ||||
273 | my $this = shift; | ||||
274 | $this->log( 'debug', @_ ); | ||||
275 | } | ||||
276 | |||||
277 | =begin TML | ||||
278 | |||||
279 | ---+++ ObjectMethod info( $message ) | ||||
280 | |||||
281 | Equivalent to log( 'info', $message ) | ||||
282 | |||||
283 | =cut | ||||
284 | |||||
285 | sub info { | ||||
286 | my $this = shift; | ||||
287 | $this->log( 'info', @_ ); | ||||
288 | } | ||||
289 | |||||
290 | =begin TML | ||||
291 | |||||
292 | ---+++ ObjectMethod notice( $message ) | ||||
293 | |||||
294 | Equivalent to log( 'notice', $message ) | ||||
295 | |||||
296 | =cut | ||||
297 | |||||
298 | sub notice { | ||||
299 | my $this = shift; | ||||
300 | $this->log( 'notice', @_ ); | ||||
301 | } | ||||
302 | |||||
303 | =begin TML | ||||
304 | |||||
305 | ---+++ ObjectMethod warn( $message ) | ||||
306 | |||||
307 | Equivalent to log( 'warn', $message ) | ||||
308 | |||||
309 | =cut | ||||
310 | |||||
311 | sub warn { | ||||
312 | my $this = shift; | ||||
313 | $this->log( 'warning', @_ ); | ||||
314 | } | ||||
315 | |||||
316 | =begin TML | ||||
317 | |||||
318 | ---+++ ObjectMethod error( $message ) | ||||
319 | |||||
320 | Equivalent to log( 'error', $message ) | ||||
321 | |||||
322 | =cut | ||||
323 | |||||
324 | sub error { | ||||
325 | my $this = shift; | ||||
326 | $this->log( 'error', @_ ); | ||||
327 | } | ||||
328 | |||||
329 | =begin TML | ||||
330 | |||||
331 | ---+++ ObjectMethod critical( $message ) | ||||
332 | |||||
333 | Equivalent to log( 'critical', $message ) | ||||
334 | |||||
335 | =cut | ||||
336 | |||||
337 | sub critical { | ||||
338 | my $this = shift; | ||||
339 | $this->log( 'critical', @_ ); | ||||
340 | } | ||||
341 | |||||
342 | =begin TML | ||||
343 | |||||
344 | ---+++ ObjectMethod alert( $message ) | ||||
345 | |||||
346 | Equivalent to log( 'alert', $message ) | ||||
347 | |||||
348 | =cut | ||||
349 | |||||
350 | sub alert { | ||||
351 | my $this = shift; | ||||
352 | $this->log( 'alert', @_ ); | ||||
353 | } | ||||
354 | |||||
355 | =begin TML | ||||
356 | |||||
357 | ---+++ ObjectMethod emergency( $message ) | ||||
358 | |||||
359 | Equivalent to log( 'emergency', $message ). | ||||
360 | |||||
361 | =cut | ||||
362 | |||||
363 | sub emergency { | ||||
364 | my $this = shift; | ||||
365 | $this->log( 'emergency', @_ ); | ||||
366 | } | ||||
367 | |||||
368 | 1 | 2µs | 1; | ||
369 | __END__ |