ServerStatusData.class.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * PMA_ServerStatusData class
  5. * Used by server_status_*.php pages
  6. *
  7. * @package PhpMyAdmin
  8. */
  9. if (! defined('PHPMYADMIN')) {
  10. exit;
  11. }
  12. /**
  13. * This class provides data about the server status
  14. *
  15. * All properties of the class are read-only
  16. *
  17. * TODO: Use lazy initialisation for some of the properties
  18. * since not all of the server_status_*.php pages need
  19. * all the data that this class provides.
  20. *
  21. * @package PhpMyAdmin
  22. */
  23. class PMA_ServerStatusData
  24. {
  25. public $status;
  26. public $sections;
  27. public $variables;
  28. public $used_queries;
  29. public $allocationMap;
  30. public $links;
  31. public $db_isLocal;
  32. public $section;
  33. public $categoryUsed;
  34. public $selfUrl;
  35. /**
  36. * An empty setter makes the above properties read-only
  37. *
  38. * @param string $a key
  39. * @param mixed $b value
  40. *
  41. * @return void
  42. */
  43. public function __set($a, $b)
  44. {
  45. // Discard everything
  46. }
  47. /**
  48. * Constructor
  49. */
  50. public function __construct()
  51. {
  52. $this->selfUrl = basename($GLOBALS['PMA_PHP_SELF']);
  53. /**
  54. * get status from server
  55. */
  56. $server_status = $GLOBALS['dbi']->fetchResult('SHOW GLOBAL STATUS', 0, 1);
  57. if (PMA_DRIZZLE) {
  58. // Drizzle doesn't put query statistics into variables, add it
  59. $sql = "SELECT concat('Com_', variable_name), variable_value "
  60. . "FROM data_dictionary.GLOBAL_STATEMENTS";
  61. $statements = $GLOBALS['dbi']->fetchResult($sql, 0, 1);
  62. $server_status = array_merge($server_status, $statements);
  63. }
  64. /**
  65. * for some calculations we require also some server settings
  66. */
  67. $server_variables = $GLOBALS['dbi']->fetchResult(
  68. 'SHOW GLOBAL VARIABLES', 0, 1
  69. );
  70. /**
  71. * cleanup of some deprecated values
  72. */
  73. $server_status = self::cleanDeprecated($server_status);
  74. /**
  75. * calculate some values
  76. */
  77. // Key_buffer_fraction
  78. if (isset($server_status['Key_blocks_unused'])
  79. && isset($server_variables['key_cache_block_size'])
  80. && isset($server_variables['key_buffer_size'])
  81. ) {
  82. $server_status['Key_buffer_fraction_%']
  83. = 100
  84. - $server_status['Key_blocks_unused']
  85. * $server_variables['key_cache_block_size']
  86. / $server_variables['key_buffer_size']
  87. * 100;
  88. } elseif (isset($server_status['Key_blocks_used'])
  89. && isset($server_variables['key_buffer_size'])
  90. ) {
  91. $server_status['Key_buffer_fraction_%']
  92. = $server_status['Key_blocks_used']
  93. * 1024
  94. / $server_variables['key_buffer_size'];
  95. }
  96. // Ratio for key read/write
  97. if (isset($server_status['Key_writes'])
  98. && isset($server_status['Key_write_requests'])
  99. && $server_status['Key_write_requests'] > 0
  100. ) {
  101. $key_writes = $server_status['Key_writes'];
  102. $key_write_requests = $server_status['Key_write_requests'];
  103. $server_status['Key_write_ratio_%']
  104. = 100 * $key_writes / $key_write_requests;
  105. }
  106. if (isset($server_status['Key_reads'])
  107. && isset($server_status['Key_read_requests'])
  108. && $server_status['Key_read_requests'] > 0
  109. ) {
  110. $key_reads = $server_status['Key_reads'];
  111. $key_read_requests = $server_status['Key_read_requests'];
  112. $server_status['Key_read_ratio_%']
  113. = 100 * $key_reads / $key_read_requests;
  114. }
  115. // Threads_cache_hitrate
  116. if (isset($server_status['Threads_created'])
  117. && isset($server_status['Connections'])
  118. && $server_status['Connections'] > 0
  119. ) {
  120. $server_status['Threads_cache_hitrate_%']
  121. = 100 - $server_status['Threads_created']
  122. / $server_status['Connections'] * 100;
  123. }
  124. /**
  125. * split variables in sections
  126. */
  127. $allocations = array(
  128. // variable name => section
  129. // variable names match when they begin with the given string
  130. 'Com_' => 'com',
  131. 'Innodb_' => 'innodb',
  132. 'Ndb_' => 'ndb',
  133. 'Handler_' => 'handler',
  134. 'Qcache_' => 'qcache',
  135. 'Threads_' => 'threads',
  136. 'Slow_launch_threads' => 'threads',
  137. 'Binlog_cache_' => 'binlog_cache',
  138. 'Created_tmp_' => 'created_tmp',
  139. 'Key_' => 'key',
  140. 'Delayed_' => 'delayed',
  141. 'Not_flushed_delayed_rows' => 'delayed',
  142. 'Flush_commands' => 'query',
  143. 'Last_query_cost' => 'query',
  144. 'Slow_queries' => 'query',
  145. 'Queries' => 'query',
  146. 'Prepared_stmt_count' => 'query',
  147. 'Select_' => 'select',
  148. 'Sort_' => 'sort',
  149. 'Open_tables' => 'table',
  150. 'Opened_tables' => 'table',
  151. 'Open_table_definitions' => 'table',
  152. 'Opened_table_definitions' => 'table',
  153. 'Table_locks_' => 'table',
  154. 'Rpl_status' => 'repl',
  155. 'Slave_' => 'repl',
  156. 'Tc_' => 'tc',
  157. 'Ssl_' => 'ssl',
  158. 'Open_files' => 'files',
  159. 'Open_streams' => 'files',
  160. 'Opened_files' => 'files',
  161. );
  162. $sections = array(
  163. // section => section name (description)
  164. 'com' => 'Com',
  165. 'query' => __('SQL query'),
  166. 'innodb' => 'InnoDB',
  167. 'ndb' => 'NDB',
  168. 'handler' => __('Handler'),
  169. 'qcache' => __('Query cache'),
  170. 'threads' => __('Threads'),
  171. 'binlog_cache' => __('Binary log'),
  172. 'created_tmp' => __('Temporary data'),
  173. 'delayed' => __('Delayed inserts'),
  174. 'key' => __('Key cache'),
  175. 'select' => __('Joins'),
  176. 'repl' => __('Replication'),
  177. 'sort' => __('Sorting'),
  178. 'table' => __('Tables'),
  179. 'tc' => __('Transaction coordinator'),
  180. 'files' => __('Files'),
  181. 'ssl' => 'SSL',
  182. 'other' => __('Other')
  183. );
  184. /**
  185. * define some needfull links/commands
  186. */
  187. // variable or section name => (name => url)
  188. $links = array();
  189. $links['table'][__('Flush (close) all tables')] = $this->selfUrl
  190. . PMA_URL_getCommon(
  191. array(
  192. 'flush' => 'TABLES'
  193. )
  194. );
  195. $links['table'][__('Show open tables')]
  196. = 'sql.php' . PMA_URL_getCommon(
  197. array(
  198. 'sql_query' => 'SHOW OPEN TABLES',
  199. 'goto' => $this->selfUrl,
  200. )
  201. );
  202. if ($GLOBALS['server_master_status']) {
  203. $links['repl'][__('Show slave hosts')]
  204. = 'sql.php' . PMA_URL_getCommon(
  205. array(
  206. 'sql_query' => 'SHOW SLAVE HOSTS',
  207. 'goto' => $this->selfUrl,
  208. )
  209. );
  210. $links['repl'][__('Show master status')] = '#replication_master';
  211. }
  212. if ($GLOBALS['server_slave_status']) {
  213. $links['repl'][__('Show slave status')] = '#replication_slave';
  214. }
  215. $links['repl']['doc'] = 'replication';
  216. $links['qcache'][__('Flush query cache')]
  217. = $this->selfUrl
  218. . PMA_URL_getCommon(
  219. array(
  220. 'flush' => 'QUERY CACHE'
  221. )
  222. );
  223. $links['qcache']['doc'] = 'query_cache';
  224. $links['threads']['doc'] = 'mysql_threads';
  225. $links['key']['doc'] = 'myisam_key_cache';
  226. $links['binlog_cache']['doc'] = 'binary_log';
  227. $links['Slow_queries']['doc'] = 'slow_query_log';
  228. $links['innodb'][__('Variables')]
  229. = 'server_engines.php?engine=InnoDB&amp;' . PMA_URL_getCommon();
  230. $links['innodb'][__('InnoDB Status')]
  231. = 'server_engines.php'
  232. . PMA_URL_getCommon(
  233. array(
  234. 'engine' => 'InnoDB',
  235. 'page' => 'Status'
  236. )
  237. );
  238. $links['innodb']['doc'] = 'innodb';
  239. // Variable to contain all com_ variables (query statistics)
  240. $used_queries = array();
  241. // Variable to map variable names to their respective section name
  242. // (used for js category filtering)
  243. $allocationMap = array();
  244. // Variable to mark used sections
  245. $categoryUsed = array();
  246. // sort vars into arrays
  247. foreach ($server_status as $name => $value) {
  248. $section_found = false;
  249. foreach ($allocations as $filter => $section) {
  250. if (strpos($name, $filter) !== false) {
  251. $allocationMap[$name] = $section;
  252. $categoryUsed[$section] = true;
  253. $section_found = true;
  254. if ($section == 'com' && $value > 0) {
  255. $used_queries[$name] = $value;
  256. }
  257. break; // Only exits inner loop
  258. }
  259. }
  260. if (!$section_found) {
  261. $allocationMap[$name] = 'other';
  262. $categoryUsed['other'] = true;
  263. }
  264. }
  265. if (PMA_DRIZZLE) {
  266. $used_queries = $GLOBALS['dbi']->fetchResult(
  267. 'SELECT * FROM data_dictionary.global_statements',
  268. 0,
  269. 1
  270. );
  271. unset($used_queries['admin_commands']);
  272. } else {
  273. // admin commands are not queries (e.g. they include COM_PING,
  274. // which is excluded from $server_status['Questions'])
  275. unset($used_queries['Com_admin_commands']);
  276. }
  277. // Set all class properties
  278. $this->db_isLocal = false;
  279. if (strtolower($GLOBALS['cfg']['Server']['host']) === 'localhost'
  280. || $GLOBALS['cfg']['Server']['host'] === '127.0.0.1'
  281. || $GLOBALS['cfg']['Server']['host'] === '::1'
  282. ) {
  283. $this->db_isLocal = true;
  284. }
  285. $this->status = $server_status;
  286. $this->sections = $sections;
  287. $this->variables = $server_variables;
  288. $this->used_queries = $used_queries;
  289. $this->allocationMap = $allocationMap;
  290. $this->links = $links;
  291. $this->categoryUsed = $categoryUsed;
  292. }
  293. /**
  294. * cleanup of some deprecated values
  295. *
  296. * @param array $server_status status array to process
  297. *
  298. * @return array
  299. */
  300. public static function cleanDeprecated($server_status)
  301. {
  302. $deprecated = array(
  303. 'Com_prepare_sql' => 'Com_stmt_prepare',
  304. 'Com_execute_sql' => 'Com_stmt_execute',
  305. 'Com_dealloc_sql' => 'Com_stmt_close',
  306. );
  307. foreach ($deprecated as $old => $new) {
  308. if (isset($server_status[$old]) && isset($server_status[$new])) {
  309. unset($server_status[$old]);
  310. }
  311. }
  312. return $server_status;
  313. }
  314. /**
  315. * cleanup of some deprecated values
  316. *
  317. * @return array
  318. */
  319. public function getMenuHtml()
  320. {
  321. $url_params = PMA_URL_getCommon();
  322. $items = array(
  323. array(
  324. 'name' => __('Server'),
  325. 'url' => 'server_status.php'
  326. ),
  327. array(
  328. 'name' => __('Query statistics'),
  329. 'url' => 'server_status_queries.php'
  330. ),
  331. array(
  332. 'name' => __('All status variables'),
  333. 'url' => 'server_status_variables.php'
  334. ),
  335. array(
  336. 'name' => __('Monitor'),
  337. 'url' => 'server_status_monitor.php'
  338. ),
  339. array(
  340. 'name' => __('Advisor'),
  341. 'url' => 'server_status_advisor.php'
  342. )
  343. );
  344. $retval = '<ul id="topmenu2">';
  345. foreach ($items as $item) {
  346. $class = '';
  347. if ($item['url'] === $this->selfUrl) {
  348. $class = ' class="tabactive"';
  349. }
  350. $retval .= '<li>';
  351. $retval .= '<a' . $class;
  352. $retval .= ' href="' . $item['url'] . '?' . $url_params . '">';
  353. $retval .= $item['name'];
  354. $retval .= '</a>';
  355. $retval .= '</li>';
  356. }
  357. $retval .= '</ul>';
  358. $retval .= '<div class="clearfloat"></div>';
  359. return $retval;
  360. }
  361. }
  362. ?>