The Statisfaction Ruby Gem provides an easy way to store and retrieve statistics on the usage of methods.
You can specify which methods are watched, see the Usage section for examples.
Add this line to your application's Gemfile:
gem 'statisfaction'
And then execute:
$ bundle
Or install it yourself as:
$ gem install statisfaction
To setup Statisfaction in your application:
$ rails generate statisfaction:install
This process
- creates a migration,
- adds a route to the engine if the current Rails version is >= 3.1
- adds an initializer that denies everybody view access to Statisfaction data:
Statisfaction::StatisticsController.configure do
usable_if { false }
end
Don't forget to update the initializer to grant access :) The block has access to any instance methods that are present in ApplicationController (and, if you really want it, StatisfactionController).
Now run
$ rake db:migrate
and you're done!
Methods for which statistics are collected are configured in the class itself by calling
class MyClass
statisfy do
record :my_method
record :another_method
end
end
This records when :my_method and :another_method are called on instances of MyClass. Of course, a shorthand is available in the form of
class MyClass
statisfy do
record :my_method, :another_method
end
end
There are also some sensible defaults for ActiveRecord: create, update, destroy:
class MyAR < ActiveRecord::Base
statisfy
end
which is equivalent to
class MyAR < ActiveRecord::Base
statisfy do
statisfaction_defaults
end
end
You can specify them separately with:
class MyAR < ActiveRecord::Base
statisfy do
ar_create
ar_update
ar_destroy
end
end
The second form also allows collecting other methods in addition to the defaults:
class MyAR < ActiveRecord::Base
statisfy do
statisfaction_defaults
# You can still add your own methods to record
record :my_method
record :another_method
end
end
You can specify an attribute to be recorded when the specified method is called:
class MyClass
attr_accessor :user
statisfy do
record :my_method, storing: :user
end
end
If you want to record the same attribute for multiple methods, you can specify a default attribute:
class MyClass
attr_accessor :user, :another_attribute
statisfy(storing: :user) do
record :my_method
record :another_method
# for calls to :yet_another_method, do not store
# user, but :another_attribute
record :yet_another_method, storing: :another_attribute
end
end
Some time in the future, we'd like to support blocks as well:
class MyClass
statisfy(recording: :user) do
# NOTE: This is not supported yet
record :my_method, storing: proc { User.find(params[:id]) }
end
end
There is support for if/unless statements to regulate when to record events:
class MyClass
def should_log
false
end
def earth_is_flat
false
end
statisfy do
record :my_method, :if => :should_log
record :my_other_method, :unless => :earth_is_flat
end
Don't use both :if and :unless in the same record statement. For complex behavior, define a method and use that.
In some cases, you might want to log an event under a different name. The main reason would be recording the same method call under different names.
The example below demonstrates how we handle recording ActiveRecord create/update callsO
class MyClass < ActiveRecord::Base
statisfy do
record :save, :as => :create, :if => :new_record?
record :save, :as => :update, :unless => :new_record?
end
end
Note that the :as-parameter must be unique for each method. In other words, the above statement is valid, as well as this one:
...
statisfy do
record :save, :as => :create
record :new, :as => :create
end
The next statement would be invalid:
...
statisfy do
# This is invalid, don't do it!
# The :if-options are not really relevant but provide an example for why you'd want to do this
record :save, :as => :create, :if => :should_log_case_1
record :save, :as => :create, :if => :should_log_case_2
end
Statisfaction allows tables to be extracted from the recorded data. To get a table of the MyClass#my_method calls that occurred between 3 and 2 months ago, counted by month, you would use the following call:
table = Statisfaction::Table.for(MyClass, :my_method).from(3.months.ago).to(2.months.ago).by(:month)
Calling #rows on this table provides you with an array of arrays, where each of the level-2 arrays is a table row.
- Each column contains the data for a different event type (except the first, which contains the date labels)
- Each row contains the data for a different month (except the first, which contains the event-type labels)
For example:
table.rows
=> [["month", "MyClass,my_method"], [Sun, 01 Apr 2012 00:00:00 +0000, 12]]
Statisfaction exposes a JSON API which allows you to retrieve statistics from your application.
By default, by issuing a GET request like
/statisfaction/get.json?for[]=MyClass,create&for[]=MyClass,destroy&start=2012-01-01&end=2012-05-01&granularity=month
you retrieve statistics for the :create and :destroy method on MyClass.
This path is accessible on the server side as
statisfaction.get_path( {
for: %w{MyClass,create MyClass,destroy},
start: "2012-01-01",
end: "2012-05-01",
granularity: :month
} )
In Rails 3.0, this path is called 'statisfaction_get_path" instead, since the engine's routes cannot be properly mounted prior to Rails 3.1
name | description |
---|---|
for[] | a list of class,method-tuples |
start, end | a datetime in ISO8601 format |
granularity | 'hour', 'day', 'week', 'month', 'year' |
All parameters are mandatory.
Statisfaction allows permanent and temporary activation and deactivation. When deactivated, no events will be recorded. Deactivation is done by
Statisfaction.deactivate
Likewise, Statisfaction can be (re-)activated using
Statisfaction.activate
To execute small snippets of code without recording events, Statisfaction also provides some methods which accept blocks:
Statisfaction.activate
# events will be recorded for code placed here...
Statisfaction.without_statisfaction do
# ... but not for code placed here...
end
# recording events again...
Statisfaction.deactivate
# stopped recording events...
Statisfaction.with_statisfaction do
# recording events again...
end
# stopped recording events again.
By default, Statisfaction is disabled in Rails test environments to speed up automated tests. This can be changed by editing your application's config/initializers/statisfaction.rb.
Statisfaction will not work with SQLite, since it does not support queries like 'GROUP BY MONTH(created_at)'
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Added some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request