Вход Регистрация
Файл: framework/logging/CProfileLogRoute.php
Строк: 169
<?php
/**
 * CProfileLogRoute class file.
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @link http://www.yiiframework.com/
 * @copyright Copyright &copy; 2008-2011 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 */

/**
 * CProfileLogRoute displays the profiling results in Web page.
 *
 * The profiling is done by calling {@link YiiBase::beginProfile()} and {@link YiiBase::endProfile()},
 * which marks the begin and end of a code block.
 *
 * CProfileLogRoute supports two types of report by setting the {@link setReport report} property:
 * <ul>
 * <li>summary: list the execution time of every marked code block</li>
 * <li>callstack: list the mark code blocks in a hierarchical view reflecting their calling sequence.</li>
 * </ul>
 *
 * @property string $report The type of the profiling report to display. Defaults to 'summary'.
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @package system.logging
 * @since 1.0
 */
class CProfileLogRoute extends CWebLogRoute
{
    
/**
     * @var boolean whether to aggregate results according to profiling tokens.
     * If false, the results will be aggregated by categories.
     * Defaults to true. Note that this property only affects the summary report
     * that is enabled when {@link report} is 'summary'.
     */
    
public $groupByToken=true;
    
/**
     * @var string type of profiling report to display
     */
    
private $_report='summary';

    
/**
     * Initializes the route.
     * This method is invoked after the route is created by the route manager.
     */
    
public function init()
    {
        
$this->levels=CLogger::LEVEL_PROFILE;
    }

    
/**
     * @return string the type of the profiling report to display. Defaults to 'summary'.
     */
    
public function getReport()
    {
        return 
$this->_report;
    }

    
/**
     * @param string $value the type of the profiling report to display. Valid values include 'summary' and 'callstack'.
     */
    
public function setReport($value)
    {
        if(
$value==='summary' || $value==='callstack')
            
$this->_report=$value;
        else
            throw new 
CException(Yii::t('yii','CProfileLogRoute.report "{report}" is invalid. Valid values include "summary" and "callstack".',
                array(
'{report}'=>$value)));
    }

    
/**
     * Displays the log messages.
     * @param array $logs list of log messages
     */
    
public function processLogs($logs)
    {
        
$app=Yii::app();
        if(!(
$app instanceof CWebApplication) || $app->getRequest()->getIsAjaxRequest())
            return;

        if(
$this->getReport()==='summary')
            
$this->displaySummary($logs);
        else
            
$this->displayCallstack($logs);
    }

    
/**
     * Displays the callstack of the profiling procedures for display.
     * @param array $logs list of logs
     */
    
protected function displayCallstack($logs)
    {
        
$stack=array();
        
$results=array();
        
$n=0;
        foreach(
$logs as $log)
        {
            if(
$log[1]!==CLogger::LEVEL_PROFILE)
                continue;
            
$message=$log[0];
            if(!
strncasecmp($message,'begin:',6))
            {
                
$log[0]=substr($message,6);
                
$log[4]=$n;
                
$stack[]=$log;
                
$n++;
            }
            elseif(!
strncasecmp($message,'end:',4))
            {
                
$token=substr($message,4);
                if((
$last=array_pop($stack))!==null && $last[0]===$token)
                {
                    
$delta=$log[3]-$last[3];
                    
$results[$last[4]]=array($token,$delta,count($stack));
                }
                else
                    throw new 
CException(Yii::t('yii','CProfileLogRoute found a mismatching code block "{token}". Make sure the calls to Yii::beginProfile() and Yii::endProfile() be properly nested.',
                        array(
'{token}'=>$token)));
            }
        }
        
// remaining entries should be closed here
        
$now=microtime(true);
        while((
$last=array_pop($stack))!==null)
            
$results[$last[4]]=array($last[0],$now-$last[3],count($stack));
        
ksort($results);
        
$this->render('profile-callstack',$results);
    }

    
/**
     * Displays the summary report of the profiling result.
     * @param array $logs list of logs
     */
    
protected function displaySummary($logs)
    {
        
$stack=array();
        foreach(
$logs as $log)
        {
            if(
$log[1]!==CLogger::LEVEL_PROFILE)
                continue;
            
$message=$log[0];
            if(!
strncasecmp($message,'begin:',6))
            {
                
$log[0]=substr($message,6);
                
$stack[]=$log;
            }
            elseif(!
strncasecmp($message,'end:',4))
            {
                
$token=substr($message,4);
                if((
$last=array_pop($stack))!==null && $last[0]===$token)
                {
                    
$delta=$log[3]-$last[3];
                    if(!
$this->groupByToken)
                        
$token=$log[2];
                    if(isset(
$results[$token]))
                        
$results[$token]=$this->aggregateResult($results[$token],$delta);
                    else
                        
$results[$token]=array($token,1,$delta,$delta,$delta);
                }
                else
                    throw new 
CException(Yii::t('yii','CProfileLogRoute found a mismatching code block "{token}". Make sure the calls to Yii::beginProfile() and Yii::endProfile() be properly nested.',
                        array(
'{token}'=>$token)));
            }
        }

        
$now=microtime(true);
        while((
$last=array_pop($stack))!==null)
        {
            
$delta=$now-$last[3];
            
$token=$this->groupByToken $last[0] : $last[2];
            if(isset(
$results[$token]))
                
$results[$token]=$this->aggregateResult($results[$token],$delta);
            else
                
$results[$token]=array($token,1,$delta,$delta,$delta);
        }

        
$entries=array_values($results);
        
$func=create_function('$a,$b','return $a[4]<$b[4]?1:0;');
        
usort($entries,$func);

        
$this->render('profile-summary',$entries);
    }

    
/**
     * Aggregates the report result.
     * @param array $result log result for this code block
     * @param float $delta time spent for this code block
     * @return array
     */
    
protected function aggregateResult($result,$delta)
    {
        list(
$token,$calls,$min,$max,$total)=$result;
        if(
$delta<$min)
            
$min=$delta;
        elseif(
$delta>$max)
            
$max=$delta;
        
$calls++;
        
$total+=$delta;
        return array(
$token,$calls,$min,$max,$total);
    }
}
Онлайн: 1
Реклама