@ -59,7 +59,7 @@ class Logger extends Component
*/
const LEVEL_INFO = 0x04;
/**
* Tracing message level. An tracing message is one that reveals the code execution flow.
* Tracing message level. A tracing message is one that reveals the code execution flow.
*/
const LEVEL_TRACE = 0x08;
/**
@ -67,13 +67,13 @@ class Logger extends Component
*/
const LEVEL_PROFILE = 0x40;
/**
* Profiling message level. This indicates the message is for profiling purpose. It marks the
* beginning of a profiling block.
* Profiling message level. This indicates the message is for profiling purpose. It marks the beginning
* of a profiling block.
*/
const LEVEL_PROFILE_BEGIN = 0x50;
/**
* Profiling message level. This indicates the message is for profiling purpose. It marks the
* end of a profiling block.
* Profiling message level. This indicates the message is for profiling purpose. It marks the end
* of a profiling block.
*/
const LEVEL_PROFILE_END = 0x60;
@ -95,7 +95,7 @@ class Logger extends Component
public $messages = [];
/**
* @var int how many messages should be logged before they are flushed from memory and sent to targets.
* Defaults to 1000, meaning the [[flush]] method will be invoked once every 1000 messages logged.
* Defaults to 1000, meaning the [[flush() ]] method will be invoked once every 1000 messages logged.
* Set this property to be 0 if you don't want to flush messages until the application terminates.
* This property mainly affects how much memory will be taken by the logged messages.
* A smaller value means less memory, but will increase the execution time due to the overhead of [[flush()]].
@ -116,13 +116,15 @@ class Logger extends Component
* @since 2.0.41
*/
public $dbEventNames = ['yii\db\Command::query', 'yii\db\Command::execute'];
/**
* @var array of profiling related messages.
* Structure of a log message is the same as in [[$messages]].
* @var bool whether the profiling-aware mode should be switched on.
* If on, [[flush()]] makes sure that profiling blocks are flushed in pairs. In case that any dangling messages are
* detected these are kept for the next flush interval to find their pair. To prevent memory leaks, when number of
* dangling messages reaches flushInterval value, logger flushes them immediately and triggers a warning.
* Keep in mind that profiling-aware mode is more time and memory consuming.
* @since 2.0.43
*/
protected $profileMessages = [];
public $profilingAware = false ;
/**
@ -147,7 +149,7 @@ class Logger extends Component
* @param string|array $message the message to be logged. This can be a simple string or a more
* complex data structure that will be handled by a [[Target|log target]].
* @param int $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`,
* `Logger::LEVEL_ERROR`, `Logger::LEVEL_WARNING`, `Logger::LEVEL_INFO`, `Logger::LEVEL_TRACE`, `Logger::LEVEL_PROFILE`,
* `Logger::LEVEL_PROFILE_BEGIN`, `Logger::LEVEL_PROFILE_END`.
* @param string $category the category of the message.
*/
@ -170,10 +172,12 @@ class Logger extends Component
}
}
$data = [$message, $level, $category, $time, $traces, memory_get_usage()];
if ($this->profilingAware & & in_array($level, [self::LEVEL_PROFILE_BEGIN, self::LEVEL_PROFILE_END])) {
$this->messages[($level == self::LEVEL_PROFILE_BEGIN ? 'begin-' : 'end-') . md5(json_encode($message))] = $data;
} else {
$this->messages[] = $data;
if ($level == self::LEVEL_PROFILE_BEGIN || $level == self::LEVEL_PROFILE_END) {
$this->profileMessages[] = $data;
}
if ($this->flushInterval > 0 & & count($this->messages) >= $this->flushInterval) {
$this->flush();
}
@ -185,10 +189,40 @@ class Logger extends Component
*/
public function flush($final = false)
{
if ($this->profilingAware) {
$keep = [];
$messages = [];
foreach ($this->messages as $index => $message) {
if (is_int($index)) {
$messages[] = $message;
} else {
if (strpos($index, 'begin-') === 0) {
$oppositeProfile = 'end-' . substr($index, 6);
} else {
$oppositeProfile = 'begin-' . substr($index, 4);
}
if (array_key_exists($oppositeProfile, $this->messages)) {
$messages[] = $message;
} else {
$keep[$index] = $message;
}
}
}
if ($this->flushInterval > 0 & & count($keep) >= $this->flushInterval) {
$this->messages = [];
$this->log(
'Number of dangling profiling block messages reached flushInterval value and therefore these were flushed. Please consider setting higher flushInterval value or making profiling blocks shorter.',
self::LEVEL_WARNING
);
$messages = array_merge($messages, array_values($keep));
} else {
$this->messages = $keep;
}
} else {
$messages = $this->messages;
// https://github.com/yiisoft/yii2/issues/5619
// new messages could be logged while the existing ones are being handled by targets
$this->messages = [];
}
if ($this->dispatcher instanceof Dispatcher) {
$this->dispatcher->dispatch($messages, $final);
}
@ -224,7 +258,7 @@ class Logger extends Component
*/
public function getProfiling($categories = [], $excludeCategories = [])
{
$timings = $this->calculateTimings($this->profileM essages);
$timings = $this->calculateTimings($this->m essages);
if (empty($categories) & & empty($excludeCategories)) {
return $timings;
}