Lately at NextThought we've been much more focused on using application level metrics to proactively monitor and understand the run-time characteristics of our applications. Much of the open source stack we are built on top of is already instrumented with the great perfmetrics library. Because of this, when it was time to expand the metrics we collected, perfmetrics was the obvious choice. However we quickly ran into a problem. How should we test the metrics we generated were actually emitted as the StatsD metrics we expected?

We needed a perfmetrics compatible fake StatsD client that we could drop in during testing. Ultimately we wanted something that was to perfmetrics as fakeredis is to redis-py. We couldn't find what we were looking for on PyPi or GitHub so we wrote our own.

Today we are excited to introduce nti.fakestatsd, a testing client for verifying StatsD metrics emitted by perfmetrics.

It's easy to create a new client for use in testing:

>>> from nti.fakestatsd import FakeStatsDClient
>>> test_client = FakeStatsDClient()

This client exposes the same public interface as perfmetrics.statsd.StatsdClient. For example we can increment counters, set gauges, etc:

>>> test_client.incr('request_c')
>>> test_client.gauge('active_sessions', 320)

Unlike perfmetrics.statsd.StatsdClient, FakeStatsDClient simply tracks the statsd packets that would be sent. This information is exposed on our test_client both as the raw statsd packet, and for convenience this information is also parsed and exposed as Metric objects. For complete details see FakeStatsDClient and Metric.

>>> test_client.packets
['request_c:1|c', 'active_sessions:320|g']
>>> test_client.metrics
[<nti.fakestatsd.metric.Metric object at ...>, <nti.fakestatsd.metric.Metric object at ...>]

For validating metrics we provide a set of hamcrest matchers for use in test assertions:

>>> from hamcrest import assert_that
>>> from hamcrest import contains
>>> from nti.fakestatsd.matchers import is_metric
>>> from nti.fakestatsd.matchers import is_gauge
>>> assert_that(test_client,
...     contains(is_metric('c', 'request_c', '1'),
...              is_gauge('active_sessions', '320')))
>>> assert_that(test_client,
...     contains(is_gauge('request_c', '1'),
...              is_gauge('active_sessions', '320')))
Traceback (most recent call last):
...
AssertionError:
Expected: a sequence containing [Metric of form <request_c:1|g>, Metric of form <active_sessions:320|g>]
     but: item 0: was <request_c:1|c>

As with all our open-source projects we encourage you to check it out on github and, of course, Pull Requests are always welcome.