Project

General

Profile

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
		$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
			$this->forcedLog($this->fqcn, $throwable, $level, $message);
174
		}
175
	}
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
		if($assertion == false) {
186
			$this->error($msg);
187
		}
188
	}
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
		if (!($throwable instanceof Exception)) {
206
			$throwable = null;
207
		}
208
		$this->callAppenders(new LoggerLoggingEvent($fqcn, $this, $level, $message, null, $throwable));
209
	} 
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
		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
		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
		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
		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
		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
		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
		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
		$appenderName = $appender->getName();
283
		$this->appenders[$appenderName] = $appender;
284
	}
285
	
286
	/** Removes all appenders from the Logger. */
287
	public function removeAllAppenders() {
288
		foreach($this->appenders as $name => $appender) {
289
			$this->removeAppender($name);
290
		}
291
	} 
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
		if($appender instanceof LoggerAppender) {
299
			$appender->close();
300
			unset($this->appenders[$appender->getName()]);
301
		} else if (is_string($appender) and isset($this->appenders[$appender])) {
302
			$this->appenders[$appender]->close();
303
			unset($this->appenders[$appender]);
304
		}
305
	}
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
		foreach($this->appenders as $appender) {
314
			$appender->doAppend($event);
315
		}
316
		
317
		// Forward the event upstream if additivity is turned on
318
		if(isset($this->parent) && $this->getAdditivity()) {
319
			$this->parent->callAppenders($event);
320
		}
321
	}
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
		return $this->appenders;
329
	}
330
	
331
	/**
332
	 * Returns a linked appender by name.
333
	 * @return LoggerAppender
334
	 */
335
	public function getAppender($name) {
336
		return $this->appenders[$name];
337
	}
338

    
339
	/**
340
	 * Sets the additivity flag.
341
	 * @param boolean $additive
342
	 */
343
	public function setAdditivity($additive) {
344
		$this->additive = (bool)$additive;
345
	}
346
	
347
	/**
348
	 * Returns the additivity flag.
349
	 * @return boolean
350
	 */
351
	public function getAdditivity() {
352
		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
		for($logger = $this; $logger !== null; $logger = $logger->getParent()) {
362
			if($logger->getLevel() !== null) {
363
				return $logger->getLevel();
364
			}
365
		}
366
	}
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
		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
		$this->level = $level;
383
	}
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
		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
		$this->parent = $logger;
402
	} 
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
		if(!isset(self::$hierarchy)) {
425
			self::$hierarchy = new LoggerHierarchy(new LoggerRoot());
426
		}
427
		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
		if(!self::isInitialized()) {
438
			self::configure();
439
		}
440
		return self::getHierarchy()->getLogger($name);
441
	}
442
	
443
	/**
444
	 * Returns the Root Logger.
445
	 * @return LoggerRoot
446
	 */
447
	public static function getRootLogger() {
448
		if(!self::isInitialized()) {
449
			self::configure();
450
		}
451
		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
		return self::getHierarchy()->clear();
460
	}
461
	
462
	/**
463
	 * Destroy configurations for logger definitions
464
	 */
465
	public static function resetConfiguration() {
466
		self::getHierarchy()->resetConfiguration();
467
		self::getHierarchy()->clear(); // TODO: clear or not?
468
		self::$initialized = false;
469
	}
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
		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
		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
		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
		self::resetConfiguration();
516
		$configurator = self::getConfigurator($configurator);
517
		$configurator->configure(self::getHierarchy(), $configuration);
518
		self::$initialized = true;
519
	}
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
		if ($configurator === null) {
531
			return new LoggerConfiguratorDefault();
532
		}
533
		
534
		if (is_object($configurator)) {
535
			if ($configurator instanceof LoggerConfigurator) {
536
				return $configurator;
537
			} else {
538
				trigger_error("log4php: Given configurator object [$configurator] does not implement the LoggerConfigurator interface. Reverting to default configurator.", E_USER_WARNING);
539
				return new LoggerConfiguratorDefault();
540
			}
541
		}
542
		
543
		if (is_string($configurator)) {
544
			if (!class_exists($configurator)) {
545
				trigger_error("log4php: Specified configurator class [$configurator] does not exist. Reverting to default configurator.", E_USER_WARNING);
546
				return new LoggerConfiguratorDefault();
547
			}
548
			
549
			$instance = new $configurator();
550
				
551
			if (!($instance instanceof LoggerConfigurator)) {
552
				trigger_error("log4php: Specified configurator class [$configurator] does not implement the LoggerConfigurator interface. Reverting to default configurator.", E_USER_WARNING);
553
				return new LoggerConfiguratorDefault();
554
			}
555
			
556
			return $instance;
557
		}
558
		
559
		trigger_error("log4php: Invalid configurator specified. Expected either a string or a LoggerConfigurator instance. Reverting to default configurator.", E_USER_WARNING);
560
		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
		return self::$initialized;
569
	}
570
	
571
}
(1-1/19)