Metric Driven Development Fueled by StatsD and GraphitePosted by Goncalo Pereira on April 18th, 2012 – Be the first to comment
Since I joined 7digital I’ve seen the API grow from a brand new feature side by side with the (then abundant) websites to be the main focus of the company. The traffic grew and grew and keeps on growing in an accelerated pace and that brings us new challenges.
We’ve brought the agile perspective into play which has made us adapt faster and make fewer errors but:
- We can do unit tests but they don’t bring out the behaviour.
- We can do integration tests but they won’t show the whole flow.
- We can do smoke tests but they won’t show us realistic usage.
- We can do load test but they won’t have realistic weighting.
Even when we do acceptance criteria we are actually being driven by assumptions, even with an experienced developer he is really just sampling all his previous work and as we move to a larger number of servers and applications it’s not humanly possible to take all variables into consideration.
It is common to hear statements like ‘keep an eye on the error log/server log/payments log when releasing this new feature’ but when something breaks it’s all about ‘what was released/when was it released/is it a specific server?’. As the data grows it becomes harder to sample and deduce from it quickly enough to feedback without causing issues, especially when agile tends to implement intermediary solutions which might have different behaviours from the final solution that have not been studied.
The truth is that nothing replaces real life data and statistics – including developers opinions – if it the issue is a black swan then we need to churn out usable information fast!
Taken from @gregyoung
This has been seen before by other companies; for example, Flickr on their Counting and Timing blog post. See also Building Scalable Websites by Flickr’s Cal Henderson.
How to do it?
Decided to start with a winning horse I picked up the tools used by these companies:
StatsD is described as “a network daemon for aggregating statistics (counters and timers), rolling them up, then sending them to graphite”.
Graphite is described as “a highly scalable real-time graphing system. As a user, you write an application that collects numeric time-series data that you are interested i[...]. The data can then be visualized through graphite’s web interfaces.”
The way to implement these is available in several tutorials and I used StatsD own example C# client to poll our own API request log for API users, endpoints used, caching and errors.
In the future it would be ideal for the application to access StatsD itself instead of running a polling daemon.
There are a lot of usable features on Graphite. The ones I’ve used so far include Moving Average which will smooth out spikes in the graphs making it easier to see behaviour trends in a short time range and Sort by Maxima.
There are even tools to forecast future behaviour and growth using Holt Winters Forecasting Statistics and this is used by companies to understand future scalability and performance requirements based on data from previous weeks, months or years (seen in this Etsy presentation on Metrics)
How it looks and some findings
Right away I got some usable results. An API client had a bug in their implementation which meant they required a specific endpoint more often than they would use it – this data can help out with debugging and also prevent abuse.
Sampled and smoothed usage per endpoint per API user…
Another useful graph is error rates, which might be linked with abuse, deploying new features or other causes.
Error chart smoothed with a few spikes but even those are on the 0.001 % rate
Here is some useful caching information per endpoint to know how to tune up TTLs or look for stampede behaviour.
Sampled and smoothed Cache Miss per Endpoint
After you start using live data to provide feedback for your work there is no going back. It is my opinion that analysis of short and long term live results of any type of work should be mandatory as we move out of an environment that is small enough to be maintained exclusively by a team’s knowledge.