1 <?php |
|
2 /** |
|
3 * Licensed to the Apache Software Foundation (ASF) under one or more |
|
4 * contributor license agreements. See the NOTICE file distributed with |
|
5 * this work for additional information regarding copyright ownership. |
|
6 * The ASF licenses this file to You under the Apache License, Version 2.0 |
|
7 * (the "License"); you may not use this file except in compliance with |
|
8 * the License. You may obtain a copy of the License at |
|
9 * |
|
10 * http://www.apache.org/licenses/LICENSE-2.0 |
|
11 * |
|
12 * Unless required by applicable law or agreed to in writing, software |
|
13 * distributed under the License is distributed on an "AS IS" BASIS, |
|
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
15 * See the License for the specific language governing permissions and |
|
16 * limitations under the License. |
|
17 * |
|
18 * @package log4php |
|
19 */ |
|
20 |
|
21 require dirname(__FILE__) . '/LoggerAutoloader.php'; |
|
22 |
|
23 /** |
|
24 * This is the central class in the log4php package. All logging operations |
|
25 * are done through this class. |
|
26 * |
|
27 * The main logging methods are: |
|
28 * <ul> |
|
29 * <li>{@link trace()}</li> |
|
30 * <li>{@link debug()}</li> |
|
31 * <li>{@link info()}</li> |
|
32 * <li>{@link warn()}</li> |
|
33 * <li>{@link error()}</li> |
|
34 * <li>{@link fatal()}</li> |
|
35 * </ul> |
|
36 * |
|
37 * @package log4php |
|
38 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 |
|
39 * @version SVN: $Id: Logger.php 1395241 2012-10-07 08:28:53Z ihabunek $ |
|
40 * @link http://logging.apache.org/log4php |
|
41 */ |
|
42 class Logger { |
|
43 |
|
44 /** |
|
45 * Logger additivity. If set to true then child loggers will inherit |
|
46 * the appenders of their ancestors by default. |
|
47 * @var boolean |
|
48 */ |
|
49 private $additive = true; |
|
50 |
|
51 /** |
|
52 * The Logger's fully qualified class name. |
|
53 * TODO: Determine if this is useful. |
|
54 */ |
|
55 private $fqcn = 'Logger'; |
|
56 |
|
57 /** The assigned Logger level. */ |
|
58 private $level; |
|
59 |
|
60 /** The name of this Logger instance. */ |
|
61 private $name; |
|
62 |
|
63 /** The parent logger. Set to null if this is the root logger. */ |
|
64 private $parent; |
|
65 |
|
66 /** A collection of appenders linked to this logger. */ |
|
67 private $appenders = array(); |
|
68 |
|
69 /** |
|
70 * Constructor. |
|
71 * @param string $name Name of the logger. |
|
72 */ |
|
73 public function __construct($name) { |
|
74 $this->name = $name; |
|
75 } |
|
76 |
|
77 /** |
|
78 * Returns the logger name. |
|
79 * @return string |
|
80 */ |
|
81 public function getName() { |
|
82 return $this->name; |
|
83 } |
|
84 |
|
85 /** |
|
86 * Returns the parent Logger. Can be null if this is the root logger. |
|
87 * @return Logger |
|
88 */ |
|
89 public function getParent() { |
|
90 return $this->parent; |
|
91 } |
|
92 |
|
93 // ****************************************** |
|
94 // *** Logging methods *** |
|
95 // ****************************************** |
|
96 |
|
97 /** |
|
98 * Log a message object with the TRACE level. |
|
99 * |
|
100 * @param mixed $message message |
|
101 * @param Exception $throwable Optional throwable information to include |
|
102 * in the logging event. |
|
103 */ |
|
104 public function trace($message, $throwable = null) { |
|
105 $this->log(LoggerLevel::getLevelTrace(), $message, $throwable); |
|
106 } |
|
107 |
|
108 /** |
|
109 * Log a message object with the DEBUG level. |
|
110 * |
|
111 * @param mixed $message message |
|
112 * @param Exception $throwable Optional throwable information to include |
|
113 * in the logging event. |
|
114 */ |
|
115 public function debug($message, $throwable = null) { |
|
116 $this->log(LoggerLevel::getLevelDebug(), $message, $throwable); |
|
117 } |
|
118 |
|
119 /** |
|
120 * Log a message object with the INFO Level. |
|
121 * |
|
122 * @param mixed $message message |
|
123 * @param Exception $throwable Optional throwable information to include |
|
124 * in the logging event. |
|
125 */ |
|
126 public function info($message, $throwable = null) { |
|
127 $this->log(LoggerLevel::getLevelInfo(), $message, $throwable); |
|
128 } |
|
129 |
|
130 /** |
|
131 * Log a message with the WARN level. |
|
132 * |
|
133 * @param mixed $message message |
|
134 * @param Exception $throwable Optional throwable information to include |
|
135 * in the logging event. |
|
136 */ |
|
137 public function warn($message, $throwable = null) { |
|
138 $this->log(LoggerLevel::getLevelWarn(), $message, $throwable); |
|
139 } |
|
140 |
|
141 /** |
|
142 * Log a message object with the ERROR level. |
|
143 * |
|
144 * @param mixed $message message |
|
145 * @param Exception $throwable Optional throwable information to include |
|
146 * in the logging event. |
|
147 */ |
|
148 public function error($message, $throwable = null) { |
|
149 $this->log(LoggerLevel::getLevelError(), $message, $throwable); |
|
150 } |
|
151 |
|
152 /** |
|
153 * Log a message object with the FATAL level. |
|
154 * |
|
155 * @param mixed $message message |
|
156 * @param Exception $throwable Optional throwable information to include |
|
157 * in the logging event. |
|
158 */ |
|
159 public function fatal($message, $throwable = null) { |
|
160 $this->log(LoggerLevel::getLevelFatal(), $message, $throwable); |
|
161 } |
|
162 |
|
163 /** |
|
164 * Log a message using the provided logging level. |
|
165 * |
|
166 * @param LoggerLevel $level The logging level. |
|
167 * @param mixed $message Message to log. |
|
168 * @param Exception $throwable Optional throwable information to include |
|
169 * in the logging event. |
|
170 */ |
|
171 public function log(LoggerLevel $level, $message, $throwable = null) { |
|
172 if ($this->isEnabledFor($level)) { |
|
173 $event = new LoggerLoggingEvent($this->fqcn, $this, $level, $message, null, $throwable); |
|
174 $this->callAppenders($event); |
|
175 } |
|
176 |
|
177 // Forward the event upstream if additivity is turned on |
|
178 if (isset($this->parent) && $this->getAdditivity()) { |
|
179 |
|
180 // Use the event if already created |
|
181 if (isset($event)) { |
|
182 $this->parent->logEvent($event); |
|
183 } else { |
|
184 $this->parent->log($level, $message, $throwable); |
|
185 } |
|
186 } |
|
187 } |
|
188 |
|
189 /** |
|
190 * Logs an already prepared logging event object. |
|
191 * @param LoggerLoggingEvent $event |
|
192 */ |
|
193 public function logEvent(LoggerLoggingEvent $event) { |
|
194 if ($this->isEnabledFor($event->getLevel())) { |
|
195 $this->callAppenders($event); |
|
196 } |
|
197 |
|
198 // Forward the event upstream if additivity is turned on |
|
199 if (isset($this->parent) && $this->getAdditivity()) { |
|
200 $this->parent->logEvent($event); |
|
201 } |
|
202 } |
|
203 |
|
204 /** |
|
205 * If assertion parameter evaluates as false, then logs the message |
|
206 * using the ERROR level. |
|
207 * |
|
208 * @param bool $assertion |
|
209 * @param string $msg message to log |
|
210 */ |
|
211 public function assertLog($assertion = true, $msg = '') { |
|
212 if ($assertion == false) { |
|
213 $this->error($msg); |
|
214 } |
|
215 } |
|
216 |
|
217 /** |
|
218 * This method creates a new logging event and logs the event without |
|
219 * further checks. |
|
220 * |
|
221 * It should not be called directly. Use {@link trace()}, {@link debug()}, |
|
222 * {@link info()}, {@link warn()}, {@link error()} and {@link fatal()} |
|
223 * wrappers. |
|
224 * |
|
225 * @param string $fqcn Fully qualified class name of the Logger |
|
226 * @param Exception $throwable Optional throwable information to include |
|
227 * in the logging event. |
|
228 * @param LoggerLevel $level log level |
|
229 * @param mixed $message message to log |
|
230 */ |
|
231 public function forcedLog($fqcn, $throwable, LoggerLevel $level, $message) { |
|
232 $event = new LoggerLoggingEvent($fqcn, $this, $level, $message, null, $throwable); |
|
233 $this->callAppenders($event); |
|
234 |
|
235 // Forward the event upstream if additivity is turned on |
|
236 if (isset($this->parent) && $this->getAdditivity()) { |
|
237 $this->parent->logEvent($event); |
|
238 } |
|
239 } |
|
240 |
|
241 /** |
|
242 * Forwards the given logging event to all linked appenders. |
|
243 * @param LoggerLoggingEvent $event |
|
244 */ |
|
245 public function callAppenders($event) { |
|
246 foreach ($this->appenders as $appender) { |
|
247 $appender->doAppend($event); |
|
248 } |
|
249 } |
|
250 |
|
251 // ****************************************** |
|
252 // *** Checker methods *** |
|
253 // ****************************************** |
|
254 |
|
255 /** |
|
256 * Check whether this Logger is enabled for a given Level passed as parameter. |
|
257 * |
|
258 * @param LoggerLevel level |
|
259 * @return boolean |
|
260 */ |
|
261 public function isEnabledFor(LoggerLevel $level) { |
|
262 return $level->isGreaterOrEqual($this->getEffectiveLevel()); |
|
263 } |
|
264 |
|
265 /** |
|
266 * Check whether this Logger is enabled for the TRACE Level. |
|
267 * @return boolean |
|
268 */ |
|
269 public function isTraceEnabled() { |
|
270 return $this->isEnabledFor(LoggerLevel::getLevelTrace()); |
|
271 } |
|
272 |
|
273 /** |
|
274 * Check whether this Logger is enabled for the DEBUG Level. |
|
275 * @return boolean |
|
276 */ |
|
277 public function isDebugEnabled() { |
|
278 return $this->isEnabledFor(LoggerLevel::getLevelDebug()); |
|
279 } |
|
280 |
|
281 /** |
|
282 * Check whether this Logger is enabled for the INFO Level. |
|
283 * @return boolean |
|
284 */ |
|
285 public function isInfoEnabled() { |
|
286 return $this->isEnabledFor(LoggerLevel::getLevelInfo()); |
|
287 } |
|
288 |
|
289 /** |
|
290 * Check whether this Logger is enabled for the WARN Level. |
|
291 * @return boolean |
|
292 */ |
|
293 public function isWarnEnabled() { |
|
294 return $this->isEnabledFor(LoggerLevel::getLevelWarn()); |
|
295 } |
|
296 |
|
297 /** |
|
298 * Check whether this Logger is enabled for the ERROR Level. |
|
299 * @return boolean |
|
300 */ |
|
301 public function isErrorEnabled() { |
|
302 return $this->isEnabledFor(LoggerLevel::getLevelError()); |
|
303 } |
|
304 |
|
305 /** |
|
306 * Check whether this Logger is enabled for the FATAL Level. |
|
307 * @return boolean |
|
308 */ |
|
309 public function isFatalEnabled() { |
|
310 return $this->isEnabledFor(LoggerLevel::getLevelFatal()); |
|
311 } |
|
312 |
|
313 // ****************************************** |
|
314 // *** Configuration methods *** |
|
315 // ****************************************** |
|
316 |
|
317 /** |
|
318 * Adds a new appender to the Logger. |
|
319 * @param LoggerAppender $appender The appender to add. |
|
320 */ |
|
321 public function addAppender($appender) { |
|
322 $appenderName = $appender->getName(); |
|
323 $this->appenders[$appenderName] = $appender; |
|
324 } |
|
325 |
|
326 /** Removes all appenders from the Logger. */ |
|
327 public function removeAllAppenders() { |
|
328 foreach ($this->appenders as $name => $appender) { |
|
329 $this->removeAppender($name); |
|
330 } |
|
331 } |
|
332 |
|
333 /** |
|
334 * Remove the appender passed as parameter form the Logger. |
|
335 * @param mixed $appender an appender name or a {@link LoggerAppender} instance. |
|
336 */ |
|
337 public function removeAppender($appender) { |
|
338 if ($appender instanceof LoggerAppender) { |
|
339 $appender->close(); |
|
340 unset($this->appenders[$appender->getName()]); |
|
341 } else if (is_string($appender) and isset($this->appenders[$appender])) { |
|
342 $this->appenders[$appender]->close(); |
|
343 unset($this->appenders[$appender]); |
|
344 } |
|
345 } |
|
346 |
|
347 /** |
|
348 * Returns the appenders linked to this logger as an array. |
|
349 * @return array collection of appender names |
|
350 */ |
|
351 public function getAllAppenders() { |
|
352 return $this->appenders; |
|
353 } |
|
354 |
|
355 /** |
|
356 * Returns a linked appender by name. |
|
357 * @return LoggerAppender |
|
358 */ |
|
359 public function getAppender($name) { |
|
360 return $this->appenders[$name]; |
|
361 } |
|
362 |
|
363 /** |
|
364 * Sets the additivity flag. |
|
365 * @param boolean $additive |
|
366 */ |
|
367 public function setAdditivity($additive) { |
|
368 $this->additive = (bool)$additive; |
|
369 } |
|
370 |
|
371 /** |
|
372 * Returns the additivity flag. |
|
373 * @return boolean |
|
374 */ |
|
375 public function getAdditivity() { |
|
376 return $this->additive; |
|
377 } |
|
378 |
|
379 /** |
|
380 * Starting from this Logger, search the Logger hierarchy for a non-null level and return it. |
|
381 * @see LoggerLevel |
|
382 * @return LoggerLevel or null |
|
383 */ |
|
384 public function getEffectiveLevel() { |
|
385 for ($logger = $this; $logger !== null; $logger = $logger->getParent()) { |
|
386 if ($logger->getLevel() !== null) { |
|
387 return $logger->getLevel(); |
|
388 } |
|
389 } |
|
390 } |
|
391 |
|
392 /** |
|
393 * Get the assigned Logger level. |
|
394 * @return LoggerLevel The assigned level or null if none is assigned. |
|
395 */ |
|
396 public function getLevel() { |
|
397 return $this->level; |
|
398 } |
|
399 |
|
400 /** |
|
401 * Set the Logger level. |
|
402 * |
|
403 * Use LoggerLevel::getLevelXXX() methods to get a LoggerLevel object, e.g. |
|
404 * <code>$logger->setLevel(LoggerLevel::getLevelInfo());</code> |
|
405 * |
|
406 * @param LoggerLevel $level The level to set, or NULL to clear the logger level. |
|
407 */ |
|
408 public function setLevel(LoggerLevel $level = null) { |
|
409 $this->level = $level; |
|
410 } |
|
411 |
|
412 /** |
|
413 * Checks whether an appender is attached to this logger instance. |
|
414 * |
|
415 * @param LoggerAppender $appender |
|
416 * @return boolean |
|
417 */ |
|
418 public function isAttached(LoggerAppender $appender) { |
|
419 return isset($this->appenders[$appender->getName()]); |
|
420 } |
|
421 |
|
422 /** |
|
423 * Sets the parent logger. |
|
424 * @param Logger $logger |
|
425 */ |
|
426 public function setParent(Logger $logger) { |
|
427 $this->parent = $logger; |
|
428 } |
|
429 |
|
430 // ****************************************** |
|
431 // *** Static methods and properties *** |
|
432 // ****************************************** |
|
433 |
|
434 /** The logger hierarchy used by log4php. */ |
|
435 private static $hierarchy; |
|
436 |
|
437 /** Inidicates if log4php has been initialized */ |
|
438 private static $initialized = false; |
|
439 |
|
440 /** |
|
441 * Returns the hierarchy used by this Logger. |
|
442 * |
|
443 * Caution: do not use this hierarchy unless you have called initialize(). |
|
444 * To get Loggers, use the Logger::getLogger and Logger::getRootLogger |
|
445 * methods instead of operating on on the hierarchy directly. |
|
446 * |
|
447 * @return LoggerHierarchy |
|
448 */ |
|
449 public static function getHierarchy() { |
|
450 if (!isset(self::$hierarchy)) { |
|
451 self::$hierarchy = new LoggerHierarchy(new LoggerRoot()); |
|
452 } |
|
453 return self::$hierarchy; |
|
454 } |
|
455 |
|
456 /** |
|
457 * Returns a Logger by name. If it does not exist, it will be created. |
|
458 * |
|
459 * @param string $name The logger name |
|
460 * @return Logger |
|
461 */ |
|
462 public static function getLogger($name) { |
|
463 if (!self::isInitialized()) { |
|
464 self::configure(); |
|
465 } |
|
466 return self::getHierarchy()->getLogger($name); |
|
467 } |
|
468 |
|
469 /** |
|
470 * Returns the Root Logger. |
|
471 * @return LoggerRoot |
|
472 */ |
|
473 public static function getRootLogger() { |
|
474 if (!self::isInitialized()) { |
|
475 self::configure(); |
|
476 } |
|
477 return self::getHierarchy()->getRootLogger(); |
|
478 } |
|
479 |
|
480 /** |
|
481 * Clears all Logger definitions from the logger hierarchy. |
|
482 * @return boolean |
|
483 */ |
|
484 public static function clear() { |
|
485 return self::getHierarchy()->clear(); |
|
486 } |
|
487 |
|
488 /** |
|
489 * Destroy configurations for logger definitions |
|
490 */ |
|
491 public static function resetConfiguration() { |
|
492 self::getHierarchy()->resetConfiguration(); |
|
493 self::getHierarchy()->clear(); // TODO: clear or not? |
|
494 self::$initialized = false; |
|
495 } |
|
496 |
|
497 /** |
|
498 * Safely close all appenders. |
|
499 * @deprecated This is no longer necessary due the appenders shutdown via |
|
500 * destructors. |
|
501 */ |
|
502 public static function shutdown() { |
|
503 return self::getHierarchy()->shutdown(); |
|
504 } |
|
505 |
|
506 /** |
|
507 * check if a given logger exists. |
|
508 * |
|
509 * @param string $name logger name |
|
510 * @return boolean |
|
511 */ |
|
512 public static function exists($name) { |
|
513 return self::getHierarchy()->exists($name); |
|
514 } |
|
515 |
|
516 /** |
|
517 * Returns an array this whole Logger instances. |
|
518 * @see Logger |
|
519 * @return array |
|
520 */ |
|
521 public static function getCurrentLoggers() { |
|
522 return self::getHierarchy()->getCurrentLoggers(); |
|
523 } |
|
524 |
|
525 /** |
|
526 * Configures log4php. |
|
527 * |
|
528 * This method needs to be called before the first logging event has |
|
529 * occured. If this method is not called before then the default |
|
530 * configuration will be used. |
|
531 * |
|
532 * @param string|array $configuration Either a path to the configuration |
|
533 * file, or a configuration array. |
|
534 * |
|
535 * @param string|LoggerConfigurator $configurator A custom |
|
536 * configurator class: either a class name (string), or an object which |
|
537 * implements the LoggerConfigurator interface. If left empty, the default |
|
538 * configurator implementation will be used. |
|
539 */ |
|
540 public static function configure($configuration = null, $configurator = null) { |
|
541 self::resetConfiguration(); |
|
542 $configurator = self::getConfigurator($configurator); |
|
543 $configurator->configure(self::getHierarchy(), $configuration); |
|
544 self::$initialized = true; |
|
545 } |
|
546 |
|
547 /** |
|
548 * Creates a logger configurator instance based on the provided |
|
549 * configurator class. If no class is given, returns an instance of |
|
550 * the default configurator. |
|
551 * |
|
552 * @param string|LoggerConfigurator $configurator The configurator class |
|
553 * or LoggerConfigurator instance. |
|
554 */ |
|
555 private static function getConfigurator($configurator = null) { |
|
556 if ($configurator === null) { |
|
557 return new LoggerConfiguratorDefault(); |
|
558 } |
|
559 |
|
560 if (is_object($configurator)) { |
|
561 if ($configurator instanceof LoggerConfigurator) { |
|
562 return $configurator; |
|
563 } else { |
|
564 trigger_error("log4php: Given configurator object [$configurator] does not implement the LoggerConfigurator interface. Reverting to default configurator.", E_USER_WARNING); |
|
565 return new LoggerConfiguratorDefault(); |
|
566 } |
|
567 } |
|
568 |
|
569 if (is_string($configurator)) { |
|
570 if (!class_exists($configurator)) { |
|
571 trigger_error("log4php: Specified configurator class [$configurator] does not exist. Reverting to default configurator.", E_USER_WARNING); |
|
572 return new LoggerConfiguratorDefault(); |
|
573 } |
|
574 |
|
575 $instance = new $configurator(); |
|
576 |
|
577 if (!($instance instanceof LoggerConfigurator)) { |
|
578 trigger_error("log4php: Specified configurator class [$configurator] does not implement the LoggerConfigurator interface. Reverting to default configurator.", E_USER_WARNING); |
|
579 return new LoggerConfiguratorDefault(); |
|
580 } |
|
581 |
|
582 return $instance; |
|
583 } |
|
584 |
|
585 trigger_error("log4php: Invalid configurator specified. Expected either a string or a LoggerConfigurator instance. Reverting to default configurator.", E_USER_WARNING); |
|
586 return new LoggerConfiguratorDefault(); |
|
587 } |
|
588 |
|
589 /** |
|
590 * Returns true if the log4php framework has been initialized. |
|
591 * @return boolean |
|
592 */ |
|
593 private static function isInitialized() { |
|
594 return self::$initialized; |
|
595 } |
|
596 } |
|