README.md in harness-0.3.0 vs README.md in harness-0.4.0

- old
+ new

@@ -5,10 +5,12 @@ redis before being sent to the service. Currently Supported Services: * Librato +* Statsd (thanks to fluxlux) +* Stathat Current Features: * Track counters over time (# of registered users) * Read time specific values (# time to cache something) @@ -43,24 +45,30 @@ ## Installation Add this line to your application's Gemfile: - gem 'harness' +``` +gem 'harness' +``` And then execute: - $ bundle +``` +$ bundle +``` Or install it yourself as: - $ gem install harness +``` +$ gem install harness +``` ## Usage In the metrics world there are two types of things: Gauges and Counters. -Gauges are time senstive and represent something at a specific point in +Gauges are time sensitive and represent something at a specific point in time. Counters keep track of things and should be increasing. Counters can be reset back to zero. You can combine counters and/or gauges to correlate data about your application. Meters monitor counters. They allow you look at rates of counters (read: counters per second). @@ -92,30 +100,48 @@ stored in redis and incremented. This means you can simply pass `:counter => true` in instrumentations if you'd like to count it. You may also pass `:counter => 5` if you'd like to provide your own value. This value is stored in redis so the next time `:counter => true` will work correctly. You can reset all the counters back to zero by calling: -`Harness.reset_counters!`. +`Harness.reset_counters!`. +**NOTE**: You should use the bundled rake task to reset counters with +a cron job. This will prevent unbounded growth of this metadata. You +can call `rake harness:reset_counters` to do this. You should call +this rake task at whatever your longest measurable interval is. Here's +an example: You log gauges every 12 hours. You should reset the +counters every 12 hours. This issue is discussed [here](https://github.com/twinturbo/harness/issues/15). + ```ruby class MyClass def important_method(stuff) ActiveSupport::Notifications.instrument "important_method.my_class", :counter => true do do_important_stuff end end end ``` -The instuments name will be sent as the name (`important_method.my_class`) +The instruments name will be sent as the name (`important_method.my_class`) for that gauge or counter. +Note that `ActiveSupport::Notifications.instrument` doesn't require +a block. This can be useful when you are taking an instant measurement. + +```ruby +class MyClass + def important_method(stuff) + ActiveSupport::Notifications.instrument "important_method.my_class", :counter => true + end +end +``` + Harness will do all the extra work in sending these metrics to whatever service you're using. Once you the counters are you are instrumented, then you can meter them. -Meters allow you take arbitary readings of counter rates. The results +Meters allow you take arbitrary readings of counter rates. The results return a gauge so they can be logged as well. ```ruby # Define a counter class MyClass @@ -135,29 +161,34 @@ meter.per_hour ``` ## Customizing -You can pash a hash to `:counter` or `:gauge` to initialize the +You can pass a hash to `:counter` or `:gauge` to initialize the measurement your own way. +If you pass a value attribute to a gauge, it will be the value +sent instead of the duration of the block. + ```ruby class MyClass def important_method(stuff) - ActiveSupport::Notifications.instrument "important_method.my_class", :gauge => { :id => 'custom-id', :name => "My Measurement" } do + ActiveSupport::Notifications.instrument "important_method.my_class", + :gauge => { :id => 'custom-id', :name => "My Measurement", + :value => my_current_val, :units => 'cogs' } do do_important_stuff end end end ``` ## One Off Gauges and Counters -You can instantiate `Harness::Counter` and `Harness::Guage` wherever you +You can instantiate `Harness::Counter` and `Harness::Gauge` wherever you want. Events from `ActiveSupport` are just converted to these classes under the covers anyways. You can use these class if you want to take -peridocial measurements or tracking something that happens outside the +periodic measurements or tracking something that happens outside the application. ```ruby gauge = Harness::Gauge.new gauge.id = "foo.bar" @@ -172,27 +203,57 @@ counter.name = "# of Foo bars" counter.time # defaults to Time.now counter.value = read_total_users_in_database counter.log -# Both class take an option hash +### Both classes take an option hash -gauge = Harness::Guage.new :time => Time.now, :id => 'foo.bar' +gauge = Harness::Gauge.new :time => Time.now, :id => 'foo.bar' counter = Harness::Counter.new :time => Time.now, :id => 'foo.bar' ``` ## Configuration +### Librato ```ruby Harness.config.adapter = :librato Harness.config.librato.email = 'example@example.com' Harness.config.librato.token = 'your-api-key' -Harness.redis = Redis.new ``` +### StatsD + +Harness does **not** configure StatsD for you. It uses the StatsD class +under the covers. If you've already configured that in your own way, great. +If not, you can use the configuration proxy as described below. You +must also add `statsd-instrument` to your `Gemfile`. This is a soft +dependency that is not installed for you. + +```ruby +Harness.config.adapter = :statsd + +# Harness.config.statsd is a proxy for the StatsD class +Harness.config.statsd.host = 'localhost' +Harness.config.statsd.port = '8080' +Harness.config.statsd.default_sample_rate = 0.1 +Harness.config.statsd.logger = Rails.logger + +# You can assign your own StatsD implementation +# by setting the "backend" attribute +Harness.config.statsd.backend = CustomStatsD +``` + +### Stathat + +```ruby +Harness.config.adapter = :stathat + +Harness.config.stathat.ezkey = 'example@example.com' +``` + ## Rails Integration Harness will automatically log metrics coming from `ActionPack`, `ActiveRecord`, and `ActionMailer`. `ActiveSupport` instrumentation is disabled by default. Also, custom integrations are disabled by default. @@ -207,12 +268,12 @@ You can configure Harness from `application.rb` ```ruby config.harness.adapter = :librato -config.librato.email = 'example@example.com' -config.librato.token = 'your-api-key' +config.harness.librato.email = 'example@example.com' +config.harness.librato.token = 'your-api-key' ``` Redis will be automatically configured if you `REDISTOGO_URL` or `REDIS_URL` environment variables at set. They are wrapped in a namespace so there will be no conflicts. If they are not present, the @@ -223,11 +284,11 @@ require 'erb' file = Rails.root.join 'config', 'resque.yml' config = YAML.load(ERB.new(File.read(Rails.root.join('config', 'redis.yml'))).result) -Harness.redis = Redis.new(:url => config[Rails.env]) +Harness.redis = Redis::Namespace.new('harness', :redis => Redis.connect(:url => config[Rails.env])) ``` `rake harness:reset_counters` is also added. ### Rails Environments @@ -237,13 +298,13 @@ logged in production. ### Background Processing Harness integrates automatically with Resque or Sidekiq. This is because -reporting measurements can take time and add unncessary overhead to the +reporting measurements can take time and add unnecessary overhead to the response time. If neither of these libraries are present, measurements **will be posted in realtime.** You can set your own queue by -specifiying a class like so: +specifying a class like so: ```ruby Harness.config.queue = MyCustomQueue ```