From e1f98e573c249d8528f59b3f810cc1ca89927972 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Mon, 19 Dec 2022 01:11:43 +0900 Subject: [PATCH] Fix #1944 add option to display complete call stack for queries --- common/css/rhymix.less | 6 ++++++ common/defaults/config.php | 1 + common/framework/db.php | 19 ++++++++----------- common/js/debug.js | 16 ++++++++++++++++ common/tpl/debug_comment.html | 14 ++++++++++++++ modules/admin/admin.admin.controller.php | 1 + modules/admin/admin.admin.view.php | 1 + modules/admin/lang/en.php | 2 ++ modules/admin/lang/ko.php | 2 ++ modules/admin/tpl/config_debug.html | 8 ++++++++ 10 files changed, 59 insertions(+), 11 deletions(-) diff --git a/common/css/rhymix.less b/common/css/rhymix.less index a38914f4d..c17143abf 100644 --- a/common/css/rhymix.less +++ b/common/css/rhymix.less @@ -365,6 +365,12 @@ a img { list-style: disc; margin: 0; padding: 0; text-indent: 0; color: #888; + ul { + padding-left: 20px; + li { + list-style: circle; + } + } } } } diff --git a/common/defaults/config.php b/common/defaults/config.php index 58cbae632..3656254c6 100644 --- a/common/defaults/config.php +++ b/common/defaults/config.php @@ -101,6 +101,7 @@ return array( 'display_content' => array('request_info', 'entries', 'errors', 'queries'), 'display_to' => 'admin', 'query_comment' => false, + 'query_full_stack' => false, 'write_error_log' => 'fatal', 'allow' => array(), ), diff --git a/common/framework/db.php b/common/framework/db.php index c27ea0586..80678687d 100644 --- a/common/framework/db.php +++ b/common/framework/db.php @@ -42,8 +42,10 @@ class DB protected $_query_id = ''; protected $_errno = 0; protected $_errstr = ''; + protected $_debug_queries = false; protected $_debug_comment = false; - + protected $_debug_full_stack = false; + /** * Transaction level. */ @@ -130,7 +132,9 @@ class DB $this->db_version = $this->_handle->getAttribute(\PDO::ATTR_SERVER_VERSION); // Cache the debug comment setting. - $this->_debug_comment = config('debug.query_comment') ? true : false; + $this->_debug_queries = in_array('queries', Config::get('debug.display_content') ?: []); + $this->_debug_comment = !!config('debug.query_comment'); + $this->_debug_full_stack = !!Config::get('debug.query_full_stack'); } /** @@ -1160,13 +1164,6 @@ class DB */ public function getQueryLog(string $query, float $elapsed_time): array { - // Cache the debug status to improve performance. - static $debug_queries = null; - if ($debug_queries === null) - { - $debug_queries = in_array('queries', Config::get('debug.display_content') ?: []); - } - // Compose the basic structure of the log entry. $result = array( 'query' => preg_replace('!\n/\* .+ \*/$!s', '', $query), @@ -1183,7 +1180,7 @@ class DB ); // Add debug information if enabled. - if ($this->_errno || $debug_queries) + if ($this->_errno || $this->_debug_queries) { $backtrace = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS); foreach ($backtrace as $no => $call) @@ -1196,7 +1193,7 @@ class DB if (isset($backtrace[$no])) { $result['called_method'] = $backtrace[$no]['class'] . $backtrace[$no]['type'] . $backtrace[$no]['function']; - $result['backtrace'] = array_slice($backtrace, $no, 1); + $result['backtrace'] = $this->_debug_full_stack ? array_slice($backtrace, $no) : []; } else { diff --git a/common/js/debug.js b/common/js/debug.js index aadd4cbc6..34123b5a2 100644 --- a/common/js/debug.js +++ b/common/js/debug.js @@ -131,6 +131,14 @@ $(function() { description.append($('
  • ').text("Connection: " + data.queries[i].query_connection)); description.append($('
  • ').text("Query ID: " + data.queries[i].query_id)); description.append($('
  • ').text("Query Time: " + (data.queries[i].query_time ? (data.queries[i].query_time.toFixed(4) + " sec") : ""))); + if (data.queries[i].backtrace && data.queries[i].backtrace.length) { + backtrace = $('').appendTo(description.find('li:first-child')); + for (j in data.queries[i].backtrace) { + if (data.queries[i].backtrace[j].file) { + backtrace.append($('
  • ').text(data.queries[i].backtrace[j].file + ":" + data.queries[i].backtrace[j].line)); + } + } + } } description.append($('
  • ').text("Result: " + ((data.queries[i].message === "success" || !data.queries[i].message) ? "success" : data.queries[i].message))); } @@ -149,6 +157,14 @@ $(function() { description.append($('
  • ').text("Connection: " + data.slow_queries[i].query_connection)); description.append($('
  • ').text("Query ID: " + data.slow_queries[i].query_id)); description.append($('
  • ').text("Query Time: " + (data.slow_queries[i].query_time ? (data.slow_queries[i].query_time.toFixed(4) + " sec") : ""))); + if (data.queries[i].backtrace && data.queries[i].backtrace.length) { + backtrace = $('').appendTo(description.find('li:first-child')); + for (j in data.queries[i].backtrace) { + if (data.queries[i].backtrace[j].file) { + backtrace.append($('
  • ').text(data.queries[i].backtrace[j].file + ":" + data.queries[i].backtrace[j].line)); + } + } + } } description.append($('
  • ').text("Result: " + ((data.slow_queries[i].message === "success" || !data.slow_queries[i].message) ? "success" : ("error " + data.slow_queries[i].error_code + " " + data.slow_queries[i].message)))); } diff --git a/common/tpl/debug_comment.html b/common/tpl/debug_comment.html index 243e01ef8..684ac25bc 100644 --- a/common/tpl/debug_comment.html +++ b/common/tpl/debug_comment.html @@ -99,6 +99,13 @@ Database Queries $query_result = ($query->message === 'success') ? 'success' : $query->message; echo sprintf('%02d. %s', ++$query_count, $query->query_string) . "\n"; echo sprintf(' - Caller: %s', $query_caller) . "\n"; + foreach ($query->backtrace ?? [] as $key => $backtrace) + { + if (isset($backtrace['file']) && isset($backtrace['line'])) + { + echo sprintf(' %s line %d', $backtrace['file'], $backtrace['line']) . "\n"; + } + } echo sprintf(' - Connection: %s', $query->query_connection) . "\n"; echo sprintf(' - Query ID: %s', $query->query_id) . "\n"; echo sprintf(' - Query Time: %0.4f sec', $query->query_time) . "\n"; @@ -122,6 +129,13 @@ Slow Queries $query_result = ($query->message === 'success') ? 'success' : sprintf('error %d %s', $query->error_code, $query->message); echo sprintf('%02d. %s', ++$query_count, $query->query_string) . "\n"; echo sprintf(' - Caller: %s', $query_caller) . "\n"; + foreach ($query->backtrace ?? [] as $key => $backtrace) + { + if (isset($backtrace['file']) && isset($backtrace['line'])) + { + echo sprintf(' %s line %d', $backtrace['file'], $backtrace['line']) . "\n"; + } + } echo sprintf(' - Connection: %s', $query->query_connection) . "\n"; echo sprintf(' - Query ID: %s', $query->query_id) . "\n"; echo sprintf(' - Query Time: %0.4f sec', $query->query_time) . "\n"; diff --git a/modules/admin/admin.admin.controller.php b/modules/admin/admin.admin.controller.php index f255bb1b0..c026a11ba 100644 --- a/modules/admin/admin.admin.controller.php +++ b/modules/admin/admin.admin.controller.php @@ -918,6 +918,7 @@ class adminAdminController extends admin Rhymix\Framework\Config::set('debug.display_type', $display_type); Rhymix\Framework\Config::set('debug.display_to', strval($vars->debug_display_to) ?: 'admin'); Rhymix\Framework\Config::set('debug.query_comment', $vars->debug_query_comment === 'Y'); + Rhymix\Framework\Config::set('debug.query_full_stack', $vars->debug_query_full_stack === 'Y'); Rhymix\Framework\Config::set('debug.write_error_log', strval($vars->debug_write_error_log) ?: 'fatal'); // Debug content diff --git a/modules/admin/admin.admin.view.php b/modules/admin/admin.admin.view.php index a6abf9f5e..4b17fdb4f 100644 --- a/modules/admin/admin.admin.view.php +++ b/modules/admin/admin.admin.view.php @@ -628,6 +628,7 @@ class adminAdminView extends admin Context::set('debug_display_content', Rhymix\Framework\Config::get('debug.display_content')); Context::set('debug_display_to', Rhymix\Framework\Config::get('debug.display_to')); Context::set('debug_query_comment', Rhymix\Framework\Config::get('debug.query_comment')); + Context::set('debug_query_full_stack', Rhymix\Framework\Config::get('debug.query_full_stack')); Context::set('debug_write_error_log', Rhymix\Framework\Config::get('debug.write_error_log')); // IP access control diff --git a/modules/admin/lang/en.php b/modules/admin/lang/en.php index f5e4cd8a9..a239c25c0 100644 --- a/modules/admin/lang/en.php +++ b/modules/admin/lang/en.php @@ -228,6 +228,7 @@ $lang->debug_display_to_ip = 'Visitors from IP adresses listed below'; $lang->debug_display_to_everyone = 'Everyone'; $lang->debug_log_filename = 'Log filename'; $lang->debug_query_comment = 'Add Comment to Queries'; +$lang->debug_query_full_stack = 'Show Complete Call Stack for Queries'; $lang->debug_write_error_log = 'Write to Error Log'; $lang->debug_write_error_log_all = 'All errors and warnings'; $lang->debug_write_error_log_fatal = 'Fatal errors only'; @@ -237,6 +238,7 @@ $lang->about_debug_write_error_log = 'Select how much information will be record $lang->about_debug_error_log_path = 'The error log location that is currently configured in php.ini is %s'; $lang->about_debug_error_log_path_empty = '(none)'; $lang->about_debug_query_comment = 'Add a comment containing the query name and IP address to every SQL statement. This may help you determine where slow queries are coming from.'; +$lang->about_debug_query_full_stack = 'Show the complete call stack for each query. This can increase the size of debug data considerably.'; $lang->msg_debug_log_filename_not_writable = 'Rhymix cannot write log files in the specified path.'; $lang->debug_allowed_ip = 'Allowed IP addresses'; $lang->seo_main_title = 'Main Page Title'; diff --git a/modules/admin/lang/ko.php b/modules/admin/lang/ko.php index 4401cb904..44facc04a 100644 --- a/modules/admin/lang/ko.php +++ b/modules/admin/lang/ko.php @@ -224,6 +224,7 @@ $lang->debug_display_to_ip = '아래 IP의 방문자에게만 표시'; $lang->debug_display_to_everyone = '모두에게 표시'; $lang->debug_log_filename = '디버그 정보 기록 파일'; $lang->debug_query_comment = '쿼리에 주석 추가'; +$lang->debug_query_full_stack = '쿼리 콜 스택 전체 표시'; $lang->debug_write_error_log = '에러 로그에 기록'; $lang->debug_write_error_log_all = '모든 에러와 경고를 기록'; $lang->debug_write_error_log_fatal = '치명적인 에러만 기록'; @@ -233,6 +234,7 @@ $lang->about_debug_write_error_log = 'PHP 에러 로그에 얼마나 많은 정 $lang->about_debug_error_log_path = '현재 php.ini에서 설정된 에러 로그 경로는 %s 입니다.'; $lang->about_debug_error_log_path_empty = '(없음)'; $lang->about_debug_query_comment = '쿼리명과 IP 주소를 포함하는 주석을 모든 쿼리에 추가하여, 부하를 유발하는 쿼리 및 방문자를 DB에서 쉽게 파악할 수 있도록 합니다.'; +$lang->about_debug_query_full_stack = '쿼리와 관련된 콜 스택을 모두 표시합니다. 디버그 정보의 분량이 크게 늘어날 수 있습니다.'; $lang->msg_debug_log_filename_not_writable = '지정한 경로에 로그 파일을 작성할 수 없습니다.'; $lang->debug_allowed_ip = '디버그 허용 IP'; $lang->seo_main_title = '메인화면 제목'; diff --git a/modules/admin/tpl/config_debug.html b/modules/admin/tpl/config_debug.html index 8e6c6cb9a..20c3dc3b0 100644 --- a/modules/admin/tpl/config_debug.html +++ b/modules/admin/tpl/config_debug.html @@ -95,6 +95,14 @@

    {$lang->about_debug_query_comment}

    +
    + +
    + + +

    {$lang->about_debug_query_full_stack}

    +
    +