Fast analytics using Redis
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.
LICENSE Adds LICENSE and example usage Oct 31, 2012



Code Climate

Build Status

Minutemen were members of teams from Massachusetts that were well-prepared militia companies of select men from the American colonial partisan militia during the American Revolutionary War. They provided a highly mobile, rapidly deployed force that allowed the colonies to respond immediately to war threats, hence the name.


gem install minuteman


Configuration exists within the config block:

Minuteman.configure do |config|
  # You need to use Redic to define a new Redis connection
  config.redis ="redis://")

  # The prefix affects operations
  config.prefix = "Tomato"

  # The patterns is what Minuteman uses for the tracking/counting and the
  # different analyzers
  config.patterns = {
    dia: -> (time) { time.strftime("%Y-%m-%d") }


Tracking is the most basic scenario for Minuteman:

# This will create the "landing:new" event in all the defined patterns and since
# there is no user here it will create an annonymous one.
# This user only exists in the Minuteman context.
user = Minuteman.track("landing:new")

# The id it's an internal representation, not useful for you  # => "1"

# This is the unique id. With this you can have an identifier for the user
user.uid # => "787c8770-0ac2-4654-9fa4-e57d152fa341"

# You can use the `user` to keep tracking things:

# Or use it as an argument
Minuteman.track("help:page", user)

# Or track several users at once
Minuteman.track("help:page", [user1, user2, user3])

# By default all the tracking and counting events are triggered with ``
# but you can change that as well:
Minuteman.track("setup:account", user,, 2, 10))


There is a powerful engine behind all the operations which is Redis + Lua <3

# The analysis of information relies on `Minuteman.patterns` and if you don't
# change it you'll get acess to `year`, `month`, `day`, `hour`, `minute`.
# To get information about `register:page` for today:

# You can always pass a `Time` instance to set the time you need information.
Minuteman.analyze("register:page").day(, 2, 12))

# You also have a shorthand for analysis:
register_page_month = Minuteman("register:page").month

# And the power of Minuteman relies on the operations you can do with that.
# Counting the amount:
register_page_month.count # => 10

# Or knowing if a user is included in that set:
register_page_month.include?(User[42]) # => true

# But the most important part is the ability to do bit operations on that:
# You can intersect sets using bitwise AND(`&`), OR(`|`), NOT(`~`, `-`) and XOR(`^`).
# Also you can use plus(`+`) and minus(`-`) operations.
# In this example we'll get all the users that accessed our site via a promo
# invite but didn't buy anything
  Minuteman("promo:email").day & Minuteman("promo:google").day
) - Minuteman("buy:success").day


Since Minuteman 2.0 there's the possibility to have counters.

# Counting works in a very similar way to tracking but with some important
# differences. Trackings are idempotent unlike countings and they do not provide
# operations between sets... you can use plain ruby for that.
# This will add 1 to the `hits:page` counter:

# You can also pass a `Time` instance to define when this tracking ocurred:
Minuteman.add("hits:page",, 20, 01))

# And you can also send users to also count the times that given user did that
# event
Minuteman.add("hits:page",, 20, 01), user)

# You can access counting information similar to tracking:
Minuteman.count("hits:page").day.count # => 201

# Or with a shorthand:
Counterman("hits:page").day.count # => 201


Minuteman 2.0 adds the concept of users which can be annonymous or have a relation with your own database.

# This will create an annonymous user
user = Minuteman::User.create

# Users are just a part of Minuteman and do not interfere with your own.
# They do have some properties like a unique identifier you can use to find it
# in the future
user.uid # => "787c8770-0ac2-4654-9fa4-e57d152fa341"

# User lookup works like this:
# And you can use that unique identifier as a key in a cookie to see what your
# users do when no one is looking

# But since the point is to be able to get tied to your data you can promote a
# user, from anonymous to "real"

# Lookups also work with promoted ids

# Having a user you can do all the same operations minus the hussle.
# Like tracking:

# or adding:

# or counting
user.count("failed:login").month.count # => 23

# But also the counted events go to the big picture
Counterman("failed:login").month.count # => 512