diff --git a/framework/logging/DbTarget.php b/framework/logging/DbTarget.php index aa253ab..56a27bc 100644 --- a/framework/logging/DbTarget.php +++ b/framework/logging/DbTarget.php @@ -94,7 +94,5 @@ class DbTarget extends Target ':message' => $message[0], ))->execute(); } - - $this->messages = array(); } } diff --git a/framework/logging/EmailTarget.php b/framework/logging/EmailTarget.php index f7b1fb2..0b3cc2d 100644 --- a/framework/logging/EmailTarget.php +++ b/framework/logging/EmailTarget.php @@ -53,8 +53,6 @@ class EmailTarget extends Target foreach ($this->emails as $email) { $this->sendEmail($subject, $body, $email, $this->sentFrom, $this->headers); } - - $this->messages = array(); } /** diff --git a/framework/logging/FileTarget.php b/framework/logging/FileTarget.php index 3601010..276043f 100644 --- a/framework/logging/FileTarget.php +++ b/framework/logging/FileTarget.php @@ -79,8 +79,6 @@ class FileTarget extends Target $messages[] = $this->formatMessage($message); } @file_put_contents($logFile, implode('', $messages), FILE_APPEND | LOCK_EX); - - $this->messages = array(); } /** diff --git a/framework/logging/Logger.php b/framework/logging/Logger.php index 187a9c8..2f0cf89 100644 --- a/framework/logging/Logger.php +++ b/framework/logging/Logger.php @@ -37,24 +37,16 @@ class Logger extends \yii\base\Component * Defaults to 1000, meaning the [[flush]] method will be invoked once every 1000 messages logged. * Set this property to be 0 if you don't want to flush messages until the application terminates. * This property mainly affects how much memory will be taken by the logged messages. - * A smaller value means less memory, but will increase the execution time due to the overhead of [[flush]]. + * A smaller value means less memory, but will increase the execution time due to the overhead of [[flush()]]. */ public $flushInterval = 1000; /** - * @var boolean this property will be passed as the parameter to [[flush]] when it is - * called due to the [[flushInterval]] is reached. Defaults to true, meaning the flushed - * messages will be exported to the actual storage medium (e.g. DB, email) defined by each - * log target. If false, the flushed messages will be kept in the memory of each log target. - * @see flushInterval - */ - public $autoExport = true; - /** - * @var array logged messages. This property is mainly managed by [[log]] and [[flush]]. + * @var array logged messages. This property is mainly managed by [[log()]] and [[flush()]]. * Each log message is of the following structure: * * ~~~ * array( - * [0] => message (string) + * [0] => message (mixed) * [1] => level (string) * [2] => category (string) * [3] => timestamp (float, obtained by microtime(true)) @@ -67,7 +59,7 @@ class Logger extends \yii\base\Component * Logs an error message. * An error message is typically logged when an unrecoverable error occurs * during the execution of an application. - * @param string $message the message to be logged. + * @param mixed $message the message to be logged. * @param string $category the category of the message. */ public function error($message, $category = 'application') @@ -79,7 +71,7 @@ class Logger extends \yii\base\Component * Logs a trace message. * Trace messages are logged mainly for development purpose to see * the execution work flow of some code. - * @param string $message the message to be logged. + * @param mixed $message the message to be logged. * @param string $category the category of the message. */ public function trace($message, $category = 'application') @@ -91,24 +83,24 @@ class Logger extends \yii\base\Component * Logs a warning message. * A warning message is typically logged when an error occurs while the execution * can still continue. - * @param string $message the message to be logged. + * @param mixed $message the message to be logged. * @param string $category the category of the message. */ public function warning($message, $category = 'application') { - $this->log($message, self::LEVEL_TRACE, $category); + $this->log($message, self::LEVEL_WARNING, $category); } /** * Logs an informative message. * An informative message is typically logged by an application to keep record of * something important (e.g. an administrator logs in). - * @param string $message the message to be logged. + * @param mixed $message the message to be logged. * @param string $category the category of the message. */ public function info($message, $category = 'application') { - $this->log($message, self::LEVEL_TRACE, $category); + $this->log($message, self::LEVEL_INFO, $category); } /** @@ -119,7 +111,7 @@ class Logger extends \yii\base\Component * @param string $category the category of this log message * @see endProfile */ - public function beginProfile($token, $category) + public function beginProfile($token, $category = 'application') { $this->log($token, self::LEVEL_PROFILE_BEGIN, $category); } @@ -131,7 +123,7 @@ class Logger extends \yii\base\Component * @param string $category the category of this log message * @see beginProfile */ - public function endProfile($token, $category) + public function endProfile($token, $category = 'application') { $this->log($token, self::LEVEL_PROFILE_END, $category); } @@ -145,9 +137,10 @@ class Logger extends \yii\base\Component * 'trace', 'info', 'warning', 'error', 'profile'. * @param string $category the category of the message. */ - public function log($message, $level, $category) + public function log($message, $level, $category = 'application') { - if (YII_DEBUG && YII_TRACE_LEVEL > 0 && $level <= self::LEVEL_TRACE) { + $time = microtime(true); + if (YII_DEBUG && YII_TRACE_LEVEL > 0) { $traces = debug_backtrace(); $count = 0; foreach ($traces as $trace) { @@ -159,25 +152,19 @@ class Logger extends \yii\base\Component } } } - - $this->messages[] = array($message, $level, $category, microtime(true)); + $this->messages[] = array($message, $level, $category, $time); if (count($this->messages) >= $this->flushInterval && $this->flushInterval > 0) { - $this->flush($this->autoExport); + $this->flush(); } } /** * Removes all recorded messages from the memory. * This method will raise a `flush` event. - * The attached event handlers can process the log messages before they are removed. - * @param boolean $export whether to notify log targets to export the filtered messages they have received. */ - public function flush($export = false) + public function flush() { - $this->trigger('flush', new \yii\base\Event($this, array( - 'export' => $export, - 'flush' => true, - ))); + $this->trigger('flush'); $this->messages = array(); } diff --git a/framework/logging/Router.php b/framework/logging/Router.php index 1a84520..162402d 100644 --- a/framework/logging/Router.php +++ b/framework/logging/Router.php @@ -57,17 +57,10 @@ namespace yii\logging; class Router extends \yii\base\ApplicationComponent { /** - * @var \yii\base\Dictionary + * @var Target[] list of log target objects or configurations. If the latter, target objects will + * be created in [[init()]] by calling [[\Yii::createObject()]] with the corresponding object configuration. */ - private $_targets; - - /** - * Constructor. - */ - public function __construct() - { - $this->_targets = new \yii\base\Dictionary; - } + public $targets = array(); /** * Initializes this application component. @@ -78,42 +71,17 @@ class Router extends \yii\base\ApplicationComponent public function init() { parent::init(); - \Yii::getLogger()->on('flush', array($this, 'processMessages')); - if (($app = \Yii::$application) !== null) { - $app->on('afterRequest', array($this, 'processMessages')); - } - } - /** - * Returns the log targets managed by this log router. - * The keys of the dictionary are the names of the log targets. - * You can use the name to access a specific log target. For example, - * - * ~~~ - * $target = $router->targets['file']; - * ~~~ - * @return \yii\base\Dictionary the targets managed by this log router. - */ - public function getTargets() - { - return $this->_targets; - } - - /** - * Sets the log targets. - * @param array $config list of log target configurations. Each array element - * represents the configuration for creating a single log target. It will be - * passed to [[\Yii::createObject()]] to create the target instance. - */ - public function setTargets($config) - { - foreach ($config as $name => $target) { - if ($target instanceof Target) { - $this->_targets[$name] = $target; - } else { - $this->_targets[$name] = \Yii::createObject($target); + foreach ($this->targets as $name => $target) { + if (!$target instanceof Target) { + $this->targets[$name] = \Yii::createObject($target); } } + + \Yii::getLogger()->on('flush', array($this, 'processMessages')); + if (\Yii::$application !== null) { + \Yii::$application->on('afterRequest', array($this, 'processMessages')); + } } /** @@ -127,11 +95,10 @@ class Router extends \yii\base\ApplicationComponent public function processMessages($event) { $messages = \Yii::getLogger()->messages; - $export = !isset($event->data['export']) || $event->data['export']; - $final = !isset($event->data['flush']) || !$event->data['flush']; - foreach ($this->_targets as $target) { + $final = $event->name !== 'flush'; + foreach ($this->targets as $target) { if ($target->enabled) { - $target->processMessages($messages, $export, $final); + $target->processMessages($messages, $final); } } } diff --git a/framework/logging/Target.php b/framework/logging/Target.php index 75cf5a4..377528b 100644 --- a/framework/logging/Target.php +++ b/framework/logging/Target.php @@ -16,11 +16,9 @@ namespace yii\logging; * to its [[levels]] and [[categories]] properties. It may also export the filtered * messages to specific destination defined by the target, such as emails, files. * - * Level filter and category filter are combinational, i.e., only messages - * satisfying both filter conditions will they be returned. Additionally, you - * may specify [[excludeCategories]]. If a message's category falls within the excluded - * categories, it will be filtered out, even if it passes the [[levels]] and - * [[categories]] filters. + * Level filter and category filter are combinatorial, i.e., only messages + * satisfying both filter conditions will be handled. Additionally, you + * may specify [[except]] to exclude messages of certain categories. * * @author Qiang Xue * @since 2.0 @@ -50,7 +48,7 @@ abstract class Target extends \yii\base\Component implements \yii\base\Initable * categories starting with 'yii\db\', such as 'yii\db\dao\Connection'. * @see categories */ - public $excludeCategories = array(); + public $except = array(); /** * @var boolean whether to prefix each log message with the current session ID. Defaults to false. */ @@ -61,7 +59,7 @@ abstract class Target extends \yii\base\Component implements \yii\base\Initable */ public $prefixUser = false; /** - * @var boolean whether to log a message containing the current user name and ID. Defaults to true. + * @var boolean whether to log a message containing the current user name and ID. Defaults to false. * @see \yii\web\User */ public $logUser = false; @@ -72,7 +70,14 @@ abstract class Target extends \yii\base\Component implements \yii\base\Initable */ public $logVars = array('_GET', '_POST', '_FILES', '_COOKIE', '_SESSION', '_SERVER'); /** + * @var boolean whether this target should export the collected messages to persistent storage + * (e.g. DB, email) whenever [[processMessages()]] is called. Defaults to true. If false, + * the collected messages will be stored in [[messages]] without any further processing. + */ + public $autoExport = true; + /** * @var array the messages that are retrieved from the logger so far by this log target. + * @see autoExport */ public $messages = array(); @@ -99,17 +104,17 @@ abstract class Target extends \yii\base\Component implements \yii\base\Initable * And if requested, it will also export the filtering result to specific medium (e.g. email). * @param array $messages log messages to be processed. See [[Logger::messages]] for the structure * of each message. - * @param boolean $export whether to export the processing result * @param boolean $final whether this method is called at the end of the current application */ - public function processMessages($messages, $export, $final) + public function processMessages($messages, $final) { $messages = $this->filterMessages($messages); $this->messages = array_merge($this->messages, $messages); - if ($export && !empty($this->messages)) { + if (!empty($this->messages) && ($this->autoExport || $final)) { $this->prepareExport($final); $this->exportMessages($final); + $this->messages = array(); } } @@ -188,7 +193,7 @@ abstract class Target extends \yii\base\Component implements \yii\base\Initable } if ($matched) { - foreach ($this->excludeCategories as $category) { + foreach ($this->except as $category) { $prefix = rtrim($category, '*'); foreach ($messages as $i => $message) { if (strpos($message[2], $prefix) === 0 && ($message[2] === $category || $prefix !== $category)) { @@ -214,6 +219,7 @@ abstract class Target extends \yii\base\Component implements \yii\base\Initable */ public function formatMessage($message) { - return @date('Y/m/d H:i:s', $message[3]) . " [{$message[1]}] [{$message[2]}] {$message[0]}\n"; + $s = is_string($message[0]) ? $message[0] : var_export($message[0], true); + return date('Y/m/d H:i:s', $message[3]) . " [{$message[1]}] [{$message[2]}] $s\n"; } }