[ Index ]

PHP Cross Reference of Drupal 6 (gatewave)

title

Body

[close]

/sites/all/modules/devel/performance/ -> performance.module (source)

   1  <?php
   2  // $Id: performance.module,v 1.2.2.33 2010/08/04 22:26:53 kbahey Exp $
   3  
   4  /**
   5   * @file
   6   *
   7   * Logs detailed and/or summary page generation time and memory
   8   * consumption for page requests.
   9   *
  10   * Copyright Khalid Baheyeldin 2008 of http://2bits.com
  11   */
  12  
  13  define('PERFORMANCE_KEY',          'dru-perf:'. $_SERVER['HTTP_HOST'] .':');
  14  define('PERFORMANCE_MEMCACHE_BIN', 'cache_performance');
  15  
  16  function performance_memcache_enabled() {
  17    global $conf;
  18  
  19    if (function_exists('dmemcache_set') && isset($conf['memcache_bins']['cache_performance'])) {
  20      return TRUE;
  21    }
  22    return FALSE;
  23  }
  24  
  25  function performance_menu() {
  26    $items = array();
  27  
  28    $items['admin/settings/performance_logging'] = array(
  29      'title'            => 'Performance logging',
  30      'description'      => 'Logs performance data: page generation times and memory usage.',
  31      'page callback'    => 'drupal_get_form',
  32      'page arguments'   => array('performance_settings'),
  33      'access arguments' => array('access administration pages'),
  34    );
  35  
  36    $items['admin/settings/performance_logging/apc_clear'] = array(
  37      'title'            => 'Clear APC',
  38      'description'      => 'Clears performance statistics collected in APC.',
  39      'page callback'    => 'drupal_get_form',
  40      'page arguments'   => array('performance_clear_apc_confirm'),
  41      'access arguments' => array('access administration pages'),
  42    );
  43  
  44    $items['admin/settings/performance_logging/memcache_clear'] = array(
  45      'title'            => 'Clear Memcache',
  46      'description'      => 'Clears performance statistics collected in Memcache.',
  47      'page callback'    => 'drupal_get_form',
  48      'page arguments'   => array('performance_clear_memcache_confirm'),
  49      'access arguments' => array('access administration pages'),
  50    );
  51  
  52    $items['admin/reports/performance_logging_summary'] = array(
  53      'title'            => 'Performance Logs: Summary',
  54      'description'      => 'View summary performance logs: page generation times and memory usage.',
  55      'page callback'    => 'performance_view_summary',
  56      'access arguments' => array('access site reports'),
  57    );
  58  
  59    $items['admin/reports/performance_logging_details'] = array(
  60      'title'            => 'Performance Logs: Details',
  61      'description'      => 'View detailed, per page, performance logs: page generation times and memory usage.',
  62      'page callback'    => 'performance_view_details',
  63      'access arguments' => array('access site reports'),
  64    );
  65  
  66    return $items;
  67  }
  68  
  69  function performance_settings() {
  70    $options = array(
  71      0 => t('Disabled'),
  72      1 => t('Enabled'),
  73    );
  74  
  75    if (function_exists('apc_cache_info')) {
  76      drupal_set_message(t('APC is enabled. It is reasonably safe to enable summary logging on live sites.'), 'status', FALSE);
  77    }
  78    else {
  79      drupal_set_message(t('APC is not enabled. It is <strong>not</strong> safe to enable summary logging to the database on live sites.'), 'error', FALSE);
  80    }
  81  
  82    $form['mode'] = array(
  83      '#type'  => 'fieldset',
  84      '#title' => t('Logging mode'),
  85      '#collapsible' => TRUE,
  86    );
  87  
  88    $form['mode']['performance_detail'] = array(
  89      '#type'          => 'select',
  90      '#title'         => t('Detailed logging'),
  91      '#default_value' => variable_get('performance_detail', 0),
  92      '#options'       => $options,
  93      '#description'   => t('Log memory usage and page generation times for every page. This logging mode is <strong>not</strong> suitable for large sites, as it can degrade performance severly. It is intended for use by developers, or on a test copy of the site.'),
  94    );
  95  
  96    $form['mode']['performance_summary_db'] = array(
  97      '#type'          => 'select',
  98      '#title'         => t('Summary logging (DB)'),
  99      '#default_value' => variable_get('performance_summary_db', 0),
 100      '#options'       => $options,
 101      '#description'   => t('Log summary data, such as average and maximum page generation times and memory usage to the database. This logging mode is <strong>not</strong> suitable for most live sites.'),
 102    );
 103  
 104    $disabled = TRUE;
 105    if (function_exists('apc_cache_info')) {
 106      $disabled = FALSE;
 107    }
 108  
 109    $form['mode']['performance_summary_apc'] = array(
 110      '#type'          => 'select',
 111      '#title'         => t('Summary logging (APC)'),
 112      '#default_value' => variable_get('performance_summary_apc', 0),
 113      '#options'       => $options,
 114      '#disabled'      => $disabled,
 115      '#description'   => t('Log summary data, such as average and maximum page generation times and memory usage to APC, if installed. The summary will be stored in APC memory, and hence there is no load on the database. This logging to APC is suitable for most live sites, unless the number of unique page accesses is excessively high.'),
 116    );
 117  
 118    $disabled = TRUE;
 119    if (performance_memcache_enabled()) {
 120      $disabled = FALSE;
 121    }
 122  
 123    $form['mode']['performance_summary_memcache'] = array(
 124      '#type'          => 'select',
 125      '#title'         => t('Summary logging (Memcached)'),
 126      '#default_value' => variable_get('performance_summary_memcache', 0),
 127      '#options'       => $options,
 128      '#disabled'      => $disabled,
 129      '#description'   => t('Log summary data, such as average and maximum page generation times and memory usage to Memcached, if installed. The summary will be stored in Memcached memory, and hence there is no load on the database. This logging to Memcached is suitable for most live sites, unless the number of unique page accesses is excessively high.'),
 130    );
 131  
 132    $form['other'] = array(
 133      '#type'  => 'fieldset',
 134      '#title' => t('Other'),
 135      '#collapsible' => TRUE,
 136    );
 137  
 138    $form['other']['dev_query'] = array(
 139      '#type'          => 'select',
 140      '#disabled'      => TRUE,
 141      '#title'         => t('Database Query timing and count'),
 142      '#default_value' => variable_get('dev_query', 0),
 143      '#options'       => $options,
 144      '#description'   => t('Log database query timing and query count for each page. This is useful to know if the bottleneck is in excessive database query counts, or the time required to execute those queries is high. Enabling this will incurr some memory overhead as query times and the actual query strings are cached in memory as arrays for each page, hence skewing the overall page memory reported. Please note that this settings is enabled or disabled in the settings of the devel module.'),
 145    );
 146  
 147    $form['other']['performance_threshold_accesses'] = array(
 148      '#type'          => 'select',
 149      '#title'         => t('Accesses threshold'),
 150      '#default_value' => variable_get('performance_threshold_accesses', 0),
 151      '#options'       => array(0, 1, 2, 5, 10),
 152      '#description'   => t('When displaying the summary report and using APC, only pages with the number of accesses larger than the specified threshold will be shown. Also, when cron runs, pages with that number of accesses or less will be removed, so as not to overflow APC\'s shared memory. This is useful on a live site with a high volume of hits. On a development site, you probably want this set to 0, so you can see all pages.'),
 153    );
 154  
 155    return system_settings_form($form);
 156  }
 157  
 158  function performance_boot() {
 159    register_shutdown_function('performance_shutdown');
 160  }
 161  
 162  function performance_shutdown() {
 163    global $queries;
 164  
 165  //  if ($_GET['q']) {
 166    if (isset($_GET['q']) && ($_GET['q'])) {
 167      // q= has a value, use that for the path
 168      $path = $_GET['q'];
 169    }
 170    else {
 171      // q= is empty, use whatever the site_frontpage is set to
 172      $path = variable_get('site_frontpage', 'node');
 173    }
 174  
 175    $params = array(
 176      'timer' => timer_read('page'),
 177      'path'  => $path,
 178    );
 179  
 180    // Memory
 181    if (function_exists('memory_get_peak_usage')) {
 182      $params['mem'] = memory_get_peak_usage(TRUE);
 183    }
 184    else {
 185      $params['mem'] = 0;
 186    }
 187  
 188    // Query time and count
 189    $query_count = 0;
 190    $query_timer = 0;
 191    $sum = 0;
 192    if (variable_get('dev_query', 0) && is_array($queries)) {
 193      foreach ($queries as $query) {
 194        $sum += $query[1];
 195      }
 196      $query_count = count($queries);
 197      $query_timer = round($sum * 1000, 2);
 198    }
 199  
 200    $params['query_count'] = $query_count;
 201    $params['query_timer'] = $query_timer;
 202  
 203    $anon = (!empty($data['anon']))? 'Yes' : 'No';
 204  
 205    $header = array(
 206      'path' => $path,
 207      'timer' => $params['timer'],
 208      'anon' => $anon,
 209    );
 210    module_invoke_all('performance', 'header', $header);
 211  
 212    if (variable_get('performance_detail', 0)) {
 213      $data = module_invoke_all('performance', 'data');
 214      if (!empty($data[0])) {
 215        $params['data'] = $data[0];
 216      }
 217  
 218      performance_log_details($params);
 219    }
 220    else {
 221      module_invoke_all('performance', 'disable');
 222    }
 223  
 224    if (variable_get('performance_summary_db', 0)) {
 225      performance_log_summary_db($params);
 226    }
 227  
 228    if (variable_get('performance_summary_apc', 0)) {
 229      if (function_exists('apc_cache_info')) {
 230        performance_log_summary_apc($params);
 231      }
 232    }
 233  
 234    if (variable_get('performance_summary_memcache', 0)) {
 235      if (performance_memcache_enabled()) {
 236        performance_log_summary_memcache($params);
 237      }
 238    }
 239  }
 240  
 241  function performance_log_summary_apc($params = array()) {
 242    $key = PERFORMANCE_KEY . $params['path'];
 243    if ($data = apc_fetch($key)) {
 244      $data = array(
 245        'path'            => $data['path'],
 246        'last_access'     => time(),
 247        'bytes_max'       => max($params['mem'], $data['bytes_max']),
 248        'bytes_avg'       => ($data['bytes_avg'] + $params['mem']) / 2,
 249        'ms_max'          => max($params['timer'], $data['ms_max']),
 250        'ms_avg'          => ($data['ms_avg'] + $params['timer']) / 2,
 251        'query_timer_max' => max($params['query_timer'], $data['query_timer_max']),
 252        'query_timer_avg' => ($data['query_timer_avg'] + $params['query_timer']) / 2,
 253        'query_count_max' => max($params['query_count'], $data['query_count_max']),
 254        'query_count_avg' => ($data['query_count_avg'] + $params['query_count']) / 2,
 255        'num_accesses'    => $data['num_accesses'] + 1,
 256      );
 257    }
 258    else {
 259      $data = array(
 260        'path'            => $params['path'],
 261        'bytes_max'       => $params['mem'],
 262        'bytes_avg'       => $params['mem'],
 263        'ms_max'          => $params['timer'],
 264        'ms_avg'          => $params['timer'],
 265        'query_timer_max' => $params['query_timer'],
 266        'query_timer_avg' => $params['query_timer'],
 267        'query_count_max' => $params['query_count'],
 268        'query_count_avg' => $params['query_count'],
 269        'num_accesses'    => 1,
 270        'last_access'     => time(),
 271      );
 272    }
 273    apc_store($key, $data);
 274  }
 275  
 276  function performance_log_summary_memcache($params = array()) {
 277    $key = PERFORMANCE_KEY . $params['path'];
 278    if ($cache = cache_get($key, PERFORMANCE_MEMCACHE_BIN)) {
 279      $type = 'existing';
 280      $values = $cache->data;
 281      $values = array(
 282        'path'            => $params['path'],
 283        'last_access'     => time(),
 284        'bytes_max'       => max($params['mem'], $values['bytes_max']),
 285        'bytes_avg'       => ($values['bytes_avg'] + $params['mem']) / 2,
 286        'ms_max'          => max($params['timer'], $values['ms_max']),
 287        'ms_avg'          => ($values['ms_avg'] + $params['timer']) / 2,
 288        'query_timer_max' => max($params['query_timer'], $values['query_timer_max']),
 289        'query_timer_avg' => ($values['query_timer_avg'] + $params['query_timer']) / 2,
 290        'query_count_max' => max($params['query_count'], $values['query_count_max']),
 291        'query_count_avg' => ($values['query_count_avg'] + $params['query_count']) / 2,
 292        'num_accesses'    => $values['num_accesses'] + 1,
 293      );
 294    }
 295    else {
 296      $type = 'new';
 297      // It is a new key
 298      $values = array(
 299        'path'            => $params['path'],
 300        'bytes_max'       => $params['mem'],
 301        'bytes_avg'       => $params['mem'],
 302        'ms_max'          => $params['timer'],
 303        'ms_avg'          => $params['timer'],
 304        'query_timer_max' => $params['query_timer'],
 305        'query_timer_avg' => $params['query_timer'],
 306        'query_count_max' => $params['query_count'],
 307        'query_count_avg' => $params['query_count'],
 308        'num_accesses'    => 1,
 309        'last_access'     => time(),
 310      );
 311  
 312      if ($keys_cache = cache_get(PERFORMANCE_KEY, PERFORMANCE_MEMCACHE_BIN)) {
 313        $keys_values = $keys_cache->data;
 314      }
 315      $keys_values[$key] = 1;
 316      cache_set(PERFORMANCE_KEY, $keys_values, PERFORMANCE_MEMCACHE_BIN, CACHE_PERMANENT);
 317    }
 318    cache_set($key, $values, PERFORMANCE_MEMCACHE_BIN, CACHE_PERMANENT);
 319  }
 320  
 321  function performance_log_summary_db($params = array()) {
 322    $row = db_fetch_object(db_query("SELECT * FROM {performance_summary} WHERE path = '%s'", $params['path']));
 323    if (!empty($row)) {
 324      db_query("UPDATE {performance_summary}
 325        SET last_access = %d,
 326        num_accesses = num_accesses + 1,
 327        bytes_max = %d,
 328        bytes_avg = %d,
 329        ms_max = %d,
 330        ms_avg = %d,
 331        query_timer_max = %d,
 332        query_timer_avg = %d,
 333        query_count_max = %d,
 334        query_count_avg = %d
 335        WHERE path = '%s'",
 336        time(),
 337        max($params['mem'], $row->bytes_max),
 338        ($row->bytes_avg + $params['mem']) / 2,
 339        max($params['timer'], $row->ms_max),
 340        ($row->ms_avg + $params['timer']) / 2,
 341        max($params['query_timer'], $row->query_timer_max),
 342        ($row->query_timer_avg + $params['query_timer']) / 2,
 343        max($params['query_count'], $row->query_count_max),
 344        ($row->query_count_avg + $params['query_count']) / 2,
 345        $params['path']);
 346    }
 347    else {
 348      // First time we log this path, write fresh values
 349      db_query("INSERT INTO {performance_summary}
 350        (path, last_access, num_accesses,
 351        bytes_max, bytes_avg, ms_max, ms_avg,
 352        query_count_max, query_count_avg, query_timer_max, query_timer_avg)
 353        VALUES
 354        ('%s', %d, %d, %d, %d, %d, %d, %d, %d, %d, %d)",
 355        $params['path'],
 356        time(),
 357        1,
 358        $params['mem'],
 359        $params['mem'],
 360        $params['timer'],
 361        $params['timer'],
 362        $params['query_count'],
 363        $params['query_count'],
 364        $params['query_timer'],
 365        $params['query_timer']
 366      );
 367    }
 368  }
 369  
 370  function performance_log_details($params = array()) {
 371    global $user;
 372    $anon = ($user->uid) ? FALSE : TRUE;
 373    db_query("INSERT INTO {performance_detail} (path, anon, bytes, ms, timestamp, query_timer, query_count, data) VALUES ('%s', %d, %d, %d, %d, %d, %d, '%s')",
 374      $params['path'],
 375      $anon,
 376      $params['mem'],
 377      $params['timer'],
 378      time(),
 379      $params['query_timer'],
 380      $params['query_count'],
 381      $params['data']
 382    );
 383  }
 384  
 385  function performance_apc_list_all() {
 386    $key_list = array();
 387    $list = apc_cache_info('user');
 388    foreach ($list['cache_list'] as $cache_id => $cache_data) {
 389      $regex = '/^'. PERFORMANCE_KEY .'/';
 390      if (preg_match($regex, $cache_data['info'])) {
 391        $key_list[] = $cache_data['info'];
 392      }
 393    }
 394    return $key_list;
 395  }
 396  
 397  /**
 398   * Custom sort for summary performance report
 399   * 
 400   * @param $x
 401   * @param $y
 402   * @return int
 403   */
 404  function performance_summary_sort($x, $y) {
 405    // This function is not working
 406    return 0;
 407  }
 408  
 409  function performance_view_summary() {
 410    $sum = array();
 411    $data_list = array();
 412    $rows = array();
 413  
 414    $sum[] = variable_get('performance_summary_db', 0);
 415    $sum[] = variable_get('performance_summary_apc', 0);
 416    $sum[] = variable_get('performance_summary_memcache', 0);
 417    $go = array_sum($sum);
 418  
 419    if (!$go) {
 420      return t('Summary performance log is not enabled. Go to the <a href="@link">settings page</a> to enable it.', array('@link' => url('admin/settings/performance_logging')));
 421    }
 422  
 423    $header = array();
 424  
 425    $header[] =  array('data' => t('Path'),               'field' => 'path');
 426    $header[] =  array('data' => t('Last access'),        'field' => 'last_access');
 427    $header[] =  array('data' => t('# accesses'),         'field' => 'num_accesses');
 428    $header[] =  array('data' => t('Max Memory (MB)'),    'field' => 'bytes_max');
 429    $header[] =  array('data' => t('Avg Memory (MB)'),    'field' => 'bytes_avg');
 430    $header[] =  array('data' => t('ms (Max)'),           'field' => 'ms_max');
 431    $header[] =  array('data' => t('ms (Avg)'),           'field' => 'ms_avg');
 432  
 433    if (variable_get('dev_query', 0)) {
 434      $header[] = array('data' => t('Query ms (Max)'),    'field' => 'query_timer_max');
 435      $header[] = array('data' => t('Query ms (Avg)'),    'field' => 'query_timer_avg');
 436      $header[] = array('data' => t('Query Count (Max)'), 'field' => 'query_count_max');
 437      $header[] = array('data' => t('Query Count (Avg)'), 'field' => 'query_count_avg');
 438    }
 439  
 440    $total_rows = $shown = $last_max = $total_bytes = $total_ms = $total_accesses = 0;
 441    $last_min = time();
 442  
 443    $threshold = variable_get('performance_threshold_accesses', 0);
 444  
 445    if (variable_get('performance_summary_memcache', 0) && performance_memcache_enabled()) {
 446      $tablesort = tablesort_init($header);
 447      // Get the data from memcache
 448      if ($keys_cache = cache_get(PERFORMANCE_KEY, PERFORMANCE_MEMCACHE_BIN)) {
 449        if ($keys_cache->data) {
 450          foreach ($keys_cache->data as $key => $v) {
 451            $cache = cache_get($key, PERFORMANCE_MEMCACHE_BIN);
 452            $data_list[] = $cache->data;
 453          }
 454        }
 455      }
 456      usort($data_list, 'performance_summary_sort');
 457    }
 458    else if (variable_get('performance_summary_apc', 0) && function_exists('apc_cache_info')) {
 459      $tablesort = tablesort_init($header);
 460      // Get the data from the APC cache
 461      foreach (performance_apc_list_all() as $key) {
 462        $data_list[] = apc_fetch($key) + $tablesort;
 463      }
 464      usort($data_list, 'performance_summary_sort');
 465    }
 466    else {
 467      // Get the data form the database table
 468      $sql = "SELECT * FROM {performance_summary}";
 469      $tablesort = tablesort_sql($header);
 470      $result = pager_query($sql . $tablesort, 50);
 471      while ($row = db_fetch_array($result)) {
 472        $data_list[] = $row;
 473      }
 474    }
 475  
 476    foreach ($data_list as $data) {
 477      $total_rows++;
 478      $last_max = max($last_max, $data['last_access']);
 479      $last_min = min($last_min, $data['last_access']);
 480  
 481      // Calculate running averages
 482      $total_bytes += $data['bytes_avg'];
 483      $total_ms += $data['ms_avg'];
 484      $total_accesses += $data['num_accesses'];
 485  
 486      $row_data = array();
 487  
 488      if ($data['num_accesses'] > $threshold) {
 489        $shown++;
 490        $row_data[] = check_plain($data['path']);
 491        $row_data[] = format_date($data['last_access'], 'small');
 492        $row_data[] = $data['num_accesses'];
 493        $row_data[] = number_format($data['bytes_max']/1024/1024, 2);
 494        $row_data[] = number_format($data['bytes_avg']/1024/1024, 2);
 495        $row_data[] = number_format($data['ms_max'], 1);
 496        $row_data[] = number_format($data['ms_avg'], 1);
 497        if (variable_get('dev_query', 0)) {
 498          $row_data[] = number_format($data['query_timer_max'], 1);
 499          $row_data[] = number_format($data['query_timer_avg'], 1);
 500          $row_data[] = $data['query_count_max'];
 501          $row_data[] = $data['query_count_avg'];
 502        }
 503      }
 504      $rows[] = array('data' => $row_data);
 505    }
 506  
 507    if (!$rows) {
 508      $rows[] = array(array('data' => t('No statistics available yet.'), 'colspan' => count($header)));
 509    }
 510  
 511    $output = '';
 512    if ($threshold) {
 513      $output .= t('Showing !shown paths with more than !threshold accesses, out of !total total paths.',
 514        array('!threshold' => $threshold, '!shown' => $shown, '!total' => $total_rows)) .'<br/>';
 515    }
 516    else {
 517      $output .= t('Showing all !total paths.', array('!total' => $total_rows)) .'<br/>';
 518    }
 519  
 520    // Protect against divide by zero
 521    if ($total_rows > 0) {
 522      $mb_avg = number_format($total_bytes/$total_rows/1024/1024, 1);
 523      $ms_avg = number_format($total_ms/$total_rows, 2);
 524    }
 525    else {
 526      $mb_avg = 'n/a';
 527      $ms_avg = 'n/a';
 528    }
 529  
 530    $output .= t('Average memory per page: !mb_avg MB', array('!mb_avg' => $mb_avg)) .'<br/>';
 531    $output .= t('Average ms per page: !ms_avg', array('!ms_avg' => $ms_avg)) .'<br/>';
 532    $output .= t('Total number of page accesses: !accesses', array('!accesses' => $total_accesses)) .'<br/>';
 533    $output .= t('First access: !access.', array('!access' => format_date($last_min, 'small'))) .'<br/>';
 534    $output .= t('Last access: !access.',  array('!access' => format_date($last_max, 'small'))) .'<br/>';
 535  
 536    $output .= theme('table', $header, $rows);
 537    $output .= theme('pager', NULL, 50, 0);
 538  
 539    return $output;
 540  }
 541  
 542  function performance_view_details() {
 543    if (!variable_get('performance_detail', 0)) {
 544      return t('Detail performance log is not enabled. Go to the <a href="@link">settings page</a> to enable it.', array('@link' => url('admin/settings/performance_logging')));
 545    }
 546  
 547    $header = array(
 548      array('data' => t('#'),                     'field' => 'pid', 'sort' => 'desc'),
 549      array('data' => t('Date'),                  'field' => 'timestamp'),
 550      array('data' => t('Path'),                  'field' => 'path'),
 551      array('data' => t('Memory (MB)'),           'field' => 'bytes'),
 552      array('data' => t('ms (Total)'),            'field' => 'ms'),
 553      array('data' => t('Anonymous?'),            'field' => 'anon'),
 554    );
 555  
 556    if (variable_get('dev_query', 0)) {
 557      $header[] = array('data' => t('# Queries'), 'field' => 'query_count');
 558      $header[] = array('data' => t('Query ms'),  'field' => 'query_timer');
 559    }
 560  
 561    $sql = "SELECT * FROM {performance_detail}";
 562    $tablesort = tablesort_sql($header);
 563    $result = pager_query($sql . $tablesort, 50);
 564  
 565    while ($data = db_fetch_array($result)) {
 566      $row_data = array();
 567  
 568      $row_data[] = $data['pid'];
 569      $row_data[] = format_date($data['timestamp'], 'small');
 570      $row_data[] = check_plain($data['path']);
 571      $row_data[] = number_format($data['bytes']/1024/1024, 2);
 572      $row_data[] = $data['ms'];
 573      $row_data[] = ($data['anon']) ? t('Yes') : t('No');
 574  
 575      if (variable_get('dev_query', 0)) {
 576        $row_data[] = $data['query_count'];
 577        $row_data[] = $data['query_timer'];
 578      }
 579  
 580      $rows[] = array('data' => $row_data);
 581    }
 582  
 583    if (!$rows) {
 584      $rows[] = array(array('data' => t('No log messages available.'), 'colspan' => count($header)));
 585    }
 586  
 587    $output  = theme('table', $header, $rows);
 588    $output .= theme('pager', NULL, 50, 0);
 589  
 590    return $output;
 591  }
 592  
 593  function performance_cron() {
 594    // One day ago ...
 595    $timestamp = time() - 24*60*60;
 596  
 597    performance_cron_db_prune($timestamp);
 598    performance_cron_apc_prune($timestamp);
 599  }
 600  
 601  function performance_cron_db_prune($timestamp = 0) {
 602    // Remove rows which have not been accessed since a certain timestamp
 603    db_query("DELETE FROM {performance_summary} WHERE last_access <= %d", $timestamp);
 604  
 605    // Remove performance_detail rows on a daily basis
 606    db_query("DELETE FROM {performance_detail} WHERE timestamp <= %d", $timestamp);
 607  }
 608  
 609  function performance_cron_apc_prune($timestamp = 0) {
 610    if (!function_exists('apc_cache_info')) {
 611      // APC not enabled, nothing to do ...
 612      return;
 613    }
 614  
 615    // Get all entries in APC's user cache
 616    $list = performance_apc_list_all();
 617    if (!count($list)) {
 618      // Nothing stored yet
 619      return;
 620    }
 621  
 622    foreach ($list as $key) {
 623      if ($data = apc_fetch($key)) {
 624        if ($data['last_access'] <= $timestamp) {
 625          apc_delete($key);
 626        }
 627      }
 628    }
 629  }
 630  
 631  function performance_clear_apc_confirm() {
 632    $form['confirm'] = array(
 633      '#value' => t('Confirm APC clear'),
 634    );
 635    return confirm_form(
 636      $form,
 637      t('Are you sure you want to clear the APC statistics for this site?'),
 638      'admin/settings/performance_logging',
 639      t('This will clear all the collected performance statistics stored in APC. This action cannot be undone.'),
 640      t('Clear'),
 641      t('Cancel'));
 642  }
 643  
 644  function performance_clear_apc_confirm_submit($form, &$form_state) {
 645    if (!function_exists('apc_cache_info')) {
 646      drupal_set_message(t('APC is not enabled. Nothing to do ...'), 'status', FALSE);
 647      drupal_goto('admin/settings/performance');
 648      return;
 649    }
 650  
 651    $list = performance_apc_list_all();
 652    if (!count($list)) {
 653      // Nothing stored yet
 654      return;
 655    }
 656  
 657    foreach ($list as $key) {
 658      if ($data = apc_fetch($key)) {
 659        apc_delete($key);
 660      }
 661    }
 662  
 663    drupal_set_message(t('Performance statistics collected in APC has been cleared.'), 'status', FALSE);
 664    drupal_goto('admin/settings/performance');
 665  }
 666  
 667  function performance_clear_memcache_confirm() {
 668    $form['confirm'] = array(
 669      '#value' => t('Confirm Memcache clear'),
 670    );
 671    return confirm_form(
 672      $form,
 673      t('Are you sure you want to clear the Memcache statistics for this site?'),
 674      'admin/settings/performance_logging',
 675      t('This will clear all the collected performance statistics stored in Memcache. This action cannot be undone.'),
 676      t('Clear'),
 677      t('Cancel'));
 678  }
 679  
 680  function performance_clear_memcache_confirm_submit($form, &$form_state) {
 681    if (!performance_memcache_enabled()) {
 682      drupal_set_message(t('Memcache is not enabled. Nothing to do ...'), 'status', FALSE);
 683      drupal_goto('admin/settings/performance');
 684      return;
 685    }
 686  
 687    // We have to iterate over all entries and delete them, reaching down 
 688    // the API stack and calling dmemcache_delete directly.
 689    // This is suboptimal, but there is no other alternative
 690    if ($keys_cache = cache_get(PERFORMANCE_KEY, PERFORMANCE_MEMCACHE_BIN)) {
 691      if ($keys_cache->data) {
 692        foreach ($keys_cache->data as $key => $v) {
 693          dmemcache_delete($key, PERFORMANCE_MEMCACHE_BIN);
 694        }
 695        dmemcache_delete(PERFORMANCE_KEY, PERFORMANCE_MEMCACHE_BIN);
 696      }
 697    }
 698  
 699    drupal_set_message(t('Performance statistics collected in Memcache has been cleared.'), 'status', FALSE);
 700    drupal_goto('admin/settings/performance');
 701  }
 702  
 703  /**
 704   * Implementation of hook_nagios_info().
 705   */
 706  function performance_nagios_info() {
 707    return array(
 708      'name'   => 'Performance logging',
 709      'id'     => 'PERF',
 710    );
 711  }
 712  
 713  /**
 714   * Implementation of hook_nagios().
 715   */
 716  function performance_nagios() {
 717    $info = performance_nagios_info();
 718    $id = $info['id'];
 719  
 720    // Find out if we have what we need enabled
 721    $sum = array();
 722  
 723    $sum[] = variable_get('performance_summary_db', 0);
 724    $sum[] = variable_get('performance_summary_apc', 0);
 725    $go = array_sum($sum);
 726  
 727    if (!$go) {
 728      return array(
 729        $id => array(
 730          'status' => NAGIOS_STATUS_UNKNOWN,
 731          'type'   => 'perf',
 732          'text'   => t('Performance logging is not enabled'),
 733        ),
 734      );
 735    }
 736  
 737    // Initialize variables
 738    $total_rows = $total_bytes = $total_ms = $total_accesses = $total_query_time = $total_query_count = 0;
 739  
 740    // Check which data store to use
 741    if (variable_get('performance_summary_apc', 0) && function_exists('apc_cache_info')) {
 742      // Get the data from the APC cache
 743      foreach (performance_apc_list_all() as $key) {
 744        $data_list[] = apc_fetch($key);
 745      }
 746    }
 747    else {
 748      // Get the data form the database table for URLs that have been accessed in the last 15 minutes
 749      $result = db_query("SELECT * FROM {performance_summary} WHERE last_access >= %d", time() - 15*60);
 750      while (is_array($row = db_fetch_array($result))) {
 751        $data_list[] = $row;
 752      }
 753    }
 754  
 755    foreach ($data_list as $data) {
 756      $total_rows++;
 757  
 758      // Calculate running averages
 759      $total_bytes       += $data['bytes_avg'];
 760      $total_ms          += $data['ms_avg'];
 761      $total_accesses    += $data['num_accesses'];
 762      $total_query_time  += $data['query_timer_avg'];
 763      $total_query_count += $data['query_count_avg'];
 764    }
 765  
 766    // Protect against divide by zero
 767    if ($total_rows > 0) {
 768      $ms_avg      = number_format($total_ms          / $total_rows, 1, '.', '');
 769      $ms_query    = number_format($total_query_time  / $total_rows, 1, '.', '');
 770      $query_count = number_format($total_query_count / $total_rows, 2, '.', '');
 771      $mb_avg      = number_format($total_bytes       / $total_rows/1024/1024, 1);
 772    }
 773    else {
 774      $ms_avg = '';
 775      $ms_query = '';
 776      $mb_avg = '';
 777      $query_count = '';
 778    }
 779  
 780    $status = NAGIOS_STATUS_OK;
 781  
 782    return array(
 783      'ACC' => array(
 784        'status' => $status,
 785        'type'   => 'perf',
 786        'text'   => $total_accesses,
 787      ),
 788      'MS' => array(
 789        'status' => $status,
 790        'type'   => 'perf',
 791        'text'   => $ms_avg,
 792      ),
 793      'MMB' => array(
 794        'status' => $status,
 795        'type'   => 'perf',
 796        'text'   => $mb_avg,
 797      ),
 798      'QRC' => array(
 799        'status' => $status,
 800        'type'   => 'perf',
 801        'text'   => $query_count,
 802      ),
 803      'QRT' => array(
 804        'status' => $status,
 805        'type'   => 'perf',
 806        'text'   => $ms_query,
 807      ),
 808    );
 809  }


Generated: Thu Mar 24 11:18:33 2011 Cross-referenced by PHPXref 0.7