diff --git a/extensions/debug/panels/DbPanel.php b/extensions/debug/panels/DbPanel.php index db20ae22cb..ba68391af3 100644 --- a/extensions/debug/panels/DbPanel.php +++ b/extensions/debug/panels/DbPanel.php @@ -86,7 +86,7 @@ class DbPanel extends Panel protected function calculateTimings() { if ($this->_timings === null) { - $this->_timings = Yii::$app->getLog()->calculateTimings($this->data['messages']); + $this->_timings = Yii::getLogger()->calculateTimings($this->data['messages']); } return $this->_timings; diff --git a/extensions/debug/panels/ProfilingPanel.php b/extensions/debug/panels/ProfilingPanel.php index 33f698413d..635f4f854e 100644 --- a/extensions/debug/panels/ProfilingPanel.php +++ b/extensions/debug/panels/ProfilingPanel.php @@ -85,7 +85,7 @@ class ProfilingPanel extends Panel { if ($this->_models === null) { $this->_models = []; - $timings = Yii::$app->getLog()->calculateTimings($this->data['messages']); + $timings = Yii::getLogger()->calculateTimings($this->data['messages']); foreach ($timings as $seq => $profileTiming) { $this->_models[] = [ diff --git a/framework/BaseYii.php b/framework/BaseYii.php index 5a1e8174d6..bfe0240b77 100644 --- a/framework/BaseYii.php +++ b/framework/BaseYii.php @@ -348,6 +348,29 @@ class BaseYii } } + private static $_logger; + + /** + * @return Logger message logger + */ + public static function getLogger() + { + if (self::$_logger !== null) { + return self::$_logger; + } else { + return self::$_logger = static::createObject('yii\log\Logger'); + } + } + + /** + * Sets the logger object. + * @param Logger $logger the logger object. + */ + public static function setLogger($logger) + { + self::$_logger = $logger; + } + /** * Logs a trace message. * Trace messages are logged mainly for development purpose to see @@ -358,7 +381,7 @@ class BaseYii public static function trace($message, $category = 'application') { if (YII_DEBUG) { - static::$app->getLog()->log($message, Logger::LEVEL_TRACE, $category); + static::getLogger()->log($message, Logger::LEVEL_TRACE, $category); } } @@ -371,7 +394,7 @@ class BaseYii */ public static function error($message, $category = 'application') { - static::$app->getLog()->log($message, Logger::LEVEL_ERROR, $category); + static::getLogger()->log($message, Logger::LEVEL_ERROR, $category); } /** @@ -383,7 +406,7 @@ class BaseYii */ public static function warning($message, $category = 'application') { - static::$app->getLog()->log($message, Logger::LEVEL_WARNING, $category); + static::getLogger()->log($message, Logger::LEVEL_WARNING, $category); } /** @@ -395,7 +418,7 @@ class BaseYii */ public static function info($message, $category = 'application') { - static::$app->getLog()->log($message, Logger::LEVEL_INFO, $category); + static::getLogger()->log($message, Logger::LEVEL_INFO, $category); } /** @@ -417,7 +440,7 @@ class BaseYii */ public static function beginProfile($token, $category = 'application') { - static::$app->getLog()->log($token, Logger::LEVEL_PROFILE_BEGIN, $category); + static::getLogger()->log($token, Logger::LEVEL_PROFILE_BEGIN, $category); } /** @@ -429,7 +452,7 @@ class BaseYii */ public static function endProfile($token, $category = 'application') { - static::$app->getLog()->log($token, Logger::LEVEL_PROFILE_END, $category); + static::getLogger()->log($token, Logger::LEVEL_PROFILE_END, $category); } /** diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index d8d92ebfcf..f8df6ae733 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -259,6 +259,7 @@ Yii Framework 2 Change Log - Chg: The signature of `Yii::createObject()` is changed. Constructor parameters must be passed as the second parameter. (qiangxue) - Chg: `Yii::$objectConfig` is removed. You should use `Yii::$container->set()` to configure default settings of classes. (qiangxue) - Chg: Removed `yii\grid\Column::getDataCellContent()` and renamed `yii\grid\DataColumn::getDataCellContent()` to `yii\grid\DataColumn::getDataCellValue()` (cebe) +- Chg: `yii\log\Logger` is split into `yii\log\Logger` and `yii\log\Dispatcher`. (qiangxue) - New #66: [Auth client library](https://github.com/yiisoft/yii2-authclient) OpenId, OAuth1, OAuth2 clients (klimov-paul) - New #503: Added `yii\di\Container` and `yii\di\ServiceLocator` (qiangxue) - New #706: Added `yii\widgets\Pjax` and enhanced `GridView` to work with `Pjax` to support AJAX-update (qiangxue) diff --git a/framework/base/Application.php b/framework/base/Application.php index 11a08b2773..506e19cfab 100644 --- a/framework/base/Application.php +++ b/framework/base/Application.php @@ -23,7 +23,7 @@ use yii\web\HttpException; * @property ErrorHandler $errorHandler The error handler application component. This property is read-only. * @property \yii\base\Formatter $formatter The formatter application component. This property is read-only. * @property \yii\i18n\I18N $i18n The internationalization component. This property is read-only. - * @property \yii\log\Logger $log The log component. This property is read-only. + * @property \yii\log\Dispatcher $log The log dispatcher component. This property is read-only. * @property \yii\mail\MailerInterface $mail The mailer interface. This property is read-only. * @property \yii\web\Request|\yii\console\Request $request The request component. This property is read-only. * @property string $runtimePath The directory that stores runtime files. Defaults to the "runtime" @@ -415,8 +415,8 @@ abstract class Application extends Module } /** - * Returns the log component. - * @return \yii\log\Logger the log component + * Returns the log dispatcher component. + * @return \yii\log\Dispatcher the log dispatcher component */ public function getLog() { @@ -512,7 +512,7 @@ abstract class Application extends Module public function coreComponents() { return [ - 'log' => ['class' => 'yii\log\Logger'], + 'log' => ['class' => 'yii\log\Dispatcher'], 'errorHandler' => ['class' => 'yii\base\ErrorHandler'], 'formatter' => ['class' => 'yii\base\Formatter'], 'i18n' => ['class' => 'yii\i18n\I18N'], diff --git a/framework/log/Dispatcher.php b/framework/log/Dispatcher.php new file mode 100644 index 0000000000..f4130535fd --- /dev/null +++ b/framework/log/Dispatcher.php @@ -0,0 +1,135 @@ +log`. + * + * You may configure the targets in application configuration, like the following: + * + * ~~~ + * [ + * 'components' => [ + * 'log' => [ + * 'targets' => [ + * 'file' => [ + * 'class' => 'yii\log\FileTarget', + * 'levels' => ['trace', 'info'], + * 'categories' => ['yii\*'], + * ], + * 'email' => [ + * 'class' => 'yii\log\EmailTarget', + * 'levels' => ['error', 'warning'], + * 'message' => [ + * 'to' => 'admin@example.com', + * ], + * ], + * ], + * ], + * ], + * ] + * ~~~ + * + * Each log target can have a name and can be referenced via the [[targets]] property + * as follows: + * + * ~~~ + * Yii::$app->log->targets['file']->enabled = false; + * ~~~ + * + * @author Qiang Xue + * @since 2.0 + */ +class Dispatcher extends Component +{ + /** + * @var array|Target[] the log targets. Each array element represents a single [[Target|log target]] instance + * or the configuration for creating the log target instance. + */ + public $targets = []; + + /** + * Initializes the logger by registering [[flush()]] as a shutdown function. + */ + public function init() + { + parent::init(); + + foreach ($this->targets as $name => $target) { + if (!$target instanceof Target) { + $this->targets[$name] = Yii::createObject($target); + } + } + + Yii::getLogger()->dispatcher = $this; + } + + /** + * @return integer how many application call stacks should be logged together with each message. + * This method returns the value of [[Logger::traceLevel]]. Defaults to 0. + */ + public function getTraceLevel() + { + return Yii::getLogger()->traceLevel; + } + + /** + * @param integer $value how many application call stacks should be logged together with each message. + * This method will set the value of [[Logger::traceLevel]]. If the value is greater than 0, + * at most that number of call stacks will be logged. Note that only application call stacks are counted. + * Defaults to 0. + */ + public function setTraceLevel($value) + { + Yii::getLogger()->traceLevel = $value; + } + + /** + * @return integer how many messages should be logged before they are sent to targets. + * This method returns the value of [[Logger::flushInterval]]. + */ + public function getFlushInterval() + { + return Yii::getLogger()->flushInterval; + } + + /** + * @param integer $value how many messages should be logged before they are sent to targets. + * This method will set the value of [[Logger::flushInterval]]. + * Defaults to 1000, meaning the [[Logger::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 [[Logger::flush()]]. + */ + public function setFlushInterval($value) + { + Yii::getLogger()->flushInterval = $value; + } + + /** + * Dispatches the logged messages to [[targets]]. + * @param array $messages the logged messages + * @param boolean $final whether this method is called at the end of the current application + */ + public function dispatch($messages, $final) + { + foreach ($this->targets as $target) { + if ($target->enabled) { + $target->collect($messages, $final); + } + } + } +} diff --git a/framework/log/Logger.php b/framework/log/Logger.php index b067e39cad..029f474502 100644 --- a/framework/log/Logger.php +++ b/framework/log/Logger.php @@ -11,11 +11,11 @@ use Yii; use yii\base\Component; /** - * Logger records logged messages in memory and sends them to different targets as needed. + * Logger records logged messages in memory and sends them to different targets if [[dispatcher]] is set. * - * Logger is registered as a core application component and can be accessed using `Yii::$app->log`. - * You can call the method [[log()]] to record a single log message. For convenience, a set of shortcut - * methods are provided for logging messages of various severity levels via the [[Yii]] class: + * Logger can be accessed via `Yii::getLogger()`. You can call the method [[log()]] to record a single log message. + * For convenience, a set of shortcut methods are provided for logging messages of various severity levels + * via the [[Yii]] class: * * - [[Yii::trace()]] * - [[Yii::error()]] @@ -24,43 +24,8 @@ use yii\base\Component; * - [[Yii::beginProfile()]] * - [[Yii::endProfile()]] * - * When enough messages are accumulated in the logger, or when the current request finishes, - * the logged messages will be sent to different [[targets]], such as log files, emails. - * - * You may configure the targets in application configuration, like the following: - * - * ~~~ - * [ - * 'components' => [ - * 'log' => [ - * 'targets' => [ - * 'file' => [ - * 'class' => 'yii\log\FileTarget', - * 'levels' => ['trace', 'info'], - * 'categories' => ['yii\*'], - * ], - * 'email' => [ - * 'class' => 'yii\log\EmailTarget', - * 'levels' => ['error', 'warning'], - * 'message' => [ - * 'to' => 'admin@example.com', - * ], - * ], - * ], - * ], - * ], - * ] - * ~~~ - * - * Each log target can have a name and can be referenced via the [[targets]] property - * as follows: - * - * ~~~ - * Yii::$app->log->targets['file']->enabled = false; - * ~~~ - * * When the application ends or [[flushInterval]] is reached, Logger will call [[flush()]] - * to send logged messages to different log targets, such as file, email, Web. + * to send logged messages to different log targets, such as file, email, Web, with the help of [[dispatcher]]. * * @property array $dbProfiling The first element indicates the number of SQL statements executed, and the * second element the total time spent in SQL execution. This property is read-only. @@ -124,16 +89,6 @@ class Logger extends Component * ~~~ */ public $messages = []; - /** - * @var array debug data. This property stores various types of debug data reported at - * different instrument places. - */ - public $data = []; - /** - * @var array|Target[] the log targets. Each array element represents a single [[Target|log target]] instance - * or the configuration for creating the log target instance. - */ - public $targets = []; /** * @var integer how many messages should be logged before they are flushed from memory and sent to targets. * Defaults to 1000, meaning the [[flush]] method will be invoked once every 1000 messages logged. @@ -146,10 +101,13 @@ class Logger extends Component * @var integer how much call stack information (file name and line number) should be logged for each message. * If it is greater than 0, at most that number of call stacks will be logged. Note that only application * call stacks are counted. - * - * If not set, it will default to 3 when `YII_ENV` is set as "dev", and 0 otherwise. */ - public $traceLevel; + public $traceLevel = 0; + /** + * @var Dispatcher the message dispatcher + */ + public $dispatcher; + /** * Initializes the logger by registering [[flush()]] as a shutdown function. @@ -157,14 +115,6 @@ class Logger extends Component public function init() { parent::init(); - if ($this->traceLevel === null) { - $this->traceLevel = YII_ENV_DEV ? 3 : 0; - } - foreach ($this->targets as $name => $target) { - if (!$target instanceof Target) { - $this->targets[$name] = Yii::createObject($target); - } - } register_shutdown_function([$this, 'flush'], true); } @@ -208,11 +158,8 @@ class Logger extends Component */ public function flush($final = false) { - /** @var Target $target */ - foreach ($this->targets as $target) { - if ($target->enabled) { - $target->collect($this->messages, $final); - } + if ($this->dispatcher instanceof Dispatcher) { + $this->dispatcher->dispatch($this->messages, $final); } $this->messages = []; }