Class yii\debug\panels\DbPanel
Inheritance | yii\debug\panels\DbPanel » yii\debug\Panel » yii\base\Component |
---|---|
Available since extension's version | 2.0 |
Source Code | https://github.com/yiisoft/yii2-debug/blob/master/src/panels/DbPanel.php |
Debugger panel that collects and displays database queries performed.
Public Properties
Property | Type | Description | Defined By |
---|---|---|---|
$actions | array | Array of actions to add to the debug modules default controller. | yii\debug\Panel |
$criticalQueryThreshold | integer|null | The threshold for determining whether the request has involved critical number of DB queries. | yii\debug\panels\DbPanel |
$data | mixed | Data associated with panel | yii\debug\Panel |
$db | string | The name of the database component to use for executing (explain) queries | yii\debug\panels\DbPanel |
$dbEventNames | array | Of event names used to get profile logs. | yii\debug\panels\DbPanel |
$defaultFilter | array | The default filter to apply to the database queries. | yii\debug\panels\DbPanel |
$defaultOrder | array | The default ordering of the database queries. | yii\debug\panels\DbPanel |
$detail | string | Content that is displayed in debugger detail view. | yii\debug\Panel |
$error | yii\debug\FlattenException|null | Error while saving the panel | yii\debug\Panel |
$excessiveCallerThreshold | integer|null | The number of DB calls the same backtrace can make before considered an "Excessive Caller". | yii\debug\panels\DbPanel |
$excessiveCallers | array | The number of DB calls indexed by the backtrace hash of excessive caller(s). | yii\debug\panels\DbPanel |
$id | string | Panel unique identifier. | yii\debug\Panel |
$ignoredPathsInBacktrace | string[] | The files and/or paths defined here will be ignored in the determination of DB "Callers". | yii\debug\panels\DbPanel |
$module | yii\debug\Module | yii\debug\Panel | |
$name | string | Name of the panel. | yii\debug\Panel |
$profileLogs | array | yii\debug\panels\DbPanel | |
$summary | string | Content that is displayed at debug toolbar. | yii\debug\Panel |
$summaryName | string | Short name of the panel, which will be use in summary. | yii\debug\panels\DbPanel |
$tag | string | Request data set identifier. | yii\debug\Panel |
$url | string | URL pointing to panel detail view. | yii\debug\Panel |
Public Methods
Method | Description | Defined By |
---|---|---|
calculateTimings() | Calculates given request profile timings. | yii\debug\panels\DbPanel |
canBeExplained() | Check if given query type can be explained. | yii\debug\panels\DbPanel |
countCallerCals() | Counts the number of times the same backtrace makes a DB query. | yii\debug\panels\DbPanel |
countDuplicateQuery() | Return associative array, where key is query string and value is number of occurrences the same query in array. | yii\debug\panels\DbPanel |
generateQueryCallersDataProvider() | Creates an ArrayDataProvider for the DB query callers. | yii\debug\panels\DbPanel |
getDb() | Returns a reference to the DB component associated with the panel | yii\debug\panels\DbPanel |
getDetail() | yii\debug\panels\DbPanel | |
getError() | yii\debug\Panel | |
getExcessiveCallers() | Get the backtrace hashes that make excessive DB cals. | yii\debug\panels\DbPanel |
getExcessiveCallersCount() | Get the number of excessive caller(s). | yii\debug\panels\DbPanel |
getName() | yii\debug\panels\DbPanel | |
getProfileLogs() | Returns all profile logs of the current request for this panel. It includes categories specified in $this->dbEventNames property. | yii\debug\panels\DbPanel |
getSummary() | yii\debug\panels\DbPanel | |
getSummaryName() | yii\debug\panels\DbPanel | |
getTraceLine() | Returns a trace line | yii\debug\Panel |
getTypes() | Returns array query types | yii\debug\panels\DbPanel |
getUrl() | yii\debug\Panel | |
hasError() | yii\debug\Panel | |
init() | yii\debug\panels\DbPanel | |
isEnabled() | Checks whether this panel is enabled. | yii\debug\panels\DbPanel |
isNumberOfCallsExcessive() | Check if the number of calls by "Caller" is excessive according to the settings. | yii\debug\panels\DbPanel |
isQueryCountCritical() | Check if given queries count is critical according to the settings. | yii\debug\panels\DbPanel |
load() | Loads data into the panel | yii\debug\Panel |
save() | Saves data to be later used in debugger detail view. | yii\debug\panels\DbPanel |
setError() | yii\debug\Panel | |
sumDuplicateQueries() | Returns sum of all duplicated queries | yii\debug\panels\DbPanel |
Protected Methods
Method | Description | Defined By |
---|---|---|
getLogMessages() | Gets messages from log target and filters according to their categories and levels. | yii\debug\Panel |
getModels() | Returns an array of models that represents logs of the current request. | yii\debug\panels\DbPanel |
getQueryType() | Returns database query type. | yii\debug\panels\DbPanel |
getTotalQueryTime() | Returns total query time. | yii\debug\panels\DbPanel |
hasExplain() | yii\debug\panels\DbPanel |
Property Details
The threshold for determining whether the request has involved
critical number of DB queries. If the number of queries exceeds this number,
the execution is considered taking critical number of DB queries.
If it is null
, this feature is disabled.
The name of the database component to use for executing (explain) queries
Of event names used to get profile logs.
The default filter to apply to the database queries. In the format of [ property => value ], for example: [ 'type' => 'SELECT' ]
The default ordering of the database queries. In the format of [ property => sort direction ], for example: [ 'duration' => SORT_DESC ]
The number of DB calls the same backtrace can make before considered an "Excessive Caller".
If it is null
, this feature is disabled.
Note: Changes will only be reflected in new requests.
The number of DB calls indexed by the backtrace hash of excessive caller(s).
The files and/or paths defined here will be ignored in the determination of DB "Callers".
The "Caller" is the backtrace lines that aren't included in the $ignoredPathsInBacktrace
,
Yii files are ignored by default.
Hint: You can use path aliases here.
Short name of the panel, which will be use in summary.
Method Details
Calculates given request profile timings.
public array calculateTimings ( ) | ||
return | array |
Timings [token, category, timestamp, traces, nesting level, elapsed time] |
---|
public function calculateTimings()
{
if ($this->_timings === null) {
$this->_timings = Yii::getLogger()->calculateTimings(isset($this->data['messages']) ? $this->data['messages'] : $this->getProfileLogs());
// Parse aliases
$ignoredPathsInBacktrace = array_map(
function($path) {
return Yii::getAlias($path);
},
$this->ignoredPathsInBacktrace
);
// Generate hash for caller
$hashAlgo = in_array('xxh3', hash_algos()) ? 'xxh3' : 'crc32';
foreach ($this->_timings as &$timing) {
if ($ignoredPathsInBacktrace) {
foreach ($timing['trace'] as $index => $trace) {
foreach ($ignoredPathsInBacktrace as $ignoredPathInBacktrace) {
if (isset($trace['file']) && strpos($trace['file'], $ignoredPathInBacktrace) === 0) {
unset($timing['trace'][$index]);
}
}
}
}
$timing['traceHash'] = hash($hashAlgo, json_encode($timing['trace']));
}
}
return $this->_timings;
}
Check if given query type can be explained.
public static boolean canBeExplained ( $type ) | ||
$type | string |
Query type |
public static function canBeExplained($type)
{
return $type !== 'SHOW';
}
Counts the number of times the same backtrace makes a DB query.
public array countCallerCals ( ) | ||
return | array |
The number of DB calls indexed by the backtrace hash of the caller. |
---|
public function countCallerCals()
{
$query = ArrayHelper::getColumn($this->calculateTimings(), 'traceHash');
return array_count_values($query);
}
Return associative array, where key is query string and value is number of occurrences the same query in array.
public array countDuplicateQuery ( $timings ) | ||
$timings |
public function countDuplicateQuery($timings)
{
$query = ArrayHelper::getColumn($timings, 'info');
return array_count_values($query);
}
Creates an ArrayDataProvider for the DB query callers.
public \yii\data\ArrayDataProvider generateQueryCallersDataProvider ( $modelData ) | ||
$modelData | array |
public function generateQueryCallersDataProvider($modelData)
{
$callers = [];
foreach ($modelData as $data) {
if (!array_key_exists($data['traceHash'], $callers)) {
$callers[$data['traceHash']] = [
'trace' => $data['trace'],
'numCalls' => 0,
'totalDuration' => 0,
'queries' => []
];
}
$callers[$data['traceHash']]['numCalls'] += 1;
$callers[$data['traceHash']]['totalDuration'] += $data['duration'];
$callers[$data['traceHash']]['queries'][] = [
'timestamp' => $data['timestamp'],
'duration' => $data['duration'],
'query' => $data['query'],
'type' => $data['type'],
'seq' => $data['seq'],
];
}
return new ArrayDataProvider([
'allModels' => $callers,
'pagination' => false,
'sort' => [
'attributes' => ['numCalls', 'totalDuration'],
'defaultOrder' => ['numCalls' => SORT_DESC],
],
]);
}
Returns a reference to the DB component associated with the panel
public \yii\db\Connection getDb ( ) | ||
throws | \yii\base\InvalidConfigException |
---|
public function getDb()
{
return Yii::$app->get($this->db);
}
public string getDetail ( ) | ||
return | string |
Content that is displayed in debugger detail view |
---|---|---|
throws | \yii\base\InvalidConfigException |
public function getDetail()
{
$searchModel = new Db();
if (!$searchModel->load(Yii::$app->request->getQueryParams())) {
$searchModel->load($this->defaultFilter, '');
}
$models = $this->getModels();
$queryDataProvider = $searchModel->search($models);
$queryDataProvider->getSort()->defaultOrder = $this->defaultOrder;
$sumDuplicates = $this->sumDuplicateQueries($models);
$callerDataProvider = $this->generateQueryCallersDataProvider($models);
return Yii::$app->view->render('panels/db/detail', [
'panel' => $this,
'queryDataProvider' => $queryDataProvider,
'callerDataProvider' => $callerDataProvider,
'searchModel' => $searchModel,
'hasExplain' => $this->hasExplain(),
'sumDuplicates' => $sumDuplicates,
]);
}
Defined in: yii\debug\Panel::getError()
public yii\debug\FlattenException|null getError ( ) |
public function getError()
{
return $this->error;
}
Get the backtrace hashes that make excessive DB cals.
public array getExcessiveCallers ( ) | ||
return | array |
The number of DB calls indexed by the backtrace hash of excessive caller(s). |
---|
public function getExcessiveCallers()
{
if ($this->excessiveCallerThreshold === null) {
return [];
}
return array_filter(
$this->countCallerCals(),
function ($count) {
return $count >= $this->excessiveCallerThreshold;
}
);
}
Get the number of excessive caller(s).
public integer getExcessiveCallersCount ( ) |
public function getExcessiveCallersCount()
{
return count($this->getExcessiveCallers());
}
Defined in: yii\debug\Panel::getLogMessages()
Gets messages from log target and filters according to their categories and levels.
See also \yii\log\Target::filterMessages().
protected array getLogMessages ( $levels = 0, $categories = [], $except = [], $stringify = false ) | ||
$levels | integer |
The message levels to filter by. This is a bitmap of level values. Value 0 means allowing all levels. |
$categories | array |
The message categories to filter by. If empty, it means all categories are allowed. |
$except | array |
The message categories to exclude. If empty, it means all categories are allowed. |
$stringify | boolean |
Convert non-string (such as closures) to strings |
return | array |
The filtered messages. |
---|
protected function getLogMessages($levels = 0, $categories = [], $except = [], $stringify = false)
{
$target = $this->module->logTarget;
$messages = $target->filterMessages($target->messages, $levels, $categories, $except);
if (!$stringify) {
return $messages;
}
foreach ($messages as &$message) {
if (!isset($message[0]) || is_string($message[0])) {
continue;
}
// exceptions may not be serializable if in the call stack somewhere is a Closure
if ($message[0] instanceof \Throwable || $message[0] instanceof \Exception) {
$message[0] = (string) $message[0];
} else {
$message[0] = VarDumper::export($message[0]);
}
}
return $messages;
}
Returns an array of models that represents logs of the current request.
Can be used with data providers such as \yii\data\ArrayDataProvider.
protected array getModels ( ) | ||
return | array |
Models |
---|
protected function getModels()
{
if ($this->_models === null) {
$this->_models = [];
$timings = $this->calculateTimings();
$duplicates = $this->countDuplicateQuery($timings);
foreach ($timings as $seq => $dbTiming) {
$this->_models[] = [
'type' => $this->getQueryType($dbTiming['info']),
'query' => $dbTiming['info'],
'duration' => ($dbTiming['duration'] * 1000), // in milliseconds
'trace' => $dbTiming['trace'],
'traceHash' => $dbTiming['traceHash'],
'timestamp' => ($dbTiming['timestamp'] * 1000), // in milliseconds
'seq' => $seq,
'duplicate' => $duplicates[$dbTiming['info']],
];
}
}
return $this->_models;
}
public string getName ( ) | ||
return | string |
Name of the panel |
---|
public function getName()
{
return 'Database';
}
Returns all profile logs of the current request for this panel. It includes categories specified in $this->dbEventNames property.
public array getProfileLogs ( ) |
public function getProfileLogs()
{
if ($this->_profileLogs === null) {
$this->_profileLogs = $this->getLogMessages(Logger::LEVEL_PROFILE, $this->dbEventNames);
}
return $this->_profileLogs;
}
Returns database query type.
protected string getQueryType ( $timing ) | ||
$timing | string |
Timing procedure string |
return | string |
Query type such as select, insert, delete, etc. |
---|
protected function getQueryType($timing)
{
$timing = ltrim($timing);
preg_match('/^([a-zA-z]*)/', $timing, $matches);
return count($matches) ? mb_strtoupper($matches[0], 'utf8') : '';
}
public string getSummary ( ) | ||
return | string |
Content that is displayed at debug toolbar |
---|
public function getSummary()
{
$timings = $this->calculateTimings();
$queryCount = count($timings);
$queryTime = number_format($this->getTotalQueryTime($timings) * 1000) . ' ms';
$excessiveCallerCount = $this->getExcessiveCallersCount();
return Yii::$app->view->render('panels/db/summary', [
'timings' => $this->calculateTimings(),
'panel' => $this,
'queryCount' => $queryCount,
'queryTime' => $queryTime,
'excessiveCallerCount' => $excessiveCallerCount,
]);
}
public string getSummaryName ( ) | ||
return | string |
Short name of the panel, which will be use in summary. |
---|
public function getSummaryName()
{
return 'DB';
}
Returns total query time.
protected integer getTotalQueryTime ( $timings ) | ||
$timings | array | |
return | integer |
Total time |
---|
protected function getTotalQueryTime($timings)
{
$queryTime = 0;
foreach ($timings as $timing) {
$queryTime += $timing['duration'];
}
return $queryTime;
}
Defined in: yii\debug\Panel::getTraceLine()
Returns a trace line
public string getTraceLine ( $options ) | ||
$options | array |
The array with trace |
return | string |
The trace line |
---|
public function getTraceLine($options)
{
/**
* If an internal PHP function, such as `call_user_func`, in the backtrace, the 'file' and 'line' not be available.
* @see https://www.php.net/manual/en/function.debug-backtrace.php#59713
*/
if (!isset($options['file'])) {
return VarDumper::dumpAsString($options);
}
if (!isset($options['text'])) {
$options['text'] = "{$options['file']}:{$options['line']}";
}
$traceLine = $this->module->traceLine;
if ($traceLine === false) {
return $options['text'];
}
$options['file'] = str_replace('\\', '/', $options['file']);
foreach ($this->module->tracePathMappings as $old => $new) {
$old = rtrim(str_replace('\\', '/', $old), '/') . '/';
if (StringHelper::startsWith($options['file'], $old)) {
$new = rtrim(str_replace('\\', '/', $new), '/') . '/';
$options['file'] = $new . substr($options['file'], strlen($old));
break;
}
}
$rawLink = $traceLine instanceof \Closure ? $traceLine($options, $this) : $traceLine;
return strtr($rawLink, ['{file}' => $options['file'], '{line}' => $options['line'], '{text}' => $options['text']]);
}
Returns array query types
public array getTypes ( ) |
public function getTypes()
{
return array_reduce(
$this->_models,
function ($result, $item) {
$result[$item['type']] = $item['type'];
return $result;
},
[]
);
}
Defined in: yii\debug\Panel::getUrl()
public string getUrl ( $additionalParams = null ) | ||
$additionalParams | null|array |
Optional additional parameters to add to the route |
return | string |
URL pointing to panel detail view |
---|
public function getUrl($additionalParams = null)
{
$route = [
'/' . $this->module->getUniqueId() . '/default/view',
'panel' => $this->id,
'tag' => $this->tag,
];
if (is_array($additionalParams)) {
$route = ArrayHelper::merge($route, $additionalParams);
}
return Url::toRoute($route);
}
Defined in: yii\debug\Panel::hasError()
public boolean hasError ( ) |
public function hasError()
{
return $this->error !== null;
}
protected boolean hasExplain ( ) | ||
return | boolean |
Whether the DB component has support for EXPLAIN queries |
---|---|---|
throws | \yii\base\InvalidConfigException |
protected function hasExplain()
{
$db = $this->getDb();
if (!($db instanceof \yii\db\Connection)) {
return false;
}
switch ($db->getDriverName()) {
case 'mysql':
case 'sqlite':
case 'pgsql':
case 'cubrid':
return true;
default:
return false;
}
}
public void init ( ) |
public function init()
{
$this->actions['db-explain'] = [
'class' => 'yii\\debug\\actions\\db\\ExplainAction',
'panel' => $this,
];
}
Checks whether this panel is enabled.
public boolean isEnabled ( ) | ||
return | boolean |
Whether this panel is enabled. |
---|
public function isEnabled()
{
try {
$this->getDb();
} catch (InvalidConfigException $exception) {
return false;
}
return parent::isEnabled();
}
Check if the number of calls by "Caller" is excessive according to the settings.
public boolean isNumberOfCallsExcessive ( $numCalls ) | ||
$numCalls | integer |
Queries count |
public function isNumberOfCallsExcessive($numCalls)
{
return (($this->excessiveCallerThreshold !== null) && ($numCalls > $this->excessiveCallerThreshold));
}
Check if given queries count is critical according to the settings.
public boolean isQueryCountCritical ( $count ) | ||
$count | integer |
Queries count |
public function isQueryCountCritical($count)
{
return (($this->criticalQueryThreshold !== null) && ($count > $this->criticalQueryThreshold));
}
Defined in: yii\debug\Panel::load()
Loads data into the panel
public void load ( $data ) | ||
$data | mixed |
public function load($data)
{
$this->data = $data;
}
Saves data to be later used in debugger detail view.
This method is called on every page where debugger is enabled.
public mixed save ( ) | ||
return | mixed |
Data to be saved |
---|
public function save()
{
return ['messages' => $this->getProfileLogs()];
}
Defined in: yii\debug\Panel::setError()
public void setError ( yii\debug\FlattenException $error ) | ||
$error | yii\debug\FlattenException |
public function setError(FlattenException $error)
{
$this->error = $error;
}
Returns sum of all duplicated queries
public integer sumDuplicateQueries ( $modelData ) | ||
$modelData |
public function sumDuplicateQueries($modelData)
{
$numDuplicates = 0;
foreach ($modelData as $data) {
if ($data['duplicate'] > 1) {
$numDuplicates++;
}
}
return $numDuplicates;
}