From 7c70f5c356d40f67be883a5f216b69c898edf454 Mon Sep 17 00:00:00 2001 From: Mark Date: Mon, 30 Dec 2013 02:36:15 +0400 Subject: [PATCH] debug module log panel improved --- extensions/yii/debug/models/search/Base.php | 37 ++++++++ extensions/yii/debug/models/search/Debug.php | 29 +----- extensions/yii/debug/models/search/Log.php | 79 ++++++++++++++++ extensions/yii/debug/panels/LogPanel.php | 103 ++++++++------------- .../yii/debug/views/default/panels/log/detail.php | 73 +++++++++++++++ .../yii/debug/views/default/panels/log/summary.php | 28 ++++++ extensions/yii/debug/views/default/view.php | 2 +- 7 files changed, 259 insertions(+), 92 deletions(-) create mode 100644 extensions/yii/debug/models/search/Base.php create mode 100644 extensions/yii/debug/models/search/Log.php create mode 100644 extensions/yii/debug/views/default/panels/log/detail.php create mode 100644 extensions/yii/debug/views/default/panels/log/summary.php diff --git a/extensions/yii/debug/models/search/Base.php b/extensions/yii/debug/models/search/Base.php new file mode 100644 index 0000000..be9b852 --- /dev/null +++ b/extensions/yii/debug/models/search/Base.php @@ -0,0 +1,37 @@ +$attribute; + + if (mb_strpos($value, '>') !== false) { + + $value = intval(str_replace('>', '', $value)); + $filter->addMatch($attribute, new matches\Greater(['value' => $value])); + + } elseif (mb_strpos($value, '<') !== false) { + + $value = intval(str_replace('<', '', $value)); + $filter->addMatch($attribute, new matches\Lower(['value' => $value])); + + } else { + $filter->addMatch($attribute, new matches\Exact(['value' => $value, 'partial' => $partial])); + } + + } + +} diff --git a/extensions/yii/debug/models/search/Debug.php b/extensions/yii/debug/models/search/Debug.php index f89990f..51bd45f 100644 --- a/extensions/yii/debug/models/search/Debug.php +++ b/extensions/yii/debug/models/search/Debug.php @@ -2,15 +2,13 @@ namespace yii\debug\models\search; -use yii\base\Model; use yii\data\ArrayDataProvider; use yii\debug\components\search\Filter; -use yii\debug\components\search\matches; /** * Debug represents the model behind the search form about requests manifest data. */ -class Debug extends Model +class Debug extends Base { /** * @var string tag attribute input search value @@ -121,29 +119,4 @@ class Debug extends Model return in_array($code, $this->criticalCodes); } - /** - * @param Filter $filter - * @param string $attribute - * @param boolean $partial - */ - public function addCondition($filter, $attribute, $partial = false) - { - $value = $this->$attribute; - - if (mb_strpos($value, '>') !== false) { - - $value = intval(str_replace('>', '', $value)); - $filter->addMatch($attribute, new matches\Greater(['value' => $value])); - - } elseif (mb_strpos($value, '<') !== false) { - - $value = intval(str_replace('<', '', $value)); - $filter->addMatch($attribute, new matches\Lower(['value' => $value])); - - } else { - $filter->addMatch($attribute, new matches\Exact(['value' => $value, 'partial' => $partial])); - } - - } - } diff --git a/extensions/yii/debug/models/search/Log.php b/extensions/yii/debug/models/search/Log.php new file mode 100644 index 0000000..ab8c754 --- /dev/null +++ b/extensions/yii/debug/models/search/Log.php @@ -0,0 +1,79 @@ + 'Level', + 'category' => 'Category', + 'message' => 'Message', + ]; + } + + /** + * Returns data provider with filled models. Filter applied if needed. + * @param array $params + * @param array $models + * @return \yii\data\ArrayDataProvider + */ + public function search($params, $models) + { + $dataProvider = new ArrayDataProvider([ + 'allModels' => $models, + 'pagination' => [ + 'pageSize' => 10, + ], + 'sort' => [ + 'attributes' => ['time','level','category','message'], + ], + ]); + + if (!($this->load($params) && $this->validate())) { + return $dataProvider; + } + + $filter = new Filter(); + $this->addCondition($filter, 'level'); + $this->addCondition($filter, 'category', true); + $this->addCondition($filter, 'message', true); + $dataProvider->allModels = $filter->filter($models); + + return $dataProvider; + } + +} diff --git a/extensions/yii/debug/panels/LogPanel.php b/extensions/yii/debug/panels/LogPanel.php index ccf4402..e80f2d8 100644 --- a/extensions/yii/debug/panels/LogPanel.php +++ b/extensions/yii/debug/panels/LogPanel.php @@ -9,9 +9,8 @@ namespace yii\debug\panels; use Yii; use yii\debug\Panel; -use yii\helpers\Html; use yii\log\Logger; -use yii\log\Target; +use yii\debug\models\search\Log; /** * Debugger panel that collects and displays logs. @@ -21,6 +20,12 @@ use yii\log\Target; */ class LogPanel extends Panel { + + /** + * @var array log messages extracted to array as models, to use with data provider. + */ + private $_models ; + public function getName() { return 'Logs'; @@ -28,72 +33,19 @@ class LogPanel extends Panel public function getSummary() { - $output = ['' . count($this->data['messages']) . '']; - $title = 'Logged ' . count($this->data['messages']) . ' messages'; - $errorCount = count(Target::filterMessages($this->data['messages'], Logger::LEVEL_ERROR)); - if ($errorCount) { - $output[] = '' . $errorCount . ''; - $title .= ", $errorCount errors"; - } - $warningCount = count(Target::filterMessages($this->data['messages'], Logger::LEVEL_WARNING)); - if ($warningCount) { - $output[] = '' . $warningCount . ''; - $title .= ", $warningCount warnings"; - } - $log = implode(' ', $output); - $url = $this->getUrl(); - return << - Log $log - -EOD; + return Yii::$app->view->render('panels/log/summary',['data' => $this->data, 'panel' => $this]); } public function getDetail() { - $rows = []; - foreach ($this->data['messages'] as $log) { - list ($message, $level, $category, $time, $traces) = $log; - $time = date('H:i:s.', $time) . sprintf('%03d', (int)(($time - (int)$time) * 1000)); - $message = nl2br(Html::encode($message)); - if (!empty($traces)) { - $message .= Html::ul($traces, [ - 'class' => 'trace', - 'item' => function ($trace) { - return "
  • {$trace['file']}({$trace['line']})
  • "; - }, - ]); - } - if ($level == Logger::LEVEL_ERROR) { - $class = ' class="danger"'; - } elseif ($level == Logger::LEVEL_WARNING) { - $class = ' class="warning"'; - } elseif ($level == Logger::LEVEL_INFO) { - $class = ' class="success"'; - } else { - $class = ''; - } - $level = Logger::getLevelName($level); - $rows[] = "$time$level$category
    $message
    "; - } - $rows = implode("\n", $rows); - return <<Log Messages + $searchModel = new Log(); + $dataProvider = $searchModel->search($_GET, $this->getModels()); - - - - - - - - - - -$rows - -
    TimeLevelCategoryMessage
    -EOD; + return Yii::$app->view->render('panels/log/detail',[ + 'dataProvider' => $dataProvider, + 'panel' => $this, + 'searchModel' => $searchModel, + ]); } public function save() @@ -102,4 +54,29 @@ EOD; $messages = $target->filterMessages($target->messages, Logger::LEVEL_ERROR | Logger::LEVEL_INFO | Logger::LEVEL_WARNING | Logger::LEVEL_TRACE); return ['messages' => $messages]; } + + /** + * Returns array of models that represents logs of the current request. Can be used with data providers, + * like yii\data\ArrayDataProvider. + * @param boolean $refresh if needed to build models from log messages and refresh them. + * @return array models + */ + protected function getModels($refresh=false) + { + if ($this->_models === null || $refresh) { + $this->_models = []; + + foreach($this->data['messages'] as $message) { + $this->_models[] = [ + 'message' => $message[0], + 'level' => $message[1], + 'category' => $message[2], + 'time' => ($message[3] * 1000), #time in milliseconds + 'trace' => $message[4] + ]; + } + } + return $this->_models; + } + } diff --git a/extensions/yii/debug/views/default/panels/log/detail.php b/extensions/yii/debug/views/default/panels/log/detail.php new file mode 100644 index 0000000..10fb879 --- /dev/null +++ b/extensions/yii/debug/views/default/panels/log/detail.php @@ -0,0 +1,73 @@ + +

    Log Messages

    + $dataProvider, + 'id' => 'log-panel-detailed-grid', + 'filterModel' => $searchModel, + 'filterUrl' => $panel->getUrl(), + 'rowOptions' => function ($model, $key, $index, $grid){ + switch($model['level']) { + case Logger::LEVEL_ERROR : return ['class' => 'danger']; + case Logger::LEVEL_WARNING : return ['class' => 'warning']; + case Logger::LEVEL_INFO : return ['class' => 'success']; + default: return []; + } + }, + 'columns' => [ + ['class' => 'yii\grid\SerialColumn'], + [ + 'attribute' => 'time', + 'value' => function ($data) + { + $timeInSeconds = $data['time'] / 1000; + $millisecondsDiff = (int)(($timeInSeconds - (int)$timeInSeconds) * 1000); + return date('H:i:s.',$timeInSeconds) . sprintf('%03d',$millisecondsDiff); + }, + ], + [ + 'attribute' => 'level', + 'value' => function ($data) + { + return Logger::getLevelName($data['level']); + }, + 'filter' => [ + Logger::LEVEL_TRACE => ' Trace ', + Logger::LEVEL_PROFILE => ' Profile ', + Logger::LEVEL_INFO => ' Info ', + Logger::LEVEL_ERROR => ' Error ', + ], + ], + 'category', + [ + 'attribute' => 'message', + 'value' => function ($data) + { + $message = nl2br(Html::encode($data['message'])); + + if (!empty($data['trace'])) { + $message .= Html::ul($data['trace'], [ + 'class' => 'trace', + 'item' => function ($trace) + { + return "
  • {$trace['file']} ({$trace['line']})
  • "; + } + ]); + }; + + return $message; + }, + 'format' => 'html', + 'options' => [ + 'width' => '50%', + ], + ], + ], +]); +?> \ No newline at end of file diff --git a/extensions/yii/debug/views/default/panels/log/summary.php b/extensions/yii/debug/views/default/panels/log/summary.php new file mode 100644 index 0000000..f2fdbdc --- /dev/null +++ b/extensions/yii/debug/views/default/panels/log/summary.php @@ -0,0 +1,28 @@ + + +$errorCount"; + $title .= ", $errorCount errors"; +} + +if ($warningCount) { + $output[] = "$warningCount"; + $title .= ", $warningCount warnings"; +} +?> + + \ No newline at end of file diff --git a/extensions/yii/debug/views/default/view.php b/extensions/yii/debug/views/default/view.php index 846653c..77eaee4 100644 --- a/extensions/yii/debug/views/default/view.php +++ b/extensions/yii/debug/views/default/view.php @@ -18,7 +18,7 @@ $this->title = 'Yii Debugger';
    - Yii Debugger + 'Back to main debug page']);?>
    getSummary() ?>