Why I Set Up Honeycomb on Small Projects
What’s the point of instrumenting a toy "hello world" app?
One of my goals for this summer is to spend some quality time with Rails. I’ve got a copy of the Ruby on Rails Tutorial, and some ideas for applications I might build. This is something I’ve wanted to do for years— since I’m entirely on-the-job taught, I’ve never had significant time to write code just to practice writing code. I chose Rails because I like the Ruby community and its values. (I’ve considered changing targets given this week’s Basecamp meltdown, but the framework remains an important part of the Ruby community’s history and install base.)
The tutorial involves starting several Rails projects, each a little more complex than the last. This is one of the experiences I haven’t had much of in my career— I’m typically working on projects several years into their existence, when all the initial patterns have been set out.
It turns out I have an odd habit when I set up a brand new project. I set up a Honeycomb integration almost immediately — in some cases before I make the initial git
commit.
Right now, for instance, I have a rails server running locally, configured to emit events to a dataset just for it. This took about ten minutes, because Honeycomb has a Rails-specific integration, and Rails generators and initializers make this the easiest integration I’ve yet set up.
It’s as simple as
echo "gem 'honeycomb-beeline'" >> Gemfile
bundle exec rails generate honeycomb YOUR_API_KEY --dataset your-dataset-name
Honeycomb itself is free for up to 20 million events a month.
Now, you might reasonably ask at this point, isn’t Honeycomb for understanding distributed systems? Finding needles in a haystack full of needles? Unknown unknowns? What’s the point of instrumenting a toy hello world
app?
The point is, I get to see what exactly what the framework is doing.
I love Ruby, but its ways can be… mysterious. Rails has a reputation for being even more so. Generated code, meta-programming, ActiveRecord — there are a lot of instructions running in a rails server that I didn’t write.
A good observability tool lets me see all that, even for the simplest apps. It lets me see that my trivial hello world app, is running four sql.active_record
calls. It lets me see that a 500 response (due to an except raised at the top of the controller) doesn’t make any, and instead runs an elaborately nested set of render_template.action_view
calls.
And, when I’m trying to understand why something isn’t working the way I expect, it gives me a place to stick the modern equivalent of a print
statement, that’s automatically in context of the action the application was supposed to be performing. No picking through a linear log stream and trying to grep my way to a coherent storyline. The trace diagram is right there.
I know little bit about Rails already, but I rely on this even more heavily when I’m working with a novel framework. Instrumenting always teaches me a ton about the basic process model for a piece of software, and that’s the kind of knowledge that pays for itself many times over in debugging.
For instance — recently I was working with a Flask application. I know very little about Python and knew nothing about Flask. I’d heard folks talking about asynchronous something-or-others, but hadn’t really retained the information, because it wasn’t connected to a problem I needed to solve.
My initial attempt to add the Honeycomb beeline didn’t work at all, so I read the documentation a little more closely, and came upon the “pre-fork model.” Turns out each request a Gunicorn server handles gets its own process!
Not the kind of thing I’d want to discover at 3am, while I’m trying to understand why, say, those processes aren’t getting cleaned up or created correctly.
I encourage anyone reading this to give Honeycomb a try. If you’d like to learn more about it, the dataset from ruby gems.org is available to query live. You can get your own API key and start sending your data by signing up for free.