memcache_admin.module in Memcache API and Integration 7
Same filename and directory in other branches
For the collection and display of memcache stats.
This module adds a small .js file to makes sure that the HTML displaying the stats is inside of the <body> part of the HTML document.
File
memcache_admin/memcache_admin.moduleView source
<?php
/**
* @file
* For the collection and display of memcache stats.
*
* This module adds a small .js file to makes sure that the HTML displaying the
* stats is inside of the <body> part of the HTML document.
*/
/**
* Implements hook_init().
*/
function memcache_admin_init() {
global $user;
if ($user->uid == 0 || strstr($_SERVER['PHP_SELF'], 'update.php') || isset($_GET['q']) && (in_array($_GET['q'], array(
'upload/js',
'admin/content/node-settings/rebuild',
)) || substr($_GET['q'], 0, strlen('system/files')) == 'system/files' || substr($_GET['q'], 0, strlen('batch')) == 'batch' || 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');
}
}
/**
* Implements hook_perm().
*/
function memcache_admin_permission() {
return array(
'access memcache statistics' => array(
'title' => t('Access memcache statistics'),
),
'access slab cachedump' => array(
'title' => t('Access cachedump of memcache slab'),
'restrict access' => TRUE,
),
);
}
/**
* Implements hook_menu().
*/
function memcache_admin_menu() {
$items['admin/config/system/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 statistics',
'description' => "View statistics for all configured memcache servers.",
'page callback' => 'memcache_admin_stats',
'access arguments' => array(
'access memcache statistics',
),
'weight' => 1,
);
$memcache_servers = variable_get('memcache_servers', array(
'127.0.0.1:11211' => 'default',
));
$clusters = array();
foreach ($memcache_servers as $server => $bin) {
if (function_exists('dmemcache_object_cluster') && ($cluster = dmemcache_object_cluster($bin))) {
$name = $cluster['cluster'];
$clusters[$name]['servers'][] = $server;
$clusters[$name]['bin'] = _memcache_admin_get_bin_for_cluster($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++,
);
foreach ($cluster_info['servers'] as $server) {
$items["admin/reports/memcache/{$cluster}/{$server}"] = array(
'title' => check_plain($server),
'type' => MENU_CALLBACK,
'page callback' => 'memcache_admin_stats_raw',
'page arguments' => array(
$cluster,
$server,
),
'access arguments' => array(
'access memcache statistics',
),
);
foreach (memcache_admin_stats_types($cluster) as $type) {
$items["admin/reports/memcache/{$cluster}/{$server}/{$type}"] = array(
'type' => MENU_CALLBACK,
'page callback' => 'memcache_admin_stats_raw',
'page arguments' => array(
$cluster,
$server,
$type,
),
'title' => $type,
'access arguments' => array(
'access memcache statistics',
),
);
}
}
}
}
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', FALSE),
'#description' => t("These statistics will be visible to users with the 'access memcache statistics' permission."),
);
return system_settings_form($form);
}
/**
* Helper function. Returns the bin name.
*/
function _memcache_admin_default_bin($bin) {
if ($bin == 'default') {
return 'cache';
}
return $bin;
}
/**
* Statistics report: format total and open connections.
*/
function _memcache_admin_stats_connections($stats) {
return t('!current open of !total total', array(
'!current' => number_format($stats['curr_connections']),
'!total' => number_format($stats['total_connections']),
));
}
/**
* Statistics report: calculate # of set cmds and total cmds.
*/
function _memcache_admin_stats_sets($stats) {
if ($stats['cmd_set'] + $stats['cmd_get'] == 0) {
$sets = 0;
}
else {
$sets = $stats['cmd_set'] / ($stats['cmd_set'] + $stats['cmd_get']) * 100;
}
if (empty($stats['uptime'])) {
$average = 0;
}
else {
$average = $sets / $stats['uptime'];
}
return t('!average/s; !set sets (!sets%) of !total commands', array(
'!average' => number_format($average, 2),
'!sets' => number_format($sets, 2),
'!set' => number_format($stats['cmd_set']),
'!total' => number_format($stats['cmd_set'] + $stats['cmd_get']),
));
}
/**
* Statistics report: calculate # of get cmds, broken down by hits and misses.
*/
function _memcache_admin_stats_gets($stats) {
if ($stats['cmd_set'] + $stats['cmd_get'] == 0) {
$gets = 0;
}
else {
$gets = $stats['cmd_get'] / ($stats['cmd_set'] + $stats['cmd_get']) * 100;
}
if (empty($stats['uptime'])) {
$average = 0;
}
else {
$average = $stats['cmd_get'] / $stats['uptime'];
}
return t('!average/s; !total gets (!gets%); !hit hits (!percent_hit%) !miss misses (!percent_miss%)', array(
'!average' => number_format($average, 2),
'!gets' => number_format($gets, 2),
'!hit' => number_format($stats['get_hits']),
'!percent_hit' => $stats['cmd_get'] > 0 ? number_format($stats['get_hits'] / $stats['cmd_get'] * 100, 2) : '0.00',
'!miss' => number_format($stats['get_misses']),
'!percent_miss' => $stats['cmd_get'] > 0 ? number_format($stats['get_misses'] / $stats['cmd_get'] * 100, 2) : '0.00',
'!total' => number_format($stats['cmd_get']),
));
}
/**
* Statistics report: calculate # of increments and decrements.
*/
function _memcache_admin_stats_counters($stats) {
if (!is_array($stats)) {
$stats = array();
}
$stats += array(
'incr_hits' => 0,
'incr_misses' => 0,
'decr_hits' => 0,
'decr_misses' => 0,
);
return t('!incr increments, !decr decrements', array(
'!incr' => number_format($stats['incr_hits'] + $stats['incr_misses']),
'!decr' => number_format($stats['decr_hits'] + $stats['decr_misses']),
));
}
/**
* Statistics report: calculate bytes transferred.
*/
function _memcache_admin_stats_transfer($stats) {
if ($stats['bytes_written'] == 0) {
$written = 0;
}
else {
$written = $stats['bytes_read'] / $stats['bytes_written'] * 100;
}
return t('!to:!from (!written% to cache)', array(
'!to' => format_size((int) $stats['bytes_read']),
'!from' => format_size((int) $stats['bytes_written']),
'!written' => number_format($written, 2),
));
}
/**
* Statistics report: calculate per-connection averages.
*/
function _memcache_admin_stats_average($stats) {
if ($stats['total_connections'] == 0) {
$get = 0;
$set = 0;
$read = 0;
$write = 0;
}
else {
$get = $stats['cmd_get'] / $stats['total_connections'];
$set = $stats['cmd_set'] / $stats['total_connections'];
$read = $stats['bytes_written'] / $stats['total_connections'];
$write = $stats['bytes_read'] / $stats['total_connections'];
}
return t('!read in !get gets; !write in !set sets', array(
'!get' => number_format($get, 2),
'!set' => number_format($set, 2),
'!read' => format_size(number_format($read, 2)),
'!write' => format_size(number_format($write, 2)),
));
}
/**
* Statistics report: calculate available memory.
*/
function _memcache_admin_stats_memory($stats) {
if ($stats['limit_maxbytes'] == 0) {
$percent = 0;
}
else {
$percent = 100 - $stats['bytes'] / $stats['limit_maxbytes'] * 100;
}
return t('!available (!percent%) of !total', array(
'!available' => format_size($stats['limit_maxbytes'] - $stats['bytes']),
'!percent' => number_format($percent, 2),
'!total' => format_size($stats['limit_maxbytes']),
));
}
/**
* Helper function, reverse map the memcache_bins variable.
*/
function memcache_admin_bin_mapping($bin = 'cache') {
$bins = array_flip(variable_get('memcache_bins', array(
'cache' => 'default',
)));
if (isset($bins[$bin])) {
return $bins[$bin];
}
else {
// The default bin is 'cache'.
return _memcache_admin_default_bin($bin);
}
}
/**
* Callback for the Memcache Stats page.
*
* @return string
* The page output.
*/
function memcache_admin_stats($bin = 'default') {
if (!class_exists('MemCacheDrupal', FALSE)) {
return t('There is a problem with your memcache configuration. Please review !readme for help resolving the following issue: %error.', array(
'!readme' => l('README.txt', 'http://cgit.drupalcode.org/memcache/tree/README.txt?id=refs/heads;id2=7.x-1.x'),
'%error' => t('cache_backends not properly configured in settings.php, failed to load required file memcache.inc'),
));
}
if ($memcache_debug_log = variable_get('memcache_debug_log', FALSE)) {
if (variable_get('memcache_debug_verbose', FALSE)) {
$verbose = t('verbose');
}
else {
$verbose = '';
}
drupal_set_message(t('You are writing !verbose debug logs to !debug_log.', array(
'!verbose' => $verbose,
'!debug_log' => $memcache_debug_log,
)), 'warning');
}
$bin = memcache_admin_bin_mapping($bin);
$output = '';
$server = array();
$stats = dmemcache_stats($bin, 'default', TRUE);
if (empty($stats[$bin])) {
// Failed to load statistics. Provide a useful error about where to get
// more information and help.
drupal_set_message(t('Failed to retreive statistics. There may be a problem with your Memcache configuration. Please review %readme and !more for more information.', array(
'%readme' => 'README.txt',
'admin/reports/status',
'!more' => module_exists('memcache') ? t('visit the Drupal admin !status page', array(
'!status' => l(t('status report'), 'admin/reports/status'),
)) : t('!enable the memcache module', array(
'!enable' => l(t('enable'), 'admin/modules', array(
'fragment' => 'edit-modules-performance-and-scalability',
)),
)),
)), 'error');
}
else {
$stats = $stats[$bin];
$aggregate = array_pop($stats);
$mc = dmemcache_object($bin);
if ($mc instanceof Memcached) {
$version = t('Memcached v!version', array(
'!version' => phpversion('Memcached'),
));
}
elseif ($mc instanceof Memcache) {
$version = t('Memcache v!version', array(
'!version' => phpversion('Memcache'),
));
}
else {
$version = t('Unknown');
drupal_set_message(t('Failed to detect the memcache PECL extension.'), 'error');
}
$memcache_servers = variable_get('memcache_servers', array(
'127.0.0.1:11211' => 'default',
));
foreach ($stats as $server => $statistics) {
if (empty($statistics['uptime'])) {
drupal_set_message(t('Failed to connect to server at %address.', array(
'%address' => $server,
)), 'error');
}
else {
$servers[] = $server;
$data['server_overview'][$server] = t('v!version running !uptime', array(
'!version' => check_plain($statistics['version']),
'!uptime' => format_interval($statistics['uptime']),
));
$data['server_pecl'][$server] = t('n/a');
$data['server_serialize'][$server] = t('n/a');
$data['server_time'][$server] = format_date($statistics['time']);
$data['server_connections'][$server] = _memcache_admin_stats_connections($statistics);
$data['cache_sets'][$server] = _memcache_admin_stats_sets($statistics);
$data['cache_gets'][$server] = _memcache_admin_stats_gets($statistics);
$data['cache_counters'][$server] = _memcache_admin_stats_counters($statistics);
$data['cache_transfer'][$server] = _memcache_admin_stats_transfer($statistics);
$data['cache_average'][$server] = _memcache_admin_stats_average($statistics);
$data['memory_available'][$server] = _memcache_admin_stats_memory($statistics);
$data['memory_evictions'][$server] = number_format($statistics['evictions']);
}
}
// Don't display aggregate totals if there's only one server.
if (count($servers) == 1) {
$aggregate = array();
}
// Build a custom report array.
$report = array();
// Report server uptime.
$item = array(
'label' => t('Uptime'),
'servers' => $data['server_overview'],
);
if (count($aggregate)) {
$item['total'] = t('n/a');
}
$report['uptime'][] = $item;
// Report server PECL extension.
$item = array(
'label' => t('PECL extension'),
);
if (count($aggregate)) {
$item['servers'] = $data['server_pecl'];
$item['total'] = $version;
}
else {
$item['servers'] = array(
$servers[0] => $version,
);
}
$report['uptime'][] = $item;
// Report which serialize function is being used.
$item = array(
'label' => t('Serialize function'),
);
$serialize_function = dmemcache_serialize();
if ($serialize_function != 'serialize') {
$serialize_function = t('!function v!version', array(
'!function' => $serialize_function,
'!version' => phpversion(dmemcache_serialize_extension()),
));
}
if (count($aggregate)) {
$item['servers'] = $data['server_serialize'];
$item['total'] = $serialize_function;
}
else {
$item['servers'] = array(
$servers[0] => $serialize_function,
);
}
$report['uptime'][] = $item;
// Report server time.
$item = array(
'label' => t('Time'),
'servers' => $data['server_time'],
);
if (count($aggregate)) {
$item['total'] = t('n/a');
}
$report['uptime'][] = $item;
// Report number of connections.
$item = array(
'label' => t('Connections'),
'servers' => $data['server_connections'],
);
if (count($aggregate)) {
$item['total'] = _memcache_admin_stats_connections($aggregate);
}
$report['uptime'][] = $item;
$stats = array(
'sets' => t('Sets'),
'gets' => t('Gets'),
'counters' => t('Counters'),
'transfer' => t('Transferred'),
'average' => t('Per-connection average'),
);
foreach ($stats as $type => $label) {
$item = array(
'label' => $label,
'servers' => $data["cache_{$type}"],
);
if (count($aggregate)) {
$func = "_memcache_admin_stats_{$type}";
$item['total'] = $func($aggregate);
}
$report['stats'][] = $item;
}
// Report on available memory.
$item = array(
'label' => t('Available memory'),
'servers' => $data['memory_available'],
);
if (count($aggregate)) {
$item['total'] = _memcache_admin_stats_memory($aggregate);
}
$report['memory'][] = $item;
// Report on memory evictions.
$item = array(
'label' => t('Evictions'),
'servers' => $data['memory_evictions'],
);
if (count($aggregate)) {
$item['total'] = number_format($aggregate['evictions']);
}
$report['memory'][] = $item;
$output = theme('memcache_admin_stats_table', array(
'bin' => $bin,
'servers' => $servers,
'report' => $report,
));
}
return $output;
}
/**
* Callback for the server statistics page.
*/
function memcache_admin_stats_raw($bin, $server, $type = 'default') {
$cluster = memcache_admin_bin_mapping($bin);
$slab = (int) arg(7);
if (arg(6) == 'cachedump' && !empty($slab) && user_access('access slab cachedump')) {
$stats = dmemcache_stats($cluster, arg(7), FALSE);
}
else {
$stats = dmemcache_stats($cluster, $type, FALSE);
}
$breadcrumbs = array(
l(t('Home'), NULL),
l(t('Administer'), 'admin'),
l(t('Reports'), 'admin/reports'),
l(t('Memcache'), 'admin/reports/memcache'),
l(t($bin), "admin/reports/memcache/{$bin}"),
);
if ($type == 'slabs' && arg(6) == 'cachedump' && user_access('access slab cachedump')) {
$breadcrumbs[] = l($server, "admin/reports/memcache/{$bin}/{$server}");
$breadcrumbs[] = l(t('slabs'), "admin/reports/memcache/{$bin}/{$server}/{$type}");
}
drupal_set_breadcrumb($breadcrumbs);
if (isset($stats[$cluster][$server]) && is_array($stats[$cluster][$server]) && count($stats[$cluster][$server])) {
$output = theme('memcache_admin_stats_raw_table', array(
'cluster' => $cluster,
'server' => $server,
'stats' => $stats[$cluster][$server],
'type' => $type,
));
}
elseif ($type == 'slabs' && is_array($stats[$cluster]) && count($stats[$cluster])) {
$output = theme('memcache_admin_stats_raw_table', array(
'cluster' => $cluster,
'server' => $server,
'stats' => $stats[$cluster],
'type' => $type,
));
}
else {
$output = theme('memcache_admin_stats_raw_table', array(
'cluster' => $cluster,
'server' => $server,
'stats' => array(),
'type' => $type,
));
drupal_set_message(t('No @type statistics for this bin.', array(
'@type' => $type,
)));
}
return $output;
}
/**
* Implements hook_theme().
*/
function memcache_admin_theme() {
return array(
'memcache_admin_stats_table' => array(
'variables' => array(
'bin' => NULL,
'servers' => NULL,
'report' => NULL,
),
),
'memcache_admin_stats_raw_table' => array(
'variables' => array(
'bin' => NULL,
'server' => NULL,
'stats' => NULL,
'type' => NULL,
),
),
);
}
/**
* Theme function for rendering the output from memcache_admin_stats.
*/
function theme_memcache_admin_stats_table($variables) {
$bin = $variables['bin'];
$servers = $variables['servers'];
$stats = $variables['report'];
$output = '';
$links = array();
$memcache_bins = variable_get('memcache_bins', array(
'cache' => 'default',
));
foreach ($servers as $server) {
$link_bin = $memcache_bins[$bin];
$links[] = l($server, check_plain("admin/reports/memcache/{$link_bin}/{$server}"));
}
if (count($servers) > 1) {
$headers = array_merge(array(
'',
t('Totals'),
), $links);
}
else {
$headers = array_merge(array(
'',
), $links);
}
foreach ($stats as $table => $data) {
$rows = array();
foreach ($data as $row) {
$r = array();
$r[] = $row['label'];
if (isset($row['total'])) {
$r[] = $row['total'];
}
foreach ($row['servers'] as $server) {
$r[] = $server;
}
$rows[] = $r;
}
$output .= theme('table', array(
'header' => $headers,
'rows' => $rows,
));
}
return $output;
}
/**
* Returns an array of available statistics types.
*/
function memcache_admin_stats_types($bin) {
module_load_include('inc', 'memcache', 'dmemcache');
if ($mc = dmemcache_object($bin)) {
if ($mc instanceof Memcache) {
// TODO: Determine which versions of the PECL memcache extension have
// these other stats types: 'malloc', 'maps', optionally detect this
// version and expose them. These stats are "subject to change without
// warning" unfortunately.
return array(
'default',
'slabs',
'items',
'sizes',
);
}
else {
// The Memcached PECL extension only offers the default statistics.
return array(
'default',
);
}
}
else {
return array();
}
}
/**
* Theme function to produce a table of statistics.
*/
function theme_memcache_admin_stats_raw_table($variables) {
$cluster = $variables['cluster'];
$server = $variables['server'];
$stats = $variables['stats'];
$current_type = isset($variables['type']) ? $variables['type'] : 'default';
$memcache_bins = variable_get('memcache_bins', array());
$bin = isset($memcache_bins[$cluster]) ? $memcache_bins[$cluster] : 'default';
// Provide navigation for the various memcache stats types.
if (count(memcache_admin_stats_types($bin)) > 1) {
foreach (memcache_admin_stats_types($bin) as $type) {
if ($current_type == $type) {
$links[] = '<strong>' . l(t($type), "admin/reports/memcache/{$bin}/{$server}/" . ($type == 'default' ? '' : $type)) . '</strong>';
}
else {
$links[] = l(t($type), "admin/reports/memcache/{$bin}/{$server}/" . ($type == 'default' ? '' : $type));
}
}
}
$output = !empty($links) ? implode(' | ', $links) : '';
$headers = array(
t('Property'),
t('Value'),
);
$rows = array();
// Items are returned as an array within an array within an array. We step
// in one level to properly display the contained statistics.
if ($current_type == 'items' && isset($stats['items'])) {
$stats = $stats['items'];
}
foreach ($stats as $key => $value) {
// Add navigation for getting a cachedump of individual slabs.
if (($current_type == 'slabs' || $current_type == 'items') && is_int($key) && user_access('access slab cachedump')) {
$key = l($key, "admin/reports/memcache/{$bin}/{$server}/slabs/cachedump/{$key}");
}
if (is_array($value)) {
$rs = array();
foreach ($value as $k => $v) {
// Format timestamp when viewing cachedump of individual slabs.
if ($current_type == 'slabs' && user_access('access slab cachedump') && arg(6) == 'cachedump' && $k == 0) {
$k = t('Size');
$v = format_size($v);
}
elseif ($current_type == 'slabs' && user_access('access slab cachedump') && arg(6) == 'cachedump' && $k == 1) {
$k = t('Expire');
$full_stats = dmemcache_stats($cluster, 'default');
$infinite = $full_stats[$cluster][$server]['time'] - $full_stats[$cluster][$server]['uptime'];
if ($v == $infinite) {
$v = t('infinite');
}
else {
$v = t('in @time', array(
'@time' => format_interval($v - time()),
));
}
}
$rs[] = array(
check_plain($k),
check_plain($v),
);
}
$rows[] = array(
$key,
theme('table', array(
'rows' => $rs,
)),
);
}
else {
$rows[] = array(
check_plain($key),
check_plain($value),
);
}
}
$output .= theme('table', array(
'header' => $headers,
'rows' => $rows,
));
return $output;
}
/**
* Retrieve the bin for any given cluster.
*
* @param string $cluster
* Cluster ID
*
* @return string
* The name of the bin.
*/
function _memcache_admin_get_bin_for_cluster($cluster) {
static $cluster_map = array();
if (!isset($cluster_map[$cluster])) {
$memcache_bins = variable_get('memcache_bins', array());
if ($mapping = array_search($cluster, $memcache_bins)) {
$cluster_map[$cluster] = $mapping;
}
else {
$cluster_map[$cluster] = 'default';
}
}
return $cluster_map[$cluster];
}
/**
* Helper function. Calculate a percentage.
*/
function _memcache_admin_stats_percent($a, $b) {
if ($a == 0) {
return 0;
}
elseif ($b == 0) {
return 100;
}
else {
return $a / ($a + $b) * 100;
}
}
/**
* Displays memcache stats in the footer. This is run as a shutdown function.
*
* @see memcache_admin_init()
*/
function memcache_admin_shutdown() {
global $_dmemcache_stats;
// Don't call theme() during shutdown if the registry has been rebuilt (such
// as when enabling/disabling modules on admin/build/modules) as things break.
// Instead, simply exit without displaying admin statistics for this page
// load. See http://drupal.org/node/616282 for discussion.
if (!function_exists('theme_get_registry') || !theme_get_registry()) {
return;
}
// Try not to break non-HTML pages.
if (function_exists('drupal_get_http_header')) {
$header = drupal_get_http_header('content-type');
if ($header) {
$formats = array(
'xml',
'javascript',
'json',
'plain',
'image',
'application',
'csv',
'x-comma-separated-values',
);
foreach ($formats as $format) {
if (strstr($header, $format)) {
return;
}
}
}
else {
// Workaround for CKEditor, see https://www.drupal.org/node/2556999
return;
}
}
if (variable_get('show_memcache_statistics', FALSE) && function_exists('user_access') && user_access('access memcache statistics')) {
$output = '';
if (!empty($_dmemcache_stats['ops'])) {
foreach ($_dmemcache_stats['ops'] as $row => $stats) {
$_dmemcache_stats['ops'][$row][0] = check_plain($stats[0]);
$_dmemcache_stats['ops'][$row][1] = number_format($stats[1], 2);
$hits = number_format(_memcache_admin_stats_percent($stats[2], $stats[3]), 1);
$misses = number_format(_memcache_admin_stats_percent($stats[3], $stats[2]), 1);
$_dmemcache_stats['ops'][$row][2] = number_format($stats[2]) . " ({$hits}%)";
$_dmemcache_stats['ops'][$row][3] = number_format($stats[3]) . " ({$misses}%)";
}
$variables = array(
'header' => array(
t('operation'),
t('total ms'),
t('total hits'),
t('total misses'),
),
'rows' => $_dmemcache_stats['ops'],
);
$output .= theme('table', $variables);
}
if (!empty($_dmemcache_stats['all'])) {
foreach ($_dmemcache_stats['all'] as $row => $stats) {
$_dmemcache_stats['all'][$row][1] = check_plain($stats[1]);
$_dmemcache_stats['all'][$row][2] = check_plain($stats[2]);
$_dmemcache_stats['all'][$row][3] = check_plain($stats[3]);
}
$variables = array(
'header' => array(
t('ms'),
t('operation'),
t('bin'),
t('key'),
t('status'),
),
'rows' => $_dmemcache_stats['all'],
);
$output .= theme('table', $variables);
}
if (!empty($output)) {
// This makes sure all of the HTML is within the <body> even though this
// <script> is outside it.
print '<div id="memcache-devel"><h2>' . t('Memcache statistics for @url', array(
'@url' => current_path(),
)) . '</h2>' . $output . '</div>';
}
}
}
Functions
Name | Description |
---|---|
memcache_admin_admin_settings | Settings form. |
memcache_admin_bin_mapping | Helper function, reverse map the memcache_bins variable. |
memcache_admin_init | Implements hook_init(). |
memcache_admin_menu | Implements hook_menu(). |
memcache_admin_permission | Implements hook_perm(). |
memcache_admin_shutdown | Displays memcache stats in the footer. This is run as a shutdown function. |
memcache_admin_stats | Callback for the Memcache Stats page. |
memcache_admin_stats_raw | Callback for the server statistics page. |
memcache_admin_stats_types | Returns an array of available statistics types. |
memcache_admin_theme | Implements hook_theme(). |
theme_memcache_admin_stats_raw_table | Theme function to produce a table of statistics. |
theme_memcache_admin_stats_table | Theme function for rendering the output from memcache_admin_stats. |
_memcache_admin_default_bin | Helper function. Returns the bin name. |
_memcache_admin_get_bin_for_cluster | Retrieve the bin for any given cluster. |
_memcache_admin_stats_average | Statistics report: calculate per-connection averages. |
_memcache_admin_stats_connections | Statistics report: format total and open connections. |
_memcache_admin_stats_counters | Statistics report: calculate # of increments and decrements. |
_memcache_admin_stats_gets | Statistics report: calculate # of get cmds, broken down by hits and misses. |
_memcache_admin_stats_memory | Statistics report: calculate available memory. |
_memcache_admin_stats_percent | Helper function. Calculate a percentage. |
_memcache_admin_stats_sets | Statistics report: calculate # of set cmds and total cmds. |
_memcache_admin_stats_transfer | Statistics report: calculate bytes transferred. |