Yii提供了一个设置,用于分析所有SQL调用以及每个调用的执行时间(CProfileLogRoute)。只是它不适用于ajax调用。如何访问此数据?
我正在尝试寻找打开登录弹出窗口的ajax调用的瓶颈...
同样,CProfileLogRoute中显示的执行时间是否包括到SQL server的网络行程?我的数据库是由Amazon的RDS托管的,我想知道这是不是瓶颈所在(在本地似乎没问题)。
发布于 2012-11-15 00:33:35
您可以尝试以下面建议的方式扩展CFileLogRoute,并在应用程序的配置中启用它,如下所示:
'log'=>array(
'class'=>'CLogRouter',
'routes'=>array(
array(
'class'=>'ProfileLogRoute',
'levels' => "profile"
)
)
)在这种情况下,所有已分析的查询都将写入位于protected/runtime目录下的日志文件中(覆盖processLogs方法也是如此,CProfileWebRoute...unfortunately CProfileWebRoute的摘要报告是从CWebLogRoute派生的):
<?php
class ProfileLogRoute extends CFileLogRoute
{
protected function processLogs($logs)
{
$logFile=$this->getLogPath().DIRECTORY_SEPARATOR.$this->getLogFile();
if(@filesize($logFile)>$this->getMaxFileSize()*1024)
$this->rotateFiles();
$fp=@fopen($logFile,'a');
@flock($fp,LOCK_EX);
$profileStack = array();
$profileResults = array();
foreach ($logs as $log)
{
if ($log[1] === CLogger::LEVEL_PROFILE)
{
$message = $log[0];
if (!strncasecmp($message, 'begin:', 6))
{
$log[0] = substr($message,6);
$profileStack[] = $log;
}
else if(!strncasecmp($message, 'end:', 4))
{
$token = substr($message,4);
if(($last = array_pop($profileStack)) !== null && $last[0] === $token)
{
$info = array(
'delta' => $log[3] - $last[3],
'category' => $last[2],
'time' => $last[3]
);
$this->aggregateResult($token, $info, $profileResults);
}
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)));
}
}
}
else
{
@fwrite($fp,$this->formatLogMessage($log[0],$log[1],$log[2],$log[3]));
}
}
if (!empty($profileResults))
{
$now = microtime(true);
while(($last = array_pop($profileStack)) !== null)
{
$info = array(
'delta' => $now - $last[3],
'category' => $last[2],
'time' => $last[3]
);
$token = $last[0];
$this->aggregateResult($token, $info, $profileResults);
}
$entries = array_values($profileResults);
$func = create_function('$a,$b','return $a["total"]<$b["total"]?1:0;');
usort($entries, $func);
foreach ($entries as $entry)
{
$message = sprintf("Min: % 11.8f Max: % 11.8f Total: % 11.8f Calls: % 3d %s", $entry['min'], $entry['max'], $entry['total'], $entry['calls'], $entry['token']);
@fwrite($fp, $this->formatLogMessage($message, CLogger::LEVEL_PROFILE, $entry['category'], $entry['time']));
}
}
@flock($fp,LOCK_UN);
@fclose($fp);
}
protected function aggregateResult($token, $info, &$results)
{
if (isset($results[$token]))
{
if ($info['delta'] < $results[$token]['min'])
$results[$token]['min'] = $info['delta'];
else if($info['delta'] > $results[$token]['max'])
$results[$token]['max'] = $info['delta'];
$results[$token]['calls']++;
$results[$token]['total'] += $info['delta'];
return;
}
$results[$token] = array(
'token' => $token,
'calls' => 1,
'min' => $info['delta'],
'max' => $info['delta'],
'total' => $info['delta'],
'category' => $info['category'],
'time' => $info['time']
);
}
}如果您想知道Yii是如何度量SQL执行时间的,可以查看CDbCommand类的源代码-- queryInternal方法,更准确地说。分析位于Yii::beginProfile('system.db.CDbCommand.query...')和Yii::endProfile('system.db.CDbCommand.query...')调用之间。正如您所看到的,这两个调用都在相同的方法中,因此分析时间不包括网络传输。问题可能在于您的远程数据库服务器在巨大的负载下运行。
发布于 2013-07-11 04:16:49
CProfileLogRoute类有一个名为ignoreAjaxInFireBug的属性,它的缺省值为"true“。通过将其设置为false,您可以获得有关ajax请求的分析信息。
http://www.yiiframework.com/doc/api/1.1/CWebLogRoute#ignoreAjaxInFireBug-detail
'log'=>array(
'class'=>'CLogRouter',
'routes'=>array(
array(
'class'=>'CProfileLogRoute',
'ignoreAjaxInFireBug'=>false,
'levels'=>'error, warning, trace, info, profile',
),
),我不认为你需要使用firebug来完成这项工作(这是一种用词不当的说法)。然而,如果你这样做了,只需下载firefox并安装firebug,那么你的问题仍然可以解决。
https://stackoverflow.com/questions/13332143
复制相似问题