From 4565df9313220b771520ecd1b3d962864438417c Mon Sep 17 00:00:00 2001 From: Carsten Brandt Date: Sun, 1 Dec 2013 14:17:56 +0100 Subject: [PATCH] added debug panel for elasticsearch --- extensions/elasticsearch/Connection.php | 2 +- extensions/elasticsearch/DebugPanel.php | 168 ++++++++++++++++++++++++++++++++ extensions/elasticsearch/README.md | 26 +++++ 3 files changed, 195 insertions(+), 1 deletion(-) create mode 100644 extensions/elasticsearch/DebugPanel.php diff --git a/extensions/elasticsearch/Connection.php b/extensions/elasticsearch/Connection.php index 0c28d40..098d6ee 100644 --- a/extensions/elasticsearch/Connection.php +++ b/extensions/elasticsearch/Connection.php @@ -267,7 +267,7 @@ class Connection extends Component if (strncmp($host, 'inet[/', 6) == 0) { $host = substr($host, 6, -1); } - $profile = $q . $requestBody; + $profile = $method . ' ' . $q . '#' . $requestBody; $url = 'http://' . $host . '/' . $q; } else { $profile = false; diff --git a/extensions/elasticsearch/DebugPanel.php b/extensions/elasticsearch/DebugPanel.php new file mode 100644 index 0000000..da5a824 --- /dev/null +++ b/extensions/elasticsearch/DebugPanel.php @@ -0,0 +1,168 @@ + + * @since 2.0 + */ +class DebugPanel extends Panel +{ + public function getName() + { + return 'Elasticsearch'; + } + + public function getSummary() + { + $timings = $this->calculateTimings(); + $queryCount = count($timings); + $queryTime = 0; + foreach ($timings as $timing) { + $queryTime += $timing[3]; + } + $queryTime = number_format($queryTime * 1000) . ' ms'; + $url = $this->getUrl(); + $output = << + + ES $queryCount $queryTime + + +EOD; + return $queryCount > 0 ? $output : ''; + } + + public function getDetail() + { + $rows = []; + $i = 0; + foreach ($this->data['messages'] as $log) { + list ($message, $level, $category, $time, $traces) = $log; + if ($level == Logger::LEVEL_PROFILE_BEGIN) { + continue; + } + if (($pos = mb_strpos($message, "#")) !== false) { + $url = mb_substr($message, 0, $pos); + $body = mb_substr($message, $pos + 1); + } else { + $url = $message; + $body = null; + } + $traceString = ''; + if (!empty($traces)) { + $traceString .= Html::ul($traces, [ + 'class' => 'trace', + 'item' => function ($trace) { + return "
  • {$trace['file']}({$trace['line']})
  • "; + }, + ]); + } + $runLinks = ''; + $c = 0; + \Yii::$app->elasticsearch->open(); + foreach(\Yii::$app->elasticsearch->nodes as $node) { + $pos = mb_strpos($url, ' '); + $type = mb_substr($url, 0, $pos); + if ($type == 'GET' && !empty($body)) { + $type = 'POST'; + } + $host = $node['http_address']; + if (strncmp($host, 'inet[/', 6) == 0) { + $host = substr($host, 6, -1); + } + $nodeUrl = 'http://' . $host . '/' . mb_substr($url, $pos + 1); + $nodeUrl .= (strpos($nodeUrl, '?') === false) ? '?pretty=true' : '&pretty=true'; + $nodeBody = json_encode($body); + \Yii::$app->view->registerJs(<< "elastic-link-$i-$c"]) . '
    '; + $c++; + } + $rows[] = "
    $url

    $body

    $traceString
    $runLinks"; + $i++; + } + $rows = implode("\n", $rows); + return <<Elasticsearch Queries + + + + + + + + + +$rows + +
    Url / QueryRun Query on node
    +HTML; + } + + private $_timings; + + protected function calculateTimings() + { + if ($this->_timings !== null) { + return $this->_timings; + } + $messages = $this->data['messages']; + $timings = []; + $stack = []; + foreach ($messages as $i => $log) { + list($token, $level, $category, $timestamp) = $log; + $log[5] = $i; + if ($level == Logger::LEVEL_PROFILE_BEGIN) { + $stack[] = $log; + } elseif ($level == Logger::LEVEL_PROFILE_END) { + if (($last = array_pop($stack)) !== null && $last[0] === $token) { + $timings[$last[5]] = [count($stack), $token, $last[3], $timestamp - $last[3], $last[4]]; + } + } + } + + $now = microtime(true); + while (($last = array_pop($stack)) !== null) { + $delta = $now - $last[3]; + $timings[$last[5]] = [count($stack), $last[0], $last[2], $delta, $last[4]]; + } + ksort($timings); + return $this->_timings = $timings; + } + + public function save() + { + $target = $this->module->logTarget; + $messages = $target->filterMessages($target->messages, Logger::LEVEL_PROFILE, ['yii\elasticsearch\Connection::httpRequest']); + return ['messages' => $messages]; + } +} diff --git a/extensions/elasticsearch/README.md b/extensions/elasticsearch/README.md index 57497e2..2a07155 100644 --- a/extensions/elasticsearch/README.md +++ b/extensions/elasticsearch/README.md @@ -146,3 +146,29 @@ $query->search(); // gives you all the records + stats about the visit_count fie ``` And there is so much more in it. "it’s endless what you can build"[¹](http://www.elasticsearch.org/) + + +Using the elasticsearch DebugPanel +---------------------------------- + +The yii2 elasticsearch extensions provides a `DebugPanel` that can be integrated with the yii debug module +an shows the executed elasticsearch queries. It also allows to run these queries on different cluster nodes +an view the results. + +Add the following to you application config to enable it: + +```php + // ... + 'preload' => 'debug', + 'modules' => [ + 'debug' => [ + 'class' => 'yii\\debug\\Module', + 'panels' => [ + 'elasticsearch' => [ + 'class' => 'yii\\elasticsearch\\DebugPanel', + ], + ], + ], + ], + // ... +```