Newer
Older
<?php
// $Id$
/**
* For the collection of memcache stats. This small .js file makes sure that the
* HTML displaying the stats is inside of the <body> 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' => array(
'title' => t('Access memcache statistics'),
),
);
}
/**
* Implementation of hook_menu().
*/
function memcache_admin_menu() {
$items['admin/config/system/memcache'] = array(
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
'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', 'reset', '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, reset, 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', array('server' => $server, 'stats' => $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(
'variables' => 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($variables) {
$server = $variables['server'];
$stats = $variables['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('header' => array(), 'rows' => $rs)));
}
else {
$rows[] = array($key, $value);
}
}
return theme('table', array('header' => array(t('Property'), t('Value')), 'rows' => $rows, 'caption' => $server));
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
}
/**
* 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')) {
$stats = array();
foreach ($_memcache_statistics as $stat => $value) {
$items = array('items' => $value);
$stats[] = "<strong>$stat:</strong> ". theme('item_list', array('items' => $value));
}
if (!empty($stats)) {
$output = theme('item_list', array('items' => $stats));
// 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'). '</h2>'. $output. '</div>';
}
}
}