Announcing Measure::Everything

tl;dr: New on CPAN: Measure::Everything - Log::Any for Stats

The next step0 in our quest to collect lots of data from our services is to enable apps to easily offload stats somewhere. We want to be able to generate stats everywhere, be it Controllers, Models, helper scripts, utility classes or roles, etc.

I really like how Log::Any enables you to log from everywhere in your code without having to schlepp a log object around. Yes, Log::Any isn't much more than a fancy global value, but it's used exactly for what global values are good for. Logging (and measuring stats) is completely detached1 from your regular code flow.

Anyways, we decided to clone Log::Any's API and twist it a bit to fit the domain of measuring stats, resulting in Measure::Everything2!

Example

  package MyProject::SomeController;
  use Measure::Everything qw($stats);
  
  $stats->write(
      'jigawats',
      1.21,
      {
          source   => 'Plutonium',
          location => 'Hill Valley'
      }
  );

So let's say you want to measure how many jigawats your controller needs for some action. You just use Measure::Everything and get a object called $stats imported into your namespace. Then, call write on $stats to write some stats.

By default this will do exactly nothing, as you haven't specified a Measure::Everything::Adapter yet, and per default we use Measure::Everything::Adapter::Null.

In the script you use to execute MyProject::SomeController (probably something like app.psgi), set up an adapter:

  use Measure::Everything::Adapter;
  Measure::Everything::Adapter->set('InfluxDB::File',
      file => '/tmp/stats/myapp.stats'
  );

This will set up the only currently existing adapter, Measure::Everything::Adapter::InfluxDB::File. This adapter will convert the measurement data into the InfluxDB line protocol using InfluxDB::LineProtocol (read more about it here), and write the line into the file /tmp/stats/myapp.stats.

Of course you will then need to somehow process this file to send the lines to InfluxDB. I plan to release our solution to this in the next week, so stay tuned!

Potential Problems

For now, Measure::Everything only supports InfluxDB, because that's what we're using. But I hope that other time series databases (or other storage backends) can be added to Measure::Everything. Unfortunately, measuring stats is not such a well-established domain like logging (where we have a set of common log levels, and basically "just" need to pass some string to some logging sink). So it is very likely that Measure::Everything cannot provide a generic API, where you can switch out Adapters without changing the measuring code. But we can try!

Anyway, I'd appreciate it if you give Measure::Everything a try, and/or send some feedback!

Footnotes

0 The previous step was InfluxDB::LineProtocol, described in this blog post.

1 One could say orthogonal if one wants to impress readers with his Greek.

2 The name of this module is of course inspired by this article: Measure Everything.