/node-statsd-instrument

Provides metaprogramming methods to inject StatsD instrumentation using node-statsd

Primary LanguageCoffeeScript

Instrumentation for the StatsD client for Node.js apps (node-statsd)

========================================================================

Etsy Node.js StatsD is a lean-and-mean server for gathering and analyzing application metrics generated by StatsD clients and then creating graphs from those metrics by dispatching them into Graphite.

This module is based on the excellent Shopify statsd-instrument Ruby module and it allows instrumentation of methods so that they will measure and count StatsD metrics without coupling the actual StatsD plumbing code with your logic code. As Shopify puts it - "lets you define all of your instrumentation in one file and not litter your code with instrumentation details".

Unlike the Shopify module, which implements it's own Ruby StatsD client handling (UDP) communication against the StatsD server, this module only provides the instrumentation functions and relies on the existing node-statsd module by sivy for communicating with the Etsy StatsD server.

Major differences from Shopify statsd-instrument for Ruby

  1. No configuration - no logging, no different modes of operation (production/testing/etc).
  2. Vows-based tests that demonstrate and test the usage of the instrumentation in an artificial scenario instead of rewriting Shopify tests in say, nodeunit.

Installation

% npm install node-statsd-instrument

Usage

Initialization

StatsD = require('node-statsd').StatsD;
StatsDInstrumentation = require('node-statsd-instrument').StatsDInstrumentation;

statsd_client = new StatsD('127.0.0.1', 8125);
statsd_instrument = new StatsDInstrumentation(statsd_client);

or you can use node-statsd StatsD client straight from this module -

instrument = require('node-statsd-instrument');

statsd_client = new instrument.StatsD('127.0.0.1', 8125);
statsd_instrument = new instrument.StatsDInstrumentation(statsd_client);

Instrumenting Object Methods

If you have a method in an object you would like to instrument, do this -

statsd_instrument.count(some_object, 'some_object_method', 'some.counter')

Instrumenting Class Methods

You can instrument prototypal class-like methods just like object methods by using the metaprogramming methods. You simply need to give the 'class' prototype as the object -

statsd_instrument.count(SomeClass.prototype, 'some_class_method', 'some.counter')

Metaprogramming Methods

Use the methods provided below to instrument methods in your objects.

count

This will increment the given key even if the method doesn't finish successfully (returns false, raises).s

statsd_instrument.count(some_object, 'some_object_method', 'some.counter')

measure

This will measure the method's runtime (in milliseconds) and report it to StatsD using the StatsD timing counter (StatsD.timing from node-statsd).

statsd_instrument.measure(some_object, 'some_object_method', 'some.timing.counter')

count_if

This will only increment the given key if the method executes successfully.

statsd_instrument.count_if(some_object, 'some_object_method', 'some.counter')

So now, if some_object.some_object_method raises an exception or returns false (ie. result == false), we won't increment the counter.

You can pass a function to evaluate what success and failure means -

some_controller.request.url = 'someFatResource'
statsd_instrument.count_success(some_controller, 'responseReceived', some_controller.request.url+'.cached', function() { 
                                this.response.source == 'cache' } )

If the response was given to the client from the cache, then the evaluating function will return true and so someFatResource.cached counter will be increased. Nothing happens if the evaluating function returns false.

Do note that the given function is binded to the instrumented object, which is some_controller in the above example (this allows access to some_controller.response.source from inside the function body).

count_success

Similar to count_if, except this will increment one key in the case of success and another key in the case of failure.

statsd_instrument.count_success(some_object, 'some_object_method', 'some.counter')

If this method fails execution (raises or returns false) the failure counter will be incremented ('some.counter.failure'), otherwise it will be the success counter ('some.counter.success').

Again, you can pass a function to evaluate what success and failure means -

some_controller.request.url = 'someFatResource'
statsd_instrument.count_success(some_controller, 'responseReceived', some_controller.request.url+'.caching', function() { 
                                this.response.source == 'cache' } )

If the response was given to the client from the cache, then the evaluating function will return true and this will be considered a success and so the someFatResource.caching.success counter will be increased. Otherwise, the evaluating function will return false and someFatResource.caching.failure will be increased, indicating that there was a failure in caching someFatResource. Again, do note that the given evaluating function is binded to the instrumented object (some_controller).