Examples for Drupal custom caching: Adding a cache timestamp to cached pages and HTTP headers

One of the nice things about Drupal is its pluggable caching system. It allows site owners to choose from a vast array of caching backends, such as memcache, APC, files, as well as others.

The memcache module is one of the most popular of these modules, providing Drupal integration with memcached, and in-memory distributed object caching daemon.

All Drupal pluggable caching modules work by providing a caching .inc file that is added in the settings.php for the site like this:

$conf['cache_inc'] = './sites/all/modules/memcache/memcache.inc';

Because of this pluggability, you can can effectively extend the caching in creative ways.

One use case for a large client was the need to find out how old the pages were in the cache when they were served.

So, we implemented a new file called custom_cache.inc, and added this functionality to it. The page generation time, the age of the cached page are displayed. As well, we have HTTP headers that show if the page was a cache hit or a miss.

We started with a copy of the memcache.inc file that comes with the memcache module, which has a function like this:

function cache_get($cid, $table = 'cache') {
  ...
  $cache = dmemcache_get($cid, $table);
  if (is_object($cache)) {
    ...
    if ($cache_lifetime && $cache->created && $cache_flush &&
      ...
      return 0;
    }
    return $cache;
  }
  return 0;
}

We then added the following section to it, before the return $cache; statement, so it looks like this:

function cache_get($cid, $table = 'cache') {
  ...
  $cache = dmemcache_get($cid, $table);
  if (is_object($cache)) {
    ...
    if ($cache_lifetime && $cache->created && $cache_flush &&
      ... {
      return 0;
    }
    // Start modifications ...
    // Add a cache time stamp
    if ($cache && $table == 'cache_page') {
      // We did get something from the cache, and it is 
      // a page cache entry ... so add some useful timestamps
      $now = time();
      $secs_ago = $now - $cache->created;
      $fmt = "Y-m-d H:i:s";
      $exec_time = timer_read('page');

      $cache->data .= "\n<!-- ";
      $cache->data .= ' cached ' . $secs_ago;
      $cache->data .= ' seconds ago at: ' . date($fmt, $cache->created);
      $cache->data .= ' now: '    . date($fmt, $now);
      $cache->data .= ' execution time: ' . $exec_time . ' ms.';
      $cache->data .= ' -->';
      header('X-Custom-Cache: HIT, Exec_Time=' . $exec_time . ', Age=' . $secs_ago);
    }
    // 2bits.com -- End modifications
    return $cache;
  }
  header('X-Custom-Cache: MISS');
  return 0;
}

We also need to point it to the full path of the dmemcache.inc file, since we are keeping this new .inc in a separate directory. We don't want it to get overwritten when we upgrade the memcache module.

require_once './sites/all/modules/memcache/dmemcache.inc';

Finally, we replace the memcache.inc file in settings.php with our own cache file:

$conf['cache_inc'] = './sites/all/modules/custom_cache/custom_cache.inc';

Now, whenever a page is served from cache, it will have the following data appended to the HTML as a comment, showing something like this.

cached 176 seconds ago at: 2010-04-14 13:25:19 now: 2010-04-14 13:28:15 execution time: 5.12 ms.

So they can see how recent (or old) the pages are, and the nerds can see the time taken to serve a page from the cache as well.

And if you happen to be using a tool that inspects HTTP headers, you will see an X-Custom-Cache header with a HIT or miss.

Contents: 

Tags: 

Comments

Thanks for the code. I

Thanks for the code. I noticed one thing that threw an error:

    // Start modifications ...
    // Add a cache time stamp
    if ($cache && $table == 'cache_page') {
      // We did get something from the cache, and it is 
      // a page cache entry ... so add some useful timestamps
      $now = time();
      $secs_ago = $now - $cache->created;
      $fmt = "Y-m-d H:i:s";

      $cache->data .= "\n";
      $cache->data .= '';
    }
    // End modifications

Added the } closing bracket. Thanks for this update, memcache has been a great module for several of our sites.

Fixed

Fixed it in the article.

Thanks ...

Doesn't work

please help me. I don't know why!!!

Minor typo in the code

$cache->data .= "\n';

That second quote character should be a double not a single. ie

$cache->data .= "\n";

Thanks

Thanks for the note.

The code was correct, but because there is an HTML comment inside it, it was not showing correctly. Some lines were dropped.

I escaped the code and it should show correctly now.