You are here

memcache_admin.module in Memcache API and Integration 5

File

memcache_admin/memcache_admin.module
View source
<?php

/**
 * 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',
  );
}

/**
 * Implementation of hook_menu
 */
function memcache_admin_menu($may_cache) {
  $items = array();
  if ($may_cache) {
    $items[] = array(
      'path' => 'admin/settings/memcache',
      'title' => t('Memcache'),
      'callback' => 'drupal_get_form',
      'callback arguments' => array(
        'memcache_admin_admin_settings',
      ),
      'access' => user_access('administer site configuration'),
      'type' => MENU_NORMAL_ITEM,
    );
    $items[] = array(
      'path' => 'admin/logs/memcache',
      'callback' => 'memcache_admin_stats',
      'title' => t('Memcache status'),
      'access' => user_access('access memcache statistics'),
      'description' => t("View the statistics for this site's memcache and generate new settings."),
      'weight' => 1,
    );
  }
  else {
    if (arg(0) == 'admin' && arg(1) == 'logs' && arg(2) == 'memcache') {
      $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[] = array(
            'path' => 'admin/logs/memcache/' . $cluster,
            'type' => $count == 0 ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK,
            'callback' => 'memcache_admin_stats',
            'callback arguments' => array(
              $cluster,
            ),
            'title' => $cluster,
            'access' => user_access('access memcache statistics'),
            'weight' => $count,
          );
          $count++;
          if ($cluster == $current_cluster) {
            $sub_count = 0;
            foreach (array(
              'default',
              'reset',
              'malloc',
              'maps',
              'slabs',
              'items',
              'sizes',
            ) as $type) {
              $items[] = array(
                'path' => 'admin/logs/memcache/' . $cluster . '/' . $type,
                'type' => $type == 'default' ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK,
                'callback' => 'memcache_admin_stats',
                'callback arguments' => array(
                  $cluster,
                  $type,
                ),
                'title' => $type,
                'access' => user_access('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', $server, $values);
        }
        else {
          drupal_set_message(t('Unable to connect to server: %server', array(
            '%server' => $server,
          )));
        }
      }
    }
    else {
      $output = '';
      drupal_set_message(t('No available statistics for this bin.'));
    }
  }
  return $output;
}

/**
 * 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')) {
    $data = array();
    foreach ($_memcache_statistics as $bin => $stats) {
      foreach ($stats as $key => $value) {
        $stats[$key] = check_plain($value);
      }
      $data[] = "<strong>{$stat}:</strong> " . theme('item_list', $stats);
    }
    if (!empty($data)) {
      $output = theme('item_list', $data);

      // 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>';
    }
  }
}

Functions

Namesort descending Description
memcache_admin_admin_settings Settings form
memcache_admin_init 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.
memcache_admin_menu Implementation of hook_menu
memcache_admin_perm Implementation of hook_perm
memcache_admin_shutdown See memcache_admin_init() which registers this function as a shutdown function. Displays memcache stats in the footer.
memcache_admin_stats Memcahe Stats page
theme_memcache_admin_stats_table Theme function for rendering the output from memcache_admin_stats
_memcache_admin_get_bin_for_cluster Retrieve the cluster for any given bin