You are here

function performance_update_6200 in Performance Logging and Monitoring 6.2

Move summary data from old performance_summary table to new cache bin. Note that we now cache per language and separate anonymous users from logged in users! During this migration, we do BASIC separation between anonymous and logged in users based on admin paths. Back up your data if you want to keep the original logs! DRUSH NOTE: make sure to set a proper $base_url using the --uri parameter or by means of a drushrc.php config file! Alternatively you can setup a $conf['performance_key'] = 'my_unique_key'; in settings.php when using multiple domains for one site.

File

./performance.install, line 266
Install and update for Performance Logging

Code

function performance_update_6200() {
  global $language;

  // Abort when improperly invoked when using drush. See DRUSH NOTE above.
  if (performance_is_cli() && variable_get('performance_key', FALSE) === FALSE && $GLOBALS['base_url'] == 'http://default') {

    // Force PHP error to make this update fail. Found no other way. Better
    // suggestion anyone? Tried the D7 approach by throwing an exception, but
    // that spews out a drupal HTML rendered error page (gasp). Update was
    // always marked as 'completed' and was not re-executed when re-running
    // drush updb.
    drush_set_error(dt("Please run drush with the --uri parameter or setup a drushrc.php file to successfully migrate the summary data! The site's domain name will be used in the cache key! Use \$conf['performance_key'] = 'my_unique_key'; in settings.php when using multiple domains on one site."));

    // Assure the user that the undefined function error is intended and
    // harmless ;-)
    drush_set_error(dt('The following undefined function error is deliberate to allow rerunning of drush updatedb. Kindly ignore it.') . "\n\n");
    performance_fake_error();

    // Ideally the first drush_set_error() message should be inside 'query' but
    // we never get here due to the line above.
    return array(
      array(
        'success' => FALSE,
        'query' => '',
      ),
    );
  }

  // Create new cache bin, see http://drupal.org/node/150220.
  $table = array(
    'description' => 'Table that holds summary performance data.',
    'fields' => array(
      'cid' => array(
        'description' => 'Primary Key: Unique cache ID.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '',
      ),
      'data' => array(
        'description' => 'A collection of data to cache.',
        'type' => 'blob',
        'not null' => FALSE,
        'size' => 'big',
      ),
      'expire' => array(
        'description' => 'A Unix timestamp indicating when the cache entry should expire, or 0 for never.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
      'created' => array(
        'description' => 'A Unix timestamp indicating when the cache entry was created.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
      'headers' => array(
        'description' => 'Any custom HTTP headers to be added to cached data.',
        'type' => 'text',
        'not null' => FALSE,
      ),
      'serialized' => array(
        'description' => 'A flag to indicate whether content is serialized (1) or not (0).',
        'type' => 'int',
        'size' => 'small',
        'not null' => TRUE,
        'default' => 0,
      ),
    ),
    'indexes' => array(
      'expire' => array(
        'expire',
      ),
    ),
    'primary key' => array(
      'cid',
    ),
  );
  $ret = $keys_cache = array();

  // Keep records for 1 day.
  $expire = time() + 24 * 60 * 60;

  // Extra check to prevent errors when running this update multiple times.
  if (db_table_exists('performance_summary') && !db_table_exists('cache_performance')) {
    db_create_table($ret, 'cache_performance', $table);
    $result = db_query('SELECT * FROM {performance_summary}');
    while ($row = db_fetch_object($result)) {

      // Make some BASIC separation between anonymous users and logged in users.
      $anonymous = 1;
      if (preg_match('/^(admin|admin\\/.*|node\\/add.*)$/i', $row->path) || preg_match('/^(node|user)\\/\\d+\\/(edit|translate|delete|revisions.*)$/i', $row->path)) {
        $anonymous = 0;
      }
      $data = array(
        'path' => $row->path,
        'bytes_max' => $row->bytes_max,
        'bytes_sum' => $row->bytes_avg * $row->num_accesses,
        'ms_max' => $row->ms_max,
        'ms_sum' => $row->ms_avg * $row->num_accesses,
        'query_timer_max' => $row->query_timer_max,
        'query_timer_sum' => $row->query_timer_avg * $row->num_accesses,
        'query_count_max' => $row->query_count_max,
        'query_count_sum' => $row->query_count_avg * $row->num_accesses,
        'num_accesses' => $row->num_accesses,
        'last_access' => $row->last_access,
        'anon' => $anonymous,
        'language' => $language->language,
      );

      // We now cache per language and distinguish between anonymous users and
      // logged in users. As usual, we keep logs for one day!
      $key = PERFORMANCE_KEY . $row->path . ':' . $language->language . ':' . $anonymous;
      cache_set($key, $data, 'cache_performance', $expire);

      // Keep the key for the key cache store. We do it this way so that keys
      // will replace eachother which would not happen when using
      // $keys_cache[] = $key;
      $keys_cache[$key] = 1;
    }

    // This will allow easy retrieval of data as we cannot use SQL queries since
    // the cache store can by anything!
    cache_set(PERFORMANCE_KEY, $keys_cache, 'cache_performance');

    // No longer needed!
    db_drop_table($ret, 'performance_summary');

    // Preserve summary logging setting if enabled.
    // There can, in theory, be unlimited variables named performance_summary_%
    // where we do not know what % is, hence this approach.
    $result = db_query('SELECT value FROM {variable} WHERE name LIKE "performance_summary\\_%"');
    while ($row = db_fetch_object($result)) {
      if (unserialize($row->value)) {
        variable_set('performance_summary', 1);
        break;
      }
    }

    // Delete old performance summary variables!
    db_query('DELETE FROM {variable} WHERE name LIKE "performance_summary\\_%"');
    return $ret;
  }
}