Memcache statistics from the command line

To help debug memcache issues it's really useful to be able to see the output of the stats command. I got bored of using telnet to talk to the memcache daemon so I whipped up this simple Ruby script to spit out the statistics without all that fuss.

#! /usr/bin/env ruby

require 'socket'

socket = TCPSocket.open('localhost', '11211')
socket.send("stats\r\n", 0)

statistics = []
loop do
  data = socket.recv(4096)
  if !data || data.length == 0
    break
  end
  statistics << data
  if statistics.join.split(/\n/)[-1] =~ /END/
    break
  end
end

puts statistics.join()

Fail Silently with Memcache Client

For web applications caching is king and I've recently been playing with memcached to cache the results of expensive queries in a Rails application. As a client I've chosen Seattle RB's memcache-client.

The memcache-client library is rather lovely, but it does seem to have the opinion that if a memcached instance fails it should throw an exception which your code has to deal with. I don't agree with that: when a cache fails it doesn't matter. Either the application can continue running in an uncached mode - slow, but possible - or there are other memcache instances that can be used. Switching to either of these should require no special effort in code that uses the library.

Ruby, being awesome, lets me change the behaviour of the client library very easily. Monkey patching may be frowned upon, but it does have a use.

# A simple monkey-patch of MemCache so that broken memcached instances don't 
# cause fatal errors in the application. Performance may be severaly degraded
# but it should be possible to use the app anyway!
# 
# A typical use would look something like:
# 
#   result = if cache.alive?
#     fetch = cache.get(:foo)
#     if !fetch
#       fetch = calculate(:foo)
#       cache.set(:foo, fetch)
#     end
#     fetch
#   else
#     calculate(:foo)
#   end
# 
class MemCache
  # Does the cache configuration contain any memcached instances that can 
  # currently be used?
  # 
  # Author: Conor Curran [http://forwind.net/]
  # 
  def alive?
    !!cache.servers.detect{ |s| s.alive? }
  end

  # Rescue from MemCache::MemCacheError -- we want the cache to fail silently
  # (at least from the point of view of the application - you should still
  # monitor memcached).
  # 
  def get_with_rescue(*args)
    get_without_rescue(*args)
  rescue MemCache::MemCacheError
  end
  alias_method :get_without_rescue, :get
  alias_method :get, :get_with_rescue
  alias_method :[], :get
  
  # Rescue from MemCache::MemCacheError -- we want the cache to fail silently
  # (at least from the point of view of the application - you should still
  # monitor memcached).
  # 
  def set_with_rescue(*args)
    set_without_rescue(*args)
  rescue MemCache::MemCacheError
  end
  alias_method :set_without_rescue, :set
  alias_method :set, :set_with_rescue
  alias_method :[]=, :set
  alias_method :add, :set

  # Rescue from MemCache::MemCacheError -- we want the cache to fail silently
  # (at least from the point of view of the application - you should still
  # monitor memcached).
  # 
  def delete_with_rescue(*args)
    delete_without_rescue(*args)
  rescue MemCache::MemCacheError
  end
  alias_method :delete_without_rescue, :delete
  alias_method :delete, :delete_with_rescue
end

About the boy

A picture of Craig in grayscale

Craig Webster is a software engineer living in London. He usually works with Ruby although sometimes he sneaks in some Erlang or JavaScript. He's into rock climbing, snowboarding, skating, photography and fencing. Yes, this does mean he has a sword.

Near here you'll find Craig's homepage, contact details, PGP key and keysigning policy, and talks.

Licence

The entire content of this blog is public domain. Use it however you fancy. You don't even need to attribute it to me, although it would be nice if you did. Just don't sue me and we'll all be happy.

I Work With Rails

Recommend Me

My Travels

I go places. Do you go places too? Let's meet up!.