Overactive Vocabulary

When In Doubt, Ameliorate



The other day I was cranking along on part of our Spreedly codebase, furiously working to get it ready for the launch of our new marketing site and the publicity that (we hoped) was due to come with it. Now, it may not be obvious from the outside, but we re-did a lot more than just the look and feel of Spreedly, and as part of that I was working on getting billing working smoothly throughout the system.

One of the key things about how we bill is that a lot of it’s made up of very small metered charges. Because they’re so small, it’s not a huge deal if a metered fee here or there falls on the floor, and so as long as we never over charge a customer we’re more concerned with fixing issues that come up than we are with capturing every last penny. Thus there are various places in the chain of “add a fee” where things could go wrong that we just let them fail and notify ourselves rather than writing fancy recovery code.

But of course, this only works if you notify yourself in such a way that you can fix the problem, and that means a stack trace should show up in the notification. As I coded along I found myself in a situation where something could go wrong and yet it wasn’t due to an exception but rather just due to an “unexpected input” situation. That meant I had no exception to grab the stack trace off of, and for a few minutes I was stumped.

Now, I knew about Kernel#caller, but the problem with it is that it starts with (as indicated by the name) your caller’s stack, and in this case I wanted the stack to start right where I was creating the notification. Turns out there’s a simple solution:

module Kernel
  def backtrace

I dropped that code in a Rails initializer and then just called backtrace when building my notification, and it works beautifully.

Now, I’m pretty cautious about going in and adding methods to Kernel, but I think this is a good example of why it’s nice that Ruby lets us do so when we want to. If you find yourself needing a backtrace without raising an exception, I hope this helps you out!