part of the HTML * document. */ function memcache_admin_init() { global $user; if (($user->uid == 0) || strstr($_SERVER['PHP_SELF'], 'update.php') || strstr($_GET['q'], 'autocomplete')) { // update.php relies on standard error handler } else { if ($user->uid) { drupal_add_js(drupal_get_path('module', 'memcache_admin'). '/memcache.js'); } register_shutdown_function('memcache_admin_shutdown'); } } /** * Implementation of hook_perm(). */ function memcache_admin_perm() { return array('access memcache statistics'); } /** * Implementation of hook_menu(). */ function memcache_admin_menu() { $items['admin/settings/memcache'] = array( 'title' => 'Memcache', 'description' => 'Show or hide memcache statistics at the bottom of each page.', 'page callback' => 'drupal_get_form', 'page arguments' => array('memcache_admin_admin_settings'), 'access arguments' => array('administer site configuration'), ); $items['admin/reports/memcache'] = array( 'title' => 'Memcache status', 'description' => "View the statistics for this site's memcache.", 'page callback' => 'memcache_admin_stats', 'access arguments' => array('access memcache statistics'), 'weight' => 1, ); $memache_servers = variable_get('memcache_servers', array()); $clusters = array(); foreach($memache_servers as $server => $cluster) { $clusters[$cluster]['servers'][] = $server; $clusters[$cluster]['bin'] = _memcache_admin_get_bin_for_cluster($cluster); } $count = 0; foreach ($clusters as $cluster => $cluster_info) { if ($cluster_info['bin']) { if (empty($current_cluster)) { $current_cluster = arg(3); if (empty($current_cluster)) { $current_cluster = $cluster; } } $items['admin/reports/memcache/'. $cluster] = array( 'title' => $cluster, 'type' => $count == 0 ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK, 'page callback' => 'memcache_admin_stats', 'page arguments' => array($cluster), 'access arguments' => array('access memcache statistics'), 'weight' => $count, ); $count++; $sub_count = 0; foreach (array('default', 'malloc', 'maps', 'slabs', 'items', 'sizes') as $type) { $items['admin/reports/memcache/'. $cluster .'/'. $type] = array( 'type' => $type == 'default' ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK, 'page callback' => 'memcache_admin_stats', 'page arguments' => array($cluster, $type), 'title' => $type, 'access arguments' => array('access memcache statistics'), 'weight' => $sub_count, ); $sub_count++; } } } return $items; } /** * Settings form. */ function memcache_admin_admin_settings() { $form['show_memcache_statistics'] = array('#type' => 'checkbox', '#title' => t('Show memcache statistics at the bottom of each page'), '#default_value' => variable_get('show_memcache_statistics', 1), '#description' => t("These statistics will be visible to users with the 'access memcache statistics' permission."), ); return system_settings_form($form); } /** * Memcahe Stats page * * @param string $cluster - which cluster to view? * @param string $type - which type of stat, eg: default, malloc, maps, cachedump, slabs, items or sizes * @return string */ function memcache_admin_stats($cluster = 'default', $type = 'default') { $bin = _memcache_admin_get_bin_for_cluster($cluster); if ($bin) { $stats = dmemcache_stats($bin, $type); if (is_array($stats) && count($stats)) { $output = ''; foreach ($stats as $server => $values) { if (is_array($values)) { // Do some custome value tweaks for specific stat page types. switch ($type) { case 'default' : $values['uptime'] = format_interval($values['uptime']); $values['time'] = format_date($values['time']); $values['bytes'] = format_size($values['bytes']); $values['bytes_read'] = format_size($values['bytes_read']); $values['bytes_written'] = format_size($values['bytes_written']); $values['limit_maxbytes'] = format_size($values['limit_maxbytes']); //Custom Entries $values['hit_percentage'] = ($values['cmd_get'] > 0) ? number_format(100.0 * $values['get_hits'] / $values['cmd_get'], 2) . '%' : '0'; $mem_used = intval($values['bytes']) / (intval($values['limit_maxbytes']) * 1024); $values['mem_used'] = number_format(100.0 * $mem_used, 2) . '%'; break; } $output .= theme('memcache_admin_stats_table', $server, $values); } else { drupal_set_message(t('Unable to get statistic from server %server', array('%server' => $server))); } } } else { $output = ''; drupal_set_message(t('No available statistics for this bin.')); } } return $output; } /** * Implementation of hook_theme(). */ function memcache_admin_theme() { return array( 'memcache_admin_stats_table' => array( 'arguments' => array('server' => NULL, 'stats' => NULL), ) ); } /** * Theme function for rendering the output from memcache_admin_stats * * @param string $server - Server name:port for caption for the table * @param array $stats - array of key/value string pairs for the table results * @return string */ function theme_memcache_admin_stats_table($server, $stats) { $rows = array(); foreach ($stats as $key => $value) { if (is_array($value)) { $rs = array(); foreach ($value as $k => $v) { $rs[] = array($k, $v); } $rows[] = array($key, theme('table', array(), $rs)); } else { $rows[] = array($key, $value); } } return theme('table', array(t('Property'), t('Value')), $rows, array(), $server); } /** * Retrieve the cluster for any given bin * * @param string $cluster - Cluster ID * @return string */ function _memcache_admin_get_bin_for_cluster($cluster) { static $cluster_map = array(); if (!isset($cluster_map[$cluster])) { $memache_bins = variable_get('memcache_bins', array()); if ($mapping = array_search($cluster, $memache_bins)) { $cluster_map[$cluster] = $mapping; } else { $cluster_map[$cluster] = 'default'; } } return $cluster_map[$cluster]; } /** * See memcache_admin_init() which registers this function as a shutdown function. * Displays memcache stats in the footer. */ function memcache_admin_shutdown() { global $_memcache_statistics; // Try not to break non-HTML pages. if (function_exists('drupal_get_headers')) { $headers = drupal_get_headers(); if(strstr($headers, 'xml') || strstr($headers, 'javascript') || strstr($headers, 'plain')) { return; } } if (variable_get('show_memcache_statistics', TRUE) && function_exists('user_access') && user_access('access memcache statistics')) { if (!empty($_memcache_statistics)) { foreach ($_memcache_statistics as $row => $stats) { $_memcache_statistics[$row][1] = check_plain($stats[1]); $_memcache_statistics[$row][2] = check_plain($stats[2]); } $headers = array(t('Operation'), t('Bin'), t('Key'), t('Hit')); $output = theme('table', $headers, $_memcache_statistics); // this makes sure all of the HTML is within the even though this