1. 組成
Yii2的logger主要分為三個(gè)部分:
- Logger 負(fù)責(zé)日志級(jí)別恳守,記錄格式等等的配置和管理;
- Dispatcher 負(fù)責(zé)日志的收集和對(duì)target的管理催烘;
- target 負(fù)責(zé)執(zhí)行寫入的操作颗圣,可以是寫文件聘萨,寫數(shù)據(jù)庫等等芜飘。
(我是覺得代碼寫得不是很好茧妒,Dispatcher作為L(zhǎng)ogger的成員及老,而Logger也作為Dispatcher的成員,我覺得耦合性太強(qiáng)了食铐,monolog相對(duì)就好很多,有空再寫這個(gè)源碼的分析)
2. 部分源碼
1. 先看application類里面注冊(cè)的核心組件
\yii\base\Application::coreComponents
/**
* Returns the configuration of core application components.
* @see set()
*/
public function coreComponents()
{
return [
'log' => ['class' => 'yii\log\Dispatcher'],
'view' => ['class' => 'yii\web\View'],
'formatter' => ['class' => 'yii\i18n\Formatter'],
'i18n' => ['class' => 'yii\i18n\I18N'],
'mailer' => ['class' => 'yii\swiftmailer\Mailer'],
'urlManager' => ['class' => 'yii\web\UrlManager'],
'assetManager' => ['class' => 'yii\web\AssetManager'],
'security' => ['class' => 'yii\base\Security'],
];
}
- 2 初始化log組件
- 0. \yii\base\Application::getLog
- 1. \yii\log\Dispatcher::__construct 初始化logger
/**
* @inheritdoc
*/
public function __construct($config = [])
{
// ensure logger gets set before any other config option
if (isset($config['logger'])) {
$this->setLogger($config['logger']);
unset($config['logger']);
}
// connect logger and dispatcher
$this->getLogger(); // 重要
parent::__construct($config);
}
- 2. \yii\log\Dispatcher::getLogger 創(chuàng)建一個(gè)logger單例
/**
* Gets the connected logger.
* If not set, [[\Yii::getLogger()]] will be used.
* @property Logger the logger. If not set, [[\Yii::getLogger()]] will be used.
* @return Logger the logger.
*/
public function getLogger()
{
if ($this->_logger === null) {
$this->setLogger(Yii::getLogger());
}
return $this->_logger;
}
- 3. 從上一步的getLogger追代碼到:\yii\log\Dispatcher::setLogger
/**
* Sets the connected logger.
* @param Logger $value the logger.
*/
public function setLogger($value)
{
$this->_logger = $value;
$this->_logger->dispatcher = $this; //這一步重要寞秃,把logger里的dispatcher關(guān)聯(lián)了自己
}
- 4. \yii\log\Dispatcher::init 初始化注冊(cè)的target
/**
* @inheritdoc
*/
public function init()
{
parent::init();
foreach ($this->targets as $name => $target) {
if (!$target instanceof Target) {
$this->targets[$name] = Yii::createObject($target);
}
}
}
關(guān)鍵步驟就是以上了。
- 打日志朗涩,調(diào)用 Yii::error.
- 1.調(diào)用 Yii::error其實(shí)就是調(diào)用\yii\BaseYii::error
/**
* 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 string $category the category of the message.
*/
public static function error($message, $category = 'application')
{
static::getLogger()->log($message, Logger::LEVEL_ERROR, $category);
}
- 2.再看getLogger
/**
* @return Logger message logger
*/
public static function getLogger()
{
if (self::$_logger !== null) {
return self::$_logger;
} else {
return self::$_logger = static::createObject('yii\log\Logger'); //返回單例
}
}
- 3. 注意到初始化組件的時(shí)候谢床, \yii\log\Dispatcher::getLogger調(diào)用的就是上面的 getLogger()厘线,
所以皆的,這是同一個(gè)對(duì)象來的,打日志就可以用logger里面的dispatcher來管理target了费薄,target就是執(zhí)行寫日志的功能。