server_status_monitor.lib.php 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * functions for displaying server status sub item: monitor
  5. *
  6. * @usedby server_status_monitor.php
  7. *
  8. * @package PhpMyAdmin
  9. */
  10. if (! defined('PHPMYADMIN')) {
  11. exit;
  12. }
  13. /**
  14. * Prints html with monitor
  15. *
  16. * @param PMA_ServerStatusData $ServerStatusData Server status data
  17. *
  18. * @return string
  19. */
  20. function PMA_getHtmlForMonitor($ServerStatusData)
  21. {
  22. $retval = PMA_getHtmlForTabLinks();
  23. $retval .= PMA_getHtmlForSettingsDialog();
  24. $retval .= PMA_getHtmlForInstructionsDialog();
  25. $retval .= PMA_getHtmlForAddChartDialog();
  26. if (! PMA_DRIZZLE) {
  27. $retval .= PMA_getHtmlForAnalyseDialog();
  28. }
  29. $retval .= '<table class="clearfloat" id="chartGrid"></table>';
  30. $retval .= '<div id="logTable">';
  31. $retval .= '<br/>';
  32. $retval .= '</div>';
  33. $retval .= '<script type="text/javascript">';
  34. $retval .= 'variableNames = [ ';
  35. $i=0;
  36. foreach ($ServerStatusData->status as $name=>$value) {
  37. if (is_numeric($value)) {
  38. if ($i++ > 0) {
  39. $retval .= ", ";
  40. }
  41. $retval .= "'" . $name . "'";
  42. }
  43. }
  44. $retval .= '];';
  45. $retval .= '</script>';
  46. return $retval;
  47. }
  48. /**
  49. * Builds a <select> list for refresh rates
  50. *
  51. * @param string $name Name of select
  52. * @param int $defaultRate Currently chosen rate
  53. * @param array $refreshRates List of refresh rates
  54. *
  55. * @return string
  56. */
  57. function PMA_getHtmlForRefreshList($name,
  58. $defaultRate = 5,
  59. $refreshRates = Array(1, 2, 5, 10, 20, 40, 60, 120, 300, 600)
  60. ) {
  61. $return = '<select name="' . $name . '" id="id_' . $name
  62. . '" class="refreshRate">';
  63. foreach ($refreshRates as $rate) {
  64. $selected = ($rate == $defaultRate)?' selected="selected"':'';
  65. $return .= '<option value="' . $rate . '"' . $selected . '>';
  66. if ($rate < 60) {
  67. $return .= sprintf(_ngettext('%d second', '%d seconds', $rate), $rate);
  68. } else {
  69. $rate = $rate / 60;
  70. $return .= sprintf(_ngettext('%d minute', '%d minutes', $rate), $rate);
  71. }
  72. $return .= '</option>';
  73. }
  74. $return .= '</select>';
  75. return $return;
  76. }
  77. /**
  78. * Returns html for Analyse Dialog
  79. *
  80. * @return string
  81. */
  82. function PMA_getHtmlForAnalyseDialog()
  83. {
  84. $retval = '<div id="logAnalyseDialog" title="';
  85. $retval .= __('Log statistics') . '" style="display:none;">';
  86. $retval .= '<p>' . __('Selected time range:');
  87. $retval .= '<input type="text" name="dateStart"'
  88. . ' class="datetimefield" value="" /> - ';
  89. $retval .= '<input type="text" name="dateEnd" class="datetimefield" value="" />';
  90. $retval .= '</p>';
  91. $retval .= '<input type="checkbox" id="limitTypes"'
  92. . ' value="1" checked="checked" />';
  93. $retval .= '<label for="limitTypes">';
  94. $retval .= __('Only retrieve SELECT,INSERT,UPDATE and DELETE Statements');
  95. $retval .= '</label>';
  96. $retval .= '<br/>';
  97. $retval .= '<input type="checkbox" id="removeVariables"'
  98. . ' value="1" checked="checked" />';
  99. $retval .= '<label for="removeVariables">';
  100. $retval .= __('Remove variable data in INSERT statements for better grouping');
  101. $retval .= '</label>';
  102. $retval .= '<p>';
  103. $retval .= __(
  104. 'Choose from which log you want the statistics to be generated from.'
  105. );
  106. $retval .= '</p>';
  107. $retval .= '<p>';
  108. $retval .= __('Results are grouped by query text.');
  109. $retval .= '</p>';
  110. $retval .= '</div>';
  111. $retval .= '<div id="queryAnalyzerDialog" title="';
  112. $retval .= __('Query analyzer') . '" style="display:none;">';
  113. $retval .= '<textarea id="sqlquery"> </textarea>';
  114. $retval .= '<p></p>';
  115. $retval .= '<div class="placeHolder"></div>';
  116. $retval .= '</div>';
  117. return $retval;
  118. }
  119. /**
  120. * Returns html for Instructions Dialog
  121. *
  122. * @return string
  123. */
  124. function PMA_getHtmlForInstructionsDialog()
  125. {
  126. $retval = '<div id="monitorInstructionsDialog" title="';
  127. $retval .= __('Monitor Instructions') . '" style="display:none;">';
  128. $retval .= __(
  129. 'The phpMyAdmin Monitor can assist you in optimizing the server'
  130. . ' configuration and track down time intensive queries. For the latter you'
  131. . ' will need to set log_output to \'TABLE\' and have either the'
  132. . ' slow_query_log or general_log enabled. Note however, that the'
  133. . ' general_log produces a lot of data and increases server load'
  134. . ' by up to 15%.'
  135. );
  136. $retval .= '<p></p>';
  137. $retval .= '<img class="ajaxIcon" src="';
  138. $retval .= $GLOBALS['pmaThemeImage'] . 'ajax_clock_small.gif"';
  139. $retval .= ' alt="' . __('Loading…') . '" />';
  140. $retval .= '<div class="ajaxContent"></div>';
  141. $retval .= '<div class="monitorUse" style="display:none;">';
  142. $retval .= '<p></p>';
  143. $retval .= '<strong>';
  144. $retval .= __('Using the monitor:');
  145. $retval .= '</strong><p>';
  146. $retval .= __(
  147. 'Your browser will refresh all displayed charts in a regular interval.'
  148. . ' You may add charts and change the refresh rate under \'Settings\','
  149. . ' or remove any chart using the cog icon on each respective chart.'
  150. );
  151. $retval .= '</p><p>';
  152. $retval .= __(
  153. 'To display queries from the logs, select the relevant time span on any'
  154. . ' chart by holding down the left mouse button and panning over the'
  155. . ' chart. Once confirmed, this will load a table of grouped queries,'
  156. . ' there you may click on any occurring SELECT statements to further'
  157. . ' analyze them.'
  158. );
  159. $retval .= '</p>';
  160. $retval .= '<p>';
  161. $retval .= PMA_Util::getImage('s_attention.png');
  162. $retval .= '<strong>';
  163. $retval .= __('Please note:');
  164. $retval .= '</strong><br />';
  165. $retval .= __(
  166. 'Enabling the general_log may increase the server load by'
  167. . ' 5-15%. Also be aware that generating statistics from the logs is a'
  168. . ' load intensive task, so it is advisable to select only a small time'
  169. . ' span and to disable the general_log and empty its table once'
  170. . ' monitoring is not required any more.'
  171. );
  172. $retval .= '</p>';
  173. $retval .= '</div>';
  174. $retval .= '</div>';
  175. return $retval;
  176. }
  177. /**
  178. * Returns html for addChartDialog
  179. *
  180. * @return string
  181. */
  182. function PMA_getHtmlForAddChartDialog()
  183. {
  184. $retval = '<div id="addChartDialog" title="'
  185. . __('Add chart') . '" style="display:none;">';
  186. $retval .= '<div id="tabGridVariables">';
  187. $retval .= '<p><input type="text" name="chartTitle" value="'
  188. . __('Chart Title') . '" /></p>';
  189. $retval .= '<input type="radio" name="chartType"'
  190. . ' value="preset" id="chartPreset" />';
  191. $retval .= '<label for="chartPreset">' . __('Preset chart') . '</label>';
  192. $retval .= '<select name="presetCharts"></select><br/>';
  193. $retval .= '<input type="radio" name="chartType" value="variable" '
  194. . 'id="chartStatusVar" checked="checked" />';
  195. $retval .= '<label for="chartStatusVar">';
  196. $retval .= __('Status variable(s)');
  197. $retval .= '</label><br/>';
  198. $retval .= '<div id="chartVariableSettings">';
  199. $retval .= '<label for="chartSeries">' . __('Select series:') . '</label><br />';
  200. $retval .= '<select id="chartSeries" name="varChartList" size="1">';
  201. $retval .= '<option>' . __('Commonly monitored') . '</option>';
  202. $retval .= '<option>Processes</option>';
  203. $retval .= '<option>Questions</option>';
  204. $retval .= '<option>Connections</option>';
  205. $retval .= '<option>Bytes_sent</option>';
  206. $retval .= '<option>Bytes_received</option>';
  207. $retval .= '<option>Threads_connected</option>';
  208. $retval .= '<option>Created_tmp_disk_tables</option>';
  209. $retval .= '<option>Handler_read_first</option>';
  210. $retval .= '<option>Innodb_buffer_pool_wait_free</option>';
  211. $retval .= '<option>Key_reads</option>';
  212. $retval .= '<option>Open_tables</option>';
  213. $retval .= '<option>Select_full_join</option>';
  214. $retval .= '<option>Slow_queries</option>';
  215. $retval .= '</select><br />';
  216. $retval .= '<label for="variableInput">';
  217. $retval .= __('or type variable name:');
  218. $retval .= ' </label>';
  219. $retval .= '<input type="text" name="variableInput" id="variableInput" />';
  220. $retval .= '<p></p>';
  221. $retval .= '<input type="checkbox" name="differentialValue"'
  222. . ' id="differentialValue" value="differential" checked="checked" />';
  223. $retval .= '<label for="differentialValue">';
  224. $retval .= __('Display as differential value');
  225. $retval .= '</label><br />';
  226. $retval .= '<input type="checkbox" id="useDivisor"'
  227. . ' name="useDivisor" value="1" />';
  228. $retval .= '<label for="useDivisor">' . __('Apply a divisor') . '</label>';
  229. $retval .= '<span class="divisorInput" style="display:none;">';
  230. $retval .= '<input type="text" name="valueDivisor" size="4" value="1" />';
  231. $retval .= '(<a href="#kibDivisor">' . __('KiB') . '</a>, ';
  232. $retval .= '<a href="#mibDivisor">' . __('MiB') . '</a>)';
  233. $retval .= '</span><br />';
  234. $retval .= '<input type="checkbox" id="useUnit" name="useUnit" value="1" />';
  235. $retval .= '<label for="useUnit">';
  236. $retval .= __('Append unit to data values');
  237. $retval .= '</label>';
  238. $retval .= '<span class="unitInput" style="display:none;">';
  239. $retval .= '<input type="text" name="valueUnit" size="4" value="" />';
  240. $retval .= '</span>';
  241. $retval .= '<p>';
  242. $retval .= '<a href="#submitAddSeries"><b>' . __('Add this series') . '</b></a>';
  243. $retval .= '<span id="clearSeriesLink" style="display:none;">';
  244. $retval .= ' | <a href="#submitClearSeries">' . __('Clear series') . '</a>';
  245. $retval .= '</span>';
  246. $retval .= '</p>';
  247. $retval .= __('Series in Chart:');
  248. $retval .= '<br/>';
  249. $retval .= '<span id="seriesPreview">';
  250. $retval .= '<i>' . __('None') . '</i>';
  251. $retval .= '</span>';
  252. $retval .= '</div>';
  253. $retval .= '</div>';
  254. $retval .= '</div>';
  255. return $retval;
  256. }
  257. /**
  258. * Returns html with Tab Links
  259. *
  260. * @return string
  261. */
  262. function PMA_getHtmlForTabLinks()
  263. {
  264. $retval = '<div class="tabLinks">';
  265. $retval .= '<a href="#pauseCharts">';
  266. $retval .= PMA_Util::getImage('play.png') . __('Start Monitor');
  267. $retval .= '</a>';
  268. $retval .= '<a href="#settingsPopup" class="popupLink">';
  269. $retval .= PMA_Util::getImage('s_cog.png') . __('Settings');
  270. $retval .= '</a>';
  271. if (! PMA_DRIZZLE) {
  272. $retval .= '<a href="#monitorInstructionsDialog">';
  273. $retval .= PMA_Util::getImage('b_help.png') . __('Instructions/Setup');
  274. }
  275. $retval .= '<a href="#endChartEditMode" style="display:none;">';
  276. $retval .= PMA_Util::getImage('s_okay.png');
  277. $retval .= __('Done dragging (rearranging) charts');
  278. $retval .= '</a>';
  279. $retval .= '</div>';
  280. return $retval;
  281. }
  282. /**
  283. * Returns html with Settings dialog
  284. *
  285. * @return string
  286. */
  287. function PMA_getHtmlForSettingsDialog()
  288. {
  289. $retval = '<div class="popupContent settingsPopup">';
  290. $retval .= '<a href="#addNewChart">';
  291. $retval .= PMA_Util::getImage('b_chart.png') . __('Add chart');
  292. $retval .= '</a>';
  293. $retval .= '<a href="#rearrangeCharts">';
  294. $retval .= PMA_Util::getImage('b_tblops.png') . __('Enable charts dragging');
  295. $retval .= '</a>';
  296. $retval .= '<div class="clearfloat paddingtop"></div>';
  297. $retval .= '<div class="floatleft">';
  298. $retval .= __('Refresh rate') . '<br />';
  299. $retval .= PMA_getHtmlForRefreshList(
  300. 'gridChartRefresh',
  301. 5,
  302. Array(2, 3, 4, 5, 10, 20, 40, 60, 120, 300, 600, 1200)
  303. );
  304. $retval .= '<br />';
  305. $retval .= '</div>';
  306. $retval .= '<div class="floatleft">';
  307. $retval .= __('Chart columns');
  308. $retval .= '<br />';
  309. $retval .= '<select name="chartColumns">';
  310. $retval .= '<option>1</option>';
  311. $retval .= '<option>2</option>';
  312. $retval .= '<option>3</option>';
  313. $retval .= '<option>4</option>';
  314. $retval .= '<option>5</option>';
  315. $retval .= '<option>6</option>';
  316. $retval .= '</select>';
  317. $retval .= '</div>';
  318. $retval .= '<div class="clearfloat paddingtop">';
  319. $retval .= '<b>' . __('Chart arrangement') . '</b> ';
  320. $retval .= PMA_Util::showHint(
  321. __(
  322. 'The arrangement of the charts is stored to the browsers local storage. '
  323. . 'You may want to export it if you have a complicated set up.'
  324. )
  325. );
  326. $retval .= '<br/>';
  327. $retval .= '<a class="ajax" href="#importMonitorConfig">';
  328. $retval .= __('Import');
  329. $retval .= '</a>';
  330. $retval .= '&nbsp;&nbsp;';
  331. $retval .= '<a class="disableAjax" href="#exportMonitorConfig">';
  332. $retval .= __('Export');
  333. $retval .= '</a>';
  334. $retval .= '&nbsp;&nbsp;';
  335. $retval .= '<a href="#clearMonitorConfig">';
  336. $retval .= __('Reset to default');
  337. $retval .= '</a>';
  338. $retval .= '</div>';
  339. $retval .= '</div>';
  340. return $retval;
  341. }
  342. /**
  343. * Define some data and links needed on the client side
  344. *
  345. * @param PMA_ServerStatusData $ServerStatusData Server status data
  346. *
  347. * @return string
  348. */
  349. function PMA_getHtmlForClientSideDataAndLinks($ServerStatusData)
  350. {
  351. /**
  352. * Define some data needed on the client side
  353. */
  354. $input = '<input type="hidden" name="%s" value="%s" />';
  355. $form = '<form id="js_data" class="hide">';
  356. $form .= sprintf($input, 'server_time', microtime(true) * 1000);
  357. $form .= sprintf($input, 'server_os', PHP_OS);
  358. $form .= sprintf($input, 'is_superuser', $GLOBALS['dbi']->isSuperuser());
  359. $form .= sprintf($input, 'server_db_isLocal', $ServerStatusData->db_isLocal);
  360. $form .= '</form>';
  361. /**
  362. * Define some links used on client side
  363. */
  364. $links = '<div id="profiling_docu" class="hide">';
  365. $links .= PMA_Util::showMySQLDocu('general-thread-states');
  366. $links .= '</div>';
  367. $links .= '<div id="explain_docu" class="hide">';
  368. $links .= PMA_Util::showMySQLDocu('explain-output');
  369. $links .= '</div>';
  370. return $form . $links;
  371. }
  372. /***************************Ajax request function***********************************/
  373. /**
  374. * Returns JSon for real-time charting data
  375. *
  376. * @return Array
  377. */
  378. function PMA_getJsonForChartingData()
  379. {
  380. $ret = json_decode($_REQUEST['requiredData'], true);
  381. $statusVars = array();
  382. $serverVars = array();
  383. $sysinfo = $cpuload = $memory = 0;
  384. /* Accumulate all required variables and data */
  385. list($serverVars, $statusVars, $ret) = PMA_getJsonForChartingDataGet(
  386. $ret, $serverVars, $statusVars, $sysinfo, $cpuload, $memory
  387. );
  388. // Retrieve all required status variables
  389. if (count($statusVars)) {
  390. $statusVarValues = $GLOBALS['dbi']->fetchResult(
  391. "SHOW GLOBAL STATUS WHERE Variable_name='"
  392. . implode("' OR Variable_name='", $statusVars) . "'",
  393. 0,
  394. 1
  395. );
  396. } else {
  397. $statusVarValues = array();
  398. }
  399. // Retrieve all required server variables
  400. if (count($serverVars)) {
  401. $serverVarValues = $GLOBALS['dbi']->fetchResult(
  402. "SHOW GLOBAL VARIABLES WHERE Variable_name='"
  403. . implode("' OR Variable_name='", $serverVars) . "'",
  404. 0,
  405. 1
  406. );
  407. } else {
  408. $serverVarValues = array();
  409. }
  410. // ...and now assign them
  411. $ret = PMA_getJsonForChartingDataSet($ret, $statusVarValues, $serverVarValues);
  412. $ret['x'] = microtime(true) * 1000;
  413. return $ret;
  414. }
  415. /**
  416. * Assign the variables for real-time charting data
  417. *
  418. * @param array $ret Real-time charting data
  419. * @param array $statusVarValues Status variable values
  420. * @param array $serverVarValues Server variable values
  421. *
  422. * @return array
  423. */
  424. function PMA_getJsonForChartingDataSet($ret, $statusVarValues, $serverVarValues)
  425. {
  426. foreach ($ret as $chart_id => $chartNodes) {
  427. foreach ($chartNodes as $node_id => $nodeDataPoints) {
  428. foreach ($nodeDataPoints as $point_id => $dataPoint) {
  429. switch ($dataPoint['type']) {
  430. case 'statusvar':
  431. $ret[$chart_id][$node_id][$point_id]['value']
  432. = $statusVarValues[$dataPoint['name']];
  433. break;
  434. case 'servervar':
  435. $ret[$chart_id][$node_id][$point_id]['value']
  436. = $serverVarValues[$dataPoint['name']];
  437. break;
  438. }
  439. }
  440. }
  441. }
  442. return $ret;
  443. }
  444. /**
  445. * Get called to get JSON for charting data
  446. *
  447. * @param array $ret Real-time charting data
  448. * @param array $serverVars Server variable values
  449. * @param array $statusVars Status variable values
  450. * @param mixed $sysinfo System info
  451. * @param mixed $cpuload CPU load
  452. * @param mixed $memory Memory
  453. *
  454. * @return array
  455. */
  456. function PMA_getJsonForChartingDataGet(
  457. $ret, $serverVars, $statusVars, $sysinfo, $cpuload, $memory
  458. ) {
  459. // For each chart
  460. foreach ($ret as $chart_id => $chartNodes) {
  461. // For each data series
  462. foreach ($chartNodes as $node_id => $nodeDataPoints) {
  463. // For each data point in the series (usually just 1)
  464. foreach ($nodeDataPoints as $point_id => $dataPoint) {
  465. list($serverVars, $statusVars, $ret[$chart_id][$node_id][$point_id])
  466. = PMA_getJsonForChartingDataSwitch(
  467. $dataPoint['type'], $dataPoint['name'], $serverVars,
  468. $statusVars, $ret[$chart_id][$node_id][$point_id],
  469. $sysinfo, $cpuload, $memory
  470. );
  471. } /* foreach */
  472. } /* foreach */
  473. }
  474. return array($serverVars, $statusVars, $ret);
  475. }
  476. /**
  477. * Switch called to get JSON for charting data
  478. *
  479. * @param string $type Type
  480. * @param string $pName Name
  481. * @param array $serverVars Server variable values
  482. * @param array $statusVars Status variable values
  483. * @param array $ret Real-time charting data
  484. * @param mixed $sysinfo System info
  485. * @param mixed $cpuload CPU load
  486. * @param mixed $memory Memory
  487. *
  488. * @return array
  489. */
  490. function PMA_getJsonForChartingDataSwitch(
  491. $type, $pName, $serverVars, $statusVars, $ret,
  492. $sysinfo, $cpuload, $memory
  493. ) {
  494. switch ($type) {
  495. /* We only collect the status and server variables here to
  496. * read them all in one query,
  497. * and only afterwards assign them.
  498. * Also do some white list filtering on the names
  499. */
  500. case 'servervar':
  501. if (!preg_match('/[^a-zA-Z_]+/', $pName)) {
  502. $serverVars[] = $pName;
  503. }
  504. break;
  505. case 'statusvar':
  506. if (!preg_match('/[^a-zA-Z_]+/', $pName)) {
  507. $statusVars[] = $pName;
  508. }
  509. break;
  510. case 'proc':
  511. $result = $GLOBALS['dbi']->query('SHOW PROCESSLIST');
  512. $ret['value'] = $GLOBALS['dbi']->numRows($result);
  513. break;
  514. case 'cpu':
  515. if (!$sysinfo) {
  516. include_once 'libraries/sysinfo.lib.php';
  517. $sysinfo = PMA_getSysInfo();
  518. }
  519. if (!$cpuload) {
  520. $cpuload = $sysinfo->loadavg();
  521. }
  522. if (PMA_getSysInfoOs() == 'Linux') {
  523. $ret['idle'] = $cpuload['idle'];
  524. $ret['busy'] = $cpuload['busy'];
  525. } else {
  526. $ret['value'] = $cpuload['loadavg'];
  527. }
  528. break;
  529. case 'memory':
  530. if (!$sysinfo) {
  531. include_once 'libraries/sysinfo.lib.php';
  532. $sysinfo = PMA_getSysInfo();
  533. }
  534. if (!$memory) {
  535. $memory = $sysinfo->memory();
  536. }
  537. $ret['value'] = isset($memory[$pName]) ? $memory[$pName] : 0;
  538. break;
  539. }
  540. return array($serverVars, $statusVars, $ret);
  541. }
  542. /**
  543. * Returns JSon for log data with type: slow
  544. *
  545. * @param int $start Unix Time: Start time for query
  546. * @param int $end Unix Time: End time for query
  547. *
  548. * @return Array
  549. */
  550. function PMA_getJsonForLogDataTypeSlow($start, $end)
  551. {
  552. $query = 'SELECT start_time, user_host, ';
  553. $query .= 'Sec_to_Time(Sum(Time_to_Sec(query_time))) as query_time, ';
  554. $query .= 'Sec_to_Time(Sum(Time_to_Sec(lock_time))) as lock_time, ';
  555. $query .= 'SUM(rows_sent) AS rows_sent, ';
  556. $query .= 'SUM(rows_examined) AS rows_examined, db, sql_text, ';
  557. $query .= 'COUNT(sql_text) AS \'#\' ';
  558. $query .= 'FROM `mysql`.`slow_log` ';
  559. $query .= 'WHERE start_time > FROM_UNIXTIME(' . $start . ') ';
  560. $query .= 'AND start_time < FROM_UNIXTIME(' . $end . ') GROUP BY sql_text';
  561. $result = $GLOBALS['dbi']->tryQuery($query);
  562. $return = array('rows' => array(), 'sum' => array());
  563. while ($row = $GLOBALS['dbi']->fetchAssoc($result)) {
  564. $type = strtolower(
  565. substr($row['sql_text'], 0, strpos($row['sql_text'], ' '))
  566. );
  567. switch($type) {
  568. case 'insert':
  569. case 'update':
  570. //Cut off big inserts and updates, but append byte count instead
  571. if (strlen($row['sql_text']) > 220) {
  572. $implode_sql_text = implode(
  573. ' ',
  574. PMA_Util::formatByteDown(
  575. strlen($row['sql_text']), 2, 2
  576. )
  577. );
  578. $row['sql_text'] = substr($row['sql_text'], 0, 200)
  579. . '... [' . $implode_sql_text . ']';
  580. }
  581. break;
  582. default:
  583. break;
  584. }
  585. if (! isset($return['sum'][$type])) {
  586. $return['sum'][$type] = 0;
  587. }
  588. $return['sum'][$type] += $row['#'];
  589. $return['rows'][] = $row;
  590. }
  591. $return['sum']['TOTAL'] = array_sum($return['sum']);
  592. $return['numRows'] = count($return['rows']);
  593. $GLOBALS['dbi']->freeResult($result);
  594. return $return;
  595. }
  596. /**
  597. * Returns JSon for log data with type: general
  598. *
  599. * @param int $start Unix Time: Start time for query
  600. * @param int $end Unix Time: End time for query
  601. *
  602. * @return Array
  603. */
  604. function PMA_getJsonForLogDataTypeGeneral($start, $end)
  605. {
  606. $limitTypes = '';
  607. if (isset($_REQUEST['limitTypes']) && $_REQUEST['limitTypes']) {
  608. $limitTypes
  609. = 'AND argument REGEXP \'^(INSERT|SELECT|UPDATE|DELETE)\' ';
  610. }
  611. $query = 'SELECT TIME(event_time) as event_time, user_host, thread_id, ';
  612. $query .= 'server_id, argument, count(argument) as \'#\' ';
  613. $query .= 'FROM `mysql`.`general_log` ';
  614. $query .= 'WHERE command_type=\'Query\' ';
  615. $query .= 'AND event_time > FROM_UNIXTIME(' . $start . ') ';
  616. $query .= 'AND event_time < FROM_UNIXTIME(' . $end . ') ';
  617. $query .= $limitTypes . 'GROUP by argument'; // HAVING count > 1';
  618. $result = $GLOBALS['dbi']->tryQuery($query);
  619. $return = array('rows' => array(), 'sum' => array());
  620. $insertTables = array();
  621. $insertTablesFirst = -1;
  622. $i = 0;
  623. $removeVars = isset($_REQUEST['removeVariables'])
  624. && $_REQUEST['removeVariables'];
  625. while ($row = $GLOBALS['dbi']->fetchAssoc($result)) {
  626. preg_match('/^(\w+)\s/', $row['argument'], $match);
  627. $type = strtolower($match[1]);
  628. if (! isset($return['sum'][$type])) {
  629. $return['sum'][$type] = 0;
  630. }
  631. $return['sum'][$type] += $row['#'];
  632. switch($type) {
  633. case 'insert':
  634. // Group inserts if selected
  635. if ($removeVars
  636. && preg_match(
  637. '/^INSERT INTO (`|\'|"|)([^\s\\1]+)\\1/i',
  638. $row['argument'], $matches
  639. )
  640. ) {
  641. $insertTables[$matches[2]]++;
  642. if ($insertTables[$matches[2]] > 1) {
  643. $return['rows'][$insertTablesFirst]['#']
  644. = $insertTables[$matches[2]];
  645. // Add a ... to the end of this query to indicate that
  646. // there's been other queries
  647. $temp = $return['rows'][$insertTablesFirst]['argument'];
  648. if ($temp[strlen($temp) - 1] != '.') {
  649. $return['rows'][$insertTablesFirst]['argument']
  650. .= '<br/>...';
  651. }
  652. // Group this value, thus do not add to the result list
  653. continue 2;
  654. } else {
  655. $insertTablesFirst = $i;
  656. $insertTables[$matches[2]] += $row['#'] - 1;
  657. }
  658. }
  659. // No break here
  660. case 'update':
  661. // Cut off big inserts and updates,
  662. // but append byte count therefor
  663. if (strlen($row['argument']) > 220) {
  664. $row['argument'] = substr($row['argument'], 0, 200)
  665. . '... ['
  666. . implode(
  667. ' ',
  668. PMA_Util::formatByteDown(
  669. strlen($row['argument']),
  670. 2,
  671. 2
  672. )
  673. )
  674. . ']';
  675. }
  676. break;
  677. default:
  678. break;
  679. }
  680. $return['rows'][] = $row;
  681. $i++;
  682. }
  683. $return['sum']['TOTAL'] = array_sum($return['sum']);
  684. $return['numRows'] = count($return['rows']);
  685. $GLOBALS['dbi']->freeResult($result);
  686. return $return;
  687. }
  688. /**
  689. * Returns JSon for logging vars
  690. *
  691. * @return Array
  692. */
  693. function PMA_getJsonForLoggingVars()
  694. {
  695. if (isset($_REQUEST['varName']) && isset($_REQUEST['varValue'])) {
  696. $value = PMA_Util::sqlAddSlashes($_REQUEST['varValue']);
  697. if (! is_numeric($value)) {
  698. $value="'" . $value . "'";
  699. }
  700. if (! preg_match("/[^a-zA-Z0-9_]+/", $_REQUEST['varName'])) {
  701. $GLOBALS['dbi']->query(
  702. 'SET GLOBAL ' . $_REQUEST['varName'] . ' = ' . $value
  703. );
  704. }
  705. }
  706. $loggingVars = $GLOBALS['dbi']->fetchResult(
  707. 'SHOW GLOBAL VARIABLES WHERE Variable_name IN'
  708. . ' ("general_log","slow_query_log","long_query_time","log_output")',
  709. 0,
  710. 1
  711. );
  712. return $loggingVars;
  713. }
  714. /**
  715. * Returns JSon for query_analyzer
  716. *
  717. * @return Array
  718. */
  719. function PMA_getJsonForQueryAnalyzer()
  720. {
  721. $return = array();
  722. if (strlen($_REQUEST['database'])) {
  723. $GLOBALS['dbi']->selectDb($_REQUEST['database']);
  724. }
  725. if ($profiling = PMA_Util::profilingSupported()) {
  726. $GLOBALS['dbi']->query('SET PROFILING=1;');
  727. }
  728. // Do not cache query
  729. $query = preg_replace(
  730. '/^(\s*SELECT)/i',
  731. '\\1 SQL_NO_CACHE',
  732. $_REQUEST['query']
  733. );
  734. $result = $GLOBALS['dbi']->tryQuery($query);
  735. $return['affectedRows'] = $GLOBALS['cached_affected_rows'];
  736. $result = $GLOBALS['dbi']->tryQuery('EXPLAIN ' . $query);
  737. while ($row = $GLOBALS['dbi']->fetchAssoc($result)) {
  738. $return['explain'][] = $row;
  739. }
  740. // In case an error happened
  741. $return['error'] = $GLOBALS['dbi']->getError();
  742. $GLOBALS['dbi']->freeResult($result);
  743. if ($profiling) {
  744. $return['profiling'] = array();
  745. $result = $GLOBALS['dbi']->tryQuery(
  746. 'SELECT seq,state,duration FROM INFORMATION_SCHEMA.PROFILING'
  747. . ' WHERE QUERY_ID=1 ORDER BY seq'
  748. );
  749. while ($row = $GLOBALS['dbi']->fetchAssoc($result)) {
  750. $return['profiling'][]= $row;
  751. }
  752. $GLOBALS['dbi']->freeResult($result);
  753. }
  754. return $return;
  755. }
  756. ?>