Yii的log分析

我们可以通过Yii的日志级别和信息分类进行归类,所选的信息还可以进一步设置信息路由到答不同的目的地,例如一个文件,数据库,Email,浏览器窗口等。

日志级别有:

* trace: 这是在 Yii::trace 中使用的级别。它用于在开发中 跟踪程序的执行流程。
* info: 这个用于记录普通的信息。
* profile: 这个是性能概述(profile)。下面马上会有更详细的说明。
* warning: 这个用于警告(warning)信息。
* error: 这个用于致命错误(fatal error)信息。

在 Yii 中,有下列几种日志路由可用:

* CDbLogRoute: 将信息保存到数据库的表中。
* CEmailLogRoute: 发送信息到指定的 Email 地址。
* CFileLogRoute: 保存信息到应用程序 runtime 目录中的一个文件中。
* CWebLogRoute: 将 信息 显示在当前页面的底部。
* CProfileLogRoute: 在页面的底部显示概述(profiling)信息。

信息可以通过 Yii::log 或 Yii::trace 记录。其 区别是后者只在当应用程序运行在 调试模式(debug mode) 中时才会记录信息。
Yii::log($message, $level, $category);
Yii::trace($message, $category);


示例:
需先在main.php中进行配置,例子选择将日志存储在文件(系统默认为webapp\protected\runtime\application.log)中,为只存储trace和error级别,过滤以orange开始的log。
'components'=>array(
...............
'log'=>array(
'class'=>'CLogRouter',
'routes'=>array(
array(
'class'=>'CFileLogRoute',
'levels'=>'trace,error',
'categories'=>'orange.*'
),
),
),
...............
)


在控制器中定义方法并执行,在此为OrangeController控制器
 public function actionTest(){
Yii::log('This is a trace log','trace','orange.test');
}

执行以后可在日志文件中看到我们的trace信息,为
2012/09/28 15:40:11 [trace] [orange.test] This is a  trace log
in D:\PHP\www\yii\orange\protected\controllers\OrangeController.php (24)



Yii的日志主要由CLogger,CLogRoute,CLogRouter三类来完成,其中CLogger在内存中记录日志信息,CLogRoute用不同的方式处理日志信息,CLogRouter将CLogger记录的信息发送给各个CLogRoute进行处理。类图如下:
[img]http://dl.iteye.com/upload/attachment/0074/5181/2002c055-709b-3337-89b8-181024053831.png[/img]
在此简单介绍一下路由的整个过程:
1.Yii类中CLogger的实例化,调用 Yii::log('This is a trace log','trace','orange.test');时,Yii类(其实是YiiBase是如何反应的。
代码路径:framework\YiiBase.php#461
public static function log($msg,$level=CLogger::LEVEL_INFO,$category='application')
{
if(self::$_logger===null)
self::$_logger=new CLogger;//如果_logger为null,则实例化Clogger类
if(YII_DEBUG && YII_TRACE_LEVEL>0 && $level!==CLogger::LEVEL_PROFILE)
{
// YII_TRACE_LEVEL 设置backtrace 显示的内容条数,
//这个常量会在debug_backtrace 函数返回信息中,获取指定条数,
//如果为0(默认) 则为全部显示
$traces=debug_backtrace();
//debug_backtrace() 函数生成一个 backtrace,返回关联数组的数组,可以参考文档
$count=0;
foreach($traces as $trace)
{
if(isset($trace['file'],$trace['line']) && strpos($trace['file'],YII_PATH)!==0)
{
$msg.="\nin ".$trace['file'].' ('.$trace['line'].')';
if(++$count>=YII_TRACE_LEVEL)
break;
}
}
}
self::$_logger->log($msg,$level,$category);//调用_logger的方法处理日志
}

主要功能就是上下2条语句。
2.CLogger的log方法
class CLogger extends CComponent
{
const LEVEL_TRACE='trace';
const LEVEL_WARNING='warning';
const LEVEL_ERROR='error';
const LEVEL_INFO='info';
const LEVEL_PROFILE='profile';
.......................
public function log($message,$level='info',$category='application')
{
//保存日志(日志为一个数组,包括信息、级别、过滤、发生时间4内容)
$this->_logs[]=array($message,$level,$category,microtime(true));
//记录的日志个数自增1
$this->_logCount++;
//autoFlush为整数,表示在它们被刷新到目录前多少信息应该被记录。
//默认到10,000, 意味着每10,000条信息,这个flush方法自动被发起一次信息。
//如果为0,它意味着信息不会被自动刷新,一直保存到_logs[]中,直到调用raise onFlush事。
//_processing表示我们是否正在处理log
if($this->autoFlush>0 && $this->_logCount>=$this->autoFlush && !$this->_processing)
{
$this->_processing=true;
//autoDump默认时,这个属性为false,意味着每次flush()日志之后已经过滤的信息仍然保存在内在中。
//如果为true,已过滤的信息被保存在实际的媒介中
$this->flush($this->autoDump);
$this->_processing=false;
}
}
...........................
public function flush($dumpLogs=false)
{
$this->onFlush(new CEvent($this, array('dumpLogs'=>$dumpLogs)));
$this->_logs=array();//清空日志
$this->_logCount=0;
}

public function onFlush($event)
{
//唤醒绑定在onFlush事件处理函数
$this->raiseEvent('onFlush', $event);
}
................................
}

3.绑定在onFlush事件处理函数
这是我们的CLogRouter就出场了,CWebApplication根据mian.php中的配置实例化CLogRouter,并执行其init方法
class CLogRouter extends CApplicationComponent
{
private $_routes=array();
public function init()
{
parent::init();
foreach($this->_routes as $name=>$route)
{
//读取各个CLogRoute的配置,实例化
$route=Yii::createComponent($route);
//调用各个CLogRoute的init方法
$route->init();
//保存各个CLogRoute到_routes中
$this->_routes[$name]=$route;
}
//给CLogger onFlush事件绑定处理函数,为本类的collectLogs方法
Yii::getLogger()->attachEventHandler('onFlush',array($this,'collectLogs'));
//给CWebApplication onEndRequest事件绑定处理函数,为本类的processLogs方法
Yii::app()->attachEventHandler('onEndRequest',array($this,'processLogs'));
}
..........................
//收集log
public function collectLogs($event)
{
$logger=Yii::getLogger();
$dumpLogs=isset($event->params['dumpLogs']) && $event->params['dumpLogs'];
foreach($this->_routes as $route)
{
if($route->enabled)
//调用各个CLogRoute的collectLogs到记录所有日志的CLogger类中按照
//自己的level和categories取出自己处理的log,也可立刻处理log(这也要看dumplogs的真假,为真则为立即处理)
$route->collectLogs($logger,$dumpLogs);
}
}
//收集处理log
public function processLogs($event)
{
$logger=Yii::getLogger();
foreach($this->_routes as $route)
{
if($route->enabled)
//同上,但是此处为立刻处理log
$route->collectLogs($logger,true);
}
}
..................
}


4.调用各个CLogRoute处理日志,CLogRoute的collectLogs方法
abstract class CLogRoute extends CComponent
{
public $levels='';//过滤log用
public $categories='';//过滤log用
........................
public function collectLogs($logger, $processLogs=false)
{
//按照过滤条件到CLogger中去log
$logs=$logger->getLogs($this->levels,$this->categories);
$this->logs=empty($this->logs) ? $logs : array_merge($this->logs,$logs);
//如果设置要立刻处理
if($processLogs && !empty($this->logs))
{
if($this->filter!==null)
Yii::createComponent($this->filter)->filter($this->logs);
if($this->logs!==array())
//处理
$this->processLogs($this->logs);
$this->logs=array();
}
}

/**
*处理日志信息并发送它们到指定的目标。 派生子类必须实现这个方法。
*$logs为信息列表。每一个数组元素表示一个信息, 有下面的结构: array(
*[0] => message (string)
*[1] => level (string)
*[2] => category (string)
*[3] => timestamp (float, 从 microtime(true)获取)
* )
*/
abstract protected function processLogs($logs);
........................


其中CDbLogRoute实现方式为

 protected function processLogs($logs)
{
$command=$this->getDbConnection()->createCommand();
foreach($logs as $log)
{
//遍历数组插入到数据库
$command->insert($this->logTableName,array(
'level'=>$log[1],
'category'=>$log[2],
'logtime'=>(int)$log[3],
'message'=>$log[0],
));
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值