Commit 83a45ad1 by Qiang Xue

Improved debug backtrace tracking.

parent 52e5a5dd
......@@ -26,12 +26,6 @@ defined('YII_DEBUG') or define('YII_DEBUG', false);
*/
defined('YII_ENV') or define('YII_ENV', 'prod');
/**
* This constant defines how much call stack information (file name and line number) should be logged by Yii::trace().
* Defaults to 0, meaning no backtrace information. If it is greater than 0,
* at most that number of call stacks will be logged. Note, only user application call stacks are considered.
*/
defined('YII_TRACE_LEVEL') or define('YII_TRACE_LEVEL', 0);
/**
* This constant defines the framework installation directory.
*/
defined('YII_PATH') or define('YII_PATH', __DIR__);
......
......@@ -36,3 +36,10 @@
span.indent {
color: #ccc;
}
ul.trace {
font-size: 12px;
color: #666;
margin: 2px 0 0 20px;
}
......@@ -52,19 +52,28 @@ EOD;
{
$rows = array();
foreach ($this->data['messages'] as $log) {
$time = date('H:i:s.', $log[3]) . sprintf('%03d', (int)(($log[3] - (int)$log[3]) * 1000));
$level = Logger::getLevelName($log[1]);
$message = Html::encode(wordwrap($log[0]));
if ($log[1] == Logger::LEVEL_ERROR) {
list ($message, $level, $category, $time, $traces) = $log;
$time = date('H:i:s.', $time) . sprintf('%03d', (int)(($time - (int)$time) * 1000));
$message = Html::encode($message);
if (!empty($traces)) {
$message .= Html::ul($traces, array(
'class' => 'trace',
'item' => function ($trace) {
return "<li>{$trace['file']}({$trace['line']})</li>";
},
));
}
if ($level == Logger::LEVEL_ERROR) {
$class = ' class="error"';
} elseif ($log[1] == Logger::LEVEL_WARNING) {
} elseif ($level == Logger::LEVEL_WARNING) {
$class = ' class="warning"';
} elseif ($log[1] == Logger::LEVEL_INFO) {
} elseif ($level == Logger::LEVEL_INFO) {
$class = ' class="info"';
} else {
$class = '';
}
$rows[] = "<tr$class><td style=\"width: 100px;\">$time</td><td style=\"width: 100px;\">$level</td><td style=\"width: 250px;\">{$log[2]}</td><td>$message</td></tr>";
$level = Logger::getLevelName($level);
$rows[] = "<tr$class><td style=\"width: 100px;\">$time</td><td style=\"width: 100px;\">$level</td><td style=\"width: 250px;\">$category</td><td>$message</td></tr>";
}
$rows = implode("\n", $rows);
return <<<EOD
......
......@@ -111,6 +111,7 @@ class Logger extends Component
* [1] => level (integer)
* [2] => category (string)
* [3] => timestamp (float, obtained by microtime(true))
* [4] => traces (array, debug backtrace, contains the application code call stacks)
* )
* ~~~
*/
......@@ -133,6 +134,12 @@ class Logger extends Component
* A smaller value means less memory, but will increase the execution time due to the overhead of [[flush()]].
*/
public $flushInterval = 1000;
/**
* @var integer how much call stack information (file name and line number) should be logged for each message.
* Defaults to 0, meaning no backtrace information. If it is greater than 0,
* at most that number of call stacks will be logged. Only application call stacks are considered.
*/
public $traceLevel = 0;
/**
* Initializes the logger by registering [[flush()]] as a shutdown function.
......@@ -150,8 +157,8 @@ class Logger extends Component
/**
* Logs a message with the given type and category.
* If `YII_DEBUG` is true and `YII_TRACE_LEVEL` is greater than 0, then additional
* call stack information about application code will be appended to the message.
* If [[traceLevel]] is greater than 0, additional call stack information about
* the application code will be logged as well.
* @param string $message the message to be logged.
* @param integer $level the level of the message. This must be one of the following:
* `Logger::LEVEL_ERROR`, `Logger::LEVEL_WARNING`, `Logger::LEVEL_INFO`, `Logger::LEVEL_TRACE`,
......@@ -161,19 +168,22 @@ class Logger extends Component
public function log($message, $level, $category = 'application')
{
$time = microtime(true);
if (YII_DEBUG && YII_TRACE_LEVEL > 0 && !($level & self::LEVEL_PROFILE)) {
$traces = debug_backtrace();
$traces = array();
if ($this->traceLevel > 0) {
$count = 0;
foreach ($traces as $trace) {
$ts = debug_backtrace();
array_pop($ts); // remove the last trace since it would be the entry script, not very useful
foreach ($ts as $trace) {
if (isset($trace['file'], $trace['line']) && strpos($trace['file'], YII_PATH) !== 0) {
$message .= "\nin {$trace['file']} ({$trace['line']})";
if (++$count >= YII_TRACE_LEVEL) {
unset($trace['object'], $trace['args']);
$traces[] = $trace;
if (++$count >= $this->traceLevel) {
break;
}
}
}
}
$this->messages[] = array($message, $level, $category, $time);
$this->messages[] = array($message, $level, $category, $time, $traces);
if ($this->flushInterval > 0 && count($this->messages) >= $this->flushInterval) {
$this->flush();
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment