From 67749fa881ca2c9823dce0b84d35b95deb30a73f Mon Sep 17 00:00:00 2001 From: Rouslan Placella Date: Sat, 1 Dec 2012 12:39:56 +0000 Subject: [PATCH 01/21] Split the advisor feature into a separate page --- js/server_status.js | 91 ------------------------------------- js/server_status_advisor.js | 86 +++++++++++++++++++++++++++++++++++ server_status.php | 33 +------------- server_status_advisor.php | 62 +++++++++++++++++++++++++ 4 files changed, 150 insertions(+), 122 deletions(-) create mode 100644 js/server_status_advisor.js create mode 100644 server_status_advisor.php diff --git a/js/server_status.js b/js/server_status.js index b803c2c553..bab93b166d 100644 --- a/js/server_status.js +++ b/js/server_status.js @@ -36,8 +36,6 @@ AJAX.registerTeardown('server_status.js', function() { $('#filterText').unbind('keyup'); $('#filterCategory').unbind('change'); $('input#dontFormat').unbind('change'); - $('a[href="#openAdvisorInstructions"]').unbind('click'); - $('a[href="#startAnalyzer"]').unbind('click'); }); // Add a tablesorter parser to properly handle thousands seperated numbers and SI prefixes @@ -203,14 +201,6 @@ AJAX.registerOnload('server_status.js', function() { monitorLoaded = true; } - - // Run the advisor immediately when the user clicks the tab, but only when this is the first time - if (ui.tab.hash == '#statustabs_advisor' && $('table#rulesFired').length == 0) { - // Start with a small delay because the click event hasn't been setup yet - setTimeout(function() { - $('a[href="#startAnalyzer"]').trigger('click'); - }, 25); - } } }); @@ -738,87 +728,6 @@ AJAX.registerOnload('server_status.js', function() { return pointInfo; } - - /**** Server config advisor ****/ - - $('a[href="#openAdvisorInstructions"]').click(function() { - var dlgBtns = {}; - - dlgBtns[PMA_messages['strClose']] = function() { - $(this).dialog('close'); - }; - - $('#advisorInstructionsDialog').attr('title', PMA_messages['strAdvisorSystem']); - $('#advisorInstructionsDialog').dialog({ - width: 700, - buttons: dlgBtns - }); - }); - - $('a[href="#startAnalyzer"]').click(function() { - var $cnt = $('#statustabs_advisor .tabInnerContent'); - $cnt.html(''); - - $.get('server_status.php?' + url_query, { ajax_request: true, advisor: true }, function(data) { - var $tbody, $tr, str, even = true; - - data = $.parseJSON(data.message); - - $cnt.html(''); - - if (data.parse.errors.length > 0) { - $cnt.append('Rules file not well formed, following errors were found:
- '); - $cnt.append(data.parse.errors.join('
- ')); - $cnt.append('

'); - } - - if (data.run.errors.length > 0) { - $cnt.append('Errors occured while executing rule expressions:
- '); - $cnt.append(data.run.errors.join('
- ')); - $cnt.append('

'); - } - - if (data.run.fired.length > 0) { - $cnt.append('

' + PMA_messages['strPerformanceIssues'] + '

'); - $cnt.append('' + - '
' + PMA_messages['strIssuse'] + '' + PMA_messages['strRecommendation'] + - '
'); - $tbody = $cnt.find('table#rulesFired'); - - var rc_stripped; - - $.each(data.run.fired, function(key, value) { - // recommendation may contain links, don't show those in overview table (clicking on them redirects the user) - rc_stripped = $.trim($('
').html(value.recommendation).text()); - $tbody.append($tr = $('' + - value.issue + '' + rc_stripped + ' ')); - even = !even; - $tr.data('rule', value); - - $tr.click(function() { - var rule = $(this).data('rule'); - $('div#emptyDialog').dialog({title: PMA_messages['strRuleDetails']}); - $('div#emptyDialog').html( - '

' + PMA_messages['strIssuse'] + ':
' + rule.issue + '

' + - '

' + PMA_messages['strRecommendation'] + ':
' + rule.recommendation + '

' + - '

' + PMA_messages['strJustification'] + ':
' + rule.justification + '

' + - '

' + PMA_messages['strFormula'] + ':
' + rule.formula + '

' + - '

' + PMA_messages['strTest'] + ':
' + rule.test + '

' - ); - - var dlgBtns = {}; - dlgBtns[PMA_messages['strClose']] = function() { - $(this).dialog('close'); - }; - - $('div#emptyDialog').dialog({ width: 600, buttons: dlgBtns }); - }); - }); - } - }); - - return false; - }); }); diff --git a/js/server_status_advisor.js b/js/server_status_advisor.js new file mode 100644 index 0000000000..5b1b467c48 --- /dev/null +++ b/js/server_status_advisor.js @@ -0,0 +1,86 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * Server Status Advisor + * + * @package PhpMyAdmin + */ + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('server_status_advisor.js', function() { + $('a[href="#openAdvisorInstructions"]').unbind('click'); + $('#statustabs_advisor').html(''); +}); + +AJAX.registerOnload('server_status_advisor.js', function() { + /**** Server config advisor ****/ + + $('a[href="#openAdvisorInstructions"]').click(function() { + var dlgBtns = {}; + dlgBtns[PMA_messages['strClose']] = function() { + $(this).dialog('close'); + }; + $('#advisorInstructionsDialog').dialog({ + title: PMA_messages['strAdvisorSystem'], + width: 700, + buttons: dlgBtns + }); + }); + + var $cnt = $('#statustabs_advisor'); + var $tbody, $tr, str, even = true; + + data = $.parseJSON($('#advisorData').text()); + $cnt.html(''); + + if (data.parse.errors.length > 0) { + $cnt.append('Rules file not well formed, following errors were found:
- '); + $cnt.append(data.parse.errors.join('
- ')); + $cnt.append('

'); + } + + if (data.run.errors.length > 0) { + $cnt.append('Errors occured while executing rule expressions:
- '); + $cnt.append(data.run.errors.join('
- ')); + $cnt.append('

'); + } + + if (data.run.fired.length > 0) { + $cnt.append('

' + PMA_messages['strPerformanceIssues'] + '

'); + $cnt.append('' + + '
' + PMA_messages['strIssuse'] + '' + PMA_messages['strRecommendation'] + + '
'); + $tbody = $cnt.find('table#rulesFired'); + + var rc_stripped; + + $.each(data.run.fired, function(key, value) { + // recommendation may contain links, don't show those in overview table (clicking on them redirects the user) + rc_stripped = $.trim($('
').html(value.recommendation).text()); + $tbody.append($tr = $('' + + value.issue + '' + rc_stripped + ' ')); + even = !even; + $tr.data('rule', value); + + $tr.click(function() { + var rule = $(this).data('rule'); + $('div#emptyDialog').dialog({title: PMA_messages['strRuleDetails']}); + $('div#emptyDialog').html( + '

' + PMA_messages['strIssuse'] + ':
' + rule.issue + '

' + + '

' + PMA_messages['strRecommendation'] + ':
' + rule.recommendation + '

' + + '

' + PMA_messages['strJustification'] + ':
' + rule.justification + '

' + + '

' + PMA_messages['strFormula'] + ':
' + rule.formula + '

' + + '

' + PMA_messages['strTest'] + ':
' + rule.test + '

' + ); + + var dlgBtns = {}; + dlgBtns[PMA_messages['strClose']] = function() { + $(this).dialog('close'); + }; + + $('div#emptyDialog').dialog({ width: 600, buttons: dlgBtns }); + }); + }); + } +}); diff --git a/server_status.php b/server_status.php index b8d00b05fd..a8ded59b38 100644 --- a/server_status.php +++ b/server_status.php @@ -443,12 +443,6 @@ if (isset($_REQUEST['ajax_request']) && $_REQUEST['ajax_request'] == true) { exit(json_encode($return)); } - - if (isset($_REQUEST['advisor'])) { - include 'libraries/Advisor.class.php'; - $advisor = new Advisor(); - exit(json_encode($advisor->run())); - } } @@ -830,9 +824,9 @@ echo '
  • ' . __('All status variables') . '
  • '; echo '
  • ' . __('Monitor') . '
  • '; -echo '
  • ' - . __('Advisor') . '
  • '; echo ''; +echo '' + . __('Advisor') . ''; echo '
    '; echo ''; echo '
    '; diff --git a/server_status_advisor.php b/server_status_advisor.php new file mode 100644 index 0000000000..6573dc991a --- /dev/null +++ b/server_status_advisor.php @@ -0,0 +1,62 @@ +getHeader()->getScripts(); +$scripts->addFile('server_status_advisor.js'); + +$output = ''; +$output .= PMA_Util::getIcon('b_help.png', __('Instructions')); +$output .= ''; +$output .= '
    '; +$output .= ''; +$output .= ''; +$output .= ''; + +$response->addHTML($output); + +?> From 8875eb4799694230581eb542e6bd0da301dfa2d1 Mon Sep 17 00:00:00 2001 From: Rouslan Placella Date: Tue, 4 Dec 2012 00:07:25 +0000 Subject: [PATCH 02/21] Moved more features from server_status.php to own pages Dropped live charting --- js/server_status.js | 292 ----------- js/server_status_queries.js | 32 ++ js/server_status_variables.js | 102 ++++ libraries/ServerStatusData.class.php | 332 +++++++++++++ server_status.php | 527 +------------------- server_status_advisor.php | 6 +- server_status_queries.php | 156 ++++++ server_status_variables.php | 717 +++++++++++++++++++++++++++ 8 files changed, 1346 insertions(+), 818 deletions(-) create mode 100644 js/server_status_queries.js create mode 100644 js/server_status_variables.js create mode 100644 libraries/ServerStatusData.class.php create mode 100644 server_status_queries.php create mode 100644 server_status_variables.php diff --git a/js/server_status.js b/js/server_status.js index bab93b166d..838c288c73 100644 --- a/js/server_status.js +++ b/js/server_status.js @@ -28,14 +28,6 @@ AJAX.registerTeardown('server_status.js', function() { $(document).unbind('click'); // Am I sure about this? I guess not... $('div.buttonlinks select').unbind('click'); $('div.buttonlinks a.tabRefresh').unbind('click'); - $('div.buttonlinks a.livetrafficLink').unbind('click'); - $('div.buttonlinks a.liveconnectionsLink').unbind('click'); - $('div.buttonlinks a.livequeriesLink').unbind('click'); - - $('#filterAlert').unbind('change'); - $('#filterText').unbind('keyup'); - $('#filterCategory').unbind('change'); - $('input#dontFormat').unbind('change'); }); // Add a tablesorter parser to properly handle thousands seperated numbers and SI prefixes @@ -175,13 +167,6 @@ AJAX.registerOnload('server_status.js', function() { if (!$(ui.tab.hash).data('init-done')) { initTab($(ui.tab.hash), null); } - // Replot on tab switching - if (ui.tab.hash == '#statustabs_traffic' && tabChart['statustabs_traffic'] != null) { - recursiveTimer($('#statustabs_traffic'), "traffic"); - } - else if (ui.tab.hash == '#statustabs_queries' && tabChart['statustabs_queries'] != null) { - recursiveTimer($('#statustabs_queries'), "queries"); - } // Load Server status monitor if (ui.tab.hash == '#statustabs_charting' && ! monitorLoaded) { $('div#statustabs_charting').append( //PMA_messages['strLoadingMonitor'] + ' ' + @@ -217,135 +202,8 @@ AJAX.registerOnload('server_status.js', function() { }, 0.5); }); - // Handles refresh rate changing - $('.buttonlinks .refreshRate').change(function() { - - var $tab = $(this).parents('div.ui-tabs-panel'); - clearTimeout(chart_replot_timers[$tab.attr('id')]); - var tabstat = tabStatus[$tab.attr('id')]; - - if(tabstat == 'livequeries') { - recursiveTimer($tab, 'queries'); - } else if(tabstat == 'livetraffic') { - recursiveTimer($tab, 'traffic'); - } else if(tabstat == 'liveconnections') { - recursiveTimer($tab, 'proc'); - } - - var chart = tabChart[$(this).parents('div.ui-tabs-panel').attr('id')]; - // Clear current timeout and set timeout with the new refresh rate - clearTimeout(chart_activeTimeouts[chart.options.chart.renderTo]); - if (chart.options.realtime.postRequest) { - chart.options.realtime.postRequest.abort(); - } - - chart.options.realtime.refreshRate = 1000*parseInt(this.value); - - chart.xAxis[0].setExtremes( - new Date().getTime() - server_time_diff - chart.options.realtime.numMaxPoints * chart.options.realtime.refreshRate, - new Date().getTime() - server_time_diff, - true - ); - - chart_activeTimeouts[chart.options.chart.renderTo] = setTimeout( - chart.options.realtime.timeoutCallBack, - chart.options.realtime.refreshRate - ); - }); - - // Ajax refresh of variables (always the first element in each tab) - $('div.buttonlinks a.tabRefresh').click(function() { - // ui-tabs-panel class is added by the jquery tabs feature - var tab = $(this).parents('div.ui-tabs-panel'); - var that = this; - - // Show ajax load icon - $(this).find('img').show(); - - $.get($(this).attr('href'), { ajax_request: 1 }, function(data) { - $(that).find('img').hide(); - initTab(tab, data); - }); - - tabStatus[tab.attr('id')] = 'data'; - - return false; - }); - - /** Realtime charting of variables **/ - // variables to hold previous y data value to calculate difference - var previous_y_line1 = new Object(); - var previous_y_line2 = new Object(); - var series = new Object(); - - // Live traffic charting - $('div.buttonlinks a.livetrafficLink').click(function() { - // ui-tabs-panel class is added by the jquery tabs feature - var $tab = $(this).parents('div.ui-tabs-panel'); - var tabstat = tabStatus[$tab.attr('id')]; - - if (tabstat == 'static' || tabstat == 'liveconnections') { - - setupLiveChart($tab, this, getSettings('traffic')); - var set_previous = getCurrentDataSet($tab, 'traffic'); - tabChart[$tab.attr('id')] = $.jqplot($tab.attr('id') + '_chart_cnt', [[[0,0]],[[0,0]]], getSettings('traffic')); - recursiveTimer($tab, 'traffic'); - - if (tabstat == 'liveconnections') { - $tab.find('.buttonlinks a.liveconnectionsLink').html(PMA_messages['strLiveConnChart']); - } - tabStatus[$tab.attr('id')] = 'livetraffic'; - } else { - $(this).html(PMA_messages['strLiveTrafficChart']); - setupLiveChart($tab, this, null); - } - - return false; - }); - - // Live connection/process charting - $('div.buttonlinks a.liveconnectionsLink').click(function() { - var $tab = $(this).parents('div.ui-tabs-panel'); - var tabstat = tabStatus[$tab.attr('id')]; - - if (tabstat == 'static' || tabstat == 'livetraffic') { - - setupLiveChart($tab, this, getSettings('proc')); - var set_previous = getCurrentDataSet($tab, 'proc'); - tabChart[$tab.attr('id')] = $.jqplot($tab.attr('id') + '_chart_cnt', [[[0,0]],[[0,0]]], getSettings('proc')); - recursiveTimer($tab, 'proc'); - if (tabstat == 'livetraffic') { - $tab.find('.buttonlinks a.livetrafficLink').html(PMA_messages['strLiveTrafficChart']); - } - tabStatus[$tab.attr('id')] = 'liveconnections'; - } else { - $(this).html(PMA_messages['strLiveConnChart']); - setupLiveChart($tab, this, null); - } - - return false; - }); - - // Live query statistics - $('div.buttonlinks a.livequeriesLink').click(function() { - var $tab = $(this).parents('div.ui-tabs-panel'); - if (tabStatus[$tab.attr('id')] == 'static') { - - setupLiveChart($tab, this, getSettings('queries')); - var set_previous = getCurrentDataSet($tab, 'queries'); - tabChart[$tab.attr('id')] = $.jqplot($tab.attr('id') + '_chart_cnt', [[0,0]], getSettings('queries')); - recursiveTimer($tab, 'queries'); - tabStatus[$tab.attr('id')] = 'livequeries'; - - } else { - $(this).html(PMA_messages['strLiveQueryChart']); - setupLiveChart($tab, this, null); - } - return false; - }); - function recursiveTimer($tab, type) { replotLiveChart($tab, type); chart_replot_timers[$tab.attr('id')] = setTimeout(function() { @@ -487,80 +345,6 @@ AJAX.registerOnload('server_status.js', function() { tabChart[$tab.attr('id')].replot(); } - function setupLiveChart($tab, link, settings) { - if (settings != null) { - // Loading a chart with existing chart => remove old chart first - if (tabStatus[$tab.attr('id')] != 'static') { - clearTimeout(chart_activeTimeouts[$tab.attr('id') + "_chart_cnt"]); - chart_activeTimeouts[$tab.attr('id') + "_chart_cnt"] = null; - delete tabChart[$tab.attr('id')]; - // Also reset the select list - $tab.find('.buttonlinks select').get(0).selectedIndex = 2; - } - - if (! settings.chart) settings.chart = {}; - settings.chart.renderTo = $tab.attr('id') + "_chart_cnt"; - - if($('#' + $tab.attr('id') + '_chart_cnt').length == 0) { - $tab.find('.tabInnerContent') - .hide() - .after('
    '); - } - $(link).html(PMA_messages['strStaticData']); - $tab.find('.buttonlinks a.tabRefresh').hide(); - $tab.find('.buttonlinks .refreshList').show(); - } else { - clearTimeout(chart_activeTimeouts[$tab.attr('id') + "_chart_cnt"]); - chart_activeTimeouts[$tab.attr('id') + "_chart_cnt"] = null; - $tab.find('.tabInnerContent').show(); - $tab.find('div#' + $tab.attr('id') + '_chart_cnt').remove(); - tabStatus[$tab.attr('id')] = 'static'; - delete tabChart[$tab.attr('id')]; - $tab.find('.buttonlinks a.tabRefresh').show(); - $tab.find('.buttonlinks select').get(0).selectedIndex = 2; - $tab.find('.buttonlinks .refreshList').hide(); - } - clearTimeout(chart_replot_timers[$tab.attr('id')]); - previous_y_line1[$tab.attr('id')] = 0; - previous_y_line2[$tab.attr('id')] = 0; - series[$tab.attr('id')] = new Array(); - series[$tab.attr('id')][0] = new Array(); - series[$tab.attr('id')][1] = new Array(); - } - - /* 3 Filtering functions */ - $('#filterAlert').change(function() { - alertFilter = this.checked; - filterVariables(); - }); - - $('#filterText').keyup(function(e) { - var word = $(this).val().replace(/_/g, ' '); - - if (word.length == 0) { - textFilter = null; - } else { - textFilter = new RegExp("(^| )" + word, 'i'); - } - - text = word; - - filterVariables(); - }); - - $('#filterCategory').change(function() { - categoryFilter = $(this).val(); - filterVariables(); - }); - - $('input#dontFormat').change(function() { - // Hiding the table while changing values speeds up the process a lot - $('#serverstatusvariables').hide(); - $('#serverstatusvariables td.value span.original').toggle(this.checked); - $('#serverstatusvariables td.value span.formatted').toggle(! this.checked); - $('#serverstatusvariables').show(); - }); - /* Adjust DOM / Add handlers to the tabs */ function initTab(tab, data) { if ($(tab).data('init-done') && !data) { @@ -574,33 +358,6 @@ AJAX.registerOnload('server_status.js', function() { } PMA_showHints(); break; - case 'statustabs_queries': - if (data != null) { - queryPieChart.destroy(); - tab.find('.tabInnerContent').html(data.message); - } - - // Build query statistics chart - var cdata = new Array(); - $.each(jQuery.parseJSON($('#serverstatusquerieschart span').html()), function(key, value) { - cdata.push([key, parseInt(value)]); - }); - - queryPieChart = PMA_createProfilingChartJqplot( - 'serverstatusquerieschart', - cdata - ); - - initTableSorter(tab.attr('id')); - break; - - case 'statustabs_allvars': - if (data != null) { - tab.find('.tabInnerContent').html(data.message); - filterVariables(); - } - initTableSorter(tab.attr('id')); - break; } } @@ -635,55 +392,6 @@ AJAX.registerOnload('server_status.js', function() { .append(''); } - /* Filters the status variables by name/category/alert in the variables tab */ - function filterVariables() { - var useful_links = 0; - var section = text; - - if (categoryFilter.length > 0) { - section = categoryFilter; - } - - if (section.length > 1) { - $('#linkSuggestions span').each(function() { - if ($(this).attr('class').indexOf('status_' + section) != -1) { - useful_links++; - $(this).css('display', ''); - } else { - $(this).css('display', 'none'); - } - - - }); - } - - if (useful_links > 0) { - $('#linkSuggestions').css('display', ''); - } else { - $('#linkSuggestions').css('display', 'none'); - } - - odd_row = false; - $('#serverstatusvariables th.name').each(function() { - if ((textFilter == null || textFilter.exec($(this).text())) - && (! alertFilter || $(this).next().find('span.attention').length>0) - && (categoryFilter.length == 0 || $(this).parent().hasClass('s_' + categoryFilter)) - ) { - odd_row = ! odd_row; - $(this).parent().css('display', ''); - if (odd_row) { - $(this).parent().addClass('odd'); - $(this).parent().removeClass('even'); - } else { - $(this).parent().addClass('even'); - $(this).parent().removeClass('odd'); - } - } else { - $(this).parent().css('display', 'none'); - } - }); - } - // Provides a nicely formatted and sorted tooltip of each datapoint of the query statistics function sortedQueriesPointInfo(queries, lastQueries){ var max, maxIdx, num = 0; diff --git a/js/server_status_queries.js b/js/server_status_queries.js new file mode 100644 index 0000000000..94838e5d13 --- /dev/null +++ b/js/server_status_queries.js @@ -0,0 +1,32 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + */ + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('server_status_queries.js', function() { + var queryPieChart = $('#serverstatusquerieschart').data('queryPieChart'); + if (queryPieChart) { + queryPieChart.destroy(); + } +}); + +AJAX.registerOnload('server_status_queries.js', function() { + // Build query statistics chart + var cdata = []; + try { + $.each(jQuery.parseJSON($('#serverstatusquerieschart_data').text()), function(key, value) { + cdata.push([key, parseInt(value)]); + }); + $('#serverstatusquerieschart').data( + 'queryPieChart', + PMA_createProfilingChartJqplot( + 'serverstatusquerieschart', + cdata + ) + ); + } catch (exception) { + // Could not load chart, no big deal... + } +}); diff --git a/js/server_status_variables.js b/js/server_status_variables.js new file mode 100644 index 0000000000..0676e11c51 --- /dev/null +++ b/js/server_status_variables.js @@ -0,0 +1,102 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * + * + * @package PhpMyAdmin + */ + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('server_status_variables.js', function() { + $('#filterAlert').unbind('change'); + $('#filterText').unbind('keyup'); + $('#filterCategory').unbind('change'); + $('#dontFormat').unbind('change'); +}); + +AJAX.registerOnload('server_status_variables.js', function() { + // Filters for status variables + var textFilter = null; + var alertFilter = $('#filterAlert').prop('checked'); + var categoryFilter = $('#filterCategory').find(':selected').val(); + var odd_row = false; + var text = ''; // Holds filter text + + /* 3 Filtering functions */ + $('#filterAlert').change(function() { + alertFilter = this.checked; + filterVariables(); + }); + + $('#filterCategory').change(function() { + categoryFilter = $(this).val(); + filterVariables(); + }); + + $('#dontFormat').change(function() { + // Hiding the table while changing values speeds up the process a lot + $('#serverstatusvariables').hide(); + $('#serverstatusvariables td.value span.original').toggle(this.checked); + $('#serverstatusvariables td.value span.formatted').toggle(! this.checked); + $('#serverstatusvariables').show(); + }).trigger('change'); + + $('#filterText').keyup(function(e) { + var word = $(this).val().replace(/_/g, ' '); + if (word.length == 0) { + textFilter = null; + } else { + textFilter = new RegExp("(^| )" + word, 'i'); + } + text = word; + filterVariables(); + }).trigger('keyup'); + + /* Filters the status variables by name/category/alert in the variables tab */ + function filterVariables() { + var useful_links = 0; + var section = text; + + if (categoryFilter.length > 0) { + section = categoryFilter; + } + + if (section.length > 1) { + $('#linkSuggestions span').each(function() { + if ($(this).attr('class').indexOf('status_' + section) != -1) { + useful_links++; + $(this).css('display', ''); + } else { + $(this).css('display', 'none'); + } + }); + } + + if (useful_links > 0) { + $('#linkSuggestions').css('display', ''); + } else { + $('#linkSuggestions').css('display', 'none'); + } + + odd_row = false; + $('#serverstatusvariables th.name').each(function() { + if ((textFilter == null || textFilter.exec($(this).text())) + && (! alertFilter || $(this).next().find('span.attention').length>0) + && (categoryFilter.length == 0 || $(this).parent().hasClass('s_' + categoryFilter)) + ) { + odd_row = ! odd_row; + $(this).parent().css('display', ''); + if (odd_row) { + $(this).parent().addClass('odd'); + $(this).parent().removeClass('even'); + } else { + $(this).parent().addClass('even'); + $(this).parent().removeClass('odd'); + } + } else { + $(this).parent().css('display', 'none'); + } + }); + } +}); diff --git a/libraries/ServerStatusData.class.php b/libraries/ServerStatusData.class.php new file mode 100644 index 0000000000..85d507b05e --- /dev/null +++ b/libraries/ServerStatusData.class.php @@ -0,0 +1,332 @@ +selfUrl = $selfUrl; + /** + * get status from server + */ + $server_status = PMA_DBI_fetch_result('SHOW GLOBAL STATUS', 0, 1); + if (PMA_DRIZZLE) { + // Drizzle doesn't put query statistics into variables, add it + $sql = "SELECT concat('Com_', variable_name), variable_value + FROM data_dictionary.GLOBAL_STATEMENTS"; + $statements = PMA_DBI_fetch_result($sql, 0, 1); + $server_status = array_merge($server_status, $statements); + } + + /** + * for some calculations we require also some server settings + */ + $server_variables = PMA_DBI_fetch_result('SHOW GLOBAL VARIABLES', 0, 1); + + /** + * cleanup of some deprecated values + */ + $server_status = self::cleanDeprecated($server_status); + + /** + * calculate some values + */ + // Key_buffer_fraction + if (isset($server_status['Key_blocks_unused']) + && isset($server_variables['key_cache_block_size']) + && isset($server_variables['key_buffer_size']) + ) { + $server_status['Key_buffer_fraction_%'] + = 100 + - $server_status['Key_blocks_unused'] + * $server_variables['key_cache_block_size'] + / $server_variables['key_buffer_size'] + * 100; + } elseif (isset($server_status['Key_blocks_used']) + && isset($server_variables['key_buffer_size'])) { + $server_status['Key_buffer_fraction_%'] + = $server_status['Key_blocks_used'] + * 1024 + / $server_variables['key_buffer_size']; + } + + // Ratio for key read/write + if (isset($server_status['Key_writes']) + && isset($server_status['Key_write_requests']) + && $server_status['Key_write_requests'] > 0 + ) { + $server_status['Key_write_ratio_%'] + = 100 * $server_status['Key_writes'] / $server_status['Key_write_requests']; + } + + if (isset($server_status['Key_reads']) + && isset($server_status['Key_read_requests']) + && $server_status['Key_read_requests'] > 0 + ) { + $server_status['Key_read_ratio_%'] + = 100 * $server_status['Key_reads'] / $server_status['Key_read_requests']; + } + + // Threads_cache_hitrate + if (isset($server_status['Threads_created']) + && isset($server_status['Connections']) + && $server_status['Connections'] > 0 + ) { + + $server_status['Threads_cache_hitrate_%'] + = 100 - $server_status['Threads_created'] + / $server_status['Connections'] * 100; + } + + /** + * split variables in sections + */ + $allocations = array( + // variable name => section + // variable names match when they begin with the given string + + 'Com_' => 'com', + 'Innodb_' => 'innodb', + 'Ndb_' => 'ndb', + 'Handler_' => 'handler', + 'Qcache_' => 'qcache', + 'Threads_' => 'threads', + 'Slow_launch_threads' => 'threads', + + 'Binlog_cache_' => 'binlog_cache', + 'Created_tmp_' => 'created_tmp', + 'Key_' => 'key', + + 'Delayed_' => 'delayed', + 'Not_flushed_delayed_rows' => 'delayed', + + 'Flush_commands' => 'query', + 'Last_query_cost' => 'query', + 'Slow_queries' => 'query', + 'Queries' => 'query', + 'Prepared_stmt_count' => 'query', + + 'Select_' => 'select', + 'Sort_' => 'sort', + + 'Open_tables' => 'table', + 'Opened_tables' => 'table', + 'Open_table_definitions' => 'table', + 'Opened_table_definitions' => 'table', + 'Table_locks_' => 'table', + + 'Rpl_status' => 'repl', + 'Slave_' => 'repl', + + 'Tc_' => 'tc', + + 'Ssl_' => 'ssl', + + 'Open_files' => 'files', + 'Open_streams' => 'files', + 'Opened_files' => 'files', + ); + + $sections = array( + // section => section name (description) + 'com' => 'Com', + 'query' => __('SQL query'), + 'innodb' => 'InnoDB', + 'ndb' => 'NDB', + 'handler' => __('Handler'), + 'qcache' => __('Query cache'), + 'threads' => __('Threads'), + 'binlog_cache' => __('Binary log'), + 'created_tmp' => __('Temporary data'), + 'delayed' => __('Delayed inserts'), + 'key' => __('Key cache'), + 'select' => __('Joins'), + 'repl' => __('Replication'), + 'sort' => __('Sorting'), + 'table' => __('Tables'), + 'tc' => __('Transaction coordinator'), + 'files' => __('Files'), + 'ssl' => 'SSL', + 'other' => __('Other') + ); + + /** + * define some needfull links/commands + */ + // variable or section name => (name => url) + $links = array(); + + $links['table'][__('Flush (close) all tables')] + = $this->selfUrl . '?flush=TABLES&' . PMA_generate_common_url(); + $links['table'][__('Show open tables')] + = 'sql.php?sql_query=' . urlencode('SHOW OPEN TABLES') . + '&goto=' . $this->selfUrl . '&' . PMA_generate_common_url(); + + if ($GLOBALS['server_master_status']) { + $links['repl'][__('Show slave hosts')] + = 'sql.php?sql_query=' . urlencode('SHOW SLAVE HOSTS') . + '&goto=' . $this->selfUrl . '&' . PMA_generate_common_url(); + $links['repl'][__('Show master status')] = '#replication_master'; + } + if ($GLOBALS['server_slave_status']) { + $links['repl'][__('Show slave status')] = '#replication_slave'; + } + + $links['repl']['doc'] = 'replication'; + + $links['qcache'][__('Flush query cache')] + = $this->selfUrl . '?flush=' . urlencode('QUERY CACHE') . '&' . + PMA_generate_common_url(); + $links['qcache']['doc'] = 'query_cache'; + + //$links['threads'][__('Show processes')] + // = 'server_processlist.php?' . PMA_generate_common_url(); + $links['threads']['doc'] = 'mysql_threads'; + + $links['key']['doc'] = 'myisam_key_cache'; + + $links['binlog_cache']['doc'] = 'binary_log'; + + $links['Slow_queries']['doc'] = 'slow_query_log'; + + $links['innodb'][__('Variables')] + = 'server_engines.php?engine=InnoDB&' . PMA_generate_common_url(); + $links['innodb'][__('InnoDB Status')] + = 'server_engines.php?engine=InnoDB&page=Status&' . + PMA_generate_common_url(); + $links['innodb']['doc'] = 'innodb'; + + + // Variable to contain all com_ variables (query statistics) + $used_queries = array(); + + // Variable to map variable names to their respective section name + // (used for js category filtering) + $allocationMap = array(); + + // Variable to mark used sections + $categoryUsed = array(); + + // sort vars into arrays + foreach ($server_status as $name => $value) { + $section_found = false; + foreach ($allocations as $filter => $section) { + if (strpos($name, $filter) !== false) { + $allocationMap[$name] = $section; + $categoryUsed[$section] = true; + $section_found = true; + if ($section == 'com' && $value > 0) { + $used_queries[$name] = $value; + } + break; // Only exits inner loop + } + } + if (!$section_found) { + $allocationMap[$name] = 'other'; + $categoryUsed['other'] = true; + } + } + + if (PMA_DRIZZLE) { + $used_queries = PMA_DBI_fetch_result( + 'SELECT * FROM data_dictionary.global_statements', + 0, + 1 + ); + unset($used_queries['admin_commands']); + } else { + // admin commands are not queries (e.g. they include COM_PING, + // which is excluded from $server_status['Questions']) + unset($used_queries['Com_admin_commands']); + } + + // Set all class properties + $this->db_isLocal = false; + if (strtolower($GLOBALS['cfg']['Server']['host']) === 'localhost' + || $GLOBALS['cfg']['Server']['host'] === '127.0.0.1' + || $GLOBALS['cfg']['Server']['host'] === '::1' + ) { + $this->db_isLocal = true; + } + $this->status = $server_status; + $this->sections = $sections; + $this->variables = $server_variables; + $this->used_queries = $used_queries; + $this->allocationMap = $allocationMap; + $this->links = $links; + $this->categoryUsed = $categoryUsed; + } + + /** + * cleanup of some deprecated values + * + * @param array $server_status status array to process + * + * @return array + */ + public static function cleanDeprecated($server_status) + { + $deprecated = array( + 'Com_prepare_sql' => 'Com_stmt_prepare', + 'Com_execute_sql' => 'Com_stmt_execute', + 'Com_dealloc_sql' => 'Com_stmt_close', + ); + foreach ($deprecated as $old => $new) { + if (isset($server_status[$old]) && isset($server_status[$new])) { + unset($server_status[$old]); + } + } + return $server_status; + } + + /** + * cleanup of some deprecated values + * + * @param array $server_status status array to process + * + * @return array + */ + public static function getMenuHtml() + { + $retval = ''; + $retval .= '
    '; + return $retval; + } +} + +?> diff --git a/server_status.php b/server_status.php index a8ded59b38..c7a0162a99 100644 --- a/server_status.php +++ b/server_status.php @@ -8,6 +8,7 @@ */ require_once 'libraries/common.inc.php'; +require_once 'libraries/ServerStatusData.class.php'; /** * Ajax request @@ -463,7 +464,6 @@ if (PMA_DRIZZLE) { $response = PMA_Response::getInstance(); $header = $response->getHeader(); $scripts = $header->getScripts(); -$scripts->addFile('server_status.js'); $scripts->addFile('jquery/jquery.tablesorter.js'); $scripts->addFile('server_status.js'); @@ -806,147 +806,15 @@ echo '
    '; require 'libraries/server_common.inc.php'; echo '
    '; -echo '

    '; -/** - * Displays the sub-page heading - */ -echo PMA_Util::getImage('s_status.png'); +echo PMA_ServerStatusData::getMenuHtml(); -echo __('Runtime Information'); - -echo '

    '; echo '
    '; echo ''; -echo '' - . __('Advisor') . ''; - -echo '
    '; -echo ''; -echo '
    '; -printServerTraffic(); -echo '
    '; -echo '
    '; -echo '
    '; -echo ''; -echo '
    '; -printQueryStatistics(); -echo '
    '; -echo '
    '; -echo '
    '; -echo '
    '; -echo '' . __('Filters') . ''; -echo ''; -echo '
    '; -echo ''; -echo ''; -echo '
    '; -echo '
    '; -echo ''; -echo ''; -echo '
    '; -echo '
    '; -echo ''; -echo '
    '; -echo '
    '; -echo ''; -echo ''; -echo '
    '; -echo '
    '; -echo ''; -echo '
    '; -printVariablesTable(); -echo '
    '; -echo '
    '; echo '
    '; printMonitor(); @@ -955,125 +823,6 @@ echo '
    '; echo '
    '; echo '
    '; -/** - * Prints query statistincs - * - * @return void - */ -function printQueryStatistics() -{ - global $server_status, $used_queries, $url_query, $PMA_PHP_SELF; - - $hour_factor = 3600 / $server_status['Uptime']; - - $total_queries = array_sum($used_queries); - - echo '

    '; - /* l10n: Questions is the name of a MySQL Status variable */ - printf( - __('Questions since startup: %s'), - PMA_Util::formatNumber($total_queries, 0) - ); - echo ' '; - echo PMA_Util::showMySQLDocu( - 'server-status-variables', - 'server-status-variables', - false, - 'statvar_Questions' - ); - - echo '
    '; - echo ''; - - echo 'ø ' . __('per hour') . ': '; - echo PMA_Util::formatNumber($total_queries * $hour_factor, 0); - echo '
    '; - - echo 'ø ' . __('per minute') . ': '; - echo PMA_Util::formatNumber($total_queries * 60 / $server_status['Uptime'], 0); - echo '
    '; - - if ($total_queries / $server_status['Uptime'] >= 1) { - echo 'ø ' . __('per second') . ': '; - echo PMA_Util::formatNumber($total_queries / $server_status['Uptime'], 0); - } - - echo '
    '; - echo '

    '; - - // reverse sort by value to show most used statements first - arsort($used_queries); - - $odd_row = true; - $count_displayed_rows = 0; - $perc_factor = 100 / $total_queries; //(- $server_status['Connections']); - - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - - $chart_json = array(); - $query_sum = array_sum($used_queries); - $other_sum = 0; - foreach ($used_queries as $name => $value) { - $odd_row = !$odd_row; - - // For the percentage column, use Questions - Connections, because - // the number of connections is not an item of the Query types - // but is included in Questions. Then the total of the percentages is 100. - $name = str_replace(array('Com_', '_'), array('', ' '), $name); - - // Group together values that make out less than 2% into "Other", but only - // if we have more than 6 fractions already - if ($value < $query_sum * 0.02 && count($chart_json)>6) { - $other_sum += $value; - } else { - $chart_json[$name] = $value; - } - - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - } - echo ''; - echo '
    ' . __('Statements') . ''; - /* l10n: # = Amount of queries */ - echo __('#'); - echo 'ø ' . __('per hour') . '%
    ' . htmlspecialchars($name) . ''; - echo htmlspecialchars(PMA_Util::formatNumber($value, 5, 0, true)); - echo ''; - echo htmlspecialchars( - PMA_Util::formatNumber($value * $hour_factor, 4, 1, true) - ); - echo ''; - echo htmlspecialchars(PMA_Util::formatNumber($value * $perc_factor, 0, 2)); - echo '
    '; - - echo '
    '; - echo ''; - - if ($other_sum > 0) { - $chart_json[__('Other')] = $other_sum; - } - - echo json_encode($chart_json); - echo ''; - echo '
    '; -} - /** * Prints server traffic information * @@ -1482,278 +1231,6 @@ function printServerTraffic() __('The number of connections that were aborted because the client died without closing the connection properly.'), - 'Aborted_connects' => __('The number of failed attempts to connect to the MySQL server.'), - 'Binlog_cache_disk_use' => __('The number of transactions that used the temporary binary log cache but that exceeded the value of binlog_cache_size and used a temporary file to store statements from the transaction.'), - 'Binlog_cache_use' => __('The number of transactions that used the temporary binary log cache.'), - 'Connections' => __('The number of connection attempts (successful or not) to the MySQL server.'), - 'Created_tmp_disk_tables' => __('The number of temporary tables on disk created automatically by the server while executing statements. If Created_tmp_disk_tables is big, you may want to increase the tmp_table_size value to cause temporary tables to be memory-based instead of disk-based.'), - 'Created_tmp_files' => __('How many temporary files mysqld has created.'), - 'Created_tmp_tables' => __('The number of in-memory temporary tables created automatically by the server while executing statements.'), - 'Delayed_errors' => __('The number of rows written with INSERT DELAYED for which some error occurred (probably duplicate key).'), - 'Delayed_insert_threads' => __('The number of INSERT DELAYED handler threads in use. Every different table on which one uses INSERT DELAYED gets its own thread.'), - 'Delayed_writes' => __('The number of INSERT DELAYED rows written.'), - 'Flush_commands' => __('The number of executed FLUSH statements.'), - 'Handler_commit' => __('The number of internal COMMIT statements.'), - 'Handler_delete' => __('The number of times a row was deleted from a table.'), - 'Handler_discover' => __('The MySQL server can ask the NDB Cluster storage engine if it knows about a table with a given name. This is called discovery. Handler_discover indicates the number of time tables have been discovered.'), - 'Handler_read_first' => __('The number of times the first entry was read from an index. If this is high, it suggests that the server is doing a lot of full index scans; for example, SELECT col1 FROM foo, assuming that col1 is indexed.'), - 'Handler_read_key' => __('The number of requests to read a row based on a key. If this is high, it is a good indication that your queries and tables are properly indexed.'), - 'Handler_read_next' => __('The number of requests to read the next row in key order. This is incremented if you are querying an index column with a range constraint or if you are doing an index scan.'), - 'Handler_read_prev' => __('The number of requests to read the previous row in key order. This read method is mainly used to optimize ORDER BY ... DESC.'), - 'Handler_read_rnd' => __('The number of requests to read a row based on a fixed position. This is high if you are doing a lot of queries that require sorting of the result. You probably have a lot of queries that require MySQL to scan whole tables or you have joins that don\'t use keys properly.'), - 'Handler_read_rnd_next' => __('The number of requests to read the next row in the data file. This is high if you are doing a lot of table scans. Generally this suggests that your tables are not properly indexed or that your queries are not written to take advantage of the indexes you have.'), - 'Handler_rollback' => __('The number of internal ROLLBACK statements.'), - 'Handler_update' => __('The number of requests to update a row in a table.'), - 'Handler_write' => __('The number of requests to insert a row in a table.'), - 'Innodb_buffer_pool_pages_data' => __('The number of pages containing data (dirty or clean).'), - 'Innodb_buffer_pool_pages_dirty' => __('The number of pages currently dirty.'), - 'Innodb_buffer_pool_pages_flushed' => __('The number of buffer pool pages that have been requested to be flushed.'), - 'Innodb_buffer_pool_pages_free' => __('The number of free pages.'), - 'Innodb_buffer_pool_pages_latched' => __('The number of latched pages in InnoDB buffer pool. These are pages currently being read or written or that can\'t be flushed or removed for some other reason.'), - 'Innodb_buffer_pool_pages_misc' => __('The number of pages busy because they have been allocated for administrative overhead such as row locks or the adaptive hash index. This value can also be calculated as Innodb_buffer_pool_pages_total - Innodb_buffer_pool_pages_free - Innodb_buffer_pool_pages_data.'), - 'Innodb_buffer_pool_pages_total' => __('Total size of buffer pool, in pages.'), - 'Innodb_buffer_pool_read_ahead_rnd' => __('The number of "random" read-aheads InnoDB initiated. This happens when a query is to scan a large portion of a table but in random order.'), - 'Innodb_buffer_pool_read_ahead_seq' => __('The number of sequential read-aheads InnoDB initiated. This happens when InnoDB does a sequential full table scan.'), - 'Innodb_buffer_pool_read_requests' => __('The number of logical read requests InnoDB has done.'), - 'Innodb_buffer_pool_reads' => __('The number of logical reads that InnoDB could not satisfy from buffer pool and had to do a single-page read.'), - 'Innodb_buffer_pool_wait_free' => __('Normally, writes to the InnoDB buffer pool happen in the background. However, if it\'s necessary to read or create a page and no clean pages are available, it\'s necessary to wait for pages to be flushed first. This counter counts instances of these waits. If the buffer pool size was set properly, this value should be small.'), - 'Innodb_buffer_pool_write_requests' => __('The number writes done to the InnoDB buffer pool.'), - 'Innodb_data_fsyncs' => __('The number of fsync() operations so far.'), - 'Innodb_data_pending_fsyncs' => __('The current number of pending fsync() operations.'), - 'Innodb_data_pending_reads' => __('The current number of pending reads.'), - 'Innodb_data_pending_writes' => __('The current number of pending writes.'), - 'Innodb_data_read' => __('The amount of data read so far, in bytes.'), - 'Innodb_data_reads' => __('The total number of data reads.'), - 'Innodb_data_writes' => __('The total number of data writes.'), - 'Innodb_data_written' => __('The amount of data written so far, in bytes.'), - 'Innodb_dblwr_pages_written' => __('The number of pages that have been written for doublewrite operations.'), - 'Innodb_dblwr_writes' => __('The number of doublewrite operations that have been performed.'), - 'Innodb_log_waits' => __('The number of waits we had because log buffer was too small and we had to wait for it to be flushed before continuing.'), - 'Innodb_log_write_requests' => __('The number of log write requests.'), - 'Innodb_log_writes' => __('The number of physical writes to the log file.'), - 'Innodb_os_log_fsyncs' => __('The number of fsync() writes done to the log file.'), - 'Innodb_os_log_pending_fsyncs' => __('The number of pending log file fsyncs.'), - 'Innodb_os_log_pending_writes' => __('Pending log file writes.'), - 'Innodb_os_log_written' => __('The number of bytes written to the log file.'), - 'Innodb_pages_created' => __('The number of pages created.'), - 'Innodb_page_size' => __('The compiled-in InnoDB page size (default 16KB). Many values are counted in pages; the page size allows them to be easily converted to bytes.'), - 'Innodb_pages_read' => __('The number of pages read.'), - 'Innodb_pages_written' => __('The number of pages written.'), - 'Innodb_row_lock_current_waits' => __('The number of row locks currently being waited for.'), - 'Innodb_row_lock_time_avg' => __('The average time to acquire a row lock, in milliseconds.'), - 'Innodb_row_lock_time' => __('The total time spent in acquiring row locks, in milliseconds.'), - 'Innodb_row_lock_time_max' => __('The maximum time to acquire a row lock, in milliseconds.'), - 'Innodb_row_lock_waits' => __('The number of times a row lock had to be waited for.'), - 'Innodb_rows_deleted' => __('The number of rows deleted from InnoDB tables.'), - 'Innodb_rows_inserted' => __('The number of rows inserted in InnoDB tables.'), - 'Innodb_rows_read' => __('The number of rows read from InnoDB tables.'), - 'Innodb_rows_updated' => __('The number of rows updated in InnoDB tables.'), - 'Key_blocks_not_flushed' => __('The number of key blocks in the key cache that have changed but haven\'t yet been flushed to disk. It used to be known as Not_flushed_key_blocks.'), - 'Key_blocks_unused' => __('The number of unused blocks in the key cache. You can use this value to determine how much of the key cache is in use.'), - 'Key_blocks_used' => __('The number of used blocks in the key cache. This value is a high-water mark that indicates the maximum number of blocks that have ever been in use at one time.'), - 'Key_buffer_fraction_%' => __('Percentage of used key cache (calculated value)'), - 'Key_read_requests' => __('The number of requests to read a key block from the cache.'), - 'Key_reads' => __('The number of physical reads of a key block from disk. If Key_reads is big, then your key_buffer_size value is probably too small. The cache miss rate can be calculated as Key_reads/Key_read_requests.'), - 'Key_read_ratio_%' => __('Key cache miss calculated as rate of physical reads compared to read requests (calculated value)'), - 'Key_write_requests' => __('The number of requests to write a key block to the cache.'), - 'Key_writes' => __('The number of physical writes of a key block to disk.'), - 'Key_write_ratio_%' => __('Percentage of physical writes compared to write requests (calculated value)'), - 'Last_query_cost' => __('The total cost of the last compiled query as computed by the query optimizer. Useful for comparing the cost of different query plans for the same query. The default value of 0 means that no query has been compiled yet.'), - 'Max_used_connections' => __('The maximum number of connections that have been in use simultaneously since the server started.'), - 'Not_flushed_delayed_rows' => __('The number of rows waiting to be written in INSERT DELAYED queues.'), - 'Opened_tables' => __('The number of tables that have been opened. If opened tables is big, your table cache value is probably too small.'), - 'Open_files' => __('The number of files that are open.'), - 'Open_streams' => __('The number of streams that are open (used mainly for logging).'), - 'Open_tables' => __('The number of tables that are open.'), - 'Qcache_free_blocks' => __('The number of free memory blocks in query cache. High numbers can indicate fragmentation issues, which may be solved by issuing a FLUSH QUERY CACHE statement.'), - 'Qcache_free_memory' => __('The amount of free memory for query cache.'), - 'Qcache_hits' => __('The number of cache hits.'), - 'Qcache_inserts' => __('The number of queries added to the cache.'), - 'Qcache_lowmem_prunes' => __('The number of queries that have been removed from the cache to free up memory for caching new queries. This information can help you tune the query cache size. The query cache uses a least recently used (LRU) strategy to decide which queries to remove from the cache.'), - 'Qcache_not_cached' => __('The number of non-cached queries (not cachable, or not cached due to the query_cache_type setting).'), - 'Qcache_queries_in_cache' => __('The number of queries registered in the cache.'), - 'Qcache_total_blocks' => __('The total number of blocks in the query cache.'), - 'Rpl_status' => __('The status of failsafe replication (not yet implemented).'), - 'Select_full_join' => __('The number of joins that do not use indexes. If this value is not 0, you should carefully check the indexes of your tables.'), - 'Select_full_range_join' => __('The number of joins that used a range search on a reference table.'), - 'Select_range_check' => __('The number of joins without keys that check for key usage after each row. (If this is not 0, you should carefully check the indexes of your tables.)'), - 'Select_range' => __('The number of joins that used ranges on the first table. (It\'s normally not critical even if this is big.)'), - 'Select_scan' => __('The number of joins that did a full scan of the first table.'), - 'Slave_open_temp_tables' => __('The number of temporary tables currently open by the slave SQL thread.'), - 'Slave_retried_transactions' => __('Total (since startup) number of times the replication slave SQL thread has retried transactions.'), - 'Slave_running' => __('This is ON if this server is a slave that is connected to a master.'), - 'Slow_launch_threads' => __('The number of threads that have taken more than slow_launch_time seconds to create.'), - 'Slow_queries' => __('The number of queries that have taken more than long_query_time seconds.'), - 'Sort_merge_passes' => __('The number of merge passes the sort algorithm has had to do. If this value is large, you should consider increasing the value of the sort_buffer_size system variable.'), - 'Sort_range' => __('The number of sorts that were done with ranges.'), - 'Sort_rows' => __('The number of sorted rows.'), - 'Sort_scan' => __('The number of sorts that were done by scanning the table.'), - 'Table_locks_immediate' => __('The number of times that a table lock was acquired immediately.'), - 'Table_locks_waited' => __('The number of times that a table lock could not be acquired immediately and a wait was needed. If this is high, and you have performance problems, you should first optimize your queries, and then either split your table or tables or use replication.'), - 'Threads_cached' => __('The number of threads in the thread cache. The cache hit rate can be calculated as Threads_created/Connections. If this value is red you should raise your thread_cache_size.'), - 'Threads_connected' => __('The number of currently open connections.'), - 'Threads_created' => __('The number of threads created to handle connections. If Threads_created is big, you may want to increase the thread_cache_size value. (Normally this doesn\'t give a notable performance improvement if you have a good thread implementation.)'), - 'Threads_cache_hitrate_%' => __('Thread cache hit rate (calculated value)'), - 'Threads_running' => __('The number of threads that are not sleeping.') - ); - - /** - * define some alerts - */ - // name => max value before alert - $alerts = array( - // lower is better - // variable => max value - 'Aborted_clients' => 0, - 'Aborted_connects' => 0, - - 'Binlog_cache_disk_use' => 0, - - 'Created_tmp_disk_tables' => 0, - - 'Handler_read_rnd' => 0, - 'Handler_read_rnd_next' => 0, - - 'Innodb_buffer_pool_pages_dirty' => 0, - 'Innodb_buffer_pool_reads' => 0, - 'Innodb_buffer_pool_wait_free' => 0, - 'Innodb_log_waits' => 0, - 'Innodb_row_lock_time_avg' => 10, // ms - 'Innodb_row_lock_time_max' => 50, // ms - 'Innodb_row_lock_waits' => 0, - - 'Slow_queries' => 0, - 'Delayed_errors' => 0, - 'Select_full_join' => 0, - 'Select_range_check' => 0, - 'Sort_merge_passes' => 0, - 'Opened_tables' => 0, - 'Table_locks_waited' => 0, - 'Qcache_lowmem_prunes' => 0, - - 'Qcache_free_blocks' => isset($server_status['Qcache_total_blocks']) - ? $server_status['Qcache_total_blocks'] / 5 : 0, - 'Slow_launch_threads' => 0, - - // depends on Key_read_requests - // normaly lower then 1:0.01 - 'Key_reads' => isset($server_status['Key_read_requests']) - ? (0.01 * $server_status['Key_read_requests']) : 0, - // depends on Key_write_requests - // normaly nearly 1:1 - 'Key_writes' => isset($server_status['Key_write_requests']) - ? (0.9 * $server_status['Key_write_requests']) : 0, - - 'Key_buffer_fraction' => 0.5, - - // alert if more than 95% of thread cache is in use - 'Threads_cached' => isset($server_variables['thread_cache_size']) - ? 0.95 * $server_variables['thread_cache_size'] : 0 - - // higher is better - // variable => min value - //'Handler read key' => '> ', - ); - -?> - - - - - - - - - - - - - $value) { - $odd_row = !$odd_row; - echo ''; - - echo ''; - - echo ''; - echo ''; - echo ''; - } - echo ''; - echo '
    '; - echo htmlspecialchars(str_replace('_', ' ', $name)); - /* Fields containing % are calculated, they can not be described in MySQL documentation */ - if (strpos($name, '%') === false) { - echo PMA_Util::showMySQLDocu('server-status-variables', 'server-status-variables', false, 'statvar_' . $name); - } - echo ''; - if (isset($alerts[$name])) { - if ($value > $alerts[$name]) { - echo ''; - } else { - echo ''; - } - } - if ('%' === substr($name, -1, 1)) { - echo htmlspecialchars(PMA_Util::formatNumber($value, 0, 2)) . ' %'; - } elseif (strpos($name, 'Uptime') !== false) { - echo htmlspecialchars( - PMA_Util::timespanFormat($value) - ); - } elseif (is_numeric($value) && $value == (int) $value && $value > 1000) { - echo htmlspecialchars(PMA_Util::formatNumber($value, 3, 1)); - } elseif (is_numeric($value) && $value == (int) $value) { - echo htmlspecialchars(PMA_Util::formatNumber($value, 3, 0)); - } elseif (is_numeric($value)) { - echo htmlspecialchars(PMA_Util::formatNumber($value, 3, 1)); - } else { - echo htmlspecialchars($value); - } - if (isset($alerts[$name])) { - echo ''; - } - echo ''; - echo ''; - echo ''; - - if (isset($strShowStatus[$name ])) { - echo $strShowStatus[$name]; - } - - if (isset($links[$name])) { - foreach ($links[$name] as $link_name => $link_url) { - if ('doc' == $link_name) { - echo PMA_Util::showMySQLDocu($link_url, $link_url); - } else { - echo ' ' . $link_name . '' . - "\n"; - } - } - unset($link_url, $link_name); - } - echo '
    '; -} - /** * Prints html with monitor * diff --git a/server_status_advisor.php b/server_status_advisor.php index 6573dc991a..a697207077 100644 --- a/server_status_advisor.php +++ b/server_status_advisor.php @@ -8,12 +8,15 @@ require_once 'libraries/common.inc.php'; require_once 'libraries/Advisor.class.php'; +require_once 'libraries/ServerStatusData.class.php'; $response = PMA_Response::getInstance(); $scripts = $response->getHeader()->getScripts(); $scripts->addFile('server_status_advisor.js'); -$output = ''; +$output = '
    '; +$output .= PMA_ServerStatusData::getMenuHtml(); +$output .= ''; $output .= PMA_Util::getIcon('b_help.png', __('Instructions')); $output .= ''; $output .= '
    '; @@ -56,6 +59,7 @@ $output .= htmlspecialchars( ) ); $output .= '
    '; +$output .= '
    '; $response->addHTML($output); diff --git a/server_status_queries.php b/server_status_queries.php new file mode 100644 index 0000000000..5ab6f0864b --- /dev/null +++ b/server_status_queries.php @@ -0,0 +1,156 @@ +getHeader(); +$scripts = $header->getScripts(); +$scripts->addFile('server_status_queries.js'); +/* < IE 9 doesn't support canvas natively */ +if (PMA_USR_BROWSER_AGENT == 'IE' && PMA_USR_BROWSER_VER < 9) { + $scripts->addFile('jqplot/excanvas.js'); +} + +// for charting +$scripts->addFile('jqplot/jquery.jqplot.js'); +$scripts->addFile('jqplot/plugins/jqplot.pieRenderer.js'); +$scripts->addFile('jqplot/plugins/jqplot.canvasTextRenderer.js'); +$scripts->addFile('jqplot/plugins/jqplot.canvasAxisLabelRenderer.js'); +$scripts->addFile('jqplot/plugins/jqplot.dateAxisRenderer.js'); +$scripts->addFile('jqplot/plugins/jqplot.highlighter.js'); +$scripts->addFile('jqplot/plugins/jqplot.cursor.js'); + +// Add the html content to the response +$response->addHTML('
    '); +$response->addHTML(PMA_ServerStatusData::getMenuHtml()); +$response->addHTML(getQueryStatisticsHtml($ServerStatusData)); +$response->addHTML('
    '); +exit; + +/** + * Returns the html content for the query statistics + * + * @return string + */ +function getQueryStatisticsHtml($ServerStatusData) +{ + $retval = ''; + + $hour_factor = 3600 / $ServerStatusData->status['Uptime']; + $used_queries = $ServerStatusData->used_queries; + $total_queries = array_sum($used_queries); + + $retval .= '

    '; + /* l10n: Questions is the name of a MySQL Status variable */ + $retval .= sprintf( + __('Questions since startup: %s'), + PMA_Util::formatNumber($total_queries, 0) + ); + $retval .= ' '; + $retval .= PMA_Util::showMySQLDocu( + 'server-status-variables', + 'server-status-variables', + false, + 'statvar_Questions' + ); + $retval .= '
    '; + $retval .= ''; + $retval .= 'ø ' . __('per hour') . ': '; + $retval .= PMA_Util::formatNumber($total_queries * $hour_factor, 0); + $retval .= '
    '; + $retval .= 'ø ' . __('per minute') . ': '; + $retval .= PMA_Util::formatNumber($total_queries * 60 / $ServerStatusData->status['Uptime'], 0); + $retval .= '
    '; + if ($total_queries / $ServerStatusData->status['Uptime'] >= 1) { + $retval .= 'ø ' . __('per second') . ': '; + $retval .= PMA_Util::formatNumber($total_queries / $ServerStatusData->status['Uptime'], 0); + } + $retval .= '
    '; + $retval .= '

    '; + + // reverse sort by value to show most used statements first + arsort($used_queries); + + $odd_row = true; + $count_displayed_rows = 0; + $perc_factor = 100 / $total_queries; //(- $ServerStatusData->status['Connections']); + + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + + $chart_json = array(); + $query_sum = array_sum($used_queries); + $other_sum = 0; + foreach ($used_queries as $name => $value) { + $odd_row = !$odd_row; + // For the percentage column, use Questions - Connections, because + // the number of connections is not an item of the Query types + // but is included in Questions. Then the total of the percentages is 100. + $name = str_replace(array('Com_', '_'), array('', ' '), $name); + // Group together values that make out less than 2% into "Other", but only + // if we have more than 6 fractions already + if ($value < $query_sum * 0.02 && count($chart_json)>6) { + $other_sum += $value; + } else { + $chart_json[$name] = $value; + } + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + } + $retval .= ''; + $retval .= '
    ' . __('Statements') . ''; + /* l10n: # = Amount of queries */ + $retval .= __('#'); + $retval .= 'ø ' . __('per hour') . '%
    ' . htmlspecialchars($name) . ''; + $retval .= htmlspecialchars(PMA_Util::formatNumber($value, 5, 0, true)); + $retval .= ''; + $retval .= htmlspecialchars( + PMA_Util::formatNumber($value * $hour_factor, 4, 1, true) + ); + $retval .= ''; + $retval .= htmlspecialchars(PMA_Util::formatNumber($value * $perc_factor, 0, 2)); + $retval .= '
    '; + + $retval .= '
    '; + $retval .= ''; + + return $retval; +} + +?> diff --git a/server_status_variables.php b/server_status_variables.php new file mode 100644 index 0000000000..4314482313 --- /dev/null +++ b/server_status_variables.php @@ -0,0 +1,717 @@ +getHeader(); +$scripts = $header->getScripts(); +$scripts->addFile('server_status_variables.js'); + +$response->addHTML('
    '); +$response->addHTML(PMA_ServerStatusData::getMenuHtml()); +$response->addHTML(getFilterHtml($ServerStatusData)); +$response->addHTML(getLinkSuggestionsHtml($ServerStatusData)); +$response->addHTML(getVariablesTableHtml($ServerStatusData)); +$response->addHTML('
    '); + +exit; + +function getFilterHtml($ServerStatusData) +{ + + $filterAlert = ''; + if (! empty($_REQUEST['filterAlert'])) { + $filterAlert = ' checked="checked"'; + } + $filterText = ''; + if (! empty($_REQUEST['filterText'])) { + $filterText = htmlspecialchars($_REQUEST['filterText']); + } + $dontFormat = ''; + if (! empty($_REQUEST['dontFormat'])) { + $dontFormat = ' checked="checked"'; + } + + $retval = ''; + $retval .= '
    '; + $retval .= '' . __('Filters') . ''; + $retval .= '
    '; + $retval .= ''; + $retval .= '
    '; + $retval .= ''; + $retval .= ''; + $retval .= '
    '; + $retval .= '
    '; + $retval .= ''; + $retval .= ''; + $retval .= '
    '; + $retval .= '
    '; + $retval .= ''; + $retval .= '
    '; + $retval .= '
    '; + $retval .= ''; + $retval .= ''; + $retval .= '
    '; + $retval .= '
    '; + $retval .= '
    '; + + return $retval; +} + +function getLinkSuggestionsHtml($ServerStatusData) +{ + $retval = ''; + $retval .= ''; + + return $retval; +} + +/** + * Prints table with variables information + * + * @return void + */ +function getVariablesTableHtml($ServerStatusData) +{ + $retval = ''; + $strShowStatus = getStatusVariablesDescriptions(); + /** + * define some alerts + */ + // name => max value before alert + $alerts = array( + // lower is better + // variable => max value + 'Aborted_clients' => 0, + 'Aborted_connects' => 0, + + 'Binlog_cache_disk_use' => 0, + + 'Created_tmp_disk_tables' => 0, + + 'Handler_read_rnd' => 0, + 'Handler_read_rnd_next' => 0, + + 'Innodb_buffer_pool_pages_dirty' => 0, + 'Innodb_buffer_pool_reads' => 0, + 'Innodb_buffer_pool_wait_free' => 0, + 'Innodb_log_waits' => 0, + 'Innodb_row_lock_time_avg' => 10, // ms + 'Innodb_row_lock_time_max' => 50, // ms + 'Innodb_row_lock_waits' => 0, + + 'Slow_queries' => 0, + 'Delayed_errors' => 0, + 'Select_full_join' => 0, + 'Select_range_check' => 0, + 'Sort_merge_passes' => 0, + 'Opened_tables' => 0, + 'Table_locks_waited' => 0, + 'Qcache_lowmem_prunes' => 0, + + 'Qcache_free_blocks' => isset($ServerStatusData->server_status['Qcache_total_blocks']) + ? $ServerStatusData->server_status['Qcache_total_blocks'] / 5 : 0, + 'Slow_launch_threads' => 0, + + // depends on Key_read_requests + // normaly lower then 1:0.01 + 'Key_reads' => isset($ServerStatusData->status['Key_read_requests']) + ? (0.01 * $ServerStatusData->status['Key_read_requests']) : 0, + // depends on Key_write_requests + // normaly nearly 1:1 + 'Key_writes' => isset($ServerStatusData->status['Key_write_requests']) + ? (0.9 * $ServerStatusData->status['Key_write_requests']) : 0, + + 'Key_buffer_fraction' => 0.5, + + // alert if more than 95% of thread cache is in use + 'Threads_cached' => isset($ServerStatusData->variables['thread_cache_size']) + ? 0.95 * $ServerStatusData->variables['thread_cache_size'] : 0 + + // higher is better + // variable => min value + //'Handler read key' => '> ', + ); + + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + + $odd_row = false; + foreach ($ServerStatusData->status as $name => $value) { + $odd_row = !$odd_row; + $retval .= ''; + + $retval .= ''; + + $retval .= ''; + $retval .= ''; + $retval .= ''; + } + $retval .= ''; + $retval .= '
    ' . __('Variable') . '' . __('Value') . '' . __('Description') . '
    '; + $retval .= htmlspecialchars(str_replace('_', ' ', $name)); + /* Fields containing % are calculated, they can not be described in MySQL documentation */ + if (strpos($name, '%') === false) { + $retval .= PMA_Util::showMySQLDocu('server-status-variables', 'server-status-variables', false, 'statvar_' . $name); + } + $retval .= ''; + if (isset($alerts[$name])) { + if ($value > $alerts[$name]) { + $retval .= ''; + } else { + $retval .= ''; + } + } + if ('%' === substr($name, -1, 1)) { + $retval .= htmlspecialchars(PMA_Util::formatNumber($value, 0, 2)) . ' %'; + } elseif (strpos($name, 'Uptime') !== false) { + $retval .= htmlspecialchars( + PMA_Util::timespanFormat($value) + ); + } elseif (is_numeric($value) && $value == (int) $value && $value > 1000) { + $retval .= htmlspecialchars(PMA_Util::formatNumber($value, 3, 1)); + } elseif (is_numeric($value) && $value == (int) $value) { + $retval .= htmlspecialchars(PMA_Util::formatNumber($value, 3, 0)); + } elseif (is_numeric($value)) { + $retval .= htmlspecialchars(PMA_Util::formatNumber($value, 3, 1)); + } else { + $retval .= htmlspecialchars($value); + } + if (isset($alerts[$name])) { + $retval .= ''; + } + $retval .= ''; + $retval .= ''; + $retval .= ''; + + if (isset($strShowStatus[$name])) { + $retval .= $strShowStatus[$name]; + } + + if (isset($ServerStatusData->links[$name])) { + foreach ($ServerStatusData->links[$name] as $link_name => $link_url) { + if ('doc' == $link_name) { + $retval .= PMA_Util::showMySQLDocu($link_url, $link_url); + } else { + $retval .= ' ' . $link_name . ''; + } + } + unset($link_url, $link_name); + } + $retval .= '
    '; + + return $retval; +} + +function getStatusVariablesDescriptions() +{ + /** + * Messages are built using the message name + */ + return array( + 'Aborted_clients' => __( + 'The number of connections that were aborted because the client died' + . ' without closing the connection properly.' + ), + 'Aborted_connects' => __( + 'The number of failed attempts to connect to the MySQL server.' + ), + 'Binlog_cache_disk_use' => __( + 'The number of transactions that used the temporary binary log cache' + . ' but that exceeded the value of binlog_cache_size and used a' + . ' temporary file to store statements from the transaction.' + ), + 'Binlog_cache_use' => __( + 'The number of transactions that used the temporary binary log cache.' + ), + 'Connections' => __( + 'The number of connection attempts (successful or not)' + . ' to the MySQL server.' + ), + 'Created_tmp_disk_tables' => __( + 'The number of temporary tables on disk created automatically by' + . ' the server while executing statements. If' + . ' Created_tmp_disk_tables is big, you may want to increase the' + . ' tmp_table_size value to cause temporary tables to be' + . ' memory-based instead of disk-based.' + ), + 'Created_tmp_files' => __( + 'How many temporary files mysqld has created.' + ), + 'Created_tmp_tables' => __( + 'The number of in-memory temporary tables created automatically' + . ' by the server while executing statements.' + ), + 'Delayed_errors' => __( + 'The number of rows written with INSERT DELAYED for which some' + . ' error occurred (probably duplicate key).' + ), + 'Delayed_insert_threads' => __( + 'The number of INSERT DELAYED handler threads in use. Every' + . ' different table on which one uses INSERT DELAYED gets' + . ' its own thread.' + ), + 'Delayed_writes' => __( + 'The number of INSERT DELAYED rows written.' + ), + 'Flush_commands' => __( + 'The number of executed FLUSH statements.' + ), + 'Handler_commit' => __( + 'The number of internal COMMIT statements.' + ), + 'Handler_delete' => __( + 'The number of times a row was deleted from a table.' + ), + 'Handler_discover' => __( + 'The MySQL server can ask the NDB Cluster storage engine if it' + . ' knows about a table with a given name. This is called discovery.' + . ' Handler_discover indicates the number of time tables have been' + . ' discovered.' + ), + 'Handler_read_first' => __( + 'The number of times the first entry was read from an index. If this' + . ' is high, it suggests that the server is doing a lot of full' + . ' index scans; for example, SELECT col1 FROM foo, assuming that' + . ' col1 is indexed.' + ), + 'Handler_read_key' => __( + 'The number of requests to read a row based on a key. If this is' + . ' high, it is a good indication that your queries and tables' + . ' are properly indexed.' + ), + 'Handler_read_next' => __( + 'The number of requests to read the next row in key order. This is' + . ' incremented if you are querying an index column with a range' + . ' constraint or if you are doing an index scan.' + ), + 'Handler_read_prev' => __( + 'The number of requests to read the previous row in key order.' + . ' This read method is mainly used to optimize ORDER BY ... DESC.' + ), + 'Handler_read_rnd' => __( + 'The number of requests to read a row based on a fixed position.' + . ' This is high if you are doing a lot of queries that require' + . ' sorting of the result. You probably have a lot of queries that' + . ' require MySQL to scan whole tables or you have joins that' + . ' don\'t use keys properly.' + ), + 'Handler_read_rnd_next' => __( + 'The number of requests to read the next row in the data file.' + . ' This is high if you are doing a lot of table scans. Generally' + . ' this suggests that your tables are not properly indexed or that' + . ' your queries are not written to take advantage of the indexes' + . ' you have.' + ), + 'Handler_rollback' => __( + 'The number of internal ROLLBACK statements.' + ), + 'Handler_update' => __( + 'The number of requests to update a row in a table.' + ), + 'Handler_write' => __( + 'The number of requests to insert a row in a table.' + ), + 'Innodb_buffer_pool_pages_data' => __( + 'The number of pages containing data (dirty or clean).' + ), + 'Innodb_buffer_pool_pages_dirty' => __( + 'The number of pages currently dirty.' + ), + 'Innodb_buffer_pool_pages_flushed' => __( + 'The number of buffer pool pages that have been requested' + . ' to be flushed.' + ), + 'Innodb_buffer_pool_pages_free' => __( + 'The number of free pages.' + ), + 'Innodb_buffer_pool_pages_latched' => __( + 'The number of latched pages in InnoDB buffer pool. These are pages' + . ' currently being read or written or that can\'t be flushed or' + . ' removed for some other reason.' + ), + 'Innodb_buffer_pool_pages_misc' => __( + 'The number of pages busy because they have been allocated for' + . ' administrative overhead such as row locks or the adaptive' + . ' hash index. This value can also be calculated as' + . ' Innodb_buffer_pool_pages_total - Innodb_buffer_pool_pages_free' + . ' - Innodb_buffer_pool_pages_data.' + ), + 'Innodb_buffer_pool_pages_total' => __( + 'Total size of buffer pool, in pages.' + ), + 'Innodb_buffer_pool_read_ahead_rnd' => __( + 'The number of "random" read-aheads InnoDB initiated. This happens' + . ' when a query is to scan a large portion of a table but in' + . ' random order.' + ), + 'Innodb_buffer_pool_read_ahead_seq' => __( + 'The number of sequential read-aheads InnoDB initiated. This' + . ' happens when InnoDB does a sequential full table scan.' + ), + 'Innodb_buffer_pool_read_requests' => __( + 'The number of logical read requests InnoDB has done.' + ), + 'Innodb_buffer_pool_reads' => __( + 'The number of logical reads that InnoDB could not satisfy' + . ' from buffer pool and had to do a single-page read.' + ), + 'Innodb_buffer_pool_wait_free' => __( + 'Normally, writes to the InnoDB buffer pool happen in the' + . ' background. However, if it\'s necessary to read or create a page' + . ' and no clean pages are available, it\'s necessary to wait for' + . ' pages to be flushed first. This counter counts instances of' + . ' these waits. If the buffer pool size was set properly, this' + . ' value should be small.' + ), + 'Innodb_buffer_pool_write_requests' => __( + 'The number writes done to the InnoDB buffer pool.' + ), + 'Innodb_data_fsyncs' => __( + 'The number of fsync() operations so far.' + ), + 'Innodb_data_pending_fsyncs' => __( + 'The current number of pending fsync() operations.' + ), + 'Innodb_data_pending_reads' => __( + 'The current number of pending reads.' + ), + 'Innodb_data_pending_writes' => __( + 'The current number of pending writes.' + ), + 'Innodb_data_read' => __( + 'The amount of data read so far, in bytes.' + ), + 'Innodb_data_reads' => __( + 'The total number of data reads.' + ), + 'Innodb_data_writes' => __( + 'The total number of data writes.' + ), + 'Innodb_data_written' => __( + 'The amount of data written so far, in bytes.' + ), + 'Innodb_dblwr_pages_written' => __( + 'The number of pages that have been written for' + . ' doublewrite operations.' + ), + 'Innodb_dblwr_writes' => __( + 'The number of doublewrite operations that have been performed.' + ), + 'Innodb_log_waits' => __( + 'The number of waits we had because log buffer was too small and' + . ' we had to wait for it to be flushed before continuing.' + ), + 'Innodb_log_write_requests' => __( + 'The number of log write requests.' + ), + 'Innodb_log_writes' => __( + 'The number of physical writes to the log file.' + ), + 'Innodb_os_log_fsyncs' => __( + 'The number of fsync() writes done to the log file.' + ), + 'Innodb_os_log_pending_fsyncs' => __( + 'The number of pending log file fsyncs.' + ), + 'Innodb_os_log_pending_writes' => __( + 'Pending log file writes.' + ), + 'Innodb_os_log_written' => __( + 'The number of bytes written to the log file.' + ), + 'Innodb_pages_created' => __( + 'The number of pages created.' + ), + 'Innodb_page_size' => __( + 'The compiled-in InnoDB page size (default 16KB). Many values are' + . ' counted in pages; the page size allows them to be easily' + . ' converted to bytes.' + ), + 'Innodb_pages_read' => __( + 'The number of pages read.' + ), + 'Innodb_pages_written' => __( + 'The number of pages written.' + ), + 'Innodb_row_lock_current_waits' => __( + 'The number of row locks currently being waited for.' + ), + 'Innodb_row_lock_time_avg' => __( + 'The average time to acquire a row lock, in milliseconds.' + ), + 'Innodb_row_lock_time' => __( + 'The total time spent in acquiring row locks, in milliseconds.' + ), + 'Innodb_row_lock_time_max' => __( + 'The maximum time to acquire a row lock, in milliseconds.' + ), + 'Innodb_row_lock_waits' => __( + 'The number of times a row lock had to be waited for.' + ), + 'Innodb_rows_deleted' => __( + 'The number of rows deleted from InnoDB tables.' + ), + 'Innodb_rows_inserted' => __( + 'The number of rows inserted in InnoDB tables.' + ), + 'Innodb_rows_read' => __( + 'The number of rows read from InnoDB tables.' + ), + 'Innodb_rows_updated' => __( + 'The number of rows updated in InnoDB tables.' + ), + 'Key_blocks_not_flushed' => __( + 'The number of key blocks in the key cache that have changed but' + . ' haven\'t yet been flushed to disk. It used to be known as' + . ' Not_flushed_key_blocks.' + ), + 'Key_blocks_unused' => __( + 'The number of unused blocks in the key cache. You can use this' + . ' value to determine how much of the key cache is in use.' + ), + 'Key_blocks_used' => __( + 'The number of used blocks in the key cache. This value is a' + . ' high-water mark that indicates the maximum number of blocks' + . ' that have ever been in use at one time.' + ), + 'Key_buffer_fraction_%' => __( + 'Percentage of used key cache (calculated value)' + ), + 'Key_read_requests' => __( + 'The number of requests to read a key block from the cache.' + ), + 'Key_reads' => __( + 'The number of physical reads of a key block from disk. If Key_reads' + . ' is big, then your key_buffer_size value is probably too small.' + . ' The cache miss rate can be calculated as' + . ' Key_reads/Key_read_requests.' + ), + 'Key_read_ratio_%' => __( + 'Key cache miss calculated as rate of physical reads compared' + . ' to read requests (calculated value)' + ), + 'Key_write_requests' => __( + 'The number of requests to write a key block to the cache.' + ), + 'Key_writes' => __( + 'The number of physical writes of a key block to disk.' + ), + 'Key_write_ratio_%' => __( + 'Percentage of physical writes compared' + . ' to write requests (calculated value)' + ), + 'Last_query_cost' => __( + 'The total cost of the last compiled query as computed by the query' + . ' optimizer. Useful for comparing the cost of different query' + . ' plans for the same query. The default value of 0 means that' + . ' no query has been compiled yet.' + ), + 'Max_used_connections' => __( + 'The maximum number of connections that have been in use' + . ' simultaneously since the server started.' + ), + 'Not_flushed_delayed_rows' => __( + 'The number of rows waiting to be written in INSERT DELAYED queues.' + ), + 'Opened_tables' => __( + 'The number of tables that have been opened. If opened tables is' + . ' big, your table cache value is probably too small.' + ), + 'Open_files' => __( + 'The number of files that are open.' + ), + 'Open_streams' => __( + 'The number of streams that are open (used mainly for logging).' + ), + 'Open_tables' => __( + 'The number of tables that are open.' + ), + 'Qcache_free_blocks' => __( + 'The number of free memory blocks in query cache. High numbers can' + . ' indicate fragmentation issues, which may be solved by issuing' + . ' a FLUSH QUERY CACHE statement.' + ), + 'Qcache_free_memory' => __( + 'The amount of free memory for query cache.' + ), + 'Qcache_hits' => __( + 'The number of cache hits.' + ), + 'Qcache_inserts' => __( + 'The number of queries added to the cache.' + ), + 'Qcache_lowmem_prunes' => __( + 'The number of queries that have been removed from the cache to' + . ' free up memory for caching new queries. This information can' + . ' help you tune the query cache size. The query cache uses a' + . ' least recently used (LRU) strategy to decide which queries' + . ' to remove from the cache.' + ), + 'Qcache_not_cached' => __( + 'The number of non-cached queries (not cachable, or not cached' + . ' due to the query_cache_type setting).' + ), + 'Qcache_queries_in_cache' => __( + 'The number of queries registered in the cache.' + ), + 'Qcache_total_blocks' => __( + 'The total number of blocks in the query cache.' + ), + 'Rpl_status' => __( + 'The status of failsafe replication (not yet implemented).' + ), + 'Select_full_join' => __( + 'The number of joins that do not use indexes. If this value is' + . ' not 0, you should carefully check the indexes of your tables.' + ), + 'Select_full_range_join' => __( + 'The number of joins that used a range search on a reference table.' + ), + 'Select_range_check' => __( + 'The number of joins without keys that check for key usage after' + . ' each row. (If this is not 0, you should carefully check the' + . ' indexes of your tables.)' + ), + 'Select_range' => __( + 'The number of joins that used ranges on the first table. (It\'s' + . ' normally not critical even if this is big.)' + ), + 'Select_scan' => __( + 'The number of joins that did a full scan of the first table.' + ), + 'Slave_open_temp_tables' => __( + 'The number of temporary tables currently' + . ' open by the slave SQL thread.' + ), + 'Slave_retried_transactions' => __( + 'Total (since startup) number of times the replication slave SQL' + . ' thread has retried transactions.' + ), + 'Slave_running' => __( + 'This is ON if this server is a slave that is connected to a master.' + ), + 'Slow_launch_threads' => __( + 'The number of threads that have taken more than slow_launch_time' + . ' seconds to create.' + ), + 'Slow_queries' => __( + 'The number of queries that have taken more than long_query_time' + . ' seconds.' + ), + 'Sort_merge_passes' => __( + 'The number of merge passes the sort algorithm has had to do.' + . ' If this value is large, you should consider increasing the' + . ' value of the sort_buffer_size system variable.' + ), + 'Sort_range' => __( + 'The number of sorts that were done with ranges.' + ), + 'Sort_rows' => __( + 'The number of sorted rows.' + ), + 'Sort_scan' => __( + 'The number of sorts that were done by scanning the table.' + ), + 'Table_locks_immediate' => __( + 'The number of times that a table lock was acquired immediately.' + ), + 'Table_locks_waited' => __( + 'The number of times that a table lock could not be acquired' + . ' immediately and a wait was needed. If this is high, and you have' + . ' performance problems, you should first optimize your queries,' + . ' and then either split your table or tables or use replication.' + ), + 'Threads_cached' => __( + 'The number of threads in the thread cache. The cache hit rate can' + . ' be calculated as Threads_created/Connections. If this value is' + . ' red you should raise your thread_cache_size.' + ), + 'Threads_connected' => __( + 'The number of currently open connections.' + ), + 'Threads_created' => __( + 'The number of threads created to handle connections. If' + . ' Threads_created is big, you may want to increase the' + . ' thread_cache_size value. (Normally this doesn\'t give a notable' + . ' performance improvement if you have a good thread' + . ' implementation.)' + ), + 'Threads_cache_hitrate_%' => __( + 'Thread cache hit rate (calculated value)' + ), + 'Threads_running' => __( + 'The number of threads that are not sleeping.') + ); +} + +?> From 82a4de0080ca377a4a2e176b6c3feb932218cca5 Mon Sep 17 00:00:00 2001 From: Rouslan Placella Date: Tue, 4 Dec 2012 16:38:52 +0000 Subject: [PATCH 03/21] Whitespace cleanup --- js/server_status_monitor.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/js/server_status_monitor.js b/js/server_status_monitor.js index 044a96835e..d4799df235 100644 --- a/js/server_status_monitor.js +++ b/js/server_status_monitor.js @@ -2034,22 +2034,22 @@ AJAX.registerOnload('server_status_monitor.js', function() { numberTable += '' + data.profiling[i].state + ' ' + PMA_prettyProfilingNum(duration, 2) + ''; } - + // Only put those values in the pie which are > 2% for (var i = 0, l = data.profiling.length; i < l; i++) { duration = parseFloat(data.profiling[i].duration); - + if (duration / totalTime > 0.02) { chartData.push([PMA_prettyProfilingNum(duration, 2) + ' ' + data.profiling[i].state, duration]); } else { otherTime += duration; } } - + if (otherTime > 0) { chartData.push([PMA_prettyProfilingNum(otherTime, 2) + ' ' + PMA_messages['strOther'], otherTime]); } - + numberTable += '' + PMA_messages['strTotalTime'] + '' + PMA_prettyProfilingNum(totalTime, 2) + ''; numberTable += ''; From b621d2b56ccd19cdb2515fc60a99ac8a31da4abb Mon Sep 17 00:00:00 2001 From: Rouslan Placella Date: Wed, 5 Dec 2012 21:20:54 +0000 Subject: [PATCH 04/21] Split the server staus monitor features into a separate page --- js/messages.php | 11 - js/server_status.js | 429 ------- js/server_status_monitor.js | 189 +++- libraries/Menu.class.php | 10 + libraries/ServerStatusData.class.php | 53 +- libraries/common.inc.php | 4 + server_status.php | 1572 +++++--------------------- server_status_advisor.php | 11 +- server_status_monitor.php | 733 ++++++++++++ server_status_queries.php | 4 +- server_status_variables.php | 18 +- themes/original/css/common.css.php | 4 - themes/pmahomme/css/common.css.php | 4 - 13 files changed, 1205 insertions(+), 1837 deletions(-) create mode 100644 server_status_monitor.php diff --git a/js/messages.php b/js/messages.php index 8c4f2fbb70..b713d6bf20 100644 --- a/js/messages.php +++ b/js/messages.php @@ -73,18 +73,7 @@ $js_messages['strThousandsSeparator'] = __(','); /* l10n: Decimal separator */ $js_messages['strDecimalSeparator'] = __('.'); -$js_messages['strChartKBSent'] = __('KiB sent since last refresh'); -$js_messages['strChartKBReceived'] = __('KiB received since last refresh'); -$js_messages['strChartServerTraffic'] = __('Server traffic (in KiB)'); -$js_messages['strChartConnections'] = __('Connections since last refresh'); -$js_messages['strChartProcesses'] = __('Processes'); $js_messages['strChartConnectionsTitle'] = __('Connections / Processes'); -/* l10n: Questions is the name of a MySQL Status variable */ -$js_messages['strChartIssuedQueries'] = __('Questions since last refresh'); -/* l10n: Questions is the name of a MySQL Status variable */ -$js_messages['strChartIssuedQueriesTitle'] = __('Questions (executed statements by the server)'); - -$js_messages['strChartQueryPie'] = __('Query statistics'); /* server status monitor */ $js_messages['strIncompatibleMonitorConfig'] = __('Local monitor configuration incompatible'); diff --git a/js/server_status.js b/js/server_status.js index 838c288c73..e9fb3263c7 100644 --- a/js/server_status.js +++ b/js/server_status.js @@ -2,15 +2,6 @@ /** * @fileoverview functions used in server status pages * @name Server Status - * - * @requires jQuery - * @requires jQueryUI - * @requires jQueryCookie - * @requires jQueryTablesorter - * @requires jqPlot - * @requires canvg - * @requires js/functions.js - * */ var pma_token, @@ -20,16 +11,6 @@ var pma_token, is_superuser, server_db_isLocal; -/** - * Unbind all event handlers before tearing down a page - */ -AJAX.registerTeardown('server_status.js', function() { - $('a.popupLink').unbind('click'); - $(document).unbind('click'); // Am I sure about this? I guess not... - $('div.buttonlinks select').unbind('click'); - $('div.buttonlinks a.tabRefresh').unbind('click'); -}); - // Add a tablesorter parser to properly handle thousands seperated numbers and SI prefixes AJAX.registerOnload('server_status.js', function() { @@ -41,414 +22,4 @@ AJAX.registerOnload('server_status.js', function() { is_superuser = $js_data_form.find("input[name=is_superuser]").val(); server_db_isLocal = $js_data_form.find("input[name=server_db_isLocal]").val(); - // Show all javascript related parts of the page - $('#serverstatus .jsfeature').show(); - - jQuery.tablesorter.addParser({ - id: "fancyNumber", - is: function(s) { - return /^[0-9]?[0-9,\.]*\s?(k|M|G|T|%)?$/.test(s); - }, - format: function(s) { - var num = jQuery.tablesorter.formatFloat( - s.replace(PMA_messages['strThousandsSeparator'], '') - .replace(PMA_messages['strDecimalSeparator'], '.') - ); - - var factor = 1; - switch (s.charAt(s.length - 1)) { - case '%': factor = -2; break; - // Todo: Complete this list (as well as in the regexp a few lines up) - case 'k': factor = 3; break; - case 'M': factor = 6; break; - case 'G': factor = 9; break; - case 'T': factor = 12; break; - } - - return num * Math.pow(10, factor); - }, - type: "numeric" - }); - - jQuery.tablesorter.addParser({ - id: "withinSpanNumber", - is: function(s) { - return /(.*)?<\/span>/); - return (res && res.length >= 3) ? res[2] : 0; - }, - type: "numeric" - }); - - // faster zebra widget: no row visibility check, faster css class switching, no cssChildRow check - jQuery.tablesorter.addWidget({ - id: "fast-zebra", - format: function (table) { - if (table.config.debug) { - var time = new Date(); - } - $("tr:even", table.tBodies[0]) - .removeClass(table.config.widgetZebra.css[0]) - .addClass(table.config.widgetZebra.css[1]); - $("tr:odd", table.tBodies[0]) - .removeClass(table.config.widgetZebra.css[1]) - .addClass(table.config.widgetZebra.css[0]); - if (table.config.debug) { - $.tablesorter.benchmark("Applying Fast-Zebra widget", time); - } - } - }); - - // Popup behaviour - $('a.popupLink').click( function() { - var $link = $(this); - - $('div.' + $link.attr('href').substr(1)) - .show() - .offset({ top: $link.offset().top + $link.height() + 5, left: $link.offset().left }) - .addClass('openedPopup'); - - return false; - }); - - $(document).click( function(event) { - $('div.openedPopup').each(function() { - var $cnt = $(this); - var pos = $cnt.offset(); - - // Hide if the mouseclick is outside the popupcontent - if (event.pageX < pos.left - || event.pageY < pos.top - || event.pageX > pos.left + $cnt.outerWidth() - || event.pageY > pos.top + $cnt.outerHeight() - ) { - $cnt.hide().removeClass('openedPopup'); - } - }); - }); }); - -AJAX.registerOnload('server_status.js', function() { - // Filters for status variables - var textFilter = null; - var alertFilter = false; - var categoryFilter = ''; - var odd_row = false; - var text = ''; // Holds filter text - var queryPieChart = null; - var monitorLoaded = false; - - /* Chart configuration */ - // Defines what the tabs are currently displaying (realtime or data) - var tabStatus = new Object(); - // Holds the current chart instances for each tab - var tabChart = new Object(); - // Holds current live charts' timeouts - var chart_replot_timers = new Object(); - - /*** Table sort tooltip ***/ - PMA_createqTip($('table.sortable thead th'), PMA_messages['strSortHint']); - - $.ajaxSetup({ - cache: false - }); - - // Add tabs - $('#serverStatusTabs').tabs({ - // Tab persistence - cookie: { name: 'pma_serverStatusTabs', expires: 1 }, - show: function(event, ui) { - // Fixes line break in the menu bar when the page overflows and scrollbar appears - $('#topmenu').menuResizer('resize'); - - // Initialize selected tab - if (!$(ui.tab.hash).data('init-done')) { - initTab($(ui.tab.hash), null); - } - // Load Server status monitor - if (ui.tab.hash == '#statustabs_charting' && ! monitorLoaded) { - $('div#statustabs_charting').append( //PMA_messages['strLoadingMonitor'] + ' ' + - '' - ); - // Delay loading a bit so the tab loads and the user gets to see a ajax loading icon - setTimeout(function() { - var scripts = [ - {name:'jquery/timepicker.js',fire:0}, - {name:'jquery/jquery.json-2.2.js',fire:0}, - {name:'jquery/jquery.sortableTable.js',fire:0}, - {name:'server_status_monitor.js',fire:1} - ]; - AJAX.scriptHandler.load(scripts); - }, 50); - - monitorLoaded = true; - } - } - }); - - // Fixes wrong tab height with floated elements. See also http://bugs.jqueryui.com/ticket/5601 - $(".ui-widget-content:not(.ui-tabs):not(.ui-helper-clearfix)").addClass("ui-helper-clearfix"); - - // Initialize each tab - $('div.ui-tabs-panel').each(function() { - var $tab = $(this); - tabStatus[$tab.attr('id')] = 'static'; - // Initialize tabs after browser catches up with previous changes and displays tabs - setTimeout(function() { - initTab($tab, null); - }, 0.5); - }); - - /** Realtime charting of variables **/ - - function recursiveTimer($tab, type) { - replotLiveChart($tab, type); - chart_replot_timers[$tab.attr('id')] = setTimeout(function() { - recursiveTimer($tab, type) }, ($('.refreshRate :selected', $tab).val() * 1000)); - } - - function getCurrentDataSet($tab, type) { - var ret = null; - var line1 = null; - var line2 = null; - var retval = null; - - $.ajax({ - async: false, - url: 'server_status.php', - type: 'post', - data: { - 'token' : PMA_commonParams.get('token'), - 'server' : PMA_commonParams.get('server'), - 'ajax_request' : true, - 'chart_data' : true, - 'type' : type - }, - dataType: 'json', - success: function(data) { - ret = $.parseJSON(data.message); - } - }); - // get data based on chart type - if(type == 'proc') { - line1 = [ret.x, ret.y_conn - previous_y_line1[$tab.attr('id')]]; - line2 = [ret.x, ret.y_proc]; - previous_y_line1[$tab.attr('id')] = ret.y_conn; - } - else if(type == 'queries') { - line1 = [ret.x, ret.y-previous_y_line1[$tab.attr('id')]]; - previous_y_line1[$tab.attr('id')] = ret.y; - } - else if(type == 'traffic') { - ret.y_sent = ret.y_sent/1024; - ret.y_received = ret.y_received/1024; - line1 = [ret.x, ret.y_sent - previous_y_line1[$tab.attr('id')]]; - line2 = [ret.x, ret.y_received - previous_y_line2[$tab.attr('id')]]; - previous_y_line1[$tab.attr('id')] = ret.y_sent; - previous_y_line2[$tab.attr('id')] = ret.y_received; - } - - retval = [line1, line2]; - return retval; - } - - function getSettings(type) { - - var settings = { - grid: { - drawBorder: false, - shadow: false, - background: 'rgba(0,0,0,0)' - }, - axes: { - xaxis: { - renderer: $.jqplot.DateAxisRenderer, - tickOptions: { - formatString: '%H:%M:%S', - showGridline: false - } - }, - yaxis: { - autoscale:true, - label: PMA_messages['strTotalCount'], - labelRenderer: $.jqplot.CanvasAxisLabelRenderer - } - }, - seriesDefaults: { - rendererOptions: { - smooth: true - } - }, - legend: { - show: true, - location: 's', // compass direction, nw, n, ne, e, se, s, sw, w. - xoffset: 12, // pixel offset of the legend box from the x (or x2) axis. - yoffset: 12 // pixel offset of the legend box from the y (or y2) axis. - } - }; - - var title_message; - var x_legend = new Array(); - if(type == 'proc') { - title_message = PMA_messages['strChartConnectionsTitle']; - x_legend[0] = PMA_messages['strChartConnections']; - x_legend[1] = PMA_messages['strChartProcesses']; - settings.series = [ {label: x_legend[0]}, {label: x_legend[1]} ]; - } - else if(type == 'queries') { - title_message = PMA_messages['strChartIssuedQueriesTitle']; - x_legend[0] = PMA_messages['strChartIssuedQueries']; - settings.series = [ {label: x_legend[0]} ]; - } - else if(type == 'traffic') { - title_message = PMA_messages['strChartServerTraffic']; - x_legend[0] = PMA_messages['strChartKBSent']; - x_legend[1] = PMA_messages['strChartKBReceived']; - settings.series = [ {label: x_legend[0]}, {label: x_legend[1]} ]; - } - settings.title = title_message; - - return settings; - } - - function replotLiveChart($tab, type) { - var data_set = getCurrentDataSet($tab, type); - if(type == 'proc' || type == 'traffic') { - series[$tab.attr('id')][0].push(data_set[0]); - series[$tab.attr('id')][1].push(data_set[1]); - // update data set - tabChart[$tab.attr('id')].series[0].data = series[$tab.attr('id')][0]; - tabChart[$tab.attr('id')].series[1].data = series[$tab.attr('id')][1]; - } - else if(type == 'queries') { - // there is just one line to be plotted - series[$tab.attr('id')][0].push(data_set[0]); - // update data set - tabChart[$tab.attr('id')].series[0].data = series[$tab.attr('id')][0]; - } - tabChart[$tab.attr('id')].resetAxesScale(); - var current_time = new Date().getTime(); - var data_points = $('.dataPointsNumber :selected', $tab).val(); - var refresh_rate = $('.refreshRate :selected', $tab).val() * 1000; - // Min X would be decided based on refresh rate and number of data points - var minX = current_time - (refresh_rate * data_points); - var interval = (((current_time - minX)/data_points) / 1000); - interval = (data_points > 20) ? (((current_time - minX)/20) / 1000) : interval; - // update chart options - tabChart[$tab.attr('id')]['axes']['xaxis']['max'] = current_time; - tabChart[$tab.attr('id')]['axes']['xaxis']['min'] = minX; - tabChart[$tab.attr('id')]['axes']['xaxis']['tickInterval'] = interval + " seconds"; - // replot - tabChart[$tab.attr('id')].replot(); - } - - /* Adjust DOM / Add handlers to the tabs */ - function initTab(tab, data) { - if ($(tab).data('init-done') && !data) { - return; - } - $(tab).data('init-done', true); - switch(tab.attr('id')) { - case 'statustabs_traffic': - if (data != null) { - tab.find('.tabInnerContent').html(data.message); - } - PMA_showHints(); - break; - } - } - - // TODO: tablesorter shouldn't sort already sorted columns - function initTableSorter(tabid) { - var $table, opts; - switch(tabid) { - case 'statustabs_queries': - $table = $('#serverstatusqueriesdetails'); - opts = { - sortList: [[3, 1]], - widgets: ['fast-zebra'], - headers: { - 1: { sorter: 'fancyNumber' }, - 2: { sorter: 'fancyNumber' } - } - }; - break; - case 'statustabs_allvars': - $table = $('#serverstatusvariables'); - opts = { - sortList: [[0, 0]], - widgets: ['fast-zebra'], - headers: { - 1: { sorter: 'withinSpanNumber' } - } - }; - break; - } - $table.tablesorter(opts); - $table.find('tr:first th') - .append(''); - } - - // Provides a nicely formatted and sorted tooltip of each datapoint of the query statistics - function sortedQueriesPointInfo(queries, lastQueries){ - var max, maxIdx, num = 0; - var queryKeys = new Array(); - var queryValues = new Array(); - var sumOther = 0; - var sumTotal = 0; - - // Separate keys and values, then sort them - $.each(queries.pointInfo, function(key, value) { - if (value-lastQueries.pointInfo[key] > 0) { - queryKeys.push(key); - queryValues.push(value-lastQueries.pointInfo[key]); - sumTotal += value-lastQueries.pointInfo[key]; - } - }); - var numQueries = queryKeys.length; - var pointInfo = '' + PMA_messages['strTotal'] + ': ' + sumTotal + '
    '; - - while(queryKeys.length > 0) { - max = 0; - for (var i = 0; i < queryKeys.length; i++) { - if (queryValues[i] > max) { - max = queryValues[i]; - maxIdx = i; - } - } - if (numQueries > 8 && num >= 6) { - sumOther += queryValues[maxIdx]; - } else { - pointInfo += queryKeys[maxIdx].substr(4).replace('_', ' ') + ': ' + queryValues[maxIdx] + '
    '; - } - - queryKeys.splice(maxIdx, 1); - queryValues.splice(maxIdx, 1); - num++; - } - - if (sumOther>0) { - pointInfo += PMA_messages['strOther'] + ': ' + sumOther; - } - - return pointInfo; - } -}); - - -// Needs to be global as server_status_monitor.js uses it too -function serverResponseError() { - var btns = {}; - btns[PMA_messages['strReloadPage']] = function() { - window.location.reload(); - }; - $('#emptyDialog').dialog({title: PMA_messages['strRefreshFailed']}); - $('#emptyDialog').html( - PMA_getImage('s_attention.png') + - PMA_messages['strInvalidResponseExplanation'] - ); - $('#emptyDialog').dialog({ buttons: btns }); -} diff --git a/js/server_status_monitor.js b/js/server_status_monitor.js index d4799df235..30f5ada5cb 100644 --- a/js/server_status_monitor.js +++ b/js/server_status_monitor.js @@ -1,12 +1,57 @@ /* vim: set expandtab sw=4 ts=4 sts=4: */ -var runtime = {}; +var runtime = {}, + server_time_diff, + server_os, + is_superuser, + server_db_isLocal; +AJAX.registerOnload('server_status_monitor.js', function() { + var $js_data_form = $('#js_data'); + server_time_diff = new Date().getTime() - $js_data_form.find("input[name=server_time]").val(); + server_os = $js_data_form.find("input[name=server_os]").val(); + is_superuser = $js_data_form.find("input[name=is_superuser]").val(); + server_db_isLocal = $js_data_form.find("input[name=server_db_isLocal]").val(); +}); + /** * Unbind all event handlers before tearing down a page */ +AJAX.registerTeardown('server_status_monitor.js', function() { + $('a.popupLink').unbind('click'); + $('body').unbind('click'); +}); +/** + * Popup behaviour + */ +AJAX.registerOnload('server_status_monitor.js', function() { + $('a.popupLink').click( function() { + var $link = $(this); + $('div.' + $link.attr('href').substr(1)) + .show() + .offset({ top: $link.offset().top + $link.height() + 5, left: $link.offset().left }) + .addClass('openedPopup'); + + return false; + }); + $('body').click( function(event) { + $('div.openedPopup').each(function() { + var $cnt = $(this); + var pos = $cnt.offset(); + // Hide if the mouseclick is outside the popupcontent + if (event.pageX < pos.left + || event.pageY < pos.top + || event.pageX > pos.left + $cnt.outerWidth() + || event.pageY > pos.top + $cnt.outerHeight() + ) { + $cnt.hide().removeClass('openedPopup'); + } + }); + }); +}); + AJAX.registerTeardown('server_status_monitor.js', function() { $('a[href="#rearrangeCharts"], a[href="#endChartEditMode"]').unbind('click'); - $('div#statustabs_charting div.popupContent select[name="chartColumns"]').unbind('change'); - $('div#statustabs_charting div.popupContent select[name="gridChartRefresh"]').unbind('change'); + $('div.popupContent select[name="chartColumns"]').unbind('change'); + $(' div.popupContent select[name="gridChartRefresh"]').unbind('change'); $('a[href="#addNewChart"]').unbind('click'); $('a[href="#exportMonitorConfig"]').unbind('click'); $('a[href="#importMonitorConfig"]').unbind('click'); @@ -22,15 +67,13 @@ AJAX.registerTeardown('server_status_monitor.js', function() { $('a[href="#submitClearSeries"]').unbind('click'); $('a[href="#submitAddSeries"]').unbind('click'); // $("input#variableInput").destroy(); - clearTimeout(runtime.refreshTimeout); - runtime.refreshTimeout = null; - $.cookie('pma_serverStatusTabs', null); + destroyGrid(); }); AJAX.registerOnload('server_status_monitor.js', function() { // Show tab links - $('div#statustabs_charting div.tabLinks').show(); - $('div#statustabs_charting img#loadingMonitorIcon').remove(); + $('div.tabLinks').show(); + $('img#loadingMonitorIcon').remove(); // Codemirror is loaded on demand so we might need to initialize it if (! codemirror_editor) { var $elm = $('#sqlquery'); @@ -46,7 +89,8 @@ AJAX.registerOnload('server_status_monitor.js', function() { ); } } - // Timepicker is loaded on demand so we need to initialize datetime fields from the 'load log' dialog + // Timepicker is loaded on demand so we need to initialize + // datetime fields from the 'load log' dialog $('div#logAnalyseDialog .datetimefield').each(function() { PMA_addDatepicker($(this)); }); @@ -58,9 +102,10 @@ AJAX.registerOnload('server_status_monitor.js', function() { var newChart = null; var chartSpacing; - // Whenever the monitor object (runtime.charts) or the settings object (monitorSettings) - // changes in a way incompatible to the previous version, increase this number - // It will reset the users monitor and settings object in his localStorage to the default configuration + // Whenever the monitor object (runtime.charts) or the settings object + // (monitorSettings) changes in a way incompatible to the previous version, + // increase this number. It will reset the users monitor and settings object + // in his localStorage to the default configuration var monitorProtocolVersion = '1.0'; // Runtime parameter of the monitor, is being fully set in initGrid() @@ -75,7 +120,8 @@ AJAX.registerOnload('server_status_monitor.js', function() { chartAI: 0, // To play/pause the monitor redrawCharts: false, - // Object that contains a list of nodes that need to be retrieved from the server for chart updates + // Object that contains a list of nodes that need to be retrieved + // from the server for chart updates dataList: [], // Current max points per chart (needed for auto calculation) gridMaxPoints: 20, @@ -88,7 +134,8 @@ AJAX.registerOnload('server_status_monitor.js', function() { var defaultMonitorSettings = { columns: 3, chartSize: { width: 295, height: 250 }, - // Max points in each chart. Settings it to 'auto' sets gridMaxPoints to (chartwidth - 40) / 12 + // Max points in each chart. Settings it to 'auto' sets + // gridMaxPoints to (chartwidth - 40) / 12 gridMaxPoints: 'auto', /* Refresh rate of all grid charts in ms */ gridRefresh: 5000 @@ -335,14 +382,15 @@ AJAX.registerOnload('server_status_monitor.js', function() { editMode = false; } - // Icon graphics have zIndex 19, 20 and 21. Let's just hope nothing else has the same zIndex + // Icon graphics have zIndex 19, 20 and 21. + // Let's just hope nothing else has the same zIndex $('table#chartGrid div svg').find('*[zIndex=20], *[zIndex=21], *[zIndex=19]').toggle(editMode); $('a[href="#endChartEditMode"]').toggle(editMode); if (editMode) { // Close the settings popup - $('#statustabs_charting .popupContent').hide().removeClass('openedPopup'); + $('div.popupContent').hide().removeClass('openedPopup'); $("#chartGrid").sortableTable({ ignoreRect: { @@ -427,7 +475,7 @@ AJAX.registerOnload('server_status_monitor.js', function() { }); // global settings - $('div#statustabs_charting div.popupContent select[name="chartColumns"]').change(function() { + $('div.popupContent select[name="chartColumns"]').change(function() { monitorSettings.columns = parseInt(this.value); var newSize = chartSize(); @@ -452,7 +500,8 @@ AJAX.registerOnload('server_status_monitor.js', function() { numColumns++; }); - // To little cells in one row => for each cell to little, move all cells backwards by 1 + // To little cells in one row => for each cell to little, + // move all cells backwards by 1 if ($tr.next().length > 0) { var cnt = monitorSettings.columns - $tr.find('td').length; for (var i = 0; i < cnt; i++) { @@ -492,7 +541,7 @@ AJAX.registerOnload('server_status_monitor.js', function() { saveMonitor(); // Save settings }); - $('div#statustabs_charting div.popupContent select[name="gridChartRefresh"]').change(function() { + $('div.popupContent select[name="gridChartRefresh"]').change(function() { monitorSettings.gridRefresh = parseInt(this.value) * 1000; clearTimeout(runtime.refreshTimeout); @@ -522,7 +571,8 @@ AJAX.registerOnload('server_status_monitor.js', function() { if (type == 'preset') { newChart = presetCharts[$('div#addChartDialog select[name="presetCharts"]').prop('value')]; } else { - // If user builds his own chart, it's being set/updated each time he adds a series + // If user builds his own chart, it's being set/updated + // each time he adds a series // So here we only warn if he didn't add a series yet if (! newChart || ! newChart.nodes || newChart.nodes.length == 0) { alert(PMA_messages['strAddOneSeriesWarning']); @@ -585,7 +635,7 @@ AJAX.registerOnload('server_status_monitor.js', function() { $('
    ', { "class": "disableAjax", method: "post", - action: "file_echo.php?" + url_query + "&filename=1", + action: "file_echo.php?" + PMA_commonParams.get('common_query') + "&filename=1", style: "display:none;" }) .append( @@ -602,7 +652,7 @@ AJAX.registerOnload('server_status_monitor.js', function() { $('a[href="#importMonitorConfig"]').click(function() { $('div#emptyDialog').dialog({title: PMA_messages['strImportDialogTitle']}); - $('div#emptyDialog').html(PMA_messages['strImportDialogMessage'] + ':
    ' + + $('div#emptyDialog').html(PMA_messages['strImportDialogMessage'] + ':
    ' + '
    '); var dlgBtns = {}; @@ -704,7 +754,7 @@ AJAX.registerOnload('server_status_monitor.js', function() { $.extend(vars, getvars); } - $.get('server_status.php?' + url_query, vars, + $.get('server_status_monitor.php?' + PMA_commonParams.get('common_query'), vars, function(data) { var logVars = $.parseJSON(data.message), icon = PMA_getImage('s_success.png'), msg='', str=''; @@ -1008,30 +1058,6 @@ AJAX.registerOnload('server_status_monitor.js', function() { refreshChartGrid(); } - /* Destroys all monitor related resources */ - function destroyGrid() { - if (runtime.charts) { - $.each(runtime.charts, function(key, value) { - try { - value.chart.destroy(); - } catch(err) {} - }); - } - - try { - runtime.refreshRequest.abort(); - } catch(err) {} - try { - clearTimeout(runtime.refreshTimeout); - } catch(err) {} - - $('table#chartGrid').html(''); - - runtime.charts = null; - runtime.chartAI = 0; - monitorSettings = null; - } - /* Calls destroyGrid() and initGrid(), but before doing so it saves the chart * data from each chart and restores it after the monitor is initialized again */ function rebuildGrid() { @@ -1370,7 +1396,7 @@ AJAX.registerOnload('server_status_monitor.js', function() { /* Called in regular intervalls, this function updates the values of each chart in the grid */ function refreshChartGrid() { /* Send to server */ - runtime.refreshRequest = $.post('server_status.php?' + url_query, { + runtime.refreshRequest = $.post('server_status_monitor.php?' + PMA_commonParams.get('common_query'), { ajax_request: true, chart_data: 1, type: 'chartgrid', @@ -1437,7 +1463,7 @@ AJAX.registerOnload('server_status_monitor.js', function() { // Set y value, if defined if (value != undefined) { - elem.chart.series[j].data.push([chartData.x, value]); + elem.chart.series[j].data.push([chartData.x, value]); if(value > elem.maxYLabel) { elem.maxYLabel = value; } @@ -1472,7 +1498,7 @@ AJAX.registerOnload('server_status_monitor.js', function() { }); } - /* Function to get highest plotted point's y label, to scale the chart, + /* Function to get highest plotted point's y label, to scale the chart, * TODO: make jqplot's autoscale:true work here */ function getMaxYLabel(dataValues) { @@ -1488,7 +1514,8 @@ AJAX.registerOnload('server_status_monitor.js', function() { if (prev == null) { return undefined; } - // cur and prev are datapoint arrays, but containing only 1 element for cpu-linux + // cur and prev are datapoint arrays, but containing + // only 1 element for cpu-linux cur = cur[0]; prev = prev[0]; @@ -1573,7 +1600,7 @@ AJAX.registerOnload('server_status_monitor.js', function() { }); - logRequest = $.get('server_status.php?' + url_query, + logRequest = $.get('server_status_monitor.php?' + PMA_commonParams.get('common_query'), { ajax_request: true, log_data: 1, type: opts.src, @@ -1655,10 +1682,12 @@ AJAX.registerOnload('server_status_monitor.js', function() { } ); - /* Handles the actions performed when the user uses any of the log table filters - * which are the filter by name and grouping with ignoring data in WHERE clauses + /* Handles the actions performed when the user uses any of the + * log table filters which are the filter by name and grouping + * with ignoring data in WHERE clauses * - * @param boolean Should be true when the users enabled or disabled to group queries ignoring data in WHERE clauses + * @param boolean Should be true when the users enabled or disabled + * to group queries ignoring data in WHERE clauses */ function filterQueries(varFilterChange) { var odd_row = false, cell, textFilter; @@ -1699,7 +1728,8 @@ AJAX.registerOnload('server_status_monitor.js', function() { // We just assume the sql text is always in the second last column, and that the total count is right of it $('div#logTable table tbody tr td:nth-child(' + (runtime.logDataCols.length - 1) + ')').each(function() { var $t = $(this); - // If query is a SELECT and user enabled or disabled to group queries ignoring data in where statements, we + // If query is a SELECT and user enabled or disabled to group + // queries ignoring data in where statements, we // need to re-calculate the sums of each row if (varFilterChange && $t.html().match(/^SELECT/i)) { if (noVars) { @@ -1708,7 +1738,8 @@ AJAX.registerOnload('server_status_monitor.js', function() { q = $t.text().replace(equalsFilter, '$1=...$6').trim(); q = q.replace(functionFilter, ' $1(...)'); - // Js does not specify a limit on property name length, so we can abuse it as index :-) + // Js does not specify a limit on property name length, + // so we can abuse it as index :-) if (filteredQueries[q]) { filteredQueries[q] += parseInt($t.next().text()); totalSum += parseInt($t.next().text()); @@ -1740,7 +1771,8 @@ AJAX.registerOnload('server_status_monitor.js', function() { } } - // If not required to be hidden, do we need to hide because of a not matching text filter? + // If not required to be hidden, do we need + // to hide because of a not matching text filter? if (! hide && (textFilter != null && ! textFilter.exec($t.text()))) { hide = true; } @@ -1919,7 +1951,8 @@ AJAX.registerOnload('server_status_monitor.js', function() { if (codemirror_editor) { query = PMA_SQLPrettyPrint(query); codemirror_editor.setValue(query); - // Codemirror is bugged, it doesn't refresh properly sometimes. Following lines seem to fix that + // Codemirror is bugged, it doesn't refresh properly sometimes. + // Following lines seem to fix that setTimeout(function() { codemirror_editor.refresh(); },50); @@ -1965,7 +1998,7 @@ AJAX.registerOnload('server_status_monitor.js', function() { PMA_messages['strAnalyzing'] + ' '); - $.post('server_status.php?' + url_query, { + $.post('server_status_monitor.php?' + PMA_commonParams.get('common_query'), { ajax_request: true, query_analyzer: true, query: codemirror_editor ? codemirror_editor.getValue() : $('#sqlquery').val(), @@ -2105,3 +2138,39 @@ AJAX.registerOnload('server_status_monitor.js', function() { AJAX.registerOnload('server_status_monitor.js', function() { $('a[href="#pauseCharts"]').trigger('click'); }); + +// Needs to be global as server_status_monitor.js uses it too +function serverResponseError() { + var btns = {}; + btns[PMA_messages['strReloadPage']] = function() { + window.location.reload(); + }; + $('#emptyDialog').dialog({title: PMA_messages['strRefreshFailed']}); + $('#emptyDialog').html( + PMA_getImage('s_attention.png') + + PMA_messages['strInvalidResponseExplanation'] + ); + $('#emptyDialog').dialog({ buttons: btns }); +} + +/* Destroys all monitor related resources */ +function destroyGrid() { + if (runtime.charts) { + $.each(runtime.charts, function(key, value) { + try { + value.chart.destroy(); + } catch(err) {} + }); + } + + try { + runtime.refreshRequest.abort(); + } catch(err) {} + try { + clearTimeout(runtime.refreshTimeout); + } catch(err) {} + $('table#chartGrid').html(''); + runtime.charts = null; + runtime.chartAI = 0; + monitorSettings = null; +} diff --git a/libraries/Menu.class.php b/libraries/Menu.class.php index 201c0028cd..d954616f44 100644 --- a/libraries/Menu.class.php +++ b/libraries/Menu.class.php @@ -456,6 +456,16 @@ class PMA_Menu $tabs['status']['icon'] = 's_status.png'; $tabs['status']['link'] = 'server_status.php'; $tabs['status']['text'] = __('Status'); + $tabs['status']['active'] = in_array( + basename($GLOBALS['PMA_PHP_SELF']), + array( + 'server_status.php', + 'server_status_advisor.php', + 'server_status_monitor.php', + 'server_status_queries.php', + 'server_status_variables.php' + ) + ); if ($is_superuser && ! PMA_DRIZZLE) { $tabs['rights']['icon'] = 's_rights.png'; diff --git a/libraries/ServerStatusData.class.php b/libraries/ServerStatusData.class.php index 85d507b05e..fc2cfa0ef8 100644 --- a/libraries/ServerStatusData.class.php +++ b/libraries/ServerStatusData.class.php @@ -308,23 +308,48 @@ class PMA_ServerStatusData { * * @return array */ - public static function getMenuHtml() + public function getMenuHtml() { - $retval = '
      '; - $retval .= '
    • '; - $retval .= ''; - $retval .= __('Query statistics') . ''; - $retval .= '
    • '; - $retval .= '
    • '; - $retval .= ''; - $retval .= __('All status variables') . ''; - $retval .= '
    • '; - $retval .= '
    • '; - $retval .= ''; - $retval .= __('Advisor') . ''; - $retval .= '
    • '; + $url_params = PMA_generate_common_url(); + $items = array( + array( + 'name' => __('Server'), + 'url' => 'server_status.php' + ), + array( + 'name' => __('Query statistics'), + 'url' => 'server_status_queries.php' + ), + array( + 'name' => __('All status variables'), + 'url' => 'server_status_variables.php' + ), + array( + 'name' => __('Monitor'), + 'url' => 'server_status_monitor.php' + ), + array( + 'name' => __('Advisor'), + 'url' => 'server_status_advisor.php' + ) + ); + + $retval = '
        '; + foreach ($items as $item) { + $class = ''; + if ($item['url'] === $this->selfUrl) { + $class = ' class="tabactive"'; + } + $retval .= '
      • '; + $retval .= ''; + $retval .= $item['name']; + $retval .= ''; + $retval .= '
      • '; + } $retval .= '
      '; $retval .= '
      '; + return $retval; } } diff --git a/libraries/common.inc.php b/libraries/common.inc.php index 856de8871a..3c06ee66cb 100644 --- a/libraries/common.inc.php +++ b/libraries/common.inc.php @@ -391,6 +391,10 @@ $goto_whitelist = array( 'server_processlist.php', 'server_sql.php', 'server_status.php', + 'server_status_advisor.php', + 'server_status_monitor.php', + 'server_status_queries.php', + 'server_status_variables.php', 'server_variables.php', 'sql.php', 'tbl_addfield.php', diff --git a/server_status.php b/server_status.php index c7a0162a99..6840941784 100644 --- a/server_status.php +++ b/server_status.php @@ -1,452 +1,15 @@ microtime(true) * 1000, - 'y_proc' => $num_procs, - 'y_conn' => $c['Connections'] - ); - - exit(json_encode($ret)); - - case 'queries': // Query realtime chart - if (PMA_DRIZZLE) { - $sql = "SELECT concat('Com_', variable_name), variable_value - FROM data_dictionary.GLOBAL_STATEMENTS - WHERE variable_value > 0 - UNION - SELECT variable_name, variable_value - FROM data_dictionary.GLOBAL_STATUS - WHERE variable_name = 'Questions'"; - $queries = PMA_DBI_fetch_result($sql, 0, 1); - } else { - $queries = PMA_DBI_fetch_result( - "SHOW GLOBAL STATUS - WHERE - (Variable_name LIKE 'Com_%' OR Variable_name = 'Questions') - AND Value > 0", 0, 1 - ); - } - cleanDeprecated($queries); - // admin commands are not queries - unset($queries['Com_admin_commands']); - $questions = $queries['Questions']; - unset($queries['Questions']); - - //$sum=array_sum($queries); - $ret = array( - 'x' => microtime(true) * 1000, - 'y' => $questions, - 'pointInfo' => $queries - ); - - exit(json_encode($ret)); - - case 'traffic': // Traffic realtime chart - $traffic = PMA_DBI_fetch_result( - "SHOW GLOBAL STATUS - WHERE Variable_name = 'Bytes_received' - OR Variable_name = 'Bytes_sent'", 0, 1 - ); - - $ret = array( - 'x' => microtime(true) * 1000, - 'y_sent' => $traffic['Bytes_sent'], - 'y_received' => $traffic['Bytes_received'] - ); - - exit(json_encode($ret)); - - case 'chartgrid': // Data for the monitor - $ret = json_decode($_REQUEST['requiredData'], true); - $statusVars = array(); - $serverVars = array(); - $sysinfo = $cpuload = $memory = 0; - $pName = ''; - - /* Accumulate all required variables and data */ - // For each chart - foreach ($ret as $chart_id => $chartNodes) { - // For each data series - foreach ($chartNodes as $node_id => $nodeDataPoints) { - // For each data point in the series (usually just 1) - foreach ($nodeDataPoints as $point_id => $dataPoint) { - $pName = $dataPoint['name']; - - switch ($dataPoint['type']) { - /* We only collect the status and server variables here to - * read them all in one query, - * and only afterwards assign them. - * Also do some white list filtering on the names - */ - case 'servervar': - if (! preg_match('/[^a-zA-Z_]+/', $pName)) { - $serverVars[] = $pName; - } - break; - - case 'statusvar': - if (! preg_match('/[^a-zA-Z_]+/', $pName)) { - $statusVars[] = $pName; - } - break; - - case 'proc': - $result = PMA_DBI_query('SHOW PROCESSLIST'); - $ret[$chart_id][$node_id][$point_id]['value'] - = PMA_DBI_num_rows($result); - break; - - case 'cpu': - if (!$sysinfo) { - include_once 'libraries/sysinfo.lib.php'; - $sysinfo = PMA_getSysInfo(); - } - if (!$cpuload) { - $cpuload = $sysinfo->loadavg(); - } - - if (PMA_getSysInfoOs() == 'Linux') { - $ret[$chart_id][$node_id][$point_id]['idle'] - = $cpuload['idle']; - $ret[$chart_id][$node_id][$point_id]['busy'] - = $cpuload['busy']; - } else { - $ret[$chart_id][$node_id][$point_id]['value'] - = $cpuload['loadavg']; - } - - break; - - case 'memory': - if (!$sysinfo) { - include_once 'libraries/sysinfo.lib.php'; - $sysinfo = PMA_getSysInfo(); - } - if (!$memory) { - $memory = $sysinfo->memory(); - } - - $ret[$chart_id][$node_id][$point_id]['value'] - = $memory[$pName]; - break; - } /* switch */ - } /* foreach */ - } /* foreach */ - } /* foreach */ - - // Retrieve all required status variables - if (count($statusVars)) { - $statusVarValues = PMA_DBI_fetch_result( - "SHOW GLOBAL STATUS WHERE Variable_name='" - . implode("' OR Variable_name='", $statusVars) . "'", - 0, - 1 - ); - } else { - $statusVarValues = array(); - } - - // Retrieve all required server variables - if (count($serverVars)) { - $serverVarValues = PMA_DBI_fetch_result( - "SHOW GLOBAL VARIABLES WHERE Variable_name='" - . implode("' OR Variable_name='", $serverVars) . "'", - 0, - 1 - ); - } else { - $serverVarValues = array(); - } - - // ...and now assign them - foreach ($ret as $chart_id => $chartNodes) { - foreach ($chartNodes as $node_id => $nodeDataPoints) { - foreach ($nodeDataPoints as $point_id => $dataPoint) { - switch($dataPoint['type']) { - case 'statusvar': - $ret[$chart_id][$node_id][$point_id]['value'] - = $statusVarValues[$dataPoint['name']]; - break; - case 'servervar': - $ret[$chart_id][$node_id][$point_id]['value'] - = $serverVarValues[$dataPoint['name']]; - break; - } - } - } - } - - $ret['x'] = microtime(true) * 1000; - - exit(json_encode($ret)); - } - } - - if (isset($_REQUEST['log_data'])) { - if (PMA_MYSQL_INT_VERSION < 50106) { - // Table logging is only available since 5.1.6 - exit('""'); - } - - $start = intval($_REQUEST['time_start']); - $end = intval($_REQUEST['time_end']); - - if ($_REQUEST['type'] == 'slow') { - $q = 'SELECT start_time, user_host, '; - $q .= 'Sec_to_Time(Sum(Time_to_Sec(query_time))) as query_time, '; - $q .= 'Sec_to_Time(Sum(Time_to_Sec(lock_time))) as lock_time, '; - $q .= 'SUM(rows_sent) AS rows_sent, '; - $q .= 'SUM(rows_examined) AS rows_examined, db, sql_text, '; - $q .= 'COUNT(sql_text) AS \'#\' '; - $q .= 'FROM `mysql`.`slow_log` '; - $q .= 'WHERE start_time > FROM_UNIXTIME(' . $start . ') '; - $q .= 'AND start_time < FROM_UNIXTIME(' . $end . ') GROUP BY sql_text'; - - $result = PMA_DBI_try_query($q); - - $return = array('rows' => array(), 'sum' => array()); - $type = ''; - - while ($row = PMA_DBI_fetch_assoc($result)) { - $type = strtolower( - substr($row['sql_text'], 0, strpos($row['sql_text'], ' ')) - ); - - switch($type) { - case 'insert': - case 'update': - //Cut off big inserts and updates, but append byte count instead - if (strlen($row['sql_text']) > 220) { - $implode_sql_text = implode( - ' ', - PMA_Util::formatByteDown( - strlen($row['sql_text']), 2, 2 - ) - ); - $row['sql_text'] = substr($row['sql_text'], 0, 200) - . '... [' . $implode_sql_text . ']'; - } - break; - default: - break; - } - - if (! isset($return['sum'][$type])) { - $return['sum'][$type] = 0; - } - $return['sum'][$type] += $row['#']; - $return['rows'][] = $row; - } - - $return['sum']['TOTAL'] = array_sum($return['sum']); - $return['numRows'] = count($return['rows']); - - PMA_DBI_free_result($result); - - exit(json_encode($return)); - } - - if ($_REQUEST['type'] == 'general') { - $limitTypes = ''; - if (isset($_REQUEST['limitTypes']) && $_REQUEST['limitTypes']) { - $limitTypes - = 'AND argument REGEXP \'^(INSERT|SELECT|UPDATE|DELETE)\' '; - } - - $q = 'SELECT TIME(event_time) as event_time, user_host, thread_id, '; - $q .= 'server_id, argument, count(argument) as \'#\' '; - $q .= 'FROM `mysql`.`general_log` '; - $q .= 'WHERE command_type=\'Query\' '; - $q .= 'AND event_time > FROM_UNIXTIME(' . $start . ') '; - $q .= 'AND event_time < FROM_UNIXTIME(' . $end . ') '; - $q .= $limitTypes . 'GROUP by argument'; // HAVING count > 1'; - - $result = PMA_DBI_try_query($q); - - $return = array('rows' => array(), 'sum' => array()); - $type = ''; - $insertTables = array(); - $insertTablesFirst = -1; - $i = 0; - $removeVars = isset($_REQUEST['removeVariables']) - && $_REQUEST['removeVariables']; - - while ($row = PMA_DBI_fetch_assoc($result)) { - preg_match('/^(\w+)\s/', $row['argument'], $match); - $type = strtolower($match[1]); - - if (! isset($return['sum'][$type])) { - $return['sum'][$type] = 0; - } - $return['sum'][$type] += $row['#']; - - switch($type) { - case 'insert': - // Group inserts if selected - if ($removeVars - && preg_match( - '/^INSERT INTO (`|\'|"|)([^\s\\1]+)\\1/i', - $row['argument'], $matches - ) - ) { - $insertTables[$matches[2]]++; - if ($insertTables[$matches[2]] > 1) { - $return['rows'][$insertTablesFirst]['#'] - = $insertTables[$matches[2]]; - - // Add a ... to the end of this query to indicate that - // there's been other queries - $temp = $return['rows'][$insertTablesFirst]['argument']; - if ($temp[strlen($temp) - 1] != '.') { - $return['rows'][$insertTablesFirst]['argument'] - .= '
      ...'; - } - - // Group this value, thus do not add to the result list - continue 2; - } else { - $insertTablesFirst = $i; - $insertTables[$matches[2]] += $row['#'] - 1; - } - } - // No break here - - case 'update': - // Cut off big inserts and updates, - // but append byte count therefor - if (strlen($row['argument']) > 220) { - $row['argument'] = substr($row['argument'], 0, 200) - . '... [' - . implode( - ' ', - PMA_Util::formatByteDown( - strlen($row['argument']) - ), - 2, - 2 - ) - . ']'; - } - break; - - default: - break; - } - - $return['rows'][] = $row; - $i++; - } - - $return['sum']['TOTAL'] = array_sum($return['sum']); - $return['numRows'] = count($return['rows']); - - PMA_DBI_free_result($result); - - exit(json_encode($return)); - } - } - - if (isset($_REQUEST['logging_vars'])) { - if (isset($_REQUEST['varName']) && isset($_REQUEST['varValue'])) { - $value = PMA_Util::sqlAddSlashes($_REQUEST['varValue']); - if (! is_numeric($value)) { - $value="'" . $value . "'"; - } - - if (! preg_match("/[^a-zA-Z0-9_]+/", $_REQUEST['varName'])) { - PMA_DBI_query( - 'SET GLOBAL ' . $_REQUEST['varName'] . ' = ' . $value - ); - } - - } - - $loggingVars = PMA_DBI_fetch_result( - 'SHOW GLOBAL VARIABLES WHERE Variable_name IN' - . ' ("general_log","slow_query_log","long_query_time","log_output")', - 0, - 1 - ); - exit(json_encode($loggingVars)); - } - - if (isset($_REQUEST['query_analyzer'])) { - $return = array(); - - if (strlen($_REQUEST['database'])) { - PMA_DBI_select_db($_REQUEST['database']); - } - - if ($profiling = PMA_Util::profilingSupported()) { - PMA_DBI_query('SET PROFILING=1;'); - } - - // Do not cache query - $query = preg_replace( - '/^(\s*SELECT)/i', - '\\1 SQL_NO_CACHE', - $_REQUEST['query'] - ); - - $result = PMA_DBI_try_query($query); - $return['affectedRows'] = $GLOBALS['cached_affected_rows']; - - $result = PMA_DBI_try_query('EXPLAIN ' . $query); - while ($row = PMA_DBI_fetch_assoc($result)) { - $return['explain'][] = $row; - } - - // In case an error happened - $return['error'] = PMA_DBI_getError(); - - PMA_DBI_free_result($result); - - if ($profiling) { - $return['profiling'] = array(); - $result = PMA_DBI_try_query( - 'SELECT seq,state,duration FROM INFORMATION_SCHEMA.PROFILING' - . ' WHERE QUERY_ID=1 ORDER BY seq' - ); - while ($row = PMA_DBI_fetch_assoc($result)) { - $return['profiling'][]= $row; - } - PMA_DBI_free_result($result); - } - - exit(json_encode($return)); - } -} - - /** * Replication library */ @@ -458,48 +21,7 @@ if (PMA_DRIZZLE) { include_once 'libraries/replication_gui.lib.php'; } -/** - * JS Includes - */ -$response = PMA_Response::getInstance(); -$header = $response->getHeader(); -$scripts = $header->getScripts(); - -$scripts->addFile('jquery/jquery.tablesorter.js'); -$scripts->addFile('server_status.js'); -$scripts->addFile('jquery/jquery-ui-1.8.16.custom.js'); - -/* < IE 9 doesn't support canvas natively */ -if (PMA_USR_BROWSER_AGENT == 'IE' && PMA_USR_BROWSER_VER < 9) { - $scripts->addFile('jqplot/excanvas.js'); -} - -$scripts->addFile('canvg/canvg.js'); -// for charting -$scripts->addFile('jqplot/jquery.jqplot.js'); -$scripts->addFile('jqplot/plugins/jqplot.pieRenderer.js'); -$scripts->addFile('jqplot/plugins/jqplot.canvasTextRenderer.js'); -$scripts->addFile('jqplot/plugins/jqplot.canvasAxisLabelRenderer.js'); -$scripts->addFile('jqplot/plugins/jqplot.dateAxisRenderer.js'); -$scripts->addFile('jqplot/plugins/jqplot.highlighter.js'); -$scripts->addFile('jqplot/plugins/jqplot.cursor.js'); -$scripts->addFile('date.js'); - -/** - * flush status variables if requested - */ -if (isset($_REQUEST['flush'])) { - $_flush_commands = array( - 'STATUS', - 'TABLES', - 'QUERY CACHE', - ); - - if (in_array($_REQUEST['flush'], $_flush_commands)) { - PMA_DBI_query('FLUSH ' . $_REQUEST['flush'] . ';'); - } - unset($_flush_commands); -} +$ServerStatusData = new PMA_ServerStatusData('server_status.php'); /** * Kills a selected process @@ -516,514 +38,255 @@ if (! empty($_REQUEST['kill'])) { ); } $message->addParam($_REQUEST['kill']); - //$message->display(); } - - -/** - * get status from server - */ -$server_status = PMA_DBI_fetch_result('SHOW GLOBAL STATUS', 0, 1); -if (PMA_DRIZZLE) { - // Drizzle doesn't put query statistics into variables, add it - $sql = "SELECT concat('Com_', variable_name), variable_value - FROM data_dictionary.GLOBAL_STATEMENTS"; - $statements = PMA_DBI_fetch_result($sql, 0, 1); - $server_status = array_merge($server_status, $statements); -} - -/** - * for some calculations we require also some server settings - */ -$server_variables = PMA_DBI_fetch_result('SHOW GLOBAL VARIABLES', 0, 1); - -/** - * cleanup of some deprecated values - */ -cleanDeprecated($server_status); - -/** - * calculate some values - */ -// Key_buffer_fraction -if (isset($server_status['Key_blocks_unused']) - && isset($server_variables['key_cache_block_size']) - && isset($server_variables['key_buffer_size']) -) { - $server_status['Key_buffer_fraction_%'] - = 100 - - $server_status['Key_blocks_unused'] - * $server_variables['key_cache_block_size'] - / $server_variables['key_buffer_size'] - * 100; -} elseif (isset($server_status['Key_blocks_used']) - && isset($server_variables['key_buffer_size'])) { - $server_status['Key_buffer_fraction_%'] - = $server_status['Key_blocks_used'] - * 1024 - / $server_variables['key_buffer_size']; -} - -// Ratio for key read/write -if (isset($server_status['Key_writes']) - && isset($server_status['Key_write_requests']) - && $server_status['Key_write_requests'] > 0 -) { - $server_status['Key_write_ratio_%'] - = 100 * $server_status['Key_writes'] / $server_status['Key_write_requests']; -} - -if (isset($server_status['Key_reads']) - && isset($server_status['Key_read_requests']) - && $server_status['Key_read_requests'] > 0 -) { - $server_status['Key_read_ratio_%'] - = 100 * $server_status['Key_reads'] / $server_status['Key_read_requests']; -} - -// Threads_cache_hitrate -if (isset($server_status['Threads_created']) - && isset($server_status['Connections']) - && $server_status['Connections'] > 0 -) { - - $server_status['Threads_cache_hitrate_%'] - = 100 - $server_status['Threads_created'] - / $server_status['Connections'] * 100; -} - -/** - * split variables in sections - */ -$allocations = array( - // variable name => section - // variable names match when they begin with the given string - - 'Com_' => 'com', - 'Innodb_' => 'innodb', - 'Ndb_' => 'ndb', - 'Handler_' => 'handler', - 'Qcache_' => 'qcache', - 'Threads_' => 'threads', - 'Slow_launch_threads' => 'threads', - - 'Binlog_cache_' => 'binlog_cache', - 'Created_tmp_' => 'created_tmp', - 'Key_' => 'key', - - 'Delayed_' => 'delayed', - 'Not_flushed_delayed_rows' => 'delayed', - - 'Flush_commands' => 'query', - 'Last_query_cost' => 'query', - 'Slow_queries' => 'query', - 'Queries' => 'query', - 'Prepared_stmt_count' => 'query', - - 'Select_' => 'select', - 'Sort_' => 'sort', - - 'Open_tables' => 'table', - 'Opened_tables' => 'table', - 'Open_table_definitions' => 'table', - 'Opened_table_definitions' => 'table', - 'Table_locks_' => 'table', - - 'Rpl_status' => 'repl', - 'Slave_' => 'repl', - - 'Tc_' => 'tc', - - 'Ssl_' => 'ssl', - - 'Open_files' => 'files', - 'Open_streams' => 'files', - 'Opened_files' => 'files', -); - -$sections = array( - // section => section name (description) - 'com' => 'Com', - 'query' => __('SQL query'), - 'innodb' => 'InnoDB', - 'ndb' => 'NDB', - 'handler' => __('Handler'), - 'qcache' => __('Query cache'), - 'threads' => __('Threads'), - 'binlog_cache' => __('Binary log'), - 'created_tmp' => __('Temporary data'), - 'delayed' => __('Delayed inserts'), - 'key' => __('Key cache'), - 'select' => __('Joins'), - 'repl' => __('Replication'), - 'sort' => __('Sorting'), - 'table' => __('Tables'), - 'tc' => __('Transaction coordinator'), - 'files' => __('Files'), - 'ssl' => 'SSL', - 'other' => __('Other') -); - -/** - * define some needfull links/commands - */ -// variable or section name => (name => url) -$links = array(); - -$links['table'][__('Flush (close) all tables')] - = $PMA_PHP_SELF . '?flush=TABLES&' . PMA_generate_common_url(); -$links['table'][__('Show open tables')] - = 'sql.php?sql_query=' . urlencode('SHOW OPEN TABLES') . - '&goto=server_status.php&' . PMA_generate_common_url(); - -if ($server_master_status) { - $links['repl'][__('Show slave hosts')] - = 'sql.php?sql_query=' . urlencode('SHOW SLAVE HOSTS') . - '&goto=server_status.php&' . PMA_generate_common_url(); - $links['repl'][__('Show master status')] = '#replication_master'; -} -if ($server_slave_status) { - $links['repl'][__('Show slave status')] = '#replication_slave'; -} - -$links['repl']['doc'] = 'replication'; - -$links['qcache'][__('Flush query cache')] - = $PMA_PHP_SELF . '?flush=' . urlencode('QUERY CACHE') . '&' . - PMA_generate_common_url(); -$links['qcache']['doc'] = 'query_cache'; - -//$links['threads'][__('Show processes')] -// = 'server_processlist.php?' . PMA_generate_common_url(); -$links['threads']['doc'] = 'mysql_threads'; - -$links['key']['doc'] = 'myisam_key_cache'; - -$links['binlog_cache']['doc'] = 'binary_log'; - -$links['Slow_queries']['doc'] = 'slow_query_log'; - -$links['innodb'][__('Variables')] - = 'server_engines.php?engine=InnoDB&' . PMA_generate_common_url(); -$links['innodb'][__('InnoDB Status')] - = 'server_engines.php?engine=InnoDB&page=Status&' . - PMA_generate_common_url(); -$links['innodb']['doc'] = 'innodb'; - - -// Variable to contain all com_ variables (query statistics) -$used_queries = array(); - -// Variable to map variable names to their respective section name -// (used for js category filtering) -$allocationMap = array(); - -// Variable to mark used sections -$categoryUsed = array(); - -// sort vars into arrays -foreach ($server_status as $name => $value) { - $section_found = false; - foreach ($allocations as $filter => $section) { - if (strpos($name, $filter) !== false) { - $allocationMap[$name] = $section; - $categoryUsed[$section] = true; - $section_found = true; - if ($section == 'com' && $value > 0) { - $used_queries[$name] = $value; - } - break; // Only exits inner loop - } - } - if (!$section_found) { - $allocationMap[$name] = 'other'; - $categoryUsed['other'] = true; - } -} - -if (PMA_DRIZZLE) { - $used_queries = PMA_DBI_fetch_result( - 'SELECT * FROM data_dictionary.global_statements', - 0, - 1 - ); - unset($used_queries['admin_commands']); -} else { - // admin commands are not queries (e.g. they include COM_PING, - // which is excluded from $server_status['Questions']) - unset($used_queries['Com_admin_commands']); -} - -/* Ajax request refresh */ -if (isset($_REQUEST['show']) && isset($_REQUEST['ajax_request'])) { - switch($_REQUEST['show']) { - case 'query_statistics': - printQueryStatistics(); - exit(); - case 'server_traffic': - printServerTraffic(); - exit(); - case 'variables_table': - // Prints the variables table - printVariablesTable(); - exit(); - - default: - break; - } -} - -$server_db_isLocal = strtolower($cfg['Server']['host']) == 'localhost' - || $cfg['Server']['host'] == '127.0.0.1' - || $cfg['Server']['host'] == '::1'; - -$input = ''; - -echo '
      '; -printf($input, 'pma_token', $_SESSION[' PMA_token ']); -printf($input, 'url_query', str_replace('&', '&', PMA_generate_common_url($db))); -printf($input, 'server_time_diff', 'new Date().getTime() - ' . (microtime(true) * 1000)); -printf($input, 'server_os', PHP_OS); -printf($input, 'is_superuser', PMA_isSuperuser()); -printf($input, 'server_db_isLocal', $server_db_isLocal); -echo '
      '; - -echo '
      '; -echo PMA_Util::showMySQLDocu('general-thread-states', 'general-thread-states'); -echo '
      '; -echo '
      '; -echo PMA_Util::showMySQLDocu('explain-output', 'explain-output'); -echo '
      '; - /** * start output */ +$response = PMA_Response::getInstance(); +$response->addHTML('
      '); +$response->addHTML($ServerStatusData->getMenuHtml()); +$response->addHTML(getServerTrafficHtml($ServerStatusData)); +$response->addHTML('
      '); - /** - * Does the common work - */ -require 'libraries/server_common.inc.php'; - -echo '
      '; - -echo PMA_ServerStatusData::getMenuHtml(); - -echo '
      '; -echo ''; - -echo '
      '; -printMonitor(); -echo '
      '; - -echo '
      '; -echo '
      '; +exit; /** * Prints server traffic information * * @return void */ -function printServerTraffic() +function getServerTrafficHtml($ServerStatusData) { - global $server_status, $PMA_PHP_SELF; - global $server_master_status, $server_slave_status, $replication_types; - - $hour_factor = 3600 / $server_status['Uptime']; - - /** - * starttime calculation - */ + $hour_factor = 3600 / $ServerStatusData->status['Uptime']; $start_time = PMA_DBI_fetch_value( - 'SELECT UNIX_TIMESTAMP() - ' . $server_status['Uptime'] + 'SELECT UNIX_TIMESTAMP() - ' . $ServerStatusData->status['Uptime'] ); - echo '

      '; - - echo sprintf( + $retval = '

      '; + $retval .= sprintf( __('Network traffic since startup: %s'), implode( ' ', PMA_Util::formatByteDown( - $server_status['Bytes_received'] + $server_status['Bytes_sent'], + $ServerStatusData->status['Bytes_received'] + $ServerStatusData->status['Bytes_sent'], 3, 1 ) ) ); - echo '

      '; - - echo '

      '; - - printf( + $retval .= ''; + $retval .= '

      '; + $retval .= sprintf( __('This MySQL server has been running for %1$s. It started up on %2$s.'), - PMA_Util::timespanFormat($server_status['Uptime']), + PMA_Util::timespanFormat($ServerStatusData->status['Uptime']), PMA_Util::localisedDate($start_time) ) . "\n"; + $retval .= '

      '; - echo '

      '; - - if ($server_master_status || $server_slave_status) { - echo '

      '; - if ($server_master_status && $server_slave_status) { - echo __('This MySQL server works as master and slave in replication process.'); - } elseif ($server_master_status) { - echo __('This MySQL server works as master in replication process.'); - } elseif ($server_slave_status) { - echo __('This MySQL server works as slave in replication process.'); + if ($GLOBALS['server_master_status'] || $GLOBALS['server_slave_status']) { + $retval .= '

      '; + if ($GLOBALS['server_master_status'] && $GLOBALS['server_slave_status']) { + $retval .= __( + 'This MySQL server works as master and ' + . 'slave in replication process.' + ); + } elseif ($GLOBALS['server_master_status']) { + $retval .= __( + 'This MySQL server works as master ' + . 'in replication process.' + ); + } elseif ($GLOBALS['server_slave_status']) { + $retval .= __( + 'This MySQL server works as slave ' + . 'in replication process.' + ); } - echo ' '; - echo __('For further information about replication status on the server, please visit the replication section.'); - echo '

      '; + $retval .= ' '; + $retval .= __( + 'For further information about replication status on the server, ' + . 'please visit the replication section.' + ); + $retval .= '

      '; } /* * if the server works as master or slave in replication process, * display useful information */ - if ($server_master_status || $server_slave_status) { - echo '
      '; - - echo '

      ' . __('Replication status') . '

      '; - - foreach ($replication_types as $type) { + if ($GLOBALS['server_master_status'] || $GLOBALS['server_slave_status']) { + $retval .= '
      '; + $retval .= '

      ' . __('Replication status') . '

      '; + foreach ($GLOBALS['replication_types'] as $type) { if (${"server_{$type}_status"}) { PMA_replication_print_status_table($type); } } unset($types); } - ?> - - - - - - - - - - - - - - - - - - - - - - - - -
      ø
      + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= '
      '; + $retval .= __('Traffic') . ' '; + $retval .= PMA_Util::showHint( + __( + 'On a busy server, the byte counters may overrun, so those statistics ' + . 'as reported by the MySQL server may be incorrect.' + ) + ); + $retval .= 'ø ' . __('per hour') . '
      ' . __('Received') . ''; + $retval .= implode( + ' ', + PMA_Util::formatByteDown( + $ServerStatusData->status['Bytes_received'], 3, 1 + ) + ); + $retval .= ''; + $retval .= implode( + ' ', + PMA_Util::formatByteDown( + $ServerStatusData->status['Bytes_received'] * $hour_factor, 3, 1 + ) + ); + $retval .= '
      ' . __('Sent') . ''; + $retval .= implode( + ' ', + PMA_Util::formatByteDown( + $ServerStatusData->status['Bytes_sent'], 3, 1 + ) + ); + $retval .= 'status['Bytes_sent'] * $hour_factor, 3, 1 + ) + ); + $retval .= '
      ' . __('Total') . ''; + $retval .= implode( + ' ', + PMA_Util::formatByteDown( + $ServerStatusData->status['Bytes_received'] + $ServerStatusData->status['Bytes_sent'], 3, 1 + ) + ); + $retval .= ''; + $retval .= implode( + ' ', + PMA_Util::formatByteDown( + ($ServerStatusData->status['Bytes_received'] + $ServerStatusData->status['Bytes_sent']) + * $hour_factor, 3, 1 + ) + ); + $retval .= '
      '; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      ø %
      --- ---
      0 - ? PMA_Util::formatNumber( - $server_status['Aborted_connects'] * 100 / $server_status['Connections'], - 0, 2, true - ) . '%' - : '--- '; ?>
      0 - ? PMA_Util::formatNumber( - $server_status['Aborted_clients'] * 100 / $server_status['Connections'], - 0, 2, true - ) . '%' - : '--- '; ?>
      %
      - '; + $retval .= ''; + $retval .= ''; + $retval .= '' . __('Connections') . ''; + $retval .= 'ø ' . __('per hour') . ''; + $retval .= '%'; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= '' . __('max. concurrent connections') . ''; + $retval .= ''; + $retval .= PMA_Util::formatNumber( + $ServerStatusData->status['Max_used_connections'], 0 + ); + $retval .= ''; + $retval .= '--- '; + $retval .= '--- '; + $retval .= ''; + $retval .= ''; + $retval .= '' . __('Failed attempts') . ''; + $retval .= ''; + $retval .= PMA_Util::formatNumber( + $ServerStatusData->status['Aborted_connects'], 4, 1, true + ); + $retval .= ''; + $retval .= ''; + $retval .= PMA_Util::formatNumber( + $ServerStatusData->status['Aborted_connects'] * $hour_factor, 4, 2, true + ); + $retval .= ''; + $retval .= ''; + if ($ServerStatusData->status['Connections'] > 0) { + $retval .= PMA_Util::formatNumber( + $ServerStatusData->status['Aborted_connects'] * 100 / $ServerStatusData->status['Connections'], + 0, 2, true + ); + $retval .= '%'; + } else { + $retval .= '--- '; + } + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= '' . __('Aborted') . ''; + $retval .= ''; + $retval .= PMA_Util::formatNumber( + $ServerStatusData->status['Aborted_clients'], 4, 1, true + ); + $retval .= ''; + $retval .= ''; + $retval .= PMA_Util::formatNumber( + $ServerStatusData->status['Aborted_clients'] * $hour_factor, 4, 2, true + ); + $retval .= ''; + $retval .= ''; + if ($ServerStatusData->status['Connections'] > 0) { + $retval .= PMA_Util::formatNumber( + $ServerStatusData->status['Aborted_clients'] * 100 / $ServerStatusData->status['Connections'], + 0, 2, true + ); + $retval .= '%'; + } else { + $retval .= '--- '; + } + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= '' . __('Total') . ''; + $retval .= ''; + $retval .= PMA_Util::formatNumber( + $ServerStatusData->status['Connections'], 4, 0 + ); + $retval .= ''; + $retval .= ''; + $retval .= PMA_Util::formatNumber( + $ServerStatusData->status['Connections'] * $hour_factor, 4, 2 + ); + $retval .= ''; + $retval .= ''; + $retval .= PMA_Util::formatNumber(100, 0, 2); + $retval .= '%'; + $retval .= ''; + $retval .= ''; + $retval .= ''; $url_params = array(); @@ -1085,8 +348,8 @@ function printServerTraffic() " . ($show_full_sql ? 's.query' : 'left(p.info, ' . (int)$GLOBALS['cfg']['MaxCharactersInDisplayedSQL'] . ')') . " AS Info FROM data_dictionary.PROCESSLIST p " . ($show_full_sql ? 'LEFT JOIN data_dictionary.SESSIONS s ON s.session_id = p.id' : ''); - if (!empty($_REQUEST['order_by_field']) - && !empty($_REQUEST['sort_order']) + if (! empty($_REQUEST['order_by_field']) + && ! empty($_REQUEST['sort_order']) ) { $sql_query .= ' ORDER BY p.' . $_REQUEST['order_by_field'] . ' ' . $_REQUEST['sort_order']; } @@ -1094,8 +357,8 @@ function printServerTraffic() $sql_query = $show_full_sql ? 'SHOW FULL PROCESSLIST' : 'SHOW PROCESSLIST'; - if (!empty($_REQUEST['order_by_field']) - && !empty($_REQUEST['sort_order']) + if (! empty($_REQUEST['order_by_field']) + && ! empty($_REQUEST['sort_order']) ) { $sql_query = 'SELECT * FROM `INFORMATION_SCHEMA`.`PROCESSLIST` ORDER BY `' . $_REQUEST['order_by_field'] . '` ' . $_REQUEST['sort_order']; @@ -1107,15 +370,14 @@ function printServerTraffic() /** * Displays the page */ - echo ''; - echo ''; - echo ''; - echo ''; - + $retval .= '
      ' . __('Processes') . '
      '; + $retval .= ''; + $retval .= ''; + $retval .= ''; foreach ($sortable_columns as $column) { - $is_sorted = !empty($_REQUEST['order_by_field']) - && !empty($_REQUEST['sort_order']) + $is_sorted = ! empty($_REQUEST['order_by_field']) + && ! empty($_REQUEST['sort_order']) && ($_REQUEST['order_by_field'] == $column['order_by_field']); $column['sort_order'] = ($is_sorted @@ -1133,61 +395,61 @@ function printServerTraffic() } } - echo ''; + $retval .= ''; } - echo ''; - echo ''; - echo ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; $odd_row = true; while ($process = PMA_DBI_fetch_assoc($result)) { // Array keys need to modify due to the way it has used // to display column values - if (!empty($_REQUEST['order_by_field']) - && !empty($_REQUEST['sort_order']) + if (! empty($_REQUEST['order_by_field']) + && ! empty($_REQUEST['sort_order']) ) { foreach (array_keys($process) as $key) { $new_key = ucfirst(strtolower($key)); @@ -1198,347 +460,35 @@ function printServerTraffic() $url_params['kill'] = $process['Id']; $kill_process = 'server_status.php' . PMA_generate_common_url($url_params); - ?> - - - - - - - - - - '; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ''; + $retval .= ' - - '; + $retval .= ''; $odd_row = ! $odd_row; } - ?> - -
      ' . __('Processes') . ''; - echo ''; + $retval .= '>'; - echo $column['column_name']; + $retval .= $column['column_name']; if ($is_sorted) { - echo ''
+            $retval .= '<img class='; - echo ''
+            $retval .= '<img class='; } - echo ''; + $retval .= ''; if (! PMA_DRIZZLE && (0 === --$sortable_columns_count)) { - echo ''; - echo ''; + $retval .= ''; - echo ''; + $retval .= '">'; + $retval .= ''; } - echo '
      ' . __('None') . '' : $process['db']); ?> - '; + $retval .= '' . __('Kill') . '' . $process['Id'] . '' . $process['User'] . '' . $process['Host'] . '' . ((! isset($process['db']) || ! strlen($process['db'])) ? '' . __('None') . '' : $process['db']) . '' . $process['Command'] . '' . $process['Time'] . '' . (empty($process['State']) ? '---' : $process['State']) . ''; + if (empty($process['Info'])) { - echo '---'; + $retval .= '---'; } else { if (!$show_full_sql && strlen($process['Info']) > $GLOBALS['cfg']['MaxCharactersInDisplayedSQL']) { - echo htmlspecialchars(substr($process['Info'], 0, $GLOBALS['cfg']['MaxCharactersInDisplayedSQL'])) . '[...]'; + $retval .= htmlspecialchars(substr($process['Info'], 0, $GLOBALS['cfg']['MaxCharactersInDisplayedSQL'])) . '[...]'; } else { - echo PMA_SQP_formatHtml(PMA_SQP_parse($process['Info'])); + $retval .= PMA_SQP_formatHtml(PMA_SQP_parse($process['Info'])); } } - ?> -
      - '; + $retval .= ''; -/** - * Prints html with monitor - * - * @return void - */ -function printMonitor() -{ - global $server_status, $server_db_isLocal; - -?> - - -
      - - - - - -
      -
      - '; - echo PMA_getRefreshList('gridChartRefresh', 5, Array(2, 3, 4, 5, 10, 20, 40, 60, 120, 300, 600, 1200)); - ?>
      -
      -
      -
      - -
      - -
      -
      -      -
      -
      - - - - - - - - - - - - - - - - -
      -
      -
      -
      - - - list for refresh rates - * - * @param string $name Name of select - * @param int $defaultRate Currently chosen rate - * @param array $refreshRates List of refresh rates - * - * @return HTML code with select - */ -function PMA_getRefreshList($name, - $defaultRate = 5, - $refreshRates = Array(1, 2, 5, 10, 20, 40, 60, 120, 300, 600) -) { - $return = ''; - return $return; -} - -/** - * Builds a '; - foreach ($values as $number) { - $selected = ($number == $defaultValue)?' selected="selected"':''; - $html_output .= ''; - } - - $html_output .= ''; - return $html_output; -} - -/** - * cleanup of some deprecated values - * - * @param array &$server_status status array to process - * - * @return void - */ -function cleanDeprecated(&$server_status) -{ - $deprecated = array( - 'Com_prepare_sql' => 'Com_stmt_prepare', - 'Com_execute_sql' => 'Com_stmt_execute', - 'Com_dealloc_sql' => 'Com_stmt_close', - ); - - foreach ($deprecated as $old => $new) { - if (isset($server_status[$old]) && isset($server_status[$new])) { - unset($server_status[$old]); - } - } + return $retval; } ?> diff --git a/server_status_advisor.php b/server_status_advisor.php index a697207077..1b79819e2b 100644 --- a/server_status_advisor.php +++ b/server_status_advisor.php @@ -9,13 +9,22 @@ require_once 'libraries/common.inc.php'; require_once 'libraries/Advisor.class.php'; require_once 'libraries/ServerStatusData.class.php'; +if (PMA_DRIZZLE) { + $server_master_status = false; + $server_slave_status = false; +} else { + include_once 'libraries/replication.inc.php'; + include_once 'libraries/replication_gui.lib.php'; +} + +$ServerStatusData = new PMA_ServerStatusData('server_status_advisor.php'); $response = PMA_Response::getInstance(); $scripts = $response->getHeader()->getScripts(); $scripts->addFile('server_status_advisor.js'); $output = '
      '; -$output .= PMA_ServerStatusData::getMenuHtml(); +$output .= $ServerStatusData->getMenuHtml(); $output .= ''; $output .= PMA_Util::getIcon('b_help.png', __('Instructions')); $output .= ''; diff --git a/server_status_monitor.php b/server_status_monitor.php new file mode 100644 index 0000000000..945313d609 --- /dev/null +++ b/server_status_monitor.php @@ -0,0 +1,733 @@ + $chartNodes) { + // For each data series + foreach ($chartNodes as $node_id => $nodeDataPoints) { + // For each data point in the series (usually just 1) + foreach ($nodeDataPoints as $point_id => $dataPoint) { + $pName = $dataPoint['name']; + + switch ($dataPoint['type']) { + /* We only collect the status and server variables here to + * read them all in one query, + * and only afterwards assign them. + * Also do some white list filtering on the names + */ + case 'servervar': + if (! preg_match('/[^a-zA-Z_]+/', $pName)) { + $serverVars[] = $pName; + } + break; + + case 'statusvar': + if (! preg_match('/[^a-zA-Z_]+/', $pName)) { + $statusVars[] = $pName; + } + break; + + case 'proc': + $result = PMA_DBI_query('SHOW PROCESSLIST'); + $ret[$chart_id][$node_id][$point_id]['value'] + = PMA_DBI_num_rows($result); + break; + + case 'cpu': + if (!$sysinfo) { + include_once 'libraries/sysinfo.lib.php'; + $sysinfo = PMA_getSysInfo(); + } + if (!$cpuload) { + $cpuload = $sysinfo->loadavg(); + } + + if (PMA_getSysInfoOs() == 'Linux') { + $ret[$chart_id][$node_id][$point_id]['idle'] + = $cpuload['idle']; + $ret[$chart_id][$node_id][$point_id]['busy'] + = $cpuload['busy']; + } else { + $ret[$chart_id][$node_id][$point_id]['value'] + = $cpuload['loadavg']; + } + + break; + + case 'memory': + if (!$sysinfo) { + include_once 'libraries/sysinfo.lib.php'; + $sysinfo = PMA_getSysInfo(); + } + if (!$memory) { + $memory = $sysinfo->memory(); + } + + $ret[$chart_id][$node_id][$point_id]['value'] + = $memory[$pName]; + break; + } /* switch */ + } /* foreach */ + } /* foreach */ + } /* foreach */ + + // Retrieve all required status variables + if (count($statusVars)) { + $statusVarValues = PMA_DBI_fetch_result( + "SHOW GLOBAL STATUS WHERE Variable_name='" + . implode("' OR Variable_name='", $statusVars) . "'", + 0, + 1 + ); + } else { + $statusVarValues = array(); + } + + // Retrieve all required server variables + if (count($serverVars)) { + $serverVarValues = PMA_DBI_fetch_result( + "SHOW GLOBAL VARIABLES WHERE Variable_name='" + . implode("' OR Variable_name='", $serverVars) . "'", + 0, + 1 + ); + } else { + $serverVarValues = array(); + } + + // ...and now assign them + foreach ($ret as $chart_id => $chartNodes) { + foreach ($chartNodes as $node_id => $nodeDataPoints) { + foreach ($nodeDataPoints as $point_id => $dataPoint) { + switch($dataPoint['type']) { + case 'statusvar': + $ret[$chart_id][$node_id][$point_id]['value'] + = $statusVarValues[$dataPoint['name']]; + break; + case 'servervar': + $ret[$chart_id][$node_id][$point_id]['value'] + = $serverVarValues[$dataPoint['name']]; + break; + } + } + } + } + + $ret['x'] = microtime(true) * 1000; + + exit(json_encode($ret)); + } + } + + if (isset($_REQUEST['log_data'])) { + if (PMA_MYSQL_INT_VERSION < 50106) { + // Table logging is only available since 5.1.6 + exit('""'); + } + + $start = intval($_REQUEST['time_start']); + $end = intval($_REQUEST['time_end']); + + if ($_REQUEST['type'] == 'slow') { + $q = 'SELECT start_time, user_host, '; + $q .= 'Sec_to_Time(Sum(Time_to_Sec(query_time))) as query_time, '; + $q .= 'Sec_to_Time(Sum(Time_to_Sec(lock_time))) as lock_time, '; + $q .= 'SUM(rows_sent) AS rows_sent, '; + $q .= 'SUM(rows_examined) AS rows_examined, db, sql_text, '; + $q .= 'COUNT(sql_text) AS \'#\' '; + $q .= 'FROM `mysql`.`slow_log` '; + $q .= 'WHERE start_time > FROM_UNIXTIME(' . $start . ') '; + $q .= 'AND start_time < FROM_UNIXTIME(' . $end . ') GROUP BY sql_text'; + + $result = PMA_DBI_try_query($q); + + $return = array('rows' => array(), 'sum' => array()); + $type = ''; + + while ($row = PMA_DBI_fetch_assoc($result)) { + $type = strtolower( + substr($row['sql_text'], 0, strpos($row['sql_text'], ' ')) + ); + + switch($type) { + case 'insert': + case 'update': + //Cut off big inserts and updates, but append byte count instead + if (strlen($row['sql_text']) > 220) { + $implode_sql_text = implode( + ' ', + PMA_Util::formatByteDown( + strlen($row['sql_text']), 2, 2 + ) + ); + $row['sql_text'] = substr($row['sql_text'], 0, 200) + . '... [' . $implode_sql_text . ']'; + } + break; + default: + break; + } + + if (! isset($return['sum'][$type])) { + $return['sum'][$type] = 0; + } + $return['sum'][$type] += $row['#']; + $return['rows'][] = $row; + } + + $return['sum']['TOTAL'] = array_sum($return['sum']); + $return['numRows'] = count($return['rows']); + + PMA_DBI_free_result($result); + + exit(json_encode($return)); + } + + if ($_REQUEST['type'] == 'general') { + $limitTypes = ''; + if (isset($_REQUEST['limitTypes']) && $_REQUEST['limitTypes']) { + $limitTypes + = 'AND argument REGEXP \'^(INSERT|SELECT|UPDATE|DELETE)\' '; + } + + $q = 'SELECT TIME(event_time) as event_time, user_host, thread_id, '; + $q .= 'server_id, argument, count(argument) as \'#\' '; + $q .= 'FROM `mysql`.`general_log` '; + $q .= 'WHERE command_type=\'Query\' '; + $q .= 'AND event_time > FROM_UNIXTIME(' . $start . ') '; + $q .= 'AND event_time < FROM_UNIXTIME(' . $end . ') '; + $q .= $limitTypes . 'GROUP by argument'; // HAVING count > 1'; + + $result = PMA_DBI_try_query($q); + + $return = array('rows' => array(), 'sum' => array()); + $type = ''; + $insertTables = array(); + $insertTablesFirst = -1; + $i = 0; + $removeVars = isset($_REQUEST['removeVariables']) + && $_REQUEST['removeVariables']; + + while ($row = PMA_DBI_fetch_assoc($result)) { + preg_match('/^(\w+)\s/', $row['argument'], $match); + $type = strtolower($match[1]); + + if (! isset($return['sum'][$type])) { + $return['sum'][$type] = 0; + } + $return['sum'][$type] += $row['#']; + + switch($type) { + case 'insert': + // Group inserts if selected + if ($removeVars + && preg_match( + '/^INSERT INTO (`|\'|"|)([^\s\\1]+)\\1/i', + $row['argument'], $matches + ) + ) { + $insertTables[$matches[2]]++; + if ($insertTables[$matches[2]] > 1) { + $return['rows'][$insertTablesFirst]['#'] + = $insertTables[$matches[2]]; + + // Add a ... to the end of this query to indicate that + // there's been other queries + $temp = $return['rows'][$insertTablesFirst]['argument']; + if ($temp[strlen($temp) - 1] != '.') { + $return['rows'][$insertTablesFirst]['argument'] + .= '
      ...'; + } + + // Group this value, thus do not add to the result list + continue 2; + } else { + $insertTablesFirst = $i; + $insertTables[$matches[2]] += $row['#'] - 1; + } + } + // No break here + + case 'update': + // Cut off big inserts and updates, + // but append byte count therefor + if (strlen($row['argument']) > 220) { + $row['argument'] = substr($row['argument'], 0, 200) + . '... [' + . implode( + ' ', + PMA_Util::formatByteDown( + strlen($row['argument']) + ), + 2, + 2 + ) + . ']'; + } + break; + + default: + break; + } + + $return['rows'][] = $row; + $i++; + } + + $return['sum']['TOTAL'] = array_sum($return['sum']); + $return['numRows'] = count($return['rows']); + + PMA_DBI_free_result($result); + + exit(json_encode($return)); + } + } + + if (isset($_REQUEST['logging_vars'])) { + if (isset($_REQUEST['varName']) && isset($_REQUEST['varValue'])) { + $value = PMA_Util::sqlAddSlashes($_REQUEST['varValue']); + if (! is_numeric($value)) { + $value="'" . $value . "'"; + } + + if (! preg_match("/[^a-zA-Z0-9_]+/", $_REQUEST['varName'])) { + PMA_DBI_query( + 'SET GLOBAL ' . $_REQUEST['varName'] . ' = ' . $value + ); + } + + } + + $loggingVars = PMA_DBI_fetch_result( + 'SHOW GLOBAL VARIABLES WHERE Variable_name IN' + . ' ("general_log","slow_query_log","long_query_time","log_output")', + 0, + 1 + ); + exit(json_encode($loggingVars)); + } + + if (isset($_REQUEST['query_analyzer'])) { + $return = array(); + + if (strlen($_REQUEST['database'])) { + PMA_DBI_select_db($_REQUEST['database']); + } + + if ($profiling = PMA_Util::profilingSupported()) { + PMA_DBI_query('SET PROFILING=1;'); + } + + // Do not cache query + $query = preg_replace( + '/^(\s*SELECT)/i', + '\\1 SQL_NO_CACHE', + $_REQUEST['query'] + ); + + $result = PMA_DBI_try_query($query); + $return['affectedRows'] = $GLOBALS['cached_affected_rows']; + + $result = PMA_DBI_try_query('EXPLAIN ' . $query); + while ($row = PMA_DBI_fetch_assoc($result)) { + $return['explain'][] = $row; + } + + // In case an error happened + $return['error'] = PMA_DBI_getError(); + + PMA_DBI_free_result($result); + + if ($profiling) { + $return['profiling'] = array(); + $result = PMA_DBI_try_query( + 'SELECT seq,state,duration FROM INFORMATION_SCHEMA.PROFILING' + . ' WHERE QUERY_ID=1 ORDER BY seq' + ); + while ($row = PMA_DBI_fetch_assoc($result)) { + $return['profiling'][]= $row; + } + PMA_DBI_free_result($result); + } + + exit(json_encode($return)); + } +} + +/** + * JS Includes + */ +$header = $response->getHeader(); +$scripts = $header->getScripts(); +$scripts->addFile('server_status_monitor.js'); +$scripts->addFile('jquery/jquery.tablesorter.js'); +$scripts->addFile('jquery/jquery.json-2.2.js'); +$scripts->addFile('jquery/jquery.sortableTable.js'); +$scripts->addFile('jquery/timepicker.js'); +/* < IE 9 doesn't support canvas natively */ +if (PMA_USR_BROWSER_AGENT == 'IE' && PMA_USR_BROWSER_VER < 9) { + $scripts->addFile('jqplot/excanvas.js'); +} +$scripts->addFile('canvg/canvg.js'); +// for charting +$scripts->addFile('jqplot/jquery.jqplot.js'); +$scripts->addFile('jqplot/plugins/jqplot.pieRenderer.js'); +$scripts->addFile('jqplot/plugins/jqplot.canvasTextRenderer.js'); +$scripts->addFile('jqplot/plugins/jqplot.canvasAxisLabelRenderer.js'); +$scripts->addFile('jqplot/plugins/jqplot.dateAxisRenderer.js'); +$scripts->addFile('jqplot/plugins/jqplot.highlighter.js'); +$scripts->addFile('jqplot/plugins/jqplot.cursor.js'); +$scripts->addFile('date.js'); + +/** + * start output + */ +$ServerStatusData = new PMA_ServerStatusData('server_status_monitor.php'); + +echo '
      '; +echo $ServerStatusData->getMenuHtml(); +echo getPrintMonitorHtml($ServerStatusData); +/** + * Define some data needed on the client side + */ +$input = ''; +echo '
      '; +echo sprintf($input, 'server_time', microtime(true) * 1000); +echo sprintf($input, 'server_os', PHP_OS); +echo sprintf($input, 'is_superuser', PMA_isSuperuser()); +echo sprintf($input, 'server_db_isLocal', $ServerStatusData->db_isLocal); +echo '
      '; +echo '
      '; +echo PMA_Util::showMySQLDocu('general-thread-states', 'general-thread-states'); +echo '
      '; +echo '
      '; +echo PMA_Util::showMySQLDocu('explain-output', 'explain-output'); +echo '
      '; +echo '
      '; + +exit; + +/** + * Prints html with monitor + * + * @return void + */ +function getPrintMonitorHtml($ServerStatusData) +{ + $retval = ''; + + $retval .= '
      '; + $retval .= ''; + $retval .= PMA_Util::getImage('b_chart.png') . __('Add chart'); + $retval .= ''; + $retval .= ''; + $retval .= PMA_Util::getImage('b_tblops.png') . __('Rearrange/edit charts'); + $retval .= ''; + $retval .= '
      '; + $retval .= '
      '; + $retval .= __('Refresh rate') . '
      '; + $retval .= PMA_getRefreshList( + 'gridChartRefresh', + 5, + Array(2, 3, 4, 5, 10, 20, 40, 60, 120, 300, 600, 1200) + ); + $retval .= '
      '; + $retval .= '
      '; + $retval .= '
      '; + $retval .= __('Chart columns'); + $retval .= '
      '; + $retval .= ''; + $retval .= '
      '; + $retval .= '
      '; + $retval .= '' . __('Chart arrangement') . ' '; + $retval .= PMA_Util::showHint( + __( + 'The arrangement of the charts is stored to the browsers local storage. ' + . 'You may want to export it if you have a complicated set up.' + ) + ); + $retval .= '
      '; + $retval .= ''; + $retval .= __('Import'); + $retval .= ''; + $retval .= '  '; + $retval .= ''; + $retval .= __('Export'); + $retval .= ''; + $retval .= '  '; + $retval .= ''; + $retval .= __('Reset to default'); + $retval .= ''; + $retval .= '
      '; + $retval .= '
      '; + + $retval .= ''; + + $retval .= ''; + + $retval .= ''; + + if (! PMA_DRIZZLE) { + $retval .= ''; + $retval .= ''; + } + + $retval .= '
      '; + $retval .= '
      '; + $retval .= '
      '; + $retval .= '
      '; + + $retval .= ''; + + return $retval; +} + +/** + * Builds a '; + foreach ($refreshRates as $rate) { + $selected = ($rate == $defaultRate)?' selected="selected"':''; + $return .= ''; + } + $return .= ''; + return $return; +} + +?> diff --git a/server_status_queries.php b/server_status_queries.php index 5ab6f0864b..37d7908859 100644 --- a/server_status_queries.php +++ b/server_status_queries.php @@ -16,7 +16,7 @@ if (PMA_DRIZZLE) { include_once 'libraries/replication_gui.lib.php'; } -$ServerStatusData = new PMA_ServerStatusData('server_status_qyuries.php'); +$ServerStatusData = new PMA_ServerStatusData('server_status_queries.php'); $response = PMA_Response::getInstance(); $header = $response->getHeader(); @@ -38,7 +38,7 @@ $scripts->addFile('jqplot/plugins/jqplot.cursor.js'); // Add the html content to the response $response->addHTML('
      '); -$response->addHTML(PMA_ServerStatusData::getMenuHtml()); +$response->addHTML($ServerStatusData->getMenuHtml()); $response->addHTML(getQueryStatisticsHtml($ServerStatusData)); $response->addHTML('
      '); exit; diff --git a/server_status_variables.php b/server_status_variables.php index 4314482313..d6d8a2a225 100644 --- a/server_status_variables.php +++ b/server_status_variables.php @@ -16,6 +16,22 @@ if (PMA_DRIZZLE) { include_once 'libraries/replication_gui.lib.php'; } +/** + * flush status variables if requested + */ +if (isset($_REQUEST['flush'])) { + $_flush_commands = array( + 'STATUS', + 'TABLES', + 'QUERY CACHE', + ); + + if (in_array($_REQUEST['flush'], $_flush_commands)) { + PMA_DBI_query('FLUSH ' . $_REQUEST['flush'] . ';'); + } + unset($_flush_commands); +} + $ServerStatusData = new PMA_ServerStatusData('server_status_variables.php'); $response = PMA_Response::getInstance(); @@ -24,7 +40,7 @@ $scripts = $header->getScripts(); $scripts->addFile('server_status_variables.js'); $response->addHTML('
      '); -$response->addHTML(PMA_ServerStatusData::getMenuHtml()); +$response->addHTML($ServerStatusData->getMenuHtml()); $response->addHTML(getFilterHtml($ServerStatusData)); $response->addHTML(getLinkSuggestionsHtml($ServerStatusData)); $response->addHTML(getVariablesTableHtml($ServerStatusData)); diff --git a/themes/original/css/common.css.php b/themes/original/css/common.css.php index 5dcd19e261..4221682db3 100644 --- a/themes/original/css/common.css.php +++ b/themes/original/css/common.css.php @@ -1017,10 +1017,6 @@ img.sortableIcon { white-space: nowrap; } -.jsfeature { - display: none; /* Made visible with js */ -} - /* Also used for the variables page */ fieldset#tableFilter { margin-bottom:1em; diff --git a/themes/pmahomme/css/common.css.php b/themes/pmahomme/css/common.css.php index 126c21e8f3..32a9a42b4e 100644 --- a/themes/pmahomme/css/common.css.php +++ b/themes/pmahomme/css/common.css.php @@ -1262,10 +1262,6 @@ img.sortableIcon { white-space: nowrap; } -.jsfeature { - display: none; /* Made visible with js */ -} - /* Also used for the variables page */ fieldset#tableFilter { margin-bottom: 1em; From 04549d2dcc93b177c4aeb44f0a6c81647013a47c Mon Sep 17 00:00:00 2001 From: Rouslan Placella Date: Thu, 6 Dec 2012 22:05:14 +0000 Subject: [PATCH 05/21] Restored server_status table sorter --- js/server_status_queries.js | 7 +++ js/server_status_sorter.js | 89 +++++++++++++++++++++++++++++++++++ js/server_status_variables.js | 7 +++ server_status_queries.php | 2 + server_status_variables.php | 2 + 5 files changed, 107 insertions(+) create mode 100644 js/server_status_sorter.js diff --git a/js/server_status_queries.js b/js/server_status_queries.js index 94838e5d13..b1b632165a 100644 --- a/js/server_status_queries.js +++ b/js/server_status_queries.js @@ -29,4 +29,11 @@ AJAX.registerOnload('server_status_queries.js', function() { } catch (exception) { // Could not load chart, no big deal... } + + /*** Table sort tooltip ***/ + PMA_createqTip( + $('table.sortable').children('thead').children('tr').has('th'), + PMA_messages['strSortHint'] + ); + initTableSorter('statustabs_queries'); }); diff --git a/js/server_status_sorter.js b/js/server_status_sorter.js new file mode 100644 index 0000000000..383cb8ac7f --- /dev/null +++ b/js/server_status_sorter.js @@ -0,0 +1,89 @@ +// TODO: tablesorter shouldn't sort already sorted columns +function initTableSorter(tabid) { + var $table, opts; + switch(tabid) { + case 'statustabs_queries': + $table = $('#serverstatusqueriesdetails'); + opts = { + sortList: [[3, 1]], + widgets: ['fast-zebra'], + headers: { + 1: { sorter: 'fancyNumber' }, + 2: { sorter: 'fancyNumber' } + } + }; + break; + case 'statustabs_allvars': + $table = $('#serverstatusvariables'); + opts = { + sortList: [[0, 0]], + widgets: ['fast-zebra'], + headers: { + 1: { sorter: 'withinSpanNumber' } + } + }; + break; + } + $table.tablesorter(opts); + $table.find('tr:first th') + .append(''); +} + +$(function () { + $.tablesorter.addParser({ + id: "fancyNumber", + is: function(s) { + return /^[0-9]?[0-9,\.]*\s?(k|M|G|T|%)?$/.test(s); + }, + format: function(s) { + var num = jQuery.tablesorter.formatFloat( + s.replace(PMA_messages['strThousandsSeparator'], '') + .replace(PMA_messages['strDecimalSeparator'], '.') + ); + + var factor = 1; + switch (s.charAt(s.length - 1)) { + case '%': factor = -2; break; + // Todo: Complete this list (as well as in the regexp a few lines up) + case 'k': factor = 3; break; + case 'M': factor = 6; break; + case 'G': factor = 9; break; + case 'T': factor = 12; break; + } + + return num * Math.pow(10, factor); + }, + type: "numeric" + }); + + $.tablesorter.addParser({ + id: "withinSpanNumber", + is: function(s) { + return /(.*)?<\/span>/); + return (res && res.length >= 3) ? res[2] : 0; + }, + type: "numeric" + }); + + // faster zebra widget: no row visibility check, faster css class switching, no cssChildRow check + $.tablesorter.addWidget({ + id: "fast-zebra", + format: function (table) { + if (table.config.debug) { + var time = new Date(); + } + $("tr:even", table.tBodies[0]) + .removeClass(table.config.widgetZebra.css[0]) + .addClass(table.config.widgetZebra.css[1]); + $("tr:odd", table.tBodies[0]) + .removeClass(table.config.widgetZebra.css[1]) + .addClass(table.config.widgetZebra.css[0]); + if (table.config.debug) { + $.tablesorter.benchmark("Applying Fast-Zebra widget", time); + } + } + }); +}); diff --git a/js/server_status_variables.js b/js/server_status_variables.js index 0676e11c51..a8c2e652a7 100644 --- a/js/server_status_variables.js +++ b/js/server_status_variables.js @@ -16,6 +16,13 @@ AJAX.registerTeardown('server_status_variables.js', function() { }); AJAX.registerOnload('server_status_variables.js', function() { + /*** Table sort tooltip ***/ + PMA_createqTip( + $('table.sortable').children('thead').children('tr').has('th'), + PMA_messages['strSortHint'] + ); + initTableSorter('statustabs_allvars'); + // Filters for status variables var textFilter = null; var alertFilter = $('#filterAlert').prop('checked'); diff --git a/server_status_queries.php b/server_status_queries.php index 37d7908859..8bec3c26c9 100644 --- a/server_status_queries.php +++ b/server_status_queries.php @@ -35,6 +35,8 @@ $scripts->addFile('jqplot/plugins/jqplot.canvasAxisLabelRenderer.js'); $scripts->addFile('jqplot/plugins/jqplot.dateAxisRenderer.js'); $scripts->addFile('jqplot/plugins/jqplot.highlighter.js'); $scripts->addFile('jqplot/plugins/jqplot.cursor.js'); +$scripts->addFile('jquery/jquery.tablesorter.js'); +$scripts->addFile('server_status_sorter.js'); // Add the html content to the response $response->addHTML('
      '); diff --git a/server_status_variables.php b/server_status_variables.php index d6d8a2a225..bb7b75168b 100644 --- a/server_status_variables.php +++ b/server_status_variables.php @@ -38,6 +38,8 @@ $response = PMA_Response::getInstance(); $header = $response->getHeader(); $scripts = $header->getScripts(); $scripts->addFile('server_status_variables.js'); +$scripts->addFile('jquery/jquery.tablesorter.js'); +$scripts->addFile('server_status_sorter.js'); $response->addHTML('
      '); $response->addHTML($ServerStatusData->getMenuHtml()); From 6a46a0163a4f0ef57549f410649a3a03e4539dcb Mon Sep 17 00:00:00 2001 From: Rouslan Placella Date: Thu, 6 Dec 2012 22:05:23 +0000 Subject: [PATCH 06/21] Typo --- js/server_status_monitor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/server_status_monitor.js b/js/server_status_monitor.js index 30f5ada5cb..734b022fa8 100644 --- a/js/server_status_monitor.js +++ b/js/server_status_monitor.js @@ -98,7 +98,7 @@ AJAX.registerOnload('server_status_monitor.js', function() { /**** Monitor charting implementation ****/ /* Saves the previous ajax response for differential values */ var oldChartData = null; - // Holds about to created chart + // Holds about to be created chart var newChart = null; var chartSpacing; From 885bc779ab72e8b386076472687dee56169e86fa Mon Sep 17 00:00:00 2001 From: Rouslan Placella Date: Thu, 6 Dec 2012 22:11:41 +0000 Subject: [PATCH 07/21] Use response class for output --- server_status_monitor.php | 40 +++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/server_status_monitor.php b/server_status_monitor.php index 945313d609..c266da065a 100644 --- a/server_status_monitor.php +++ b/server_status_monitor.php @@ -418,27 +418,35 @@ $scripts->addFile('date.js'); */ $ServerStatusData = new PMA_ServerStatusData('server_status_monitor.php'); -echo '
      '; -echo $ServerStatusData->getMenuHtml(); -echo getPrintMonitorHtml($ServerStatusData); /** * Define some data needed on the client side */ $input = ''; -echo '
      '; -echo sprintf($input, 'server_time', microtime(true) * 1000); -echo sprintf($input, 'server_os', PHP_OS); -echo sprintf($input, 'is_superuser', PMA_isSuperuser()); -echo sprintf($input, 'server_db_isLocal', $ServerStatusData->db_isLocal); -echo '
      '; -echo '
      '; -echo PMA_Util::showMySQLDocu('general-thread-states', 'general-thread-states'); -echo '
      '; -echo '
      '; -echo PMA_Util::showMySQLDocu('explain-output', 'explain-output'); -echo '
      '; -echo '
      '; +$form = '
      '; +$form .= sprintf($input, 'server_time', microtime(true) * 1000); +$form .= sprintf($input, 'server_os', PHP_OS); +$form .= sprintf($input, 'is_superuser', PMA_isSuperuser()); +$form .= sprintf($input, 'server_db_isLocal', $ServerStatusData->db_isLocal); +$form .= '
      '; +/** + * Define some links used on client side + */ +$links = '
      '; +$links .= PMA_Util::showMySQLDocu('general-thread-states', 'general-thread-states'); +$links .= '
      '; +$links .= '
      '; +$links .= PMA_Util::showMySQLDocu('explain-output', 'explain-output'); +$links .= '
      '; +/** + * Output + */ +$response->addHTML('
      '); +$response->addHTML($ServerStatusData->getMenuHtml()); +$response->addHTML(getPrintMonitorHtml($ServerStatusData)); +$response->addHTML($form); +$response->addHTML($links); +$response->addHTML('
      '); exit; /** From 6575eb5a612f791d927cf487af1298ff2530e3a5 Mon Sep 17 00:00:00 2001 From: Rouslan Placella Date: Fri, 7 Dec 2012 17:36:29 +0000 Subject: [PATCH 08/21] Don't json_encode server status monitor responses twice --- js/server_status_monitor.js | 30 +++++++++++++++++------------- server_status_monitor.php | 15 ++++++++++----- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/js/server_status_monitor.js b/js/server_status_monitor.js index 734b022fa8..84fe1b7d3f 100644 --- a/js/server_status_monitor.js +++ b/js/server_status_monitor.js @@ -756,8 +756,13 @@ AJAX.registerOnload('server_status_monitor.js', function() { $.get('server_status_monitor.php?' + PMA_commonParams.get('common_query'), vars, function(data) { - var logVars = $.parseJSON(data.message), - icon = PMA_getImage('s_success.png'), msg='', str=''; + var logVars; + if (data.success == true) { + logVars = data.message; + } else { + return serverResponseError(); + } + var icon = PMA_getImage('s_success.png'), msg='', str=''; if (logVars['general_log'] == 'ON') { if (logVars['slow_query_log'] == 'ON') { @@ -1403,9 +1408,9 @@ AJAX.registerOnload('server_status_monitor.js', function() { requiredData: $.toJSON(runtime.dataList) }, function(data) { var chartData; - try { - chartData = $.parseJSON(data.message); - } catch(err) { + if (data.success == true) { + chartData = data.message; + } else { return serverResponseError(); } var value, i = 0; @@ -1611,9 +1616,9 @@ AJAX.registerOnload('server_status_monitor.js', function() { }, function(data) { var logData; - try { - logData = $.parseJSON(data.message); - } catch(err) { + if (data.success == true) { + logData = data.message; + } else { return serverResponseError(); } @@ -2004,14 +2009,13 @@ AJAX.registerOnload('server_status_monitor.js', function() { query: codemirror_editor ? codemirror_editor.getValue() : $('#sqlquery').val(), database: db }, function(data) { - data = $.parseJSON(data.message); - var totalTime = 0; - - if (data.error) { + if (data.success == true) { + data = data.message; + } else { $('div#queryAnalyzerDialog div.placeHolder').html('
      ' + data.error + '
      '); return; } - + var totalTime = 0; // Float sux, I'll use table :( $('div#queryAnalyzerDialog div.placeHolder') .html('
      '); diff --git a/server_status_monitor.php b/server_status_monitor.php index c266da065a..331d71a532 100644 --- a/server_status_monitor.php +++ b/server_status_monitor.php @@ -149,7 +149,8 @@ if (isset($_REQUEST['ajax_request']) && $_REQUEST['ajax_request'] == true) { $ret['x'] = microtime(true) * 1000; - exit(json_encode($ret)); + PMA_Response::getInstance()->addJSON('message', $ret); + exit; } } @@ -214,7 +215,8 @@ if (isset($_REQUEST['ajax_request']) && $_REQUEST['ajax_request'] == true) { PMA_DBI_free_result($result); - exit(json_encode($return)); + PMA_Response::getInstance()->addJSON('message', $return); + exit; } if ($_REQUEST['type'] == 'general') { @@ -313,7 +315,8 @@ if (isset($_REQUEST['ajax_request']) && $_REQUEST['ajax_request'] == true) { PMA_DBI_free_result($result); - exit(json_encode($return)); + PMA_Response::getInstance()->addJSON('message', $return); + exit; } } @@ -338,7 +341,8 @@ if (isset($_REQUEST['ajax_request']) && $_REQUEST['ajax_request'] == true) { 0, 1 ); - exit(json_encode($loggingVars)); + PMA_Response::getInstance()->addJSON('message', $loggingVars); + exit; } if (isset($_REQUEST['query_analyzer'])) { @@ -384,7 +388,8 @@ if (isset($_REQUEST['ajax_request']) && $_REQUEST['ajax_request'] == true) { PMA_DBI_free_result($result); } - exit(json_encode($return)); + PMA_Response::getInstance()->addJSON('message', $return); + exit; } } From b8354b07a53f77a070c0480ec31ed085a11cd12e Mon Sep 17 00:00:00 2001 From: Rouslan Placella Date: Fri, 7 Dec 2012 17:36:50 +0000 Subject: [PATCH 09/21] Added missing js include --- server_status_monitor.php | 1 + 1 file changed, 1 insertion(+) diff --git a/server_status_monitor.php b/server_status_monitor.php index 331d71a532..b3fe099d4e 100644 --- a/server_status_monitor.php +++ b/server_status_monitor.php @@ -400,6 +400,7 @@ $header = $response->getHeader(); $scripts = $header->getScripts(); $scripts->addFile('server_status_monitor.js'); $scripts->addFile('jquery/jquery.tablesorter.js'); +$scripts->addFile('server_status_sorter.js'); $scripts->addFile('jquery/jquery.json-2.2.js'); $scripts->addFile('jquery/jquery.sortableTable.js'); $scripts->addFile('jquery/timepicker.js'); From 19437c442ffc390f81c2e27f4dac8b7d93ed34e4 Mon Sep 17 00:00:00 2001 From: Rouslan Placella Date: Sat, 8 Dec 2012 14:37:18 +0000 Subject: [PATCH 10/21] Dropped duplicate messages --- js/messages.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/js/messages.php b/js/messages.php index b713d6bf20..6e12d5781f 100644 --- a/js/messages.php +++ b/js/messages.php @@ -86,8 +86,6 @@ $js_messages['strQueryCacheUsed'] = __('Query cache used'); $js_messages['strSystemCPUUsage'] = __('System CPU Usage'); $js_messages['strSystemMemory'] = __('System memory'); $js_messages['strSystemSwap'] = __('System swap'); -$js_messages['strMiB'] = __('MiB'); -$js_messages['strKiB'] = __('KiB'); $js_messages['strAverageLoad'] = __('Average load'); $js_messages['strTotalMemory'] = __('Total memory'); From 9775d295da6de183b34a20162a50598aaebecc6d Mon Sep 17 00:00:00 2001 From: Rouslan Placella Date: Sat, 8 Dec 2012 14:44:28 +0000 Subject: [PATCH 11/21] Improved formatting and display of data in server status monitor --- js/jqplot/plugins/jqplot.byteFormatter.js | 37 +++++++++++ js/server_status_monitor.js | 78 ++++++++--------------- server_status_monitor.php | 7 +- 3 files changed, 67 insertions(+), 55 deletions(-) create mode 100644 js/jqplot/plugins/jqplot.byteFormatter.js diff --git a/js/jqplot/plugins/jqplot.byteFormatter.js b/js/jqplot/plugins/jqplot.byteFormatter.js new file mode 100644 index 0000000000..75c7a194be --- /dev/null +++ b/js/jqplot/plugins/jqplot.byteFormatter.js @@ -0,0 +1,37 @@ +/* global PMA_messages */ +(function($) { + "use strict"; + var formatByte = function (val, index) { + var units = [ + PMA_messages.strB, + PMA_messages.strKiB, + PMA_messages.strMiB, + PMA_messages.strGiB, + PMA_messages.strTiB, + PMA_messages.strPiB, + PMA_messages.strEiB + ]; + while (val >= 1024 && index <= 6) { + val /= 1024; + index++; + } + var format = '%.1f'; + if (Math.floor(val) === val) { + format = '%.0f'; + } + return $.jqplot.sprintf( + format + ' ' + units[index], val + ); + }; + $.jqplot.byteFormatter = function (index) { + index = index || 0; + return function (format, val) { + if (typeof val === 'number') { + val = parseFloat(val, 10) || 0; + return formatByte(val, index); + } else { + return String(val); + } + }; + }; +})(jQuery); diff --git a/js/server_status_monitor.js b/js/server_status_monitor.js index 84fe1b7d3f..2903a35127 100644 --- a/js/server_status_monitor.js +++ b/js/server_status_monitor.js @@ -261,13 +261,13 @@ AJAX.registerOnload('server_status_monitor.js', function() { 'swap': { title: PMA_messages['strSystemSwap'], series: [ - { label: PMA_messages['strUsedSwap'], fill:true, stackSeries: true}, { label: PMA_messages['strCachedSwap'], fill:true, stackSeries: true}, + { label: PMA_messages['strUsedSwap'], fill:true, stackSeries: true}, { label: PMA_messages['strFreeSwap'], fill:true, stackSeries: true} ], nodes: [ - { dataPoints: [{ type: 'memory', name: 'SwapUsed' }], valueDivisor: 1024 }, { dataPoints: [{ type: 'memory', name: 'SwapCached' }], valueDivisor: 1024 }, + { dataPoints: [{ type: 'memory', name: 'SwapUsed' }], valueDivisor: 1024 }, { dataPoints: [{ type: 'memory', name: 'SwapFree' }], valueDivisor: 1024 } ], maxYLabel: 0 @@ -1134,11 +1134,30 @@ AJAX.registerOnload('server_status_monitor.js', function() { } }, highlighter: { - show: true, - showTooltip: false + show: true, + showTooltip: true, + tooltipAxes: 'y', + useAxesFormatters: true } }; + if (settings.title === PMA_messages['strSystemCPUUsage']) { + settings.axes.yaxis.tickOptions = { + formatString: "%d %%" + }; + } else if (settings.title === PMA_messages['strSystemMemory'] + || settings.title === PMA_messages['strSystemSwap'] + ) { + settings.stackSeries = true; + settings.axes.yaxis.tickOptions = { + formatter: $.jqplot.byteFormatter(2) // MiB + }; + } else if (settings.title === PMA_messages['strTraffic']) { + settings.axes.yaxis.tickOptions = { + formatter: $.jqplot.byteFormatter(1) // KiB + }; + } + settings.series = chartObj.series; if ($('#' + 'gridchart' + runtime.chartAI).length == 0) { @@ -1204,37 +1223,9 @@ AJAX.registerOnload('server_status_monitor.js', function() { }); $('#gridchart' + runtime.chartAI).bind('jqplotMouseMove', function(ev, gridpos, datapos, neighbor, plot) { - - if (neighbor != null) { - if ($('#tooltip_box').length) { - $('#tooltip_box') - .css({ - left: ev.pageX + 15, - top: ev.pageY + 15, - padding:'5px' - }) - .fadeIn(); - } - var xVal = new Date(Math.ceil(neighbor.data[0])); - var xValHours = xVal.getHours(); - (xValHours < 10) ? (xValHours = "0" + xValHours) : ""; - - var xValMinutes = xVal.getMinutes(); - (xValMinutes < 10) ? (xValMinutes = "0" + xValMinutes) : ""; - - var xValSeconds = xVal.getSeconds(); - (xValSeconds < 10) ? (xValSeconds = "0" + xValSeconds) : ""; - - xVal = xValHours + ":" + xValMinutes + ":" + xValSeconds; - var s = '' + xVal + '
      ' + neighbor.data[1] + '
      '; - - $('#tooltip_box').html(s); - } - if (! drawTimeSpan) { return; } - if (selectionStartX != undefined) { $('#selection_box') .css({ @@ -1244,26 +1235,7 @@ AJAX.registerOnload('server_status_monitor.js', function() { } }); - - $('#gridchart' + runtime.chartAI).bind('jqplotMouseEnter', function(ev, gridpos, datapos, neighbor, plot) { - if ($('#tooltip_box').length) { - tooltipBox.remove(); - } - tooltipBox = $('
      '); - $(document.body).append(tooltipBox); - tooltipBox - .attr({id: 'tooltip_box'}) - .css({ - top: ev.pageY + 15, - left: ev.pageX + 15 - }) - .fadeIn(); - }); - $('#gridchart' + runtime.chartAI).bind('jqplotMouseLeave', function(ev, gridpos, datapos, neighbor, plot) { - if ($('#tooltip_box').length) { - tooltipBox.remove(); - } drawTimeSpan = false; }); @@ -1488,8 +1460,8 @@ AJAX.registerOnload('server_status_monitor.js', function() { // update chart options elem.chart['axes']['xaxis']['max'] = runtime.xmax; elem.chart['axes']['xaxis']['min'] = runtime.xmin; - elem.chart['axes']['yaxis']['max'] = Math.ceil(elem.maxYLabel*1.2); - elem.chart['axes']['yaxis']['tickInterval'] = Math.ceil(elem.maxYLabel*1.2)/5; + elem.chart['axes']['yaxis']['max'] = Math.ceil(elem.maxYLabel*1.1); + elem.chart['axes']['yaxis']['tickInterval'] = Math.ceil(elem.maxYLabel*1.2/5); i++; if (runtime.redrawCharts) { diff --git a/server_status_monitor.php b/server_status_monitor.php index b3fe099d4e..b0396c7053 100644 --- a/server_status_monitor.php +++ b/server_status_monitor.php @@ -398,9 +398,7 @@ if (isset($_REQUEST['ajax_request']) && $_REQUEST['ajax_request'] == true) { */ $header = $response->getHeader(); $scripts = $header->getScripts(); -$scripts->addFile('server_status_monitor.js'); $scripts->addFile('jquery/jquery.tablesorter.js'); -$scripts->addFile('server_status_sorter.js'); $scripts->addFile('jquery/jquery.json-2.2.js'); $scripts->addFile('jquery/jquery.sortableTable.js'); $scripts->addFile('jquery/timepicker.js'); @@ -417,8 +415,13 @@ $scripts->addFile('jqplot/plugins/jqplot.canvasAxisLabelRenderer.js'); $scripts->addFile('jqplot/plugins/jqplot.dateAxisRenderer.js'); $scripts->addFile('jqplot/plugins/jqplot.highlighter.js'); $scripts->addFile('jqplot/plugins/jqplot.cursor.js'); +$scripts->addFile('jqplot/plugins/jqplot.byteFormatter.js'); $scripts->addFile('date.js'); +$scripts->addFile('server_status_monitor.js'); +$scripts->addFile('server_status_sorter.js'); + + /** * start output */ From 8b6c4a14d6139b4b8e7e530603e9907402ff18e2 Mon Sep 17 00:00:00 2001 From: Rouslan Placella Date: Sat, 8 Dec 2012 15:06:05 +0000 Subject: [PATCH 12/21] Reordered series in linux memory monitor --- js/server_status_monitor.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/server_status_monitor.js b/js/server_status_monitor.js index 2903a35127..2d8dff2d21 100644 --- a/js/server_status_monitor.js +++ b/js/server_status_monitor.js @@ -245,15 +245,15 @@ AJAX.registerOnload('server_status_monitor.js', function() { 'memory': { title: PMA_messages['strSystemMemory'], series: [ + { label: PMA_messages['strBufferedMemory'], fill:true, stackSeries: true}, { label: PMA_messages['strUsedMemory'], fill:true, stackSeries: true}, { label: PMA_messages['strCachedMemory'], fill:true, stackSeries: true}, - { label: PMA_messages['strBufferedMemory'], fill:true, stackSeries: true}, { label: PMA_messages['strFreeMemory'], fill:true, stackSeries: true} ], nodes: [ + { dataPoints: [{ type: 'memory', name: 'Buffers' }], valueDivisor: 1024 }, { dataPoints: [{ type: 'memory', name: 'MemUsed' }], valueDivisor: 1024 }, { dataPoints: [{ type: 'memory', name: 'Cached' }], valueDivisor: 1024 }, - { dataPoints: [{ type: 'memory', name: 'Buffers' }], valueDivisor: 1024 }, { dataPoints: [{ type: 'memory', name: 'MemFree' }], valueDivisor: 1024 } ], maxYLabel: 0 From 7bda2bb6a45d225de7a2f0e233d02a816202510d Mon Sep 17 00:00:00 2001 From: Rouslan Placella Date: Sat, 8 Dec 2012 15:06:56 +0000 Subject: [PATCH 13/21] Don't scale the y axis for the cpu monitor --- js/server_status_monitor.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/js/server_status_monitor.js b/js/server_status_monitor.js index 2d8dff2d21..416f831781 100644 --- a/js/server_status_monitor.js +++ b/js/server_status_monitor.js @@ -192,7 +192,7 @@ AJAX.registerOnload('server_status_monitor.js', function() { nodes: [ { dataPoints: [{ type: 'cpu', name: 'loadavg'}] } ], - maxYLabel: 0 + maxYLabel: 100 }, 'memory': { @@ -1460,8 +1460,10 @@ AJAX.registerOnload('server_status_monitor.js', function() { // update chart options elem.chart['axes']['xaxis']['max'] = runtime.xmax; elem.chart['axes']['xaxis']['min'] = runtime.xmin; - elem.chart['axes']['yaxis']['max'] = Math.ceil(elem.maxYLabel*1.1); - elem.chart['axes']['yaxis']['tickInterval'] = Math.ceil(elem.maxYLabel*1.2/5); + if (elem.title !== PMA_messages['strSystemCPUUsage']) { + elem.chart['axes']['yaxis']['max'] = Math.ceil(elem.maxYLabel*1.1); + elem.chart['axes']['yaxis']['tickInterval'] = Math.ceil(elem.maxYLabel*1.2/5); + } i++; if (runtime.redrawCharts) { From 401cc842448c3d71bc5cf3fee31addc61b07264c Mon Sep 17 00:00:00 2001 From: Rouslan Placella Date: Sat, 8 Dec 2012 15:49:38 +0000 Subject: [PATCH 14/21] Remove unused options --- js/server_status_monitor.js | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/js/server_status_monitor.js b/js/server_status_monitor.js index 416f831781..0c7b3dbd78 100644 --- a/js/server_status_monitor.js +++ b/js/server_status_monitor.js @@ -199,13 +199,11 @@ AJAX.registerOnload('server_status_monitor.js', function() { title: PMA_messages['strSystemMemory'], series: [ { label: PMA_messages['strTotalMemory'], - fill:true, - stackSeries: true + fill:true }, { dataType: 'memory', label: PMA_messages['strUsedMemory'], - fill:true, - stackSeries: true + fill:true } ], nodes: [{ dataPoints: [{ type: 'memory', name: 'MemTotal' }], valueDivisor: 1024 }, { dataPoints: [{ type: 'memory', name: 'MemUsed' }], valueDivisor: 1024 } @@ -217,12 +215,10 @@ AJAX.registerOnload('server_status_monitor.js', function() { title: PMA_messages['strSystemSwap'], series: [ { label: PMA_messages['strTotalSwap'], - fill:true, - stackSeries: true + fill:true }, { label: PMA_messages['strUsedSwap'], - fill:true, - stackSeries: true + fill:true } ], nodes: [{ dataPoints: [{ type: 'memory', name: 'SwapTotal' }]}, { dataPoints: [{ type: 'memory', name: 'SwapUsed' }]} @@ -245,10 +241,10 @@ AJAX.registerOnload('server_status_monitor.js', function() { 'memory': { title: PMA_messages['strSystemMemory'], series: [ - { label: PMA_messages['strBufferedMemory'], fill:true, stackSeries: true}, - { label: PMA_messages['strUsedMemory'], fill:true, stackSeries: true}, - { label: PMA_messages['strCachedMemory'], fill:true, stackSeries: true}, - { label: PMA_messages['strFreeMemory'], fill:true, stackSeries: true} + { label: PMA_messages['strBufferedMemory'], fill:true}, + { label: PMA_messages['strUsedMemory'], fill:true}, + { label: PMA_messages['strCachedMemory'], fill:true}, + { label: PMA_messages['strFreeMemory'], fill:true} ], nodes: [ { dataPoints: [{ type: 'memory', name: 'Buffers' }], valueDivisor: 1024 }, @@ -261,9 +257,9 @@ AJAX.registerOnload('server_status_monitor.js', function() { 'swap': { title: PMA_messages['strSystemSwap'], series: [ - { label: PMA_messages['strCachedSwap'], fill:true, stackSeries: true}, - { label: PMA_messages['strUsedSwap'], fill:true, stackSeries: true}, - { label: PMA_messages['strFreeSwap'], fill:true, stackSeries: true} + { label: PMA_messages['strCachedSwap'], fill:true}, + { label: PMA_messages['strUsedSwap'], fill:true}, + { label: PMA_messages['strFreeSwap'], fill:true} ], nodes: [ { dataPoints: [{ type: 'memory', name: 'SwapCached' }], valueDivisor: 1024 }, @@ -290,8 +286,8 @@ AJAX.registerOnload('server_status_monitor.js', function() { 'memory': { title: PMA_messages['strSystemMemory'], series: [ - { label: PMA_messages['strUsedMemory'], fill:true, stackSeries: true}, - { label: PMA_messages['strFreeMemory'], fill:true, stackSeries: true} + { label: PMA_messages['strUsedMemory'], fill:true }, + { label: PMA_messages['strFreeMemory'], fill:true } ], nodes: [ { dataPoints: [{ type: 'memory', name: 'MemUsed' }], valueDivisor: 1024 }, @@ -302,8 +298,8 @@ AJAX.registerOnload('server_status_monitor.js', function() { 'swap': { title: PMA_messages['strSystemSwap'], series: [ - { label: PMA_messages['strUsedSwap'], fill:true, stackSeries: true}, - { label: PMA_messages['strFreeSwap'], fill:true, stackSeries: true} + { label: PMA_messages['strUsedSwap'], fill:true }, + { label: PMA_messages['strFreeSwap'], fill:true } ], nodes: [ { dataPoints: [{ type: 'memory', name: 'SwapUsed' }], valueDivisor: 1024 }, From 7769affc3615d04d6c116e92719b021f6a624040 Mon Sep 17 00:00:00 2001 From: Rouslan Placella Date: Sat, 8 Dec 2012 18:22:18 +0000 Subject: [PATCH 15/21] Fixed memory and swap chart y axis limits --- js/server_status_monitor.js | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/js/server_status_monitor.js b/js/server_status_monitor.js index 0c7b3dbd78..dc786c8960 100644 --- a/js/server_status_monitor.js +++ b/js/server_status_monitor.js @@ -1383,6 +1383,7 @@ AJAX.registerOnload('server_status_monitor.js', function() { } var value, i = 0; var diff; + var total; /* Update values in each graph */ $.each(runtime.charts, function(orderKey, elem) { @@ -1392,6 +1393,7 @@ AJAX.registerOnload('server_status_monitor.js', function() { return; } // Draw all series + total = 0; for (var j = 0; j < elem.nodes.length; j++) { // Update x-axis if (i == 0 && j == 0) { @@ -1450,15 +1452,28 @@ AJAX.registerOnload('server_status_monitor.js', function() { elem.chart.series[j].data.shift(); } } + if (elem.title === PMA_messages['strSystemMemory'] + || elem.title === PMA_messages['strSystemSwap'] + ) { + total += value; + } } } // update chart options elem.chart['axes']['xaxis']['max'] = runtime.xmax; elem.chart['axes']['xaxis']['min'] = runtime.xmin; - if (elem.title !== PMA_messages['strSystemCPUUsage']) { + if (elem.title !== PMA_messages['strSystemCPUUsage'] + && elem.title !== PMA_messages['strSystemMemory'] + && elem.title !== PMA_messages['strSystemSwap'] + ) { elem.chart['axes']['yaxis']['max'] = Math.ceil(elem.maxYLabel*1.1); - elem.chart['axes']['yaxis']['tickInterval'] = Math.ceil(elem.maxYLabel*1.2/5); + elem.chart['axes']['yaxis']['tickInterval'] = Math.ceil(elem.maxYLabel*1.1/5); + } else if (elem.title === PMA_messages['strSystemMemory'] + || elem.title === PMA_messages['strSystemSwap'] + ) { + elem.chart['axes']['yaxis']['max'] = Math.ceil(total * 1.1 / 100) * 100; + elem.chart['axes']['yaxis']['tickInterval'] = Math.ceil(total * 1.1 / 5); } i++; From a35532e21f64ffea05ee2a3bcd61d8029e1bcf4c Mon Sep 17 00:00:00 2001 From: Rouslan Placella Date: Sat, 8 Dec 2012 23:08:07 +0000 Subject: [PATCH 16/21] Improved display of query cache efficiency monitor chart --- js/server_status_monitor.js | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/js/server_status_monitor.js b/js/server_status_monitor.js index dc786c8960..a00ef4b5d4 100644 --- a/js/server_status_monitor.js +++ b/js/server_status_monitor.js @@ -51,7 +51,7 @@ AJAX.registerOnload('server_status_monitor.js', function() { AJAX.registerTeardown('server_status_monitor.js', function() { $('a[href="#rearrangeCharts"], a[href="#endChartEditMode"]').unbind('click'); $('div.popupContent select[name="chartColumns"]').unbind('change'); - $(' div.popupContent select[name="gridChartRefresh"]').unbind('change'); + $('div.popupContent select[name="gridChartRefresh"]').unbind('change'); $('a[href="#addNewChart"]').unbind('click'); $('a[href="#exportMonitorConfig"]').unbind('click'); $('a[href="#importMonitorConfig"]').unbind('click'); @@ -67,6 +67,8 @@ AJAX.registerTeardown('server_status_monitor.js', function() { $('a[href="#submitClearSeries"]').unbind('click'); $('a[href="#submitAddSeries"]').unbind('click'); // $("input#variableInput").destroy(); + $('#chartPreset').unbind('click'); + $('#chartStatusVar').unbind('click'); destroyGrid(); }); @@ -600,8 +602,25 @@ AJAX.registerOnload('server_status_monitor.js', function() { $presetList.append(''); }); $presetList.change(function() { - $('input#chartPreset').trigger('click'); - $('input[name="chartTitle"]').val(presetCharts[$(this).val()].title); + $('input[name="chartTitle"]').val( + $presetList.find(':selected').text() + ); + $('#chartPreset').prop('checked', true); + }) + $('#chartPreset').click(function () { + $('input[name="chartTitle"]').val( + $presetList.find(':selected').text() + ); + }); + $('#chartStatusVar').click(function () { + $('input[name="chartTitle"]').val( + $('#chartSeries').find(':selected').text().replace(/_/, " ") + ); + }); + $('#chartSeries').change(function () { + $('input[name="chartTitle"]').val( + $('#chartSeries').find(':selected').text().replace(/_/, " ") + ); }); } @@ -1137,7 +1156,8 @@ AJAX.registerOnload('server_status_monitor.js', function() { } }; - if (settings.title === PMA_messages['strSystemCPUUsage']) { + if (settings.title === PMA_messages['strSystemCPUUsage'] + || settings.title === PMA_messages['strQueryCacheEfficiency']) { settings.axes.yaxis.tickOptions = { formatString: "%d %%" }; @@ -1464,6 +1484,7 @@ AJAX.registerOnload('server_status_monitor.js', function() { elem.chart['axes']['xaxis']['max'] = runtime.xmax; elem.chart['axes']['xaxis']['min'] = runtime.xmin; if (elem.title !== PMA_messages['strSystemCPUUsage'] + && elem.title !== PMA_messages['strQueryCacheEfficiency'] && elem.title !== PMA_messages['strSystemMemory'] && elem.title !== PMA_messages['strSystemSwap'] ) { From 365e0491c5329da7d64087b914d14c180657d910 Mon Sep 17 00:00:00 2001 From: Rouslan Placella Date: Sat, 8 Dec 2012 23:26:19 +0000 Subject: [PATCH 17/21] Fixed axis labels overflow in server status monitor --- js/server_status_monitor.js | 1 + 1 file changed, 1 insertion(+) diff --git a/js/server_status_monitor.js b/js/server_status_monitor.js index a00ef4b5d4..79bf69300b 100644 --- a/js/server_status_monitor.js +++ b/js/server_status_monitor.js @@ -1192,6 +1192,7 @@ AJAX.registerOnload('server_status_monitor.js', function() { series.push([emptyArr]); } + $('#gridchart' + runtime.chartAI).css('overflow', 'hidden'); chartObj.chart = $.jqplot('gridchart' + runtime.chartAI, series, settings); if (initialize != true) { From 1b34379da9db0cc40673c7fe0a9d05353ef69afc Mon Sep 17 00:00:00 2001 From: Rouslan Placella Date: Sat, 8 Dec 2012 23:48:42 +0000 Subject: [PATCH 18/21] Added custom legend to status monitor charts The legend included in jqplot failed short of the expectations --- js/server_status_monitor.js | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/js/server_status_monitor.js b/js/server_status_monitor.js index 79bf69300b..5b75444e11 100644 --- a/js/server_status_monitor.js +++ b/js/server_status_monitor.js @@ -1192,8 +1192,29 @@ AJAX.registerOnload('server_status_monitor.js', function() { series.push([emptyArr]); } - $('#gridchart' + runtime.chartAI).css('overflow', 'hidden'); chartObj.chart = $.jqplot('gridchart' + runtime.chartAI, series, settings); + var $legend = $('
      ').css('padding', '0.5em'); + for (var i in chartObj.chart.series) { + $legend.append( + $('
      ').append( + $('
      ').css({ + width: '1em', + height: '1em', + background: chartObj.chart.seriesColors[i] + }).addClass('floatleft') + ).append( + $('
      ').text( + chartObj.chart.series[i].label + ).addClass('floatleft') + ).append( + $('
      ') + ).addClass('floatleft') + ); + } + $('#gridchart' + runtime.chartAI) + .css('overflow', 'hidden') + .parent() + .append($legend); if (initialize != true) { runtime.charts['c' + runtime.chartAI] = chartObj; From 0f317d4b56d560d3e77cb906fc087fca0068e223 Mon Sep 17 00:00:00 2001 From: Rouslan Placella Date: Sun, 9 Dec 2012 00:29:49 +0000 Subject: [PATCH 19/21] Removed redundant parameter --- libraries/ServerStatusData.class.php | 4 ++-- server_status.php | 2 +- server_status_monitor.php | 2 +- server_status_queries.php | 2 +- server_status_variables.php | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/ServerStatusData.class.php b/libraries/ServerStatusData.class.php index fc2cfa0ef8..35c28ab9a3 100644 --- a/libraries/ServerStatusData.class.php +++ b/libraries/ServerStatusData.class.php @@ -26,8 +26,8 @@ class PMA_ServerStatusData { // Discard everything } - public function __construct($selfUrl) { - $this->selfUrl = $selfUrl; + public function __construct() { + $this->selfUrl = basename($GLOBALS['PMA_PHP_SELF']); /** * get status from server */ diff --git a/server_status.php b/server_status.php index 6840941784..9d2e7ea649 100644 --- a/server_status.php +++ b/server_status.php @@ -21,7 +21,7 @@ if (PMA_DRIZZLE) { include_once 'libraries/replication_gui.lib.php'; } -$ServerStatusData = new PMA_ServerStatusData('server_status.php'); +$ServerStatusData = new PMA_ServerStatusData(); /** * Kills a selected process diff --git a/server_status_monitor.php b/server_status_monitor.php index b0396c7053..dff3a6c1bf 100644 --- a/server_status_monitor.php +++ b/server_status_monitor.php @@ -425,7 +425,7 @@ $scripts->addFile('server_status_sorter.js'); /** * start output */ -$ServerStatusData = new PMA_ServerStatusData('server_status_monitor.php'); +$ServerStatusData = new PMA_ServerStatusData(); /** * Define some data needed on the client side diff --git a/server_status_queries.php b/server_status_queries.php index 8bec3c26c9..fad2461d15 100644 --- a/server_status_queries.php +++ b/server_status_queries.php @@ -16,7 +16,7 @@ if (PMA_DRIZZLE) { include_once 'libraries/replication_gui.lib.php'; } -$ServerStatusData = new PMA_ServerStatusData('server_status_queries.php'); +$ServerStatusData = new PMA_ServerStatusData(); $response = PMA_Response::getInstance(); $header = $response->getHeader(); diff --git a/server_status_variables.php b/server_status_variables.php index bb7b75168b..06486ca8ea 100644 --- a/server_status_variables.php +++ b/server_status_variables.php @@ -32,7 +32,7 @@ if (isset($_REQUEST['flush'])) { unset($_flush_commands); } -$ServerStatusData = new PMA_ServerStatusData('server_status_variables.php'); +$ServerStatusData = new PMA_ServerStatusData(); $response = PMA_Response::getInstance(); $header = $response->getHeader(); From f7f15663e2b0e5221852a2e50ef5723071e440bc Mon Sep 17 00:00:00 2001 From: Rouslan Placella Date: Sun, 9 Dec 2012 00:30:30 +0000 Subject: [PATCH 20/21] There is no radix parameter in parseFloat --- js/jqplot/plugins/jqplot.byteFormatter.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/js/jqplot/plugins/jqplot.byteFormatter.js b/js/jqplot/plugins/jqplot.byteFormatter.js index 75c7a194be..68d2d8625b 100644 --- a/js/jqplot/plugins/jqplot.byteFormatter.js +++ b/js/jqplot/plugins/jqplot.byteFormatter.js @@ -23,11 +23,15 @@ format + ' ' + units[index], val ); }; + /** + * The index indicates what unit the incoming data will be in. + * 0 for bytes, 1 for kilobytes and so on... + */ $.jqplot.byteFormatter = function (index) { index = index || 0; return function (format, val) { if (typeof val === 'number') { - val = parseFloat(val, 10) || 0; + val = parseFloat(val) || 0; return formatByte(val, index); } else { return String(val); From fe95c8988d0616a5bb93805c9bcbf5c710b87e8e Mon Sep 17 00:00:00 2001 From: Rouslan Placella Date: Sun, 9 Dec 2012 23:42:31 +0000 Subject: [PATCH 21/21] phpcs fixes --- js/jqplot/plugins/jqplot.byteFormatter.js | 7 +++- libraries/ServerStatusData.class.php | 39 ++++++++++++++++---- server_status.php | 32 ++++++++++------- server_status_monitor.php | 22 ++++++++---- server_status_queries.php | 7 +++- server_status_variables.php | 44 ++++++++++++++++++----- 6 files changed, 115 insertions(+), 36 deletions(-) diff --git a/js/jqplot/plugins/jqplot.byteFormatter.js b/js/jqplot/plugins/jqplot.byteFormatter.js index 68d2d8625b..7a18370a75 100644 --- a/js/jqplot/plugins/jqplot.byteFormatter.js +++ b/js/jqplot/plugins/jqplot.byteFormatter.js @@ -1,4 +1,9 @@ -/* global PMA_messages */ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * jqplot formatter for byte values + * + * @package phpMyAdmin + */ (function($) { "use strict"; var formatByte = function (val, index) { diff --git a/libraries/ServerStatusData.class.php b/libraries/ServerStatusData.class.php index 35c28ab9a3..ddcc9d54dd 100644 --- a/libraries/ServerStatusData.class.php +++ b/libraries/ServerStatusData.class.php @@ -1,13 +1,27 @@ selfUrl = basename($GLOBALS['PMA_PHP_SELF']); /** * get status from server @@ -186,8 +212,9 @@ class PMA_ServerStatusData { if ($GLOBALS['server_master_status']) { $links['repl'][__('Show slave hosts')] - = 'sql.php?sql_query=' . urlencode('SHOW SLAVE HOSTS') . - '&goto=' . $this->selfUrl . '&' . PMA_generate_common_url(); + = 'sql.php?sql_query=' . urlencode('SHOW SLAVE HOSTS') + . '&goto=' . $this->selfUrl . '&' + . PMA_generate_common_url(); $links['repl'][__('Show master status')] = '#replication_master'; } if ($GLOBALS['server_slave_status']) { @@ -304,8 +331,6 @@ class PMA_ServerStatusData { /** * cleanup of some deprecated values * - * @param array $server_status status array to process - * * @return array */ public function getMenuHtml() diff --git a/server_status.php b/server_status.php index 9d2e7ea649..9cbd4b622e 100644 --- a/server_status.php +++ b/server_status.php @@ -1,7 +1,7 @@ '; - $retval .= '

      ' . __('Replication status') . '

      '; + $retval .= '

      '; + $retval .= __('Replication status'); + $retval .= '

      '; foreach ($GLOBALS['replication_types'] as $type) { if (${"server_{$type}_status"}) { PMA_replication_print_status_table($type); @@ -293,9 +297,13 @@ function getServerTrafficHtml($ServerStatusData) $show_full_sql = ! empty($_REQUEST['full']); if ($show_full_sql) { $url_params['full'] = 1; - $full_text_link = 'server_status.php' . PMA_generate_common_url(array(), 'html', '?'); + $full_text_link = 'server_status.php' . PMA_generate_common_url( + array(), 'html', '?' + ); } else { - $full_text_link = 'server_status.php' . PMA_generate_common_url(array('full' => 1)); + $full_text_link = 'server_status.php' . PMA_generate_common_url( + array('full' => 1) + ); } // This array contains display name and real column name of each @@ -380,15 +388,15 @@ function getServerTrafficHtml($ServerStatusData) && ! empty($_REQUEST['sort_order']) && ($_REQUEST['order_by_field'] == $column['order_by_field']); - $column['sort_order'] = ($is_sorted - && ($_REQUEST['sort_order'] == 'ASC')) - ? 'DESC' - : 'ASC'; + $column['sort_order'] = 'ASC'; + if ($is_sorted && $_REQUEST['sort_order'] === 'ASC') { + $column['sort_order'] = 'DESC'; + } if ($is_sorted) { if ($_REQUEST['sort_order'] == 'ASC') { - $asc_display_style = 'inline'; - $desc_display_style = 'none'; + $asc_display_style = 'inline'; + $desc_display_style = 'none'; } elseif ($_REQUEST['sort_order'] == 'DESC') { $desc_display_style = 'inline'; $asc_display_style = 'none'; @@ -475,7 +483,7 @@ function getServerTrafficHtml($ServerStatusData) if (empty($process['Info'])) { $retval .= '---'; } else { - if (!$show_full_sql && strlen($process['Info']) > $GLOBALS['cfg']['MaxCharactersInDisplayedSQL']) { + if (! $show_full_sql && strlen($process['Info']) > $GLOBALS['cfg']['MaxCharactersInDisplayedSQL']) { $retval .= htmlspecialchars(substr($process['Info'], 0, $GLOBALS['cfg']['MaxCharactersInDisplayedSQL'])) . '[...]'; } else { $retval .= PMA_SQP_formatHtml(PMA_SQP_parse($process['Info'])); diff --git a/server_status_monitor.php b/server_status_monitor.php index dff3a6c1bf..4cdd525bfa 100644 --- a/server_status_monitor.php +++ b/server_status_monitor.php @@ -1,7 +1,7 @@ '; $retval .= '

      '; $retval .= PMA_Util::getImage('s_attention.png'); @@ -607,7 +610,9 @@ function getPrintMonitorHtml($ServerStatusData) $retval .= ''; $retval .= '
      '; $retval .= ''; - $retval .= '
      '; + $retval .= '
      '; $retval .= '

      '; $retval .= '
      '; $retval .= ''; - $retval .= '(' . __('KiB') . ', ' . __('MiB') . ')'; + $retval .= '(' . __('KiB') . ', '; + $retval .= '' . __('MiB') . ')'; $retval .= '
      '; $retval .= ''; - $retval .= ''; + $retval .= ''; $retval .= ''; @@ -724,7 +732,7 @@ function getPrintMonitorHtml($ServerStatusData) * @param int $defaultRate Currently chosen rate * @param array $refreshRates List of refresh rates * - * @return HTML code with select + * @return string */ function PMA_getRefreshList($name, $defaultRate = 5, diff --git a/server_status_queries.php b/server_status_queries.php index fad2461d15..218878b2c8 100644 --- a/server_status_queries.php +++ b/server_status_queries.php @@ -1,6 +1,7 @@ '; $retval .= ''; - $retval .= htmlspecialchars(PMA_Util::formatNumber($value * $perc_factor, 0, 2)); + $retval .= htmlspecialchars( + PMA_Util::formatNumber($value * $perc_factor, 0, 2) + ); $retval .= ''; $retval .= ''; } diff --git a/server_status_variables.php b/server_status_variables.php index 06486ca8ea..ba1caaa884 100644 --- a/server_status_variables.php +++ b/server_status_variables.php @@ -1,6 +1,7 @@ addHTML('
      '); exit; +/** + * Returns the html for the list filter + * + * @param Object $ServerStatusData An instance of the PMA_ServerStatusData class + * + * @return string + */ function getFilterHtml($ServerStatusData) { - $filterAlert = ''; if (! empty($_REQUEST['filterAlert'])) { $filterAlert = ' checked="checked"'; @@ -88,7 +95,9 @@ function getFilterHtml($ServerStatusData) foreach ($ServerStatusData->sections as $section_id => $section_name) { if (isset($ServerStatusData->categoryUsed[$section_id])) { - if (! empty($_REQUEST['filterCategory']) && $_REQUEST['filterCategory'] == $section_id) { + if (! empty($_REQUEST['filterCategory']) + && $_REQUEST['filterCategory'] == $section_id + ) { $selected = ' selected="selected"'; } else { $selected = ''; @@ -111,10 +120,16 @@ function getFilterHtml($ServerStatusData) return $retval; } +/** + * Prints the suggestion links + * + * @param Object $ServerStatusData An instance of the PMA_ServerStatusData class + * + * @return string + */ function getLinkSuggestionsHtml($ServerStatusData) { - $retval = ''; - $retval .= '