blob: 40cb4160d2f7a8fc58a4230987bedb91d211562d [file] [log] [blame]
<?php
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace Apache\Log4php;
/**
* This is the central class in the log4php package. All logging operations
* are done through this class.
*
* The main logging methods are:
* <ul>
* <li>{@link trace()}</li>
* <li>{@link debug()}</li>
* <li>{@link info()}</li>
* <li>{@link warn()}</li>
* <li>{@link error()}</li>
* <li>{@link fatal()}</li>
* </ul>
*
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @link http://logging.apache.org/log4php
*/
class Logger
{
/**
* Logger additivity. If set to true then child loggers will inherit
* the appenders of their ancestors by default.
* @var boolean
*/
private $additive = true;
/**
* The Logger's fully qualified class name.
* TODO: Determine if this is useful.
*/
private $fqcn = 'Logger';
/** The assigned Logger level. */
private $level;
/** The name of this Logger instance. */
private $name;
/** The parent logger. Set to null if this is the root logger. */
private $parent;
/** A collection of appenders linked to this logger. */
private $appenders = array();
/**
* Constructor.
* @param string $name Name of the logger.
*/
public function __construct($name)
{
$this->name = $name;
}
/**
* Returns the logger name.
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Returns the parent Logger. Can be null if this is the root logger.
* @return Logger
*/
public function getParent()
{
return $this->parent;
}
// ******************************************
// *** Logging methods ***
// ******************************************
/**
* Log a message object with the TRACE level.
*
* @param mixed $message message
* @param Exception $throwable Optional throwable information to include
* in the logging event.
*/
public function trace($message, $throwable = null)
{
$this->log(Level::getLevelTrace(), $message, $throwable);
}
/**
* Log a message object with the DEBUG level.
*
* @param mixed $message message
* @param Exception $throwable Optional throwable information to include
* in the logging event.
*/
public function debug($message, $throwable = null)
{
$this->log(Level::getLevelDebug(), $message, $throwable);
}
/**
* Log a message object with the INFO Level.
*
* @param mixed $message message
* @param Exception $throwable Optional throwable information to include
* in the logging event.
*/
public function info($message, $throwable = null)
{
$this->log(Level::getLevelInfo(), $message, $throwable);
}
/**
* Log a message with the WARN level.
*
* @param mixed $message message
* @param Exception $throwable Optional throwable information to include
* in the logging event.
*/
public function warn($message, $throwable = null)
{
$this->log(Level::getLevelWarn(), $message, $throwable);
}
/**
* Log a message object with the ERROR level.
*
* @param mixed $message message
* @param Exception $throwable Optional throwable information to include
* in the logging event.
*/
public function error($message, $throwable = null)
{
$this->log(Level::getLevelError(), $message, $throwable);
}
/**
* Log a message object with the FATAL level.
*
* @param mixed $message message
* @param Exception $throwable Optional throwable information to include
* in the logging event.
*/
public function fatal($message, $throwable = null)
{
$this->log(Level::getLevelFatal(), $message, $throwable);
}
/**
* Log a message using the provided logging level.
*
* @param Level $level The logging level.
* @param mixed $message Message to log.
* @param Exception $throwable Optional throwable information to include
* in the logging event.
*/
public function log(Level $level, $message, $throwable = null)
{
if ($this->isEnabledFor($level)) {
$event = new LoggingEvent($this->fqcn, $this, $level, $message, null, $throwable);
$this->callAppenders($event);
}
// Forward the event upstream if additivity is turned on
if (isset($this->parent) && $this->getAdditivity()) {
// Use the event if already created
if (isset($event)) {
$this->parent->logEvent($event);
} else {
$this->parent->log($level, $message, $throwable);
}
}
}
/**
* Logs an already prepared logging event object.
* @param LoggingEvent $event
*/
public function logEvent(LoggingEvent $event)
{
if ($this->isEnabledFor($event->getLevel())) {
$this->callAppenders($event);
}
// Forward the event upstream if additivity is turned on
if (isset($this->parent) && $this->getAdditivity()) {
$this->parent->logEvent($event);
}
}
/**
* If assertion parameter evaluates as false, then logs the message
* using the ERROR level.
*
* @param bool $assertion
* @param string $msg message to log
*/
public function assertLog($assertion = true, $msg = '')
{
if ($assertion == false) {
$this->error($msg);
}
}
/**
* This method creates a new logging event and logs the event without
* further checks.
*
* It should not be called directly. Use {@link trace()}, {@link debug()},
* {@link info()}, {@link warn()}, {@link error()} and {@link fatal()}
* wrappers.
*
* @param string $fqcn Fully qualified class name of the Logger
* @param Exception $throwable Optional throwable information to include
* in the logging event.
* @param Level $level log level
* @param mixed $message message to log
*/
public function forcedLog($fqcn, $throwable, Level $level, $message)
{
$event = new LoggingEvent($fqcn, $this, $level, $message, null, $throwable);
$this->callAppenders($event);
// Forward the event upstream if additivity is turned on
if (isset($this->parent) && $this->getAdditivity()) {
$this->parent->logEvent($event);
}
}
/**
* Forwards the given logging event to all linked appenders.
* @param LoggingEvent $event
*/
public function callAppenders($event)
{
foreach ($this->appenders as $appender) {
$appender->doAppend($event);
}
}
// ******************************************
// *** Checker methods ***
// ******************************************
/**
* Check whether this Logger is enabled for a given Level passed as parameter.
*
* @param Level level
* @return boolean
*/
public function isEnabledFor(Level $level)
{
return $level->isGreaterOrEqual($this->getEffectiveLevel());
}
/**
* Check whether this Logger is enabled for the TRACE Level.
* @return boolean
*/
public function isTraceEnabled()
{
return $this->isEnabledFor(Level::getLevelTrace());
}
/**
* Check whether this Logger is enabled for the DEBUG Level.
* @return boolean
*/
public function isDebugEnabled()
{
return $this->isEnabledFor(Level::getLevelDebug());
}
/**
* Check whether this Logger is enabled for the INFO Level.
* @return boolean
*/
public function isInfoEnabled()
{
return $this->isEnabledFor(Level::getLevelInfo());
}
/**
* Check whether this Logger is enabled for the WARN Level.
* @return boolean
*/
public function isWarnEnabled()
{
return $this->isEnabledFor(Level::getLevelWarn());
}
/**
* Check whether this Logger is enabled for the ERROR Level.
* @return boolean
*/
public function isErrorEnabled()
{
return $this->isEnabledFor(Level::getLevelError());
}
/**
* Check whether this Logger is enabled for the FATAL Level.
* @return boolean
*/
public function isFatalEnabled()
{
return $this->isEnabledFor(Level::getLevelFatal());
}
// ******************************************
// *** Configuration methods ***
// ******************************************
/**
* Adds a new appender to the Logger.
* @param Appender $appender The appender to add.
*/
public function addAppender($appender)
{
$appenderName = $appender->getName();
$this->appenders[$appenderName] = $appender;
}
/** Removes all appenders from the Logger. */
public function removeAllAppenders()
{
foreach ($this->appenders as $name => $appender) {
$this->removeAppender($name);
}
}
/**
* Remove the appender passed as parameter form the Logger.
* @param mixed $appender an appender name or a {@link Appender} instance.
*/
public function removeAppender($appender)
{
if ($appender instanceof Appender) {
$appender->close();
unset($this->appenders[$appender->getName()]);
} elseif (is_string($appender) and isset($this->appenders[$appender])) {
$this->appenders[$appender]->close();
unset($this->appenders[$appender]);
}
}
/**
* Returns the appenders linked to this logger as an array.
* @return array collection of appender names
*/
public function getAllAppenders()
{
return $this->appenders;
}
/**
* Returns a linked appender by name.
* @return Appender
*/
public function getAppender($name)
{
return $this->appenders[$name];
}
/**
* Sets the additivity flag.
* @param boolean $additive
*/
public function setAdditivity($additive)
{
$this->additive = (bool) $additive;
}
/**
* Returns the additivity flag.
* @return boolean
*/
public function getAdditivity()
{
return $this->additive;
}
/**
* Starting from this Logger, search the Logger hierarchy for a non-null level and return it.
* @see Level
* @return Level or null
*/
public function getEffectiveLevel()
{
for ($logger = $this; $logger !== null; $logger = $logger->getParent()) {
if ($logger->getLevel() !== null) {
return $logger->getLevel();
}
}
}
/**
* Get the assigned Logger level.
* @return Level The assigned level or null if none is assigned.
*/
public function getLevel()
{
return $this->level;
}
/**
* Set the Logger level.
*
* Use Level::getLevelXXX() methods to get a Level object, e.g.
* <code>$logger->setLevel(Level::getLevelInfo());</code>
*
* @param Level $level The level to set, or NULL to clear the logger level.
*/
public function setLevel(Level $level = null)
{
$this->level = $level;
}
/**
* Checks whether an appender is attached to this logger instance.
*
* @param Appender $appender
* @return boolean
*/
public function isAttached(Appender $appender)
{
return isset($this->appenders[$appender->getName()]);
}
/**
* Sets the parent logger.
* @param Logger $logger
*/
public function setParent(Logger $logger)
{
$this->parent = $logger;
}
// ******************************************
// *** Static methods and properties ***
// ******************************************
/** The logger hierarchy used by log4php. */
private static $hierarchy;
/** Inidicates if log4php has been initialized */
private static $initialized = false;
/**
* Returns the hierarchy used by this Logger.
*
* Caution: do not use this hierarchy unless you have called initialize().
* To get Loggers, use the Logger::getLogger and Logger::getRootLogger
* methods instead of operating on on the hierarchy directly.
*
* @return Hierarchy
*/
public static function getHierarchy()
{
if (!isset(self::$hierarchy)) {
self::$hierarchy = new Hierarchy(new RootLogger());
}
return self::$hierarchy;
}
/**
* Returns a Logger by name. If it does not exist, it will be created.
*
* @param string $name The logger name
* @return Logger
*/
public static function getLogger($name)
{
if (!self::isInitialized()) {
self::configure();
}
return self::getHierarchy()->getLogger($name);
}
/**
* Returns the Root Logger.
* @return RootLogger
*/
public static function getRootLogger()
{
if (!self::isInitialized()) {
self::configure();
}
return self::getHierarchy()->getRootLogger();
}
/**
* Clears all Logger definitions from the logger hierarchy.
* @return boolean
*/
public static function clear()
{
return self::getHierarchy()->clear();
}
/**
* Destroy configurations for logger definitions
*/
public static function resetConfiguration()
{
self::getHierarchy()->resetConfiguration();
self::getHierarchy()->clear(); // TODO: clear or not?
self::$initialized = false;
}
/**
* Safely close all appenders.
* @deprecated This is no longer necessary due the appenders shutdown via
* destructors.
*/
public static function shutdown()
{
return self::getHierarchy()->shutdown();
}
/**
* check if a given logger exists.
*
* @param string $name logger name
* @return boolean
*/
public static function exists($name)
{
return self::getHierarchy()->exists($name);
}
/**
* Returns an array this whole Logger instances.
* @see Logger
* @return array
*/
public static function getCurrentLoggers()
{
return self::getHierarchy()->getCurrentLoggers();
}
/**
* Configures log4php.
*
* This method needs to be called before the first logging event has
* occured. If this method is not called before then the default
* configuration will be used.
*
* @param string|array $configuration Either a path to the configuration
* file, or a configuration array.
*
* @param string|Configurator $configurator A custom
* configurator class: either a class name (string) , or an object which
* implements the Configurator interface. If left empty, the default
* configurator implementation will be used.
*/
public static function configure($configuration = null, $configurator = null)
{
self::resetConfiguration();
$configurator = self::getConfigurator($configurator);
$configurator->configure(self::getHierarchy(), $configuration);
self::$initialized = true;
}
/**
* Creates a logger configurator instance based on the provided
* configurator class. If no class is given, returns an instance of
* the default configurator.
*
* @param string|Configurator $configurator The configurator class
* or Configurator instance.
*/
private static function getConfigurator($configurator = null)
{
if ($configurator === null) {
return new Configuration\DefaultConfigurator();
}
if (is_object($configurator)) {
if ($configurator instanceof Configurator) {
return $configurator;
} else {
trigger_error(
"log4php: Given configurator object [$configurator] does not implement Configurator interface. " .
"Reverting to default configurator.",
E_USER_WARNING
);
return new Configuration\DefaultConfigurator();
}
}
if (is_string($configurator)) {
if (!class_exists($configurator)) {
trigger_error(
"log4php: Given configurator class [$configurator] does not exist. " .
"Reverting to default configurator.",
E_USER_WARNING
);
return new Configuration\DefaultConfigurator();
}
$instance = new $configurator();
if (!($instance instanceof Configurator)) {
trigger_error(
"log4php: Specified configurator class [$configurator] does not implement Configurator interface." .
" Reverting to default configurator.",
E_USER_WARNING
);
return new Configuration\DefaultConfigurator();
}
return $instance;
}
trigger_error(
"log4php: Invalid configurator specified. Expected either a string or a Configurator instance. " .
"Reverting to default configurator.",
E_USER_WARNING
);
return new Configuration\DefaultConfigurator();
}
/**
* Returns true if the log4php framework has been initialized.
* @return boolean
*/
private static function isInitialized()
{
return self::$initialized;
}
}