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.
Comments
Visitor (not verified)
Very useful! Thanks! :)
Wed, 2010/04/14 - 05:27Very useful! Thanks! :)
Visitor (not verified)
Thanks for the code. I
Thu, 2010/04/22 - 15:37Thanks for the code. I noticed one thing that threw an error:
Added the } closing bracket. Thanks for this update, memcache has been a great module for several of our sites.
Visitor (not verified)
Fixed
Thu, 2010/04/22 - 16:42Fixed it in the article.
Thanks ...
Visitor (not verified)
Doesn't work
Thu, 2010/05/27 - 04:50please help me. I don't know why!!!
Mr.j (not verified)
Minor typo in the code
Mon, 2011/10/10 - 18:16$cache->data .= "\n';
That second quote character should be a double not a single. ie
$cache->data .= "\n";
Khalid
Thanks
Mon, 2011/10/10 - 22:45Thanks 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.