Automated metrics reporting via email. It's datastore-agnostic, so you can query SQL, MongoDB, external APIs, etc. to generate the stats you need. Uses sparkle for generating sparklines. Example implementations:
Installation
This gem can be used within an existing project (e.g. a Rails app), or standalone.
# Gemfile
gem 'tricle'
# Rakefile
require 'your/tricle/subclasses'
require 'tricle/tasks'
# your/config/file.rb
# unless you already have ActionMailer set up
ActionMailer::Base.raise_delivery_errors = true
ActionMailer::Base.smtp_settings = {
# ...
}
# Optional: Override the start day of the reports (Rails >= 4.0.3 only)
# http://api.rubyonrails.org/classes/Date.html#method-i-beginning_of_week-3D
Date.beginning_of_week = :monday
See the ActionMailer guide for configuration details. Finally, execute:
bundle
Usage
Metrics
For each metric you want to report, create a new subclass of Tricle::Metric
that implements #size_for_range
and #total
:
class MyMetric < Tricle::Metric
# Retrieve the value of this metric for the provided time period. Generally
# this will be the count/value added/removed. Not necessary if #items_for_range
# is defined.
#
# @param start_at [Time]
# @param end_at [Time] non-inclusive
# @return [Fixnum]
def size_for_range(start_at, end_at)
# ...
end
# Optional: Retrieve the cumulative value for this metric. If not defined,
# the total won't be displayed in the mailer.
#
# @return [Fixnum] the grand total
def total
# ...
end
# Optional: Only necessary if using `list` for this Metric within your Mailer.
#
# @param start_at [Time]
# @param end_at [Time] non-inclusive
# @return [Enumerator]
def items_for_range(start_at, end_at)
# ...
end
end
If you would like finer-grain optimization, the methods included from the Aggregation
mixin can be overridden.
ActiveRecord Metrics
You can inherit from Tricle::ActiveRecordMetric
for even easier setup. By default, Tricle looks for records with a created_at
timestamp between the start_at
and end_at
times.
# app/metrics/new_users.rb
class NewUsers < Tricle::ActiveRecordMetric
# Apply any default scopes you need
def items
User.where(deleted_at: nil)
end
end
You can also override the time_column
method to split the time intervals based on that value. For example, to see records that have been updated:
# app/metrics/new_users.rb
class NewUsers < Tricle::ActiveRecordMetric
def items
User.where(deleted_at: nil)
end
def time_column
'updated_at'
end
end
"Lower is better" metrics
By default, Tricle highlights numbers that increased in green, and those that decreased in red. If you have a metric where a lower number is considered better, you'll want to override the #better
method so Tricle highlights your cells properly:
class LowerIsBetterMetric < Tricle::Metric
def better
:lower
end
...
end
You can also return :none
, and none of your cells for that metric will be highlighted green or red.
Mailers
Mailers specify how a particular set of Metrics should be sent. You can define one or multiple, to send different metrics to different groups of people.
class MyMailer < Tricle::Mailer
# accepts the same options as ActionMailer... see "Default Hash" at
# http://rubydoc.info/gems/actionmailer/ActionMailer/Base
default(
# ...
)
self.period = :day # options are :day, :week (default), and :month
metric MyMetric1
metric MyMetric2
# ...
# optional: metrics can be grouped
group "Group 1 Name" do
metric MyMetric3
# ...
end
group "Group 2 Name" do
metric MyMetric4
# ...
end
# optional: list the items for the specified Metric
list MyMetric2 do |item|
# return the HTML string for each particular item
end
# ...
end
e.g.
# app/mailers/weekly_insights.rb
class WeeklyInsights < Tricle::Mailer
default(
to: ['theteam@mycompany.com', 'theboss@mycompany.com'],
from: 'noreply@mycompany.com'
)
metric NewUsers
list NewUsers do |user|
<<-MARKUP
<h3>#{user.name}</h3>
<div>#{user.location}</div>
<a href="mailto:#{user.email}>#{user.email}</a>
MARKUP
end
end
The subject line will be based on the Mailer class name.
Passing options to a Metric
Sometimes, you'll want to initialize a Metric with specific options. If you pass a hash as a second argument to the mailer's metric
method, the Metric will be initialized with an @options
instance variable.
class IntelligenceBrief < Tricle::Mailer
metric NewUsers, matching_email: '@gmail.com'
# or for a list...
list NewUsers, matching_email: '@gmail.com' do |item|
...
end
end
Previewing
Since you'd probably like to preview your mailers before sending them, set up the Tricle::MailPreview
Rack app (which uses MailView).
Within a Rails app
# config/initializers/tricle.rb
require 'tricle/mail_preview'
# config/routes.rb
if Rails.env.development?
mount Tricle::MailPreview => 'mail_view'
end
and navigate to localhost:3000/mail_view.
Standalone
bundle exec rake tricle:preview
open http://localhost:8080
Global Configuration
To set global configuration options, in an initializer:
Tricle.configure do |c|
c.sparklines = false # default: true
end
Deploying
To send all Tricle emails, run
rake tricle:emails:send # sends all emails
or
rake tricle:emails:daily # sends emails with period = :day
To set a speficic time zone, use the TZ
environment variable (see the list here).
TZ=UTC rake tricle:emails:send
Heroku
-
Deploy the application.
- If this is a standalone app, you won't need a
web
process.
- If this is a standalone app, you won't need a
-
Enable an add-on for email delivery, and configure ActionMailer to send via that provider.
-
Enable Heroku Scheduler.
heroku addons:add scheduler:standard heroku addons:open scheduler
-
Add a "job".
- For a report sent once per day, use the command from Deploying.
- For a report sent once per week, use
rake tricle:emails:send_after_beginning_of_week
daily.- Heroku Scheduler only supports a maximum of daily tasks, hence needing to use a special task.
You can trigger the email(s) manually for testing with heroku run rake tricle:emails:send
.