Replace jqPlot with Chart.js for the profiling chart
Signed-off-by: Maurício Meneghini Fauth <mauricio@fauth.dev>
This commit is contained in:
parent
f22985ab15
commit
6cda25211e
@ -5,7 +5,6 @@ import { Navigation } from './modules/navigation.ts';
|
||||
import { CommonParams } from './modules/common.ts';
|
||||
import highlightSql from './modules/sql-highlight.ts';
|
||||
import { ajaxRemoveMessage, ajaxShowMessage } from './modules/ajax-message.ts';
|
||||
import createProfilingChart from './modules/functions/createProfilingChart.ts';
|
||||
import { escapeHtml } from './modules/functions/escape.ts';
|
||||
import refreshMainContent from './modules/functions/refreshMainContent.ts';
|
||||
import isStorageSupported from './modules/functions/isStorageSupported.ts';
|
||||
@ -1323,27 +1322,45 @@ AJAX.registerOnload('sql.js', function () {
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Profiling Chart
|
||||
*/
|
||||
function makeProfilingChart () {
|
||||
if ($('#profilingchart').length === 0 ||
|
||||
$('#profilingchart').html().length !== 0 ||
|
||||
! $.jqplot || ! $.jqplot.Highlighter || ! $.jqplot.PieRenderer
|
||||
) {
|
||||
function buildProfilingChart () {
|
||||
const profilingChartCanvas = document.getElementById('profilingChartCanvas') as HTMLCanvasElement;
|
||||
if (! profilingChartCanvas) {
|
||||
return;
|
||||
}
|
||||
|
||||
var data = [];
|
||||
$.each(JSON.parse($('#profilingChartData').html()), function (key, value) {
|
||||
data.push([key, parseFloat(value)]);
|
||||
const chartDataJson = profilingChartCanvas.getAttribute('data-chart-data');
|
||||
let chartData = null;
|
||||
try {
|
||||
chartData = JSON.parse(chartDataJson);
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (! (chartData && 'labels' in chartData && 'data' in chartData)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const lang = CommonParams.get('lang');
|
||||
const numberFormat = new Intl.NumberFormat(lang.replace('_', '-'), {
|
||||
style: 'unit',
|
||||
unit: 'second',
|
||||
unitDisplay: 'long',
|
||||
notation: 'engineering',
|
||||
});
|
||||
|
||||
// Remove chart and data divs contents
|
||||
$('#profilingchart').html('').show();
|
||||
$('#profilingChartData').html('');
|
||||
|
||||
createProfilingChart('profilingchart', data);
|
||||
new window.Chart(profilingChartCanvas, {
|
||||
type: 'pie',
|
||||
data: {
|
||||
labels: chartData.labels,
|
||||
datasets: [{ data: chartData.data }],
|
||||
},
|
||||
options: {
|
||||
plugins: {
|
||||
legend: { position: 'bottom' },
|
||||
tooltip: { callbacks: { label: context => context.parsed ? numberFormat.format(context.parsed) : '' } },
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1390,8 +1407,8 @@ function initProfilingTables () {
|
||||
}
|
||||
|
||||
AJAX.registerOnload('sql.js', function () {
|
||||
Sql.makeProfilingChart();
|
||||
Sql.initProfilingTables();
|
||||
buildProfilingChart();
|
||||
});
|
||||
|
||||
const Sql = {
|
||||
@ -1407,7 +1424,6 @@ const Sql = {
|
||||
browseForeignDialog: browseForeignDialog,
|
||||
getAutoSavedKey: getAutoSavedKey,
|
||||
checkSavedQuery: checkSavedQuery,
|
||||
makeProfilingChart: makeProfilingChart,
|
||||
initProfilingTables: initProfilingTables,
|
||||
};
|
||||
|
||||
|
||||
@ -644,7 +644,8 @@ class Generator
|
||||
$retval .= '<div class="card-footer tools d-print-none">' . "\n";
|
||||
$retval .= '<div class="row align-items-center">' . "\n";
|
||||
$retval .= '<div class="col-auto">' . "\n";
|
||||
$retval .= '<form action="' . Url::getFromRoute('/sql') . '" method="post" class="disableAjax">' . "\n";
|
||||
$retval .= '<form action="' . Url::getFromRoute('/sql', ['db' => $GLOBALS['db'], 'table' => $GLOBALS['table']])
|
||||
. '" method="post" class="disableAjax">' . "\n";
|
||||
$retval .= Url::getHiddenInputs($GLOBALS['db'], $GLOBALS['table']) . "\n";
|
||||
$retval .= '<input type="hidden" name="sql_query" value="'
|
||||
. htmlspecialchars($sqlQuery) . '">' . "\n";
|
||||
|
||||
@ -73,10 +73,7 @@ final class Profiling
|
||||
|
||||
$scripts = $response->getHeader()->getScripts();
|
||||
$scripts->addFiles([
|
||||
'chart.js',
|
||||
'vendor/jqplot/jquery.jqplot.js',
|
||||
'vendor/jqplot/plugins/jqplot.pieRenderer.js',
|
||||
'vendor/jqplot/plugins/jqplot.highlighter.js',
|
||||
'vendor/chart.umd.js',
|
||||
'vendor/jquery/jquery.tablesorter.js',
|
||||
]);
|
||||
}
|
||||
|
||||
@ -27,6 +27,7 @@ use function __;
|
||||
use function array_column;
|
||||
use function array_keys;
|
||||
use function array_sum;
|
||||
use function arsort;
|
||||
use function bin2hex;
|
||||
use function ceil;
|
||||
use function count;
|
||||
@ -251,7 +252,7 @@ class Sql
|
||||
* @psalm-return array{
|
||||
* total_time: float,
|
||||
* states: array<string, array{total_time: float, calls: int<1, max>}>,
|
||||
* chart: array<string, float>,
|
||||
* chart: array{labels: list<string>, data: list<float>},
|
||||
* profile: list<array{status: string, duration: string, duration_raw: numeric-string}>
|
||||
* }|array{}
|
||||
*/
|
||||
@ -263,7 +264,6 @@ class Sql
|
||||
}
|
||||
|
||||
$states = [];
|
||||
$chart = [];
|
||||
$profile = [];
|
||||
foreach ($profilingResults as $result) {
|
||||
$status = ucwords($result['Status']);
|
||||
@ -275,14 +275,15 @@ class Sql
|
||||
|
||||
if (! isset($states[$status])) {
|
||||
$states[$status] = ['total_time' => (float) $result['Duration'], 'calls' => 1];
|
||||
$chart[$status] = (float) $result['Duration'];
|
||||
} else {
|
||||
$states[$status]['calls']++;
|
||||
$states[$status]['total_time'] += $result['Duration'];
|
||||
$chart[$status] += $result['Duration'];
|
||||
}
|
||||
}
|
||||
|
||||
arsort($states);
|
||||
$chart = ['labels' => array_keys($states), 'data' => array_column($states, 'total_time')];
|
||||
|
||||
return ['total_time' => $totalTime, 'states' => $states, 'chart' => $chart, 'profile' => $profile];
|
||||
}
|
||||
|
||||
|
||||
@ -566,22 +566,6 @@ div {
|
||||
|
||||
// end serverstatus
|
||||
|
||||
// profiling
|
||||
|
||||
div#profilingchart {
|
||||
width: 850px;
|
||||
height: 370px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
#profilingchart .jqplot-highlighter-tooltip {
|
||||
top: auto !important;
|
||||
left: 11px;
|
||||
bottom: 24px;
|
||||
}
|
||||
|
||||
// end profiling
|
||||
|
||||
// table charting
|
||||
#resizer {
|
||||
border: 1px solid silver;
|
||||
|
||||
@ -817,16 +817,6 @@ div {
|
||||
|
||||
/* end serverstatus */
|
||||
|
||||
/* profiling */
|
||||
|
||||
div#profilingchart {
|
||||
width: 850px;
|
||||
height: 370px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
/* END profiling */
|
||||
|
||||
/* table charting */
|
||||
|
||||
#resizer {
|
||||
|
||||
@ -577,19 +577,6 @@ div#logTable {
|
||||
padding-left: 7px;
|
||||
}
|
||||
|
||||
/* profiling */
|
||||
div#profilingchart {
|
||||
width: 850px;
|
||||
height: 370px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
#profilingchart .jqplot-highlighter-tooltip {
|
||||
top: auto !important;
|
||||
left: 11px;
|
||||
bottom: 24px;
|
||||
}
|
||||
|
||||
textarea {
|
||||
&#sqlquery {
|
||||
width: 100%;
|
||||
|
||||
@ -752,22 +752,6 @@ div {
|
||||
|
||||
// end serverstatus
|
||||
|
||||
// profiling
|
||||
|
||||
div#profilingchart {
|
||||
width: 850px;
|
||||
height: 370px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
#profilingchart .jqplot-highlighter-tooltip {
|
||||
top: auto !important;
|
||||
left: 11px;
|
||||
bottom: 24px;
|
||||
}
|
||||
|
||||
// end profiling
|
||||
|
||||
// table charting
|
||||
#resizer {
|
||||
border: 1px solid silver;
|
||||
|
||||
@ -63,17 +63,9 @@
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<div id="profilingChartData" class="hide">{{ profiling.chart|json_encode() }}</div>
|
||||
<div id="profilingchart" class="hide"></div>
|
||||
<canvas id="profilingChartCanvas" data-chart-data="{{ profiling.chart|json_encode|e('html_attr') }}" aria-label="{{ 'Pie chart with profiling results.'|trans }}" role="img"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
window.AJAX.registerOnload('sql.js', function () {
|
||||
Sql.makeProfilingChart();
|
||||
Sql.initProfilingTables();
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
|
||||
@ -494,7 +494,7 @@ SELECT 1;
|
||||
<div class="card-footer tools d-print-none">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-auto">
|
||||
<form action="index.php?route=/sql&server=2&lang=en" method="post" class="disableAjax">
|
||||
<form action="index.php?route=/sql&db=test_db&table=test_table&server=2&lang=en" method="post" class="disableAjax">
|
||||
<input type="hidden" name="db" value="test_db"><input type="hidden" name="table" value="test_table"><input type="hidden" name="server" value="2"><input type="hidden" name="lang" value="en"><input type="hidden" name="token" value="token">
|
||||
<input type="hidden" name="sql_query" value="SELECT 1;">
|
||||
<input type="hidden" name="profiling_form" value="1">
|
||||
@ -546,7 +546,7 @@ $sql = "EXPLAIN SELECT 1;";
|
||||
<div class="card-footer tools d-print-none">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-auto">
|
||||
<form action="index.php?route=/sql&server=2&lang=en" method="post" class="disableAjax">
|
||||
<form action="index.php?route=/sql&db=test_db&table=test_table&server=2&lang=en" method="post" class="disableAjax">
|
||||
<input type="hidden" name="db" value="test_db"><input type="hidden" name="table" value="test_table"><input type="hidden" name="server" value="2"><input type="hidden" name="lang" value="en"><input type="hidden" name="token" value="token">
|
||||
<input type="hidden" name="sql_query" value="EXPLAIN SELECT 1;">
|
||||
</form></div>
|
||||
|
||||
@ -666,50 +666,75 @@ class SqlTest extends AbstractTestCase
|
||||
$expected = [
|
||||
'total_time' => 0.000299,
|
||||
'states' => [
|
||||
'Starting' => ['total_time' => 0.000017, 'calls' => 1],
|
||||
'Checking Permissions' => ['total_time' => 0.000003, 'calls' => 1],
|
||||
'Opening Tables' => ['total_time' => 0.00016, 'calls' => 2],
|
||||
'After Opening Tables' => ['total_time' => 0.000006, 'calls' => 2],
|
||||
'System Lock' => ['total_time' => 0.000004, 'calls' => 2],
|
||||
'Sending Data' => ['total_time' => 0.000029, 'calls' => 1],
|
||||
'Starting' => ['total_time' => 0.000017, 'calls' => 1],
|
||||
'Table Lock' => ['total_time' => 0.000015, 'calls' => 2],
|
||||
'Unlocking Tables' => ['total_time' => 0.000004, 'calls' => 2],
|
||||
'Closing Tables' => ['total_time' => 0.000009, 'calls' => 3],
|
||||
'Reset For Next Command' => ['total_time' => 0.000009, 'calls' => 1],
|
||||
'Init' => ['total_time' => 0.000007, 'calls' => 1],
|
||||
'Optimizing' => ['total_time' => 0.000004, 'calls' => 1],
|
||||
'Updating Status' => ['total_time' => 0.000007, 'calls' => 1],
|
||||
'After Opening Tables' => ['total_time' => 0.000006, 'calls' => 2],
|
||||
'Statistics' => ['total_time' => 0.000006, 'calls' => 1],
|
||||
'Preparing' => ['total_time' => 0.000006, 'calls' => 1],
|
||||
'Executing' => ['total_time' => 0.000002, 'calls' => 1],
|
||||
'Sending Data' => ['total_time' => 0.000029, 'calls' => 1],
|
||||
'System Lock' => ['total_time' => 0.000004, 'calls' => 2],
|
||||
'Unlocking Tables' => ['total_time' => 0.000004, 'calls' => 2],
|
||||
'Optimizing' => ['total_time' => 0.000004, 'calls' => 1],
|
||||
'Checking Permissions' => ['total_time' => 0.000003, 'calls' => 1],
|
||||
'End Of Update Loop' => ['total_time' => 0.000003, 'calls' => 1],
|
||||
'Executing' => ['total_time' => 0.000002, 'calls' => 1],
|
||||
'Query End' => ['total_time' => 0.000002, 'calls' => 1],
|
||||
'Commit' => ['total_time' => 0.000002, 'calls' => 1],
|
||||
'Starting Cleanup' => ['total_time' => 0.000002, 'calls' => 1],
|
||||
'Freeing Items' => ['total_time' => 0.000002, 'calls' => 1],
|
||||
'Updating Status' => ['total_time' => 0.000007, 'calls' => 1],
|
||||
'Reset For Next Command' => ['total_time' => 0.000009, 'calls' => 1],
|
||||
],
|
||||
'chart' => [
|
||||
'Starting' => 0.000017,
|
||||
'Checking Permissions' => 0.000003,
|
||||
'Opening Tables' => 0.00016,
|
||||
'After Opening Tables' => 0.000006,
|
||||
'System Lock' => 0.000004,
|
||||
'Table Lock' => 0.000015,
|
||||
'Unlocking Tables' => 0.000004,
|
||||
'Closing Tables' => 0.000009,
|
||||
'Init' => 0.000007,
|
||||
'Optimizing' => 0.000004,
|
||||
'Statistics' => 0.000006,
|
||||
'Preparing' => 0.000006,
|
||||
'Executing' => 0.000002,
|
||||
'Sending Data' => 0.000029,
|
||||
'End Of Update Loop' => 0.000003,
|
||||
'Query End' => 0.000002,
|
||||
'Commit' => 0.000002,
|
||||
'Starting Cleanup' => 0.000002,
|
||||
'Freeing Items' => 0.000002,
|
||||
'Updating Status' => 0.000007,
|
||||
'Reset For Next Command' => 0.000009,
|
||||
'labels' => [
|
||||
'Opening Tables',
|
||||
'Sending Data',
|
||||
'Starting',
|
||||
'Table Lock',
|
||||
'Closing Tables',
|
||||
'Reset For Next Command',
|
||||
'Init',
|
||||
'Updating Status',
|
||||
'After Opening Tables',
|
||||
'Statistics',
|
||||
'Preparing',
|
||||
'System Lock',
|
||||
'Unlocking Tables',
|
||||
'Optimizing',
|
||||
'Checking Permissions',
|
||||
'End Of Update Loop',
|
||||
'Executing',
|
||||
'Query End',
|
||||
'Commit',
|
||||
'Starting Cleanup',
|
||||
'Freeing Items',
|
||||
],
|
||||
'data' => [
|
||||
0.00016,
|
||||
0.000029,
|
||||
0.000017,
|
||||
0.000015,
|
||||
0.000009,
|
||||
0.000009,
|
||||
0.000007,
|
||||
0.000007,
|
||||
0.000006,
|
||||
0.000006,
|
||||
0.000006,
|
||||
0.000004,
|
||||
0.000004,
|
||||
0.000004,
|
||||
0.000003,
|
||||
0.000003,
|
||||
0.000002,
|
||||
0.000002,
|
||||
0.000002,
|
||||
0.000002,
|
||||
0.000002,
|
||||
],
|
||||
],
|
||||
'profile' => [
|
||||
['status' => 'Starting', 'duration' => '17 µ', 'duration_raw' => '0.000017'],
|
||||
|
||||
@ -160,6 +160,7 @@ module.exports = [
|
||||
{ from: rootPath + '/node_modules/updated-jqplot/build/plugins/jqplot.cursor.js', to: publicPath + '/js/vendor/jqplot/plugins/jqplot.cursor.js' },
|
||||
{ from: rootPath + '/node_modules/updated-jqplot/build/plugins/jqplot.highlighter.js', to: publicPath + '/js/vendor/jqplot/plugins/jqplot.highlighter.js' },
|
||||
{ from: rootPath + '/node_modules/chart.js/dist/chart.umd.js', to: publicPath + '/js/vendor/chart.umd.js' },
|
||||
{ from: rootPath + '/node_modules/chart.js/dist/chart.umd.js.map', to: publicPath + '/js/vendor/chart.umd.js.map' },
|
||||
],
|
||||
}),
|
||||
new WebpackConcatPlugin({
|
||||
|
||||
Loading…
Reference in New Issue
Block a user