Commit 6f6e739f by Qiang Xue

...

parent d991f42c
......@@ -416,27 +416,31 @@ class YiiBase
*
* ~~~
* \Yii::beginProfile('block1');
* \Yii::beginProfile('block2');
* \Yii::endProfile('block2');
* // some code to be profiled
* \Yii::beginProfile('block2');
* // some other code to be profiled
* \Yii::endProfile('block2');
* \Yii::endProfile('block1');
* ~~~
* @param string $category the category of this profile block
* @param string $token token for the code block
* @param string $category the category of this log message
* @see endProfile
*/
public static function beginProfile($category)
public static function beginProfile($token, $category)
{
self::getLogger()->beginProfile($category);
self::getLogger()->beginProfile($token, $category);
}
/**
* Marks the end of a code block for profiling.
* This has to be matched with a previous call to [[beginProfile]] with the same category name.
* @param string $category the category of this profile block
* @param string $token token for the code block
* @param string $category the category of this log message
* @see beginProfile
*/
public static function endProfile($category)
public static function endProfile($token, $category)
{
self::getLogger()->endProfile($category);
self::getLogger()->endProfile($token, $category);
}
/**
......
......@@ -196,14 +196,6 @@ class Connection extends \yii\base\ApplicationComponent
*/
public $emulatePrepare;
/**
* @var boolean whether to log the values that are bound to a prepare SQL statement.
* Defaults to false. During development, you may consider setting this property to true
* so that parameter values bound to SQL statements are logged for debugging purpose.
* You should be aware that logging parameter values could be expensive and have significant
* impact on the performance of your application.
*/
public $enableParamLogging = false;
/**
* @var boolean whether to enable profiling for the SQL statements being executed.
* Defaults to false. This should be mainly enabled and used during development
* to find out the bottleneck of SQL executions.
......@@ -436,6 +428,8 @@ class Connection extends \yii\base\ApplicationComponent
{
if ($this->_transaction !== null && $this->_transaction->active) {
return $this->_transaction;
} else {
return null;
}
}
......@@ -536,6 +530,24 @@ class Connection extends \yii\base\ApplicationComponent
}
/**
* Prefixes table names in a SQL statement with [[tablePrefix]].
* By calling this method, tokens like '{{TableName}}' in the given SQL statement will
* be replaced with 'prefixTableName', where 'prefix' refers to [[tablePrefix]].
* Note that if [[tablePrefix]] is null, this method will do nothing.
* @param string $sql the SQL statement whose table names need to be prefixed with [[tablePrefix]].
* @return string the expanded SQL statement
* @see tablePrefix
*/
public function expandTablePrefix($sql)
{
if ($this->tablePrefix !== null && strpos($sql, '{{') !== false) {
return preg_replace('/{{(.*?)}}/', $this->tablePrefix . '\1', $sql);
} else {
return $sql;
}
}
/**
* Determines the PDO type for the give PHP data type.
* @param string $type The PHP type (obtained by `gettype()` call).
* @return integer the corresponding PDO type
......
......@@ -38,8 +38,13 @@ class QueryBuilder extends \yii\base\Object
'boolean' => 'tinyint(1)',
'money' => 'decimal(19,4)',
);
/**
* @var Connection the database connection.
*/
public $connection;
/**
* @var Schema the database schema
*/
public $schema;
public function __construct($schema)
......@@ -61,11 +66,7 @@ class QueryBuilder extends \yii\base\Object
$this->buildOrderBy($query),
$this->buildLimit($query),
);
$sql = implode("\n", array_filter($clauses));
if ($this->connection->tablePrefix !== null && strpos($sql, '{') !== false) {
$sql = preg_replace('/{{(.*?)}}/', $this->connection->tablePrefix . '\1', $sql);
}
return $sql;
return $this->connection->expandTablePrefix(implode("\n", array_filter($clauses)));
}
/**
......@@ -74,7 +75,6 @@ class QueryBuilder extends \yii\base\Object
* @param string $table the table that new rows will be inserted into.
* @param array $columns the column data (name=>value) to be inserted into the table.
* @return integer number of rows affected by the execution.
* @since 1.1.6
*/
public function insert($table, $columns, &$params = array())
{
......
......@@ -50,7 +50,7 @@ class EmailTarget extends Target
$body .= $this->formatMessage($message);
}
$body = wordwrap($body, 70);
$subject = $this->subject === null ? Yii::t('yii', 'Application Log') : $this->subject;
$subject = $this->subject === null ? \Yii::t('yii', 'Application Log') : $this->subject;
foreach ($this->emails as $email) {
$this->sendEmail($subject, $body, $email, $this->sentFrom, $this->headers);
}
......@@ -71,6 +71,6 @@ class EmailTarget extends Target
if ($sentFrom !== null) {
$headers[] = "From: {$sentFrom}";
}
mail($email, $subject, $body, implode("\r\n", $headers));
mail($sentTo, $subject, $body, implode("\r\n", $headers));
}
}
\ No newline at end of file
......@@ -96,8 +96,7 @@ class FileTarget extends Target
// suppress errors because it's possible multiple processes enter into this section
if ($i === $this->maxLogFiles) {
@unlink($rotateFile);
}
else {
} else {
@rename($rotateFile, $file . '.' . ($i + 1));
}
}
......
......@@ -22,11 +22,12 @@ namespace yii\logging;
*/
class Logger extends \yii\base\Component
{
const LEVEL_TRACE = 'trace';
const LEVEL_WARNING = 'warning';
const LEVEL_ERROR = 'error';
const LEVEL_INFO = 'info';
const LEVEL_PROFILE = 'profile';
const LEVEL_ERROR = 1;
const LEVEL_WARNING = 2;
const LEVEL_INFO = 3;
const LEVEL_TRACE = 4;
const LEVEL_PROFILE_BEGIN = 5;
const LEVEL_PROFILE_END = 6;
/**
* @var integer how many messages should be logged before they are flushed from memory and sent to targets.
......@@ -111,23 +112,25 @@ class Logger extends \yii\base\Component
* Marks the beginning of a code block for profiling.
* This has to be matched with a call to [[endProfile]] with the same category name.
* The begin- and end- calls must also be properly nested. For example,
* @param string $category the category of this profile block
* @param string $token token for the code block
* @param string $category the category of this log message
* @see endProfile
*/
public function beginProfile($category)
public function beginProfile($token, $category)
{
$this->log('begin', self::LEVEL_PROFILE, $category);
$this->log($token, self::LEVEL_PROFILE_BEGIN, $category);
}
/**
* Marks the end of a code block for profiling.
* This has to be matched with a previous call to [[beginProfile]] with the same category name.
* @param string $category the category of this profile block
* @param string $token token for the code block
* @param string $category the category of this log message
* @see beginProfile
*/
public function endProfile($category)
public function endProfile($token, $category)
{
$this->log('end', self::LEVEL_PROFILE, $category);
$this->log($token, self::LEVEL_PROFILE_END, $category);
}
/**
......@@ -141,11 +144,11 @@ class Logger extends \yii\base\Component
*/
public function log($message, $level, $category)
{
if (YII_DEBUG && YII_TRACE_LEVEL > 0 && $level !== self::LEVEL_PROFILE) {
if (YII_DEBUG && YII_TRACE_LEVEL > 0 && $level <= self::LEVEL_TRACE) {
$traces = debug_backtrace();
$count = 0;
foreach ($traces as $trace) {
if (isset($trace['file'], $trace['line']) && strpos($trace['file'], YII_DIR) !== 0) {
if (isset($trace['file'], $trace['line']) && strpos($trace['file'], YII_PATH) !== 0) {
$message .= "\nin " . $trace['file'] . ' (' . $trace['line'] . ')';
if (++$count >= YII_TRACE_LEVEL) {
break;
......@@ -206,7 +209,7 @@ class Logger extends \yii\base\Component
* such as 'yii\db\dao\Connection'.
* @param array $excludeCategories list of categories that you are interested in.
* @return array the profiling results. Each array element has the following structure:
* `array($category, $time)`.
* `array($token, $category, $time)`.
*/
public function getProfiling($categories = array(), $excludeCategories = array())
{
......@@ -219,7 +222,7 @@ class Logger extends \yii\base\Component
$matched = empty($categories);
foreach ($categories as $category) {
$prefix = rtrim($category, '*');
if (strpos($timing[0], $prefix) === 0 && ($timing[0] === $category || $prefix !== $category)) {
if (strpos($timing[1], $prefix) === 0 && ($timing[1] === $category || $prefix !== $category)) {
$matched = true;
break;
}
......@@ -229,7 +232,7 @@ class Logger extends \yii\base\Component
foreach ($excludeCategories as $category) {
$prefix = rtrim($category, '*');
foreach ($timings as $i => $timing) {
if (strpos($timing[0], $prefix) === 0 && ($timing[0] === $category || $prefix !== $category)) {
if (strpos($timing[1], $prefix) === 0 && ($timing[1] === $category || $prefix !== $category)) {
$matched = false;
break;
}
......@@ -250,20 +253,17 @@ class Logger extends \yii\base\Component
$stack = array();
foreach ($this->messages as $log) {
if ($log[1] !== self::LEVEL_PROFILE) {
if ($log[1] < self::LEVEL_PROFILE_BEGIN) {
continue;
}
list($message, $level, $category, $timestamp) = $log;
if ($message === 'begin') {
list($token, $level, $category, $timestamp) = $log;
if ($level === self::LEVEL_PROFILE_BEGIN) {
$stack[] = $log;
}
else { // $message === 'end'
if (($last = array_pop($stack)) !== null && $last[2] === $category) {
$delta = $timestamp - $last[3];
$timings[] = array($category, $delta);
}
else {
throw new \yii\base\Exception('Found a mismatching profiling block: ' . $category);
} else {
if (($last = array_pop($stack)) !== null && $last[0] === $token) {
$timings[] = array($token, $category, $timestamp - $last[3]);
} else {
throw new \yii\base\Exception("Unmatched profiling block: $token");
}
}
}
......@@ -271,7 +271,7 @@ class Logger extends \yii\base\Component
$now = microtime(true);
while (($last = array_pop($stack)) !== null) {
$delta = $now - $last[3];
$timings[] = array($last[2], $delta);
$timings[] = array($last[0], $last[2], $delta);
}
return $timings;
......
......@@ -96,33 +96,33 @@ class CProfileLogRoute extends CWebLogRoute
$n = 0;
foreach ($logs as $log)
{
if ($log[1] !== CLogger::LEVEL_PROFILE)
if ($log[1] !== CLogger::LEVEL_PROFILE) {
continue;
}
$message = $log[0];
if (!strncasecmp($message, 'begin:', 6))
{
if (!strncasecmp($message, 'begin:', 6)) {
$log[0] = substr($message, 6);
$log[4] = $n;
$stack[] = $log;
$n++;
}
elseif (!strncasecmp($message, 'end:', 4))
{
} elseif (!strncasecmp($message, 'end:', 4)) {
$token = substr($message, 4);
if (($last = array_pop($stack)) !== null && $last[0] === $token)
{
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)
while (($last = array_pop($stack)) !== null) {
$results[$last[4]] = array($last[0], $now - $last[3], count($stack));
}
ksort($results);
$this->render('profile-callstack', $results);
}
......
......@@ -127,7 +127,7 @@ class Router extends \yii\base\ApplicationComponent
{
$messages = \Yii::getLogger()->messages;
$export = !isset($event->params['export']) || $event->params['export'];
$final = !isset($event-params['flush']) || !$event->params['flush'];
$final = !isset($event->params['flush']) || !$event->params['flush'];
foreach ($this->_targets as $target) {
if ($target->enabled) {
$target->processMessages($messages, $export, $final);
......
......@@ -116,7 +116,7 @@ abstract class Target extends \yii\base\Component implements \yii\base\Initable
/**
* Prepares the [[messages]] for exporting.
* This method will modify each message by prependding extra information
* This method will modify each message by prepending extra information
* if [[prefixSession]] and/or [[prefixUser]] are set true.
* It will also add an additional message showing context information if
* [[logUser]] and/or [[logVars]] are set.
......
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