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 1241439 2012-02-07 12:17:21Z 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 77 : $this->name = $name;
75 77 : }
76 :
77 : /**
78 : * Returns the logger name.
79 : * @return string
80 : */
81 : public function getName() {
82 97 : 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 12 : 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 5 : $this->log(LoggerLevel::getLevelTrace(), $message, $throwable);
106 5 : }
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 11 : $this->log(LoggerLevel::getLevelDebug(), $message, $throwable);
117 11 : }
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 17 : $this->log(LoggerLevel::getLevelInfo(), $message, $throwable);
128 17 : }
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 8 : $this->log(LoggerLevel::getLevelWarn(), $message, $throwable);
139 8 : }
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 6 : $this->log(LoggerLevel::getLevelError(), $message, $throwable);
150 6 : }
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 6 : $this->log(LoggerLevel::getLevelFatal(), $message, $throwable);
161 6 : }
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 22 : if($this->isEnabledFor($level)) {
173 22 : $this->forcedLog($this->fqcn, $throwable, $level, $message);
174 22 : }
175 22 : }
176 :
177 : /**
178 : * If assertion parameter evaluates as false, then logs the message
179 : * using the ERROR level.
180 : *
181 : * @param bool $assertion
182 : * @param string $msg message to log
183 : */
184 : public function assertLog($assertion = true, $msg = '') {
185 0 : if($assertion == false) {
186 0 : $this->error($msg);
187 0 : }
188 0 : }
189 :
190 : /**
191 : * This method creates a new logging event and logs the event without
192 : * further checks.
193 : *
194 : * It should not be called directly. Use {@link trace()}, {@link debug()},
195 : * {@link info()}, {@link warn()}, {@link error()} and {@link fatal()}
196 : * wrappers.
197 : *
198 : * @param string $fqcn Fully qualified class name of the Logger
199 : * @param Exception $throwable Optional throwable information to include
200 : * in the logging event.
201 : * @param LoggerLevel $level log level
202 : * @param mixed $message message to log
203 : */
204 : public function forcedLog($fqcn, $throwable, LoggerLevel $level, $message) {
205 22 : if (!($throwable instanceof Exception)) {
206 21 : $throwable = null;
207 21 : }
208 22 : $this->callAppenders(new LoggerLoggingEvent($fqcn, $this, $level, $message, null, $throwable));
209 22 : }
210 :
211 : // ******************************************
212 : // *** Checker methods ***
213 : // ******************************************
214 :
215 : /**
216 : * Check whether this Logger is enabled for a given Level passed as parameter.
217 : *
218 : * @param LoggerLevel level
219 : * @return boolean
220 : */
221 : public function isEnabledFor(LoggerLevel $level) {
222 23 : return $level->isGreaterOrEqual($this->getEffectiveLevel());
223 : }
224 :
225 : /**
226 : * Check whether this Logger is enabled for the TRACE Level.
227 : * @return boolean
228 : */
229 : public function isTraceEnabled() {
230 0 : return $this->isEnabledFor(LoggerLevel::getLevelTrace());
231 : }
232 :
233 : /**
234 : * Check whether this Logger is enabled for the DEBUG Level.
235 : * @return boolean
236 : */
237 : public function isDebugEnabled() {
238 1 : return $this->isEnabledFor(LoggerLevel::getLevelDebug());
239 : }
240 :
241 : /**
242 : * Check whether this Logger is enabled for the INFO Level.
243 : * @return boolean
244 : */
245 : public function isInfoEnabled() {
246 1 : return $this->isEnabledFor(LoggerLevel::getLevelInfo());
247 : }
248 :
249 : /**
250 : * Check whether this Logger is enabled for the WARN Level.
251 : * @return boolean
252 : */
253 : public function isWarnEnabled() {
254 0 : return $this->isEnabledFor(LoggerLevel::getLevelWarn());
255 : }
256 :
257 : /**
258 : * Check whether this Logger is enabled for the ERROR Level.
259 : * @return boolean
260 : */
261 : public function isErrorEnabled() {
262 0 : return $this->isEnabledFor(LoggerLevel::getLevelError());
263 : }
264 :
265 : /**
266 : * Check whether this Logger is enabled for the FATAL Level.
267 : * @return boolean
268 : */
269 : public function isFatalEnabled() {
270 0 : return $this->isEnabledFor(LoggerLevel::getLevelFatal());
271 : }
272 :
273 : // ******************************************
274 : // *** Configuration methods ***
275 : // ******************************************
276 :
277 : /**
278 : * Adds a new appender to the Logger.
279 : * @param LoggerAppender $appender The appender to add.
280 : */
281 : public function addAppender($appender) {
282 43 : $appenderName = $appender->getName();
283 43 : $this->appenders[$appenderName] = $appender;
284 43 : }
285 :
286 : /** Removes all appenders from the Logger. */
287 : public function removeAllAppenders() {
288 66 : foreach($this->appenders as $name => $appender) {
289 41 : $this->removeAppender($name);
290 66 : }
291 66 : }
292 :
293 : /**
294 : * Remove the appender passed as parameter form the Logger.
295 : * @param mixed $appender an appender name or a {@link LoggerAppender} instance.
296 : */
297 : public function removeAppender($appender) {
298 41 : if($appender instanceof LoggerAppender) {
299 0 : $appender->close();
300 0 : unset($this->appenders[$appender->getName()]);
301 41 : } else if (is_string($appender) and isset($this->appenders[$appender])) {
302 41 : $this->appenders[$appender]->close();
303 41 : unset($this->appenders[$appender]);
304 41 : }
305 41 : }
306 :
307 : /**
308 : * Forwards the given logging event to all linked appenders.
309 : * @param LoggerLoggingEvent $event
310 : */
311 : public function callAppenders($event) {
312 : // Forward the event to each linked appender
313 22 : foreach($this->appenders as $appender) {
314 22 : $appender->doAppend($event);
315 22 : }
316 :
317 : // Forward the event upstream if additivity is turned on
318 22 : if(isset($this->parent) && $this->getAdditivity()) {
319 6 : $this->parent->callAppenders($event);
320 6 : }
321 22 : }
322 :
323 : /**
324 : * Returns the appenders linked to this logger as an array.
325 : * @return array collection of appender names
326 : */
327 : public function getAllAppenders() {
328 3 : return $this->appenders;
329 : }
330 :
331 : /**
332 : * Returns a linked appender by name.
333 : * @return LoggerAppender
334 : */
335 : public function getAppender($name) {
336 6 : return $this->appenders[$name];
337 : }
338 :
339 : /**
340 : * Sets the additivity flag.
341 : * @param boolean $additive
342 : */
343 : public function setAdditivity($additive) {
344 12 : $this->additive = (bool)$additive;
345 12 : }
346 :
347 : /**
348 : * Returns the additivity flag.
349 : * @return boolean
350 : */
351 : public function getAdditivity() {
352 9 : return $this->additive;
353 : }
354 :
355 : /**
356 : * Starting from this Logger, search the Logger hierarchy for a non-null level and return it.
357 : * @see LoggerLevel
358 : * @return LoggerLevel or null
359 : */
360 : public function getEffectiveLevel() {
361 23 : for($logger = $this; $logger !== null; $logger = $logger->getParent()) {
362 23 : if($logger->getLevel() !== null) {
363 23 : return $logger->getLevel();
364 : }
365 7 : }
366 0 : }
367 :
368 : /**
369 : * Get the assigned Logger level.
370 : * @return LoggerLevel The assigned level or null if none is assigned.
371 : */
372 : public function getLevel() {
373 31 : return $this->level;
374 : }
375 :
376 : /**
377 : * Set the Logger level.
378 : *
379 : * @param LoggerLevel $level the level to set
380 : */
381 : public function setLevel($level) {
382 74 : $this->level = $level;
383 74 : }
384 :
385 : /**
386 : * Checks whether an appender is attached to this logger instance.
387 : *
388 : * @param LoggerAppender $appender
389 : * @return boolean
390 : */
391 : public function isAttached(LoggerAppender $appender) {
392 0 : return isset($this->appenders[$appender->getName()]);
393 : }
394 :
395 :
396 : /**
397 : * Sets the parent logger.
398 : * @param Logger $logger
399 : */
400 : public function setParent(Logger $logger) {
401 21 : $this->parent = $logger;
402 21 : }
403 :
404 : // ******************************************
405 : // *** Static methods and properties ***
406 : // ******************************************
407 :
408 : /** The logger hierarchy used by log4php. */
409 : private static $hierarchy;
410 :
411 : /** Inidicates if log4php has been initialized */
412 : private static $initialized = false;
413 :
414 : /**
415 : * Returns the hierarchy used by this Logger.
416 : *
417 : * Caution: do not use this hierarchy unless you have called initialize().
418 : * To get Loggers, use the Logger::getLogger and Logger::getRootLogger
419 : * methods instead of operating on on the hierarchy directly.
420 : *
421 : * @return LoggerHierarchy
422 : */
423 : public static function getHierarchy() {
424 69 : if(!isset(self::$hierarchy)) {
425 1 : self::$hierarchy = new LoggerHierarchy(new LoggerRoot());
426 1 : }
427 69 : return self::$hierarchy;
428 : }
429 :
430 : /**
431 : * Returns a Logger by name. If it does not exist, it will be created.
432 : *
433 : * @param string $name The logger name
434 : * @return Logger
435 : */
436 : public static function getLogger($name) {
437 9 : if(!self::isInitialized()) {
438 2 : self::configure();
439 2 : }
440 9 : return self::getHierarchy()->getLogger($name);
441 : }
442 :
443 : /**
444 : * Returns the Root Logger.
445 : * @return LoggerRoot
446 : */
447 : public static function getRootLogger() {
448 20 : if(!self::isInitialized()) {
449 1 : self::configure();
450 1 : }
451 20 : return self::getHierarchy()->getRootLogger();
452 : }
453 :
454 : /**
455 : * Clears all Logger definitions from the logger hierarchy.
456 : * @return boolean
457 : */
458 : public static function clear() {
459 8 : return self::getHierarchy()->clear();
460 : }
461 :
462 : /**
463 : * Destroy configurations for logger definitions
464 : */
465 : public static function resetConfiguration() {
466 62 : self::getHierarchy()->resetConfiguration();
467 62 : self::getHierarchy()->clear(); // TODO: clear or not?
468 62 : self::$initialized = false;
469 62 : }
470 :
471 : /**
472 : * Safely close all appenders.
473 : * @deprecated This is no longer necessary due the appenders shutdown via
474 : * destructors.
475 : */
476 : public static function shutdown() {
477 0 : return self::getHierarchy()->shutdown();
478 : }
479 :
480 : /**
481 : * check if a given logger exists.
482 : *
483 : * @param string $name logger name
484 : * @return boolean
485 : */
486 : public static function exists($name) {
487 1 : return self::getHierarchy()->exists($name);
488 : }
489 :
490 : /**
491 : * Returns an array this whole Logger instances.
492 : * @see Logger
493 : * @return array
494 : */
495 : public static function getCurrentLoggers() {
496 3 : return self::getHierarchy()->getCurrentLoggers();
497 : }
498 :
499 : /**
500 : * Configures log4php.
501 : *
502 : * This method needs to be called before the first logging event has
503 : * occured. If this method is not called before then the default
504 : * configuration will be used.
505 : *
506 : * @param string|array $configuration Either a path to the configuration
507 : * file, or a configuration array.
508 : *
509 : * @param string|LoggerConfigurator $configurator A custom
510 : * configurator class: either a class name (string), or an object which
511 : * implements the LoggerConfigurator interface. If left empty, the default
512 : * configurator implementation will be used.
513 : */
514 : public static function configure($configuration = null, $configurator = null) {
515 55 : self::resetConfiguration();
516 55 : $configurator = self::getConfigurator($configurator);
517 55 : $configurator->configure(self::getHierarchy(), $configuration);
518 32 : self::$initialized = true;
519 32 : }
520 :
521 : /**
522 : * Creates a logger configurator instance based on the provided
523 : * configurator class. If no class is given, returns an instance of
524 : * the default configurator.
525 : *
526 : * @param string|LoggerConfigurator $configurator The configurator class
527 : * or LoggerConfigurator instance.
528 : */
529 : private static function getConfigurator($configurator = null) {
530 55 : if ($configurator === null) {
531 55 : return new LoggerConfiguratorDefault();
532 : }
533 :
534 0 : if (is_object($configurator)) {
535 0 : if ($configurator instanceof LoggerConfigurator) {
536 0 : return $configurator;
537 : } else {
538 0 : trigger_error("log4php: Given configurator object [$configurator] does not implement the LoggerConfigurator interface. Reverting to default configurator.", E_USER_WARNING);
539 0 : return new LoggerConfiguratorDefault();
540 : }
541 : }
542 :
543 0 : if (is_string($configurator)) {
544 0 : if (!class_exists($configurator)) {
545 0 : trigger_error("log4php: Specified configurator class [$configurator] does not exist. Reverting to default configurator.", E_USER_WARNING);
546 0 : return new LoggerConfiguratorDefault();
547 : }
548 :
549 0 : $instance = new $configurator();
550 :
551 0 : if (!($instance instanceof LoggerConfigurator)) {
552 0 : trigger_error("log4php: Specified configurator class [$configurator] does not implement the LoggerConfigurator interface. Reverting to default configurator.", E_USER_WARNING);
553 0 : return new LoggerConfiguratorDefault();
554 : }
555 :
556 0 : return $instance;
557 : }
558 :
559 0 : trigger_error("log4php: Invalid configurator specified. Expected either a string or a LoggerConfigurator instance. Reverting to default configurator.", E_USER_WARNING);
560 0 : return new LoggerConfiguratorDefault();
561 : }
562 :
563 : /**
564 : * Returns true if the log4php framework has been initialized.
565 : * @return boolean
566 : */
567 : private static function isInitialized() {
568 27 : return self::$initialized;
569 : }
570 :
571 : }
|