2 /* vim: set expandtab sw=4 ts=4 sts=4: */
4 * PMA_ServerStatusData class
5 * Used by server_status_*.php pages
10 if (! defined('PHPMYADMIN')) {
15 * This class provides data about the server status
17 * All properties of the class are read-only
19 * TODO: Use lazy initialisation for some of the properties
20 * since not all of the server_status_*.php pages need
21 * all the data that this class provides.
25 class PMA_ServerStatusData
31 public $allocationMap;
40 * An empty setter makes the above properties read-only
42 * @param string $a key
43 * @param mixed $b value
47 public function __set($a, $b)
53 * Gets the allocations for constructor
57 private function _getAllocations()
60 // variable name => section
61 // variable names match when they begin with the given string
64 'Innodb_' => 'innodb',
66 'Handler_' => 'handler',
67 'Qcache_' => 'qcache',
68 'Threads_' => 'threads',
69 'Slow_launch_threads' => 'threads',
71 'Binlog_cache_' => 'binlog_cache',
72 'Created_tmp_' => 'created_tmp',
75 'Delayed_' => 'delayed',
76 'Not_flushed_delayed_rows' => 'delayed',
78 'Flush_commands' => 'query',
79 'Last_query_cost' => 'query',
80 'Slow_queries' => 'query',
82 'Prepared_stmt_count' => 'query',
84 'Select_' => 'select',
87 'Open_tables' => 'table',
88 'Opened_tables' => 'table',
89 'Open_table_definitions' => 'table',
90 'Opened_table_definitions' => 'table',
91 'Table_locks_' => 'table',
93 'Rpl_status' => 'repl',
100 'Open_files' => 'files',
101 'Open_streams' => 'files',
102 'Opened_files' => 'files',
107 * Gets the sections for constructor
111 private function _getSections()
114 // section => section name (description)
116 'query' => __('SQL query'),
117 'innodb' => 'InnoDB',
119 'handler' => __('Handler'),
120 'qcache' => __('Query cache'),
121 'threads' => __('Threads'),
122 'binlog_cache' => __('Binary log'),
123 'created_tmp' => __('Temporary data'),
124 'delayed' => __('Delayed inserts'),
125 'key' => __('Key cache'),
126 'select' => __('Joins'),
127 'repl' => __('Replication'),
128 'sort' => __('Sorting'),
129 'table' => __('Tables'),
130 'tc' => __('Transaction coordinator'),
131 'files' => __('Files'),
133 'other' => __('Other')
138 * Gets the links for constructor
142 private function _getLinks()
145 // variable or section name => (name => url)
147 $links['table'][__('Flush (close) all tables')] = $this->selfUrl
153 $links['table'][__('Show open tables')]
154 = 'sql.php' . PMA_URL_getCommon(
156 'sql_query' => 'SHOW OPEN TABLES',
157 'goto' => $this->selfUrl
,
161 if ($GLOBALS['replication_info']['master']['status']) {
162 $links['repl'][__('Show slave hosts')]
163 = 'sql.php' . PMA_URL_getCommon(
165 'sql_query' => 'SHOW SLAVE HOSTS',
166 'goto' => $this->selfUrl
,
169 $links['repl'][__('Show master status')] = '#replication_master';
171 if ($GLOBALS['replication_info']['slave']['status']) {
172 $links['repl'][__('Show slave status')] = '#replication_slave';
175 $links['repl']['doc'] = 'replication';
177 $links['qcache'][__('Flush query cache')]
181 'flush' => 'QUERY CACHE'
184 $links['qcache']['doc'] = 'query_cache';
186 $links['threads']['doc'] = 'mysql_threads';
188 $links['key']['doc'] = 'myisam_key_cache';
190 $links['binlog_cache']['doc'] = 'binary_log';
192 $links['Slow_queries']['doc'] = 'slow_query_log';
194 $links['innodb'][__('Variables')]
195 = 'server_engines.php?engine=InnoDB&'
196 . PMA_URL_getCommon(array(), 'html', '');
197 $links['innodb'][__('InnoDB Status')]
198 = 'server_engines.php'
201 'engine' => 'InnoDB',
205 $links['innodb']['doc'] = 'innodb';
211 * Calculate some values
213 * @param array $server_status contains results of SHOW GLOBAL STATUS
214 * @param array $server_variables contains results of SHOW GLOBAL VARIABLES
216 * @return array $server_status
218 private function _calculateValues($server_status, $server_variables)
220 // Key_buffer_fraction
221 if (isset($server_status['Key_blocks_unused'])
222 && isset($server_variables['key_cache_block_size'])
223 && isset($server_variables['key_buffer_size'])
225 $server_status['Key_buffer_fraction_%']
227 - $server_status['Key_blocks_unused']
228 * $server_variables['key_cache_block_size']
229 / $server_variables['key_buffer_size']
231 } elseif (isset($server_status['Key_blocks_used'])
232 && isset($server_variables['key_buffer_size'])
234 $server_status['Key_buffer_fraction_%']
235 = $server_status['Key_blocks_used']
237 / $server_variables['key_buffer_size'];
240 // Ratio for key read/write
241 if (isset($server_status['Key_writes'])
242 && isset($server_status['Key_write_requests'])
243 && $server_status['Key_write_requests'] > 0
245 $key_writes = $server_status['Key_writes'];
246 $key_write_requests = $server_status['Key_write_requests'];
247 $server_status['Key_write_ratio_%']
248 = 100 * $key_writes / $key_write_requests;
251 if (isset($server_status['Key_reads'])
252 && isset($server_status['Key_read_requests'])
253 && $server_status['Key_read_requests'] > 0
255 $key_reads = $server_status['Key_reads'];
256 $key_read_requests = $server_status['Key_read_requests'];
257 $server_status['Key_read_ratio_%']
258 = 100 * $key_reads / $key_read_requests;
261 // Threads_cache_hitrate
262 if (isset($server_status['Threads_created'])
263 && isset($server_status['Connections'])
264 && $server_status['Connections'] > 0
267 $server_status['Threads_cache_hitrate_%']
268 = 100 - $server_status['Threads_created']
269 / $server_status['Connections'] * 100;
271 return $server_status;
275 * Sort variables into arrays
277 * @param array $server_status contains results of SHOW GLOBAL STATUS
278 * @param array $allocations allocations for sections
279 * @param array $allocationMap map variables to their section
280 * @param array $sectionUsed is a section used?
281 * @param array $used_queries used queries
283 * @return array ($allocationMap, $sectionUsed, $used_queries)
285 private function _sortVariables(
286 $server_status, $allocations, $allocationMap, $sectionUsed,
289 foreach ($server_status as $name => $value) {
290 $section_found = false;
291 foreach ($allocations as $filter => $section) {
292 if (/*overload*/mb_strpos($name, $filter) !== false) {
293 $allocationMap[$name] = $section;
294 $sectionUsed[$section] = true;
295 $section_found = true;
296 if ($section == 'com' && $value > 0) {
297 $used_queries[$name] = $value;
299 break; // Only exits inner loop
302 if (! $section_found) {
303 $allocationMap[$name] = 'other';
304 $sectionUsed['other'] = true;
307 return array($allocationMap, $sectionUsed, $used_queries);
313 public function __construct()
315 $this->selfUrl
= basename($GLOBALS['PMA_PHP_SELF']);
317 // get status from server
318 $server_status_result = $GLOBALS['dbi']->tryQuery('SHOW GLOBAL STATUS');
319 $server_status = array();
320 if ($server_status_result === false) {
321 $this->dataLoaded
= false;
323 $this->dataLoaded
= true;
324 while ($arr = $GLOBALS['dbi']->fetchRow($server_status_result)) {
325 $server_status[$arr[0]] = $arr[1];
327 $GLOBALS['dbi']->freeResult($server_status_result);
331 // Drizzle doesn't put query statistics into variables, add it
332 $sql = "SELECT concat('Com_', variable_name), variable_value "
333 . "FROM data_dictionary.GLOBAL_STATEMENTS";
334 $statements = $GLOBALS['dbi']->fetchResult($sql, 0, 1);
335 $server_status = array_merge($server_status, $statements);
338 // for some calculations we require also some server settings
339 $server_variables = $GLOBALS['dbi']->fetchResult(
340 'SHOW GLOBAL VARIABLES', 0, 1
343 // cleanup of some deprecated values
344 $server_status = self
::cleanDeprecated($server_status);
346 // calculate some values
347 $server_status = $this->_calculateValues(
348 $server_status, $server_variables
351 // split variables in sections
352 $allocations = $this->_getAllocations();
354 $sections = $this->_getSections();
356 // define some needful links/commands
357 $links = $this->_getLinks();
359 // Variable to contain all com_ variables (query statistics)
360 $used_queries = array();
362 // Variable to map variable names to their respective section name
363 // (used for js category filtering)
364 $allocationMap = array();
366 // Variable to mark used sections
367 $sectionUsed = array();
369 // sort vars into arrays
371 $allocationMap, $sectionUsed, $used_queries
372 ) = $this->_sortVariables(
373 $server_status, $allocations, $allocationMap, $sectionUsed,
378 $used_queries = $GLOBALS['dbi']->fetchResult(
379 'SELECT * FROM data_dictionary.global_statements',
383 unset($used_queries['admin_commands']);
385 // admin commands are not queries (e.g. they include COM_PING,
386 // which is excluded from $server_status['Questions'])
387 unset($used_queries['Com_admin_commands']);
390 // Set all class properties
391 $this->db_isLocal
= false;
392 $serverHostToLower = /*overload*/mb_strtolower(
393 $GLOBALS['cfg']['Server']['host']
395 if ($serverHostToLower === 'localhost'
396 ||
$GLOBALS['cfg']['Server']['host'] === '127.0.0.1'
397 ||
$GLOBALS['cfg']['Server']['host'] === '::1'
399 $this->db_isLocal
= true;
401 $this->status
= $server_status;
402 $this->sections
= $sections;
403 $this->variables
= $server_variables;
404 $this->used_queries
= $used_queries;
405 $this->allocationMap
= $allocationMap;
406 $this->links
= $links;
407 $this->sectionUsed
= $sectionUsed;
411 * cleanup of some deprecated values
413 * @param array $server_status status array to process
417 public static function cleanDeprecated($server_status)
420 'Com_prepare_sql' => 'Com_stmt_prepare',
421 'Com_execute_sql' => 'Com_stmt_execute',
422 'Com_dealloc_sql' => 'Com_stmt_close',
424 foreach ($deprecated as $old => $new) {
425 if (isset($server_status[$old]) && isset($server_status[$new])) {
426 unset($server_status[$old]);
429 return $server_status;
433 * Generates menu HTML
437 public function getMenuHtml()
439 $url_params = PMA_URL_getCommon();
442 'name' => __('Server'),
443 'url' => 'server_status.php'
446 'name' => __('Processes'),
447 'url' => 'server_status_processes.php'
450 'name' => __('Query statistics'),
451 'url' => 'server_status_queries.php'
454 'name' => __('All status variables'),
455 'url' => 'server_status_variables.php'
458 'name' => __('Monitor'),
459 'url' => 'server_status_monitor.php'
462 'name' => __('Advisor'),
463 'url' => 'server_status_advisor.php'
467 $retval = '<ul id="topmenu2">';
468 foreach ($items as $item) {
470 if ($item['url'] === $this->selfUrl
) {
471 $class = ' class="tabactive"';
474 $retval .= '<a' . $class;
475 $retval .= ' href="' . $item['url'] . $url_params . '">';
476 $retval .= $item['name'];
481 $retval .= '<div class="clearfloat"></div>';
487 * Builds a <select> list for refresh rates
489 * @param string $name Name of select
490 * @param int $defaultRate Currently chosen rate
491 * @param array $refreshRates List of refresh rates
495 public static function getHtmlForRefreshList($name,
497 $refreshRates = Array(1, 2, 5, 10, 20, 40, 60, 120, 300, 600)
499 $return = '<select name="' . $name . '" id="id_' . $name
500 . '" class="refreshRate">';
501 foreach ($refreshRates as $rate) {
502 $selected = ($rate == $defaultRate)?
' selected="selected"':'';
503 $return .= '<option value="' . $rate . '"' . $selected . '>';
506 _ngettext('%d second', '%d seconds', $rate), $rate
511 _ngettext('%d minute', '%d minutes', $rate), $rate
514 $return .= '</option>';
516 $return .= '</select>';