Yii的log分析

来源:互联网 发布:淘宝官方网电话是多少 编辑:程序博客网 时间:2024/05/16 05:02

我们可以通过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。 
Java代码  收藏代码
  1. 'components'=>array(  
  2.      ...............  
  3.      'log'=>array(  
  4.                'class'=>'CLogRouter',  
  5.                'routes'=>array(  
  6.                     array(  
  7.                          'class'=>'CFileLogRoute',  
  8.                          'levels'=>'trace,error',  
  9.                          'categories'=>'orange.*'  
  10.                     ),  
  11.                ),  
  12.           ),  
  13.      ...............  
  14. )  

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

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



Yii的日志主要由CLogger,CLogRoute,CLogRouter三类来完成,其中CLogger在内存中记录日志信息,CLogRoute用不同的方式处理日志信息,CLogRouter将CLogger记录的信息发送给各个CLogRoute进行处理。类图如下: 

在此简单介绍一下路由的整个过程: 
1.Yii类中CLogger的实例化,调用 Yii::log('This is a  trace log','trace','orange.test');时,Yii类(其实是YiiBase是如何反应的。 
代码路径:framework\YiiBase.php#461 
Java代码  收藏代码
  1. public static function log($msg,$level=CLogger::LEVEL_INFO,$category='application')  
  2.      {  
  3.           if(self::$_logger===null)  
  4.                self::$_logger=new CLogger;//如果_logger为null,则实例化Clogger类  
  5.           if(YII_DEBUG && YII_TRACE_LEVEL>0 && $level!==CLogger::LEVEL_PROFILE)  
  6.           {  
  7.             // YII_TRACE_LEVEL 设置backtrace 显示的内容条数,  
  8.             //这个常量会在debug_backtrace 函数返回信息中,获取指定条数,  
  9.             //如果为0(默认) 则为全部显示  
  10.                $traces=debug_backtrace();  
  11.                //debug_backtrace() 函数生成一个 backtrace,返回关联数组的数组,可以参考文档  
  12.                $count=0;  
  13.                foreach($traces as $trace)  
  14.                {  
  15.                     if(isset($trace['file'],$trace['line']) && strpos($trace['file'],YII_PATH)!==0)  
  16.                     {  
  17.                          $msg.="\nin ".$trace['file'].' ('.$trace['line'].')';  
  18.                          if(++$count>=YII_TRACE_LEVEL)  
  19.                               break;  
  20.                     }  
  21.                }  
  22.           }  
  23.           self::$_logger->log($msg,$level,$category);//调用_logger的方法处理日志  
  24.      }  

主要功能就是上下2条语句。 
2.CLogger的log方法 
Java代码  收藏代码
  1. class CLogger extends CComponent  
  2. {  
  3.      const LEVEL_TRACE='trace';  
  4.      const LEVEL_WARNING='warning';  
  5.      const LEVEL_ERROR='error';  
  6.      const LEVEL_INFO='info';  
  7.      const LEVEL_PROFILE='profile';  
  8.      .......................  
  9.     public function log($message,$level='info',$category='application')  
  10.      {  
  11.         //保存日志(日志为一个数组,包括信息、级别、过滤、发生时间4内容)  
  12.           $this->_logs[]=array($message,$level,$category,microtime(true));  
  13.           //记录的日志个数自增1  
  14.           $this->_logCount++;  
  15.         //autoFlush为整数,表示在它们被刷新到目录前多少信息应该被记录。  
  16.         //默认到10,000, 意味着每10,000条信息,这个flush方法自动被发起一次信息。  
  17.         //如果为0,它意味着信息不会被自动刷新,一直保存到_logs[]中,直到调用raise onFlush事。  
  18.         //_processing表示我们是否正在处理log  
  19.           if($this->autoFlush>0 && $this->_logCount>=$this->autoFlush && !$this->_processing)  
  20.           {  
  21.                $this->_processing=true;  
  22.             //autoDump默认时,这个属性为false,意味着每次flush()日志之后已经过滤的信息仍然保存在内在中。  
  23.             //如果为true,已过滤的信息被保存在实际的媒介中  
  24.                $this->flush($this->autoDump);  
  25.                $this->_processing=false;  
  26.           }  
  27.      }  
  28.   ...........................  
  29.      public function flush($dumpLogs=false)  
  30.      {  
  31.           $this->onFlush(new CEvent($this, array('dumpLogs'=>$dumpLogs)));  
  32.           $this->_logs=array();//清空日志  
  33.           $this->_logCount=0;  
  34.      }  
  35.   
  36.      public function onFlush($event)  
  37.      {  
  38.         //唤醒绑定在onFlush事件处理函数  
  39.           $this->raiseEvent('onFlush', $event);  
  40.      }  
  41. ................................  
  42. }  

3.绑定在onFlush事件处理函数 
这是我们的CLogRouter就出场了,CWebApplication根据mian.php中的配置实例化CLogRouter,并执行其init方法 
Java代码  收藏代码
  1. class CLogRouter extends CApplicationComponent  
  2. {  
  3.      private $_routes=array();  
  4.      public function init()  
  5.      {  
  6.           parent::init();  
  7.           foreach($this->_routes as $name=>$route)  
  8.           {  
  9.             //读取各个CLogRoute的配置,实例化  
  10.                $route=Yii::createComponent($route);  
  11.             //调用各个CLogRoute的init方法  
  12.                $route->init();  
  13.             //保存各个CLogRoute到_routes中  
  14.                $this->_routes[$name]=$route;  
  15.           }  
  16.         //给CLogger onFlush事件绑定处理函数,为本类的collectLogs方法  
  17.           Yii::getLogger()->attachEventHandler('onFlush',array($this,'collectLogs'));  
  18.          //给CWebApplication  onEndRequest事件绑定处理函数,为本类的processLogs方法  
  19.           Yii::app()->attachEventHandler('onEndRequest',array($this,'processLogs'));  
  20.      }  
  21.     ..........................  
  22.      //收集log  
  23.    public function collectLogs($event)  
  24.      {  
  25.           $logger=Yii::getLogger();  
  26.           $dumpLogs=isset($event->params['dumpLogs']) && $event->params['dumpLogs'];  
  27.           foreach($this->_routes as $route)  
  28.           {  
  29.                if($route->enabled)  
  30.                     //调用各个CLogRoute的collectLogs到记录所有日志的CLogger类中按照  
  31.                    //自己的level和categories取出自己处理的log,也可立刻处理log(这也要看dumplogs的真假,为真则为立即处理)  
  32.                     $route->collectLogs($logger,$dumpLogs);  
  33.           }  
  34.      }  
  35.   //收集处理log  
  36.      public function processLogs($event)  
  37.      {  
  38.           $logger=Yii::getLogger();  
  39.           foreach($this->_routes as $route)  
  40.           {  
  41.                if($route->enabled)  
  42.                     //同上,但是此处为立刻处理log  
  43.                     $route->collectLogs($logger,true);  
  44.           }  
  45.      }  
  46. ..................  
  47. }  


4.调用各个CLogRoute处理日志,CLogRoute的collectLogs方法 
Java代码  收藏代码
  1. abstract class CLogRoute extends CComponent  
  2. {  
  3.        public $levels='';//过滤log用  
  4.        public $categories='';//过滤log用  
  5.        ........................  
  6.       public function collectLogs($logger, $processLogs=false)  
  7.      {  
  8.           //按照过滤条件到CLogger中去log  
  9.           $logs=$logger->getLogs($this->levels,$this->categories);  
  10.           $this->logs=empty($this->logs) ? $logs : array_merge($this->logs,$logs);  
  11.           //如果设置要立刻处理  
  12.           if($processLogs && !empty($this->logs))  
  13.           {  
  14.                if($this->filter!==null)  
  15.                     Yii::createComponent($this->filter)->filter($this->logs);  
  16.                if($this->logs!==array())  
  17.                     //处理  
  18.                     $this->processLogs($this->logs);  
  19.                $this->logs=array();  
  20.           }  
  21.      }  
  22.   
  23.      /** 
  24.      *处理日志信息并发送它们到指定的目标。 派生子类必须实现这个方法。 
  25.      *$logs为信息列表。每一个数组元素表示一个信息, 有下面的结构: array( 
  26.      *[0] => message (string) 
  27.      *[1] => level (string) 
  28.      *[2] => category (string) 
  29.      *[3] => timestamp (float, 从 microtime(true)获取) 
  30.      *  ) 
  31.      */  
  32.      abstract protected function processLogs($logs);  
  33.   ........................  
  34. }  


  其中CDbLogRoute实现方式为 

   
Java代码  收藏代码
  1. protected function processLogs($logs)  
  2.     {  
  3.          $command=$this->getDbConnection()->createCommand();  
  4.          foreach($logs as $log)  
  5.          {  
  6.               //遍历数组插入到数据库  
  7.               $command->insert($this->logTableName,array(  
  8.                    'level'=>$log[1],  
  9.                    'category'=>$log[2],  
  10.                    'logtime'=>(int)$log[3],  
  11.                    'message'=>$log[0],  
  12.               ));  
  13.          }  
  14.     }  
0 0
原创粉丝点击