Abacus is a simple counting server. It counts al kind of things as triples of strings on dates.
The three parts of this service are gathered in a rails project:
- A resque worker using a redis queue which work as the data input interface.
- A single mysql table on which stored amounts of that triple are incremented and one Model to access the table.
- A Controller to provide an API interface to gather the stored counts with diferent sort of requests.
- create database abacus_statistics_development;
- create database abacus_statistics_test;
- adjust varchar width in migration
- bundle install
- rake db:migrate
- rake db:test:prepare
- bundle exec spec spec
- rake resque:work
Intregrate this lines into the code where you want to count things:
require 'resque'
require 'ostruct'
worker = module Worker class StatisticsRecorder; @queue = 'abacus_statistics' end; end
After running this initial installation steps you can start pushing data into the redis queue
Resque.enqueue(worker, {:ns1 => 'search', :ns2 => 'horse', :ns3 => 'website', :year => 2011, :month => 1, :day => 31})
Resque.enqueue(worker, {:ns1 => 'sale', :ns2 => 'horse', :ns3 => 'iphone', :year => 2011, :month => 1 , :day => 31})
Resque.enqueue(worker, {:ns1 => 'comment', :ns2 => 'horse', :ns3 => 'iphone', :year => 2011, :month => 1 ,:day => 31})
Resque.enqueue(worker, {:ns1 => 'sales_price', :ns2 => 'horse', :ns3 => 'iphone',:amount => 2 :year => 2011, :month => 1 ,:day => 31})
Resque.enqueue(worker, {:ns1 => 'sales_price', :ns2 => 'horse', :ns3 => 'iphone',:amount => -2 :year => 2011, :month => 1 ,:day => 31})
day, month, year can be skipped then the actual date is used data is return as array of jason hashes
You can also count by posting to /statistics with curl this looks like this: curl -d 'ns1=test_ns1&ns2=test_ns2&ns3=test_ns3' localhost:3000/statistics.json
Everything that adds correctly formatted data to a redis queue the resque worker is listening on will work for counting.
You can receive the counts by sending http request with triples and date ranges as parameters to the webserver. The webserver return an Array of json hashes containing the Amount.
curl "localhost:3000/statistics?ns1=comment&ns2=horse&ns3=iphone&date_since=2011-01-31&date_till=2011-01-31&granularity=day"
[{"day":31,"ns1":"comment","month":1,"ns2":"horse","year":2011,"amount":3.0,"ns3":"iphone"}]
curl "localhost:3000/statistics?ns1=comment&ns2=horse&ns3=iphone&date_since=2011-01-29&date_till=2011-01-31&granularity=day"
[{"day":29,"ns1":"comment","month":1,"ns2":"horse","year":2011,"amount":0.0,"ns3":"iphone"},
{"day":30,"ns1":"comment","month":1,"ns2":"horse","year":2011,"amount":0.0,"ns3":"iphone"},
{"day":31,"ns1":"comment","month":1,"ns2":"horse","year":2011,"amount":1.0,"ns3":"iphone"}]
Data for multi n1, n2 and dates the cartesian product will be returned filling empty triple with 0 amount
[{"day":30,"ns1":"comment","month":1,"ns2":"horse","year":2011,"amount":0.0,"ns3":"iphone"},
{"day":31,"ns1":"comment","month":1,"ns2":"horse","year":2011,"amount":1.0,"ns3":"iphone"},
{"day":30,"ns1":"comment","month":1,"ns2":"camel","year":2011,"amount":0.0,"ns3":"iphone"},
{"day":31,"ns1":"comment","month":1,"ns2":"camel","year":2011,"amount":0.0,"ns3":"iphone"},
{"day":30,"ns1":"sale","month":1,"ns2":"horse","year":2011,"amount":0.0,"ns3":"iphone"},
{"day":31,"ns1":"sale","month":1,"ns2":"horse","year":2011,"amount":1.0,"ns3":"iphone"},
{"day":30,"ns1":"sale","month":1,"ns2":"camel","year":2011,"amount":0.0,"ns3":"iphone"},
{"day":31,"ns1":"sale","month":1,"ns2":"camel","year":2011,"amount":0.0,"ns3":"iphone"}]
[{"day":null,"ns1":"comment","month":1,"ns2":"horse","year":2011,"amount":1.0,"ns3":"iphone"}]
[{"day":null,"ns1":"comment","month":null,"ns2":"horse","year":2011,"amount":1.0,"ns3":"iphone"}]
[{"day":null,"ns1":"comment","month":null,"ns2":"horse","year":2011,"amount":1.0,"ns3":null}]