368 lines
14 KiB
JavaScript
368 lines
14 KiB
JavaScript
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
|
/**
|
|
* @fileoverview functions used in server status pages
|
|
* @name Server Status
|
|
*
|
|
* @requires jQuery
|
|
* @requires jQueryUI
|
|
* @requires jQueryCookie
|
|
* @requires jQueryTablesorter
|
|
* @requires Highcharts
|
|
* @requires canvg
|
|
* @requires js/functions.js
|
|
*
|
|
*/
|
|
|
|
// Add a tablesorter parser to properly handle thousands seperated numbers and SI prefixes
|
|
$(function() {
|
|
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['strThousandsSeperator'],'').replace(PMA_messages['strDecimalSeperator'],'.') );
|
|
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"
|
|
});
|
|
});
|
|
|
|
$(function() {
|
|
// Filters for status variables
|
|
var textFilter=null;
|
|
var alertFilter = false;
|
|
var categoryFilter='';
|
|
var odd_row=false;
|
|
var text=''; // Holds filter text
|
|
|
|
/* 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();
|
|
|
|
// Add tabs
|
|
$('#serverStatusTabs').tabs({
|
|
// Tab persistence
|
|
cookie: { name: 'pma_serverStatusTabs', expires: 1 },
|
|
// Fixes line break in the menu bar when the page overflows and scrollbar appears
|
|
show: function() { menuResize(); }
|
|
});
|
|
|
|
// 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");
|
|
|
|
// Build query statistics chart
|
|
var cdata = new Array();
|
|
$.each(jQuery.parseJSON($('#serverstatusquerieschart').html()),function(key,value) {
|
|
cdata.push([key,parseInt(value)]);
|
|
});
|
|
|
|
PMA_createChart({
|
|
chart: {
|
|
renderTo: 'serverstatusquerieschart'
|
|
|
|
},
|
|
title: {
|
|
text:'',
|
|
margin:0
|
|
},
|
|
series: [{
|
|
type:'pie',
|
|
name: 'Query statistics',
|
|
data: cdata
|
|
}],
|
|
plotOptions: {
|
|
pie: {
|
|
allowPointSelect: true,
|
|
cursor: 'pointer',
|
|
dataLabels: {
|
|
enabled: true,
|
|
formatter: function() {
|
|
return '<b>'+ this.point.name +'</b><br> '+ Highcharts.numberFormat(this.percentage, 2) +' %';
|
|
}
|
|
}
|
|
}
|
|
},
|
|
tooltip: {
|
|
formatter: function() { return '<b>'+ this.point.name +'</b><br/>'+Highcharts.numberFormat(this.y, 2)+'<br/>('+Highcharts.numberFormat(this.percentage, 2) +' %)'; }
|
|
}
|
|
});
|
|
|
|
// Table sorting
|
|
initTableSorter('statustabs_queries');
|
|
initTableSorter('statustabs_allvars');
|
|
|
|
$('.statuslinks select').change(function() {
|
|
var chart=tabChart[$(this).parents('div.ui-tabs-panel').attr('id')];
|
|
chart.options.realtime.refreshRate = 1000*parseInt(this.value);
|
|
chart.xAxis[0].setExtremes(new Date().getTime() - chart.options.realtime.numMaxPoints * chart.options.realtime.refreshRate, chart.xAxis[0].getExtremes().max, true);
|
|
clearTimeout(chart_activeTimeouts[chart.options.chart.renderTo]);
|
|
chart_activeTimeouts[chart.options.chart.renderTo] = setTimeout(chart.options.realtime.timeoutCallBack, chart.options.realtime.refreshRate);
|
|
});
|
|
|
|
// Ajax refresh of variables (always the first link in each tab)
|
|
$('.statuslinks a:nth-child(2)').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 (always the second link) **/
|
|
$('.statuslinks a:nth-child(3)').click(function() {
|
|
// ui-tabs-panel class is added by the jquery tabs feature
|
|
var tab=$(this).parents('div.ui-tabs-panel');
|
|
|
|
if(tabStatus[tab.attr('id')]!='realtime') {
|
|
var series, title;
|
|
var settings = new Object();
|
|
|
|
switch(tab.attr('id')) {
|
|
case 'statustabs_traffic':
|
|
settings = {
|
|
series: [{name:'Connections since last refresh', data:[]},{name:'Processes', data:[]}],
|
|
title: {text:'Connections / Processes'},
|
|
realtime:{ url:'server_status.php?'+url_query,
|
|
type: 'proc',
|
|
callback: function(chartObj, curVal, lastVal,numLoadedPoints) {
|
|
if(lastVal==null) return;
|
|
chartObj.series[0].addPoint(
|
|
{ x:curVal.x, y:curVal.y_conn-lastVal.y_conn },
|
|
false, numLoadedPoints >= chartObj.options.realtime.numMaxPoints
|
|
);
|
|
chartObj.series[1].addPoint(
|
|
{ x:curVal.x, y:curVal.y_proc },
|
|
true, numLoadedPoints >= chartObj.options.realtime.numMaxPoints
|
|
);
|
|
}
|
|
}
|
|
};
|
|
break;
|
|
case 'statustabs_queries':
|
|
settings = {
|
|
series: [{name:'Issued queries since last refresh', data:[]}],
|
|
title: {text:'Issued queries'},
|
|
tooltip: { formatter:function() { return this.point.name; } },
|
|
realtime:{ url:'server_status.php?'+url_query,
|
|
type: 'queries',
|
|
callback: function(chartObj, curVal, lastVal,numLoadedPoints) {
|
|
if(lastVal==null) return;
|
|
chartObj.series[0].addPoint(
|
|
{ x:curVal.x, y:curVal.y-lastVal.y, name:sortedQueriesPointInfo(curVal,lastVal) },
|
|
true, numLoadedPoints >= chartObj.options.realtime.numMaxPoints
|
|
);
|
|
}
|
|
}
|
|
};
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
|
|
if(!settings.chart) settings.chart = {};
|
|
settings.chart.renderTo=tab.attr('id')+"_chart_cnt";
|
|
|
|
tab.find('.tabInnerContent')
|
|
.hide()
|
|
.after('<div style="clear:both; min-width:500px; height:400px; padding-bottom:80px;" id="'+tab.attr('id')+'_chart_cnt"></div>');
|
|
tabStatus[tab.attr('id')]='realtime';
|
|
tabChart[tab.attr('id')]=PMA_createChart(settings);
|
|
$(this).html(PMA_messages['strStaticData']);
|
|
tab.find('.statuslinks a:nth-child(2)').hide();
|
|
$('.statuslinks select').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')]='data';
|
|
tabChart[tab.attr('id')].destroy();
|
|
$(this).html(PMA_messages['strRealtimeChart']);
|
|
tab.find('.statuslinks a:nth-child(2)').show();
|
|
$('.statuslinks select').hide();
|
|
}
|
|
return false;
|
|
});
|
|
|
|
|
|
/* 3 Filtering functions */
|
|
$('#filterAlert').change(function() {
|
|
alertFilter = this.checked;
|
|
filterVariables();
|
|
});
|
|
|
|
$('#filterText').keyup(function(e) {
|
|
if($(this).val().length==0) textFilter=null;
|
|
else textFilter = new RegExp("(^|_)"+$(this).val(),'i');
|
|
text=$(this).val();
|
|
filterVariables();
|
|
});
|
|
|
|
$('#filterCategory').change(function() {
|
|
categoryFilter = $(this).val();
|
|
filterVariables();
|
|
});
|
|
|
|
/* Adjust DOM / Add handlers to the tabs */
|
|
function initTab(tab,data) {
|
|
switch(tab.attr('id')) {
|
|
case 'statustabs_traffic':
|
|
tab.find('.tabInnerContent').html(data);
|
|
initTooltips();
|
|
break;
|
|
case 'statustabs_queries':
|
|
tab.find('.tabInnerContent').html(data);
|
|
break;
|
|
case 'statustabs_allvars':
|
|
tab.find('.tabInnerContent').html(data);
|
|
filterVariables();
|
|
break;
|
|
}
|
|
|
|
initTableSorter(tab.attr('id'));
|
|
}
|
|
|
|
function initTableSorter(tabid) {
|
|
switch(tabid) {
|
|
case 'statustabs_queries':
|
|
$('#serverstatusqueriesdetails').tablesorter({
|
|
sortList: [[3,1]],
|
|
widgets: ['zebra'],
|
|
headers: {
|
|
1: { sorter: 'fancyNumber' },
|
|
2: { sorter: 'fancyNumber' }
|
|
}
|
|
});
|
|
|
|
$('#serverstatusqueriesdetails tr:first th')
|
|
.append('<img class="sortableIcon" src="'+pma_theme_image+'cleardot.gif" alt="">');
|
|
|
|
break;
|
|
|
|
case 'statustabs_allvars':
|
|
$('#serverstatusvariables').tablesorter({
|
|
sortList: [[0,0]],
|
|
widgets: ['zebra'],
|
|
headers: {
|
|
1: { sorter: 'fancyNumber' }
|
|
}
|
|
});
|
|
|
|
$('#serverstatusvariables tr:first th')
|
|
.append('<img class="sortableIcon" src="'+pma_theme_image+'cleardot.gif" alt="">');
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* 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;
|
|
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 = '<b>' + PMA_messages['strTotal'] + ': ' + sumTotal + '</b><br>';
|
|
|
|
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] + '<br>';
|
|
|
|
queryKeys.splice(maxIdx,1);
|
|
queryValues.splice(maxIdx,1);
|
|
num++;
|
|
}
|
|
|
|
if(sumOther>0)
|
|
pointInfo += PMA_messages['strOther'] + ': ' + sumOther;
|
|
|
|
return pointInfo;
|
|
}
|
|
|
|
}); |