bodhi 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +11 -0
- data/Gemfile.lock +92 -0
- data/README.markdown +113 -0
- data/Rakefile +2 -0
- data/bodhi.gemspec +46 -0
- data/lib/bodhi.rb +10 -0
- data/lib/bodhi/definitions/aggregate.rb +38 -0
- data/lib/bodhi/definitions/count.rb +25 -0
- data/lib/bodhi/metric.rb +76 -0
- data/lib/bodhi/storage/metric_value.rb +4 -0
- data/lib/bodhi/version.rb +3 -0
- data/lib/generators/bodhi/install_generator.rb +24 -0
- data/lib/generators/bodhi/templates/bodhi.rb +6 -0
- data/lib/generators/bodhi/templates/create_metric_values.rb +16 -0
- data/spec/aggregate_metrics_spec.rb +29 -0
- data/spec/metric_spec.rb +23 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/support/mock_model.rb +24 -0
- data/spec/support/persistence_spec.rb +30 -0
- metadata +147 -0
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
bodhi (0.0.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: http://rubygems.org/
|
8
|
+
specs:
|
9
|
+
abstract (1.0.0)
|
10
|
+
actionmailer (3.0.5)
|
11
|
+
actionpack (= 3.0.5)
|
12
|
+
mail (~> 2.2.15)
|
13
|
+
actionpack (3.0.5)
|
14
|
+
activemodel (= 3.0.5)
|
15
|
+
activesupport (= 3.0.5)
|
16
|
+
builder (~> 2.1.2)
|
17
|
+
erubis (~> 2.6.6)
|
18
|
+
i18n (~> 0.4)
|
19
|
+
rack (~> 1.2.1)
|
20
|
+
rack-mount (~> 0.6.13)
|
21
|
+
rack-test (~> 0.5.7)
|
22
|
+
tzinfo (~> 0.3.23)
|
23
|
+
activemodel (3.0.5)
|
24
|
+
activesupport (= 3.0.5)
|
25
|
+
builder (~> 2.1.2)
|
26
|
+
i18n (~> 0.4)
|
27
|
+
activerecord (3.0.5)
|
28
|
+
activemodel (= 3.0.5)
|
29
|
+
activesupport (= 3.0.5)
|
30
|
+
arel (~> 2.0.2)
|
31
|
+
tzinfo (~> 0.3.23)
|
32
|
+
activeresource (3.0.5)
|
33
|
+
activemodel (= 3.0.5)
|
34
|
+
activesupport (= 3.0.5)
|
35
|
+
activesupport (3.0.5)
|
36
|
+
arel (2.0.9)
|
37
|
+
builder (2.1.2)
|
38
|
+
diff-lcs (1.1.2)
|
39
|
+
erubis (2.6.6)
|
40
|
+
abstract (>= 1.0.0)
|
41
|
+
i18n (0.5.0)
|
42
|
+
mail (2.2.15)
|
43
|
+
activesupport (>= 2.3.6)
|
44
|
+
i18n (>= 0.4.0)
|
45
|
+
mime-types (~> 1.16)
|
46
|
+
treetop (~> 1.4.8)
|
47
|
+
mime-types (1.16)
|
48
|
+
polyglot (0.3.1)
|
49
|
+
rack (1.2.2)
|
50
|
+
rack-mount (0.6.13)
|
51
|
+
rack (>= 1.0.0)
|
52
|
+
rack-test (0.5.7)
|
53
|
+
rack (>= 1.0)
|
54
|
+
rails (3.0.5)
|
55
|
+
actionmailer (= 3.0.5)
|
56
|
+
actionpack (= 3.0.5)
|
57
|
+
activerecord (= 3.0.5)
|
58
|
+
activeresource (= 3.0.5)
|
59
|
+
activesupport (= 3.0.5)
|
60
|
+
bundler (~> 1.0)
|
61
|
+
railties (= 3.0.5)
|
62
|
+
railties (3.0.5)
|
63
|
+
actionpack (= 3.0.5)
|
64
|
+
activesupport (= 3.0.5)
|
65
|
+
rake (>= 0.8.7)
|
66
|
+
thor (~> 0.14.4)
|
67
|
+
rake (0.8.7)
|
68
|
+
rspec (2.5.0)
|
69
|
+
rspec-core (~> 2.5.0)
|
70
|
+
rspec-expectations (~> 2.5.0)
|
71
|
+
rspec-mocks (~> 2.5.0)
|
72
|
+
rspec-core (2.5.1)
|
73
|
+
rspec-expectations (2.5.0)
|
74
|
+
diff-lcs (~> 1.1.2)
|
75
|
+
rspec-mocks (2.5.0)
|
76
|
+
sqlite3 (1.3.3)
|
77
|
+
thor (0.14.6)
|
78
|
+
treetop (1.4.9)
|
79
|
+
polyglot (>= 0.3.1)
|
80
|
+
tzinfo (0.3.26)
|
81
|
+
|
82
|
+
PLATFORMS
|
83
|
+
ruby
|
84
|
+
|
85
|
+
DEPENDENCIES
|
86
|
+
activerecord
|
87
|
+
activesupport
|
88
|
+
bodhi!
|
89
|
+
i18n
|
90
|
+
rails (~> 3.0)
|
91
|
+
rspec
|
92
|
+
sqlite3
|
data/README.markdown
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
# Bodhi
|
2
|
+
**A straightforward DSL for generating and reporting on simple metrics in Ruby.**
|
3
|
+
|
4
|
+
Bodhi helps you generate simple, straightforward reporting metrics for your Rails application. You
|
5
|
+
can generate reports for anything that can be expressed as a value over time with a simple API.
|
6
|
+
|
7
|
+
Bodhi works by letting you define what reporting metrics you want to track in a simple initializer
|
8
|
+
file, and by periodically gathering results about those metrics.
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
### Rails 3
|
13
|
+
|
14
|
+
Add the following to your Gemfile, and run `bundle install`
|
15
|
+
|
16
|
+
gem 'bodhi'
|
17
|
+
|
18
|
+
After installing Bodhi, run the following generator and run `rake db:migrate`. This will create
|
19
|
+
a table where Bodhi can store past metric values.
|
20
|
+
|
21
|
+
rails generate bodhi:install
|
22
|
+
|
23
|
+
Finally, you'll need to put a call to the metric generator in something that will be run at a
|
24
|
+
scheduled interval (a cron rake task is perfect for this). Don't worry about how often it
|
25
|
+
runs, Bodhi will be able to take care of what needs to be run when.
|
26
|
+
|
27
|
+
Bodhi::Metric.generate_all
|
28
|
+
|
29
|
+
|
30
|
+
## Basic Usage
|
31
|
+
|
32
|
+
### Definining Metrics
|
33
|
+
|
34
|
+
Using Bodhi is as simple as definining what metrics you would like to use in `/initializers/bodhi.rb`.
|
35
|
+
Bodhi provides several helpers to cover common metrics that you may want to to track.
|
36
|
+
|
37
|
+
#### Counting
|
38
|
+
|
39
|
+
Counting metrics count the number of a given model in the database. By default, it counts the total
|
40
|
+
number in the database at the time of execution, but you can limit this to only items created or
|
41
|
+
updated when the metrics were run.
|
42
|
+
|
43
|
+
Metric.count :dogs # Counts the total number of the 'dogs' model
|
44
|
+
Metric.count :dogs, :new # Counts all new instances of the 'dogs' model
|
45
|
+
Metric.count :dogs, :updated # Counts all updated instances of the 'dogs' model
|
46
|
+
|
47
|
+
#### Aggregating by column
|
48
|
+
|
49
|
+
You can also aggregate any numerical column using Bodhi. The following examples aggregate an
|
50
|
+
integer column:
|
51
|
+
|
52
|
+
Metric.average :dogs, :num_puppies # Calculates the average number of puppies for a given dog
|
53
|
+
Metric.sum :dogs, :num_puppies # Calculates the total number of puppies.
|
54
|
+
Metric.minimum :dogs, :num_puppies # Calculates the minimum puppy count for any dog
|
55
|
+
Metric.maximum :dogs, :num_puppies # Calculates the maximum puppy count for any dog
|
56
|
+
|
57
|
+
|
58
|
+
#### Custom Metrics
|
59
|
+
|
60
|
+
If you need more sophisticated functionality than what the provided helpers define, you can define
|
61
|
+
custom metrics using Metric.define. Just specify a block that returns a float value. A hash will
|
62
|
+
be passed to your block that specifies start and end times of your metric run in a block.
|
63
|
+
|
64
|
+
Metric.define :percentage_with_puppies do |run|
|
65
|
+
relevant_dogs = Dog.where("created_at between ? and ?", run[:start], run[:end])
|
66
|
+
|
67
|
+
total_count = relevant_dogs.count
|
68
|
+
puppy_count = relevant_dogs.where("num_puppies > 0").count
|
69
|
+
total_count == 0 ? 0 : total_count / puppy_count
|
70
|
+
end
|
71
|
+
|
72
|
+
### Using Metrics
|
73
|
+
|
74
|
+
Metrics can be accessed by passing the name of the metric to the Metric class, like so:
|
75
|
+
|
76
|
+
m = Metric[:percentage_with_puppies]
|
77
|
+
|
78
|
+
At any time, you can get the current value of a metric (from the beginning of the current date to now) by calling
|
79
|
+
`current` on a metric:
|
80
|
+
|
81
|
+
Metric[:percentage_with_puppies].current
|
82
|
+
|
83
|
+
You can access historical values by calling `for_period` for a given metric:
|
84
|
+
|
85
|
+
m = Metric[:percentage_with_puppies]
|
86
|
+
m.for_period 1.month.ago, Time.now
|
87
|
+
|
88
|
+
If the second parameter is omitted on `for_period`, the current date is assumed.
|
89
|
+
|
90
|
+
#### Generating Metrics
|
91
|
+
|
92
|
+
You can generate metrics (run metrics up to the current date), by calling `generate` on a particular Metric,
|
93
|
+
or all metrics with Metric.generate_all
|
94
|
+
|
95
|
+
Metric[:percentage_with_puppies].generate
|
96
|
+
Metric.generate_all
|
97
|
+
|
98
|
+
This will store metric values to the database. You'll need to add calls to generate_all to something that
|
99
|
+
runs at a scheduled interval (like a cron rake task), to ensure metrics are generated correctly. Don't worry
|
100
|
+
about the frequency of your runs, Bodhi won't generate duplicate metrics and will backfill any missing metrics.
|
101
|
+
|
102
|
+
## TODO
|
103
|
+
|
104
|
+
* Support for blocks passed to helper functions
|
105
|
+
* Support for parameterized metrics (or metric groups?)
|
106
|
+
* Charting and pretty output for metrics.
|
107
|
+
* Support for Mongoid or non-ActiveRecord environments
|
108
|
+
|
109
|
+
## Contributing
|
110
|
+
|
111
|
+
Feel free to fork and make any changes necessary. If you'd like to contribute back, I'd appreciate a topic
|
112
|
+
branch and relevant tests.
|
113
|
+
|
data/Rakefile
ADDED
data/bodhi.gemspec
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "bodhi/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "bodhi"
|
7
|
+
s.version = Bodhi::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Ryan Brunner"]
|
10
|
+
s.email = ["ryan@ryanbrunner.com"]
|
11
|
+
s.homepage = ""
|
12
|
+
s.summary = %q{A simple, flexible DSL for generating reports.}
|
13
|
+
s.description = %q{}
|
14
|
+
|
15
|
+
s.rubyforge_project = "bodhi"
|
16
|
+
|
17
|
+
s.add_development_dependency "rspec"
|
18
|
+
s.add_development_dependency "sqlite3"
|
19
|
+
s.add_development_dependency 'activesupport'
|
20
|
+
s.add_development_dependency 'i18n'
|
21
|
+
s.add_development_dependency 'activerecord'
|
22
|
+
|
23
|
+
|
24
|
+
s.files = [
|
25
|
+
"Gemfile",
|
26
|
+
"Gemfile.lock",
|
27
|
+
"README.markdown",
|
28
|
+
"Rakefile",
|
29
|
+
"bodhi.gemspec",
|
30
|
+
"lib/generators/bodhi/install_generator.rb",
|
31
|
+
"lib/generators/bodhi/templates/bodhi.rb",
|
32
|
+
"lib/generators/bodhi/templates/create_metric_values.rb",
|
33
|
+
"lib/bodhi.rb",
|
34
|
+
"lib/bodhi/metric.rb",
|
35
|
+
"lib/bodhi/version.rb",
|
36
|
+
"lib/bodhi/definitions/aggregate.rb",
|
37
|
+
"lib/bodhi/definitions/count.rb",
|
38
|
+
"lib/bodhi/storage/metric_value.rb",
|
39
|
+
"spec/support/mock_model.rb",
|
40
|
+
"spec/support/persistence_spec.rb",
|
41
|
+
"spec/aggregate_metrics_spec.rb",
|
42
|
+
"spec/metric_spec.rb",
|
43
|
+
"spec/spec_helper.rb"
|
44
|
+
]
|
45
|
+
s.require_paths = ["lib"]
|
46
|
+
end
|
data/lib/bodhi.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'bodhi/definitions/count'
|
2
|
+
require 'bodhi/definitions/aggregate'
|
3
|
+
require 'bodhi/storage/metric_value'
|
4
|
+
require 'bodhi/metric'
|
5
|
+
require 'bodhi/helpers/bodhi_helpers'
|
6
|
+
|
7
|
+
module Bodhi
|
8
|
+
ActionView::Base.send :include, Bodhi::Helpers if defined?(ActionView::Base)
|
9
|
+
end
|
10
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Bodhi
|
2
|
+
module AggregateMetrics
|
3
|
+
def average (*args)
|
4
|
+
aggregate *args.unshift(:average)
|
5
|
+
end
|
6
|
+
|
7
|
+
def sum (*args)
|
8
|
+
aggregate *args.unshift(:sum)
|
9
|
+
end
|
10
|
+
|
11
|
+
def maximum (*args)
|
12
|
+
aggregate *args.unshift(:maximum)
|
13
|
+
end
|
14
|
+
|
15
|
+
def minimum (*args)
|
16
|
+
aggregate *args.unshift(:minimum)
|
17
|
+
end
|
18
|
+
|
19
|
+
def aggregate (*args)
|
20
|
+
options = args.extract_options!
|
21
|
+
|
22
|
+
agg_method = args[0]
|
23
|
+
options[:model_name] = args[1]
|
24
|
+
field = args[2]
|
25
|
+
|
26
|
+
options[:block] = get_agg_block(agg_method, field)
|
27
|
+
options[:name] ||= "#{options[:model_name]}_#{agg_method}_#{field}"
|
28
|
+
|
29
|
+
define(options)
|
30
|
+
end
|
31
|
+
|
32
|
+
protected
|
33
|
+
def get_agg_block(agg_method, field)
|
34
|
+
lambda { |run| run[:model].calculate(agg_method, field)}
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Bodhi
|
2
|
+
module CountMetrics
|
3
|
+
def count (*args)
|
4
|
+
options = args.extract_options!
|
5
|
+
options[:model_name] = args[0] if args[0].is_a? Symbol
|
6
|
+
count_type = args[1] || options[:count_type] || :total
|
7
|
+
options[:block] = get_block(count_type)
|
8
|
+
options[:name] ||= "#{options[:model_name]}_count_#{count_type}"
|
9
|
+
|
10
|
+
define(options)
|
11
|
+
end
|
12
|
+
|
13
|
+
protected
|
14
|
+
def get_block(count_type)
|
15
|
+
case count_type
|
16
|
+
when :new
|
17
|
+
lambda { |run| run[:model].where("created_at between ? and ?", run[:start], run[:end]).count }
|
18
|
+
when :updated
|
19
|
+
lambda { |run| run[:model].where("updated_at between ? and ?", run[:start], run[:end]).count }
|
20
|
+
when :total
|
21
|
+
lambda { |run| run[:model].count }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/bodhi/metric.rb
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'active_support/all'
|
2
|
+
|
3
|
+
module Bodhi
|
4
|
+
class Metric
|
5
|
+
extend CountMetrics
|
6
|
+
extend AggregateMetrics
|
7
|
+
|
8
|
+
include Enumerable
|
9
|
+
|
10
|
+
@@metrics = {}
|
11
|
+
|
12
|
+
def self.define (*args, &block)
|
13
|
+
options = args.extract_options!
|
14
|
+
|
15
|
+
options[:name] = args[0] if args[0].is_a? Symbol
|
16
|
+
options[:block] ||= block if block
|
17
|
+
|
18
|
+
m = Metric.new (options)
|
19
|
+
@@metrics[m.name] = m
|
20
|
+
|
21
|
+
m
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.[] (key)
|
25
|
+
@@metrics[key]
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.all
|
29
|
+
@@metrics.each_value
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.generate_all
|
33
|
+
@@metrics.each_value { |m| m.generate }
|
34
|
+
end
|
35
|
+
|
36
|
+
attr_accessor :name, :model_name, :block
|
37
|
+
|
38
|
+
def initialize (params)
|
39
|
+
@name = params[:name]
|
40
|
+
@model_name = params[:model_name]
|
41
|
+
@block = params[:block]
|
42
|
+
end
|
43
|
+
|
44
|
+
def current
|
45
|
+
@block.call(get_run_opts.merge(:start => Time.now.beginning_of_day, :end => Time.now.end_of_day))
|
46
|
+
end
|
47
|
+
|
48
|
+
def for_period (start_date, end_date = Time.now)
|
49
|
+
MetricValue.where("start between ? and ?", start_date, end_date)
|
50
|
+
end
|
51
|
+
|
52
|
+
def generate
|
53
|
+
# Remove any runs from today
|
54
|
+
MetricValue.where(:metric => self.name).where("start >= ?", Date.today).destroy_all
|
55
|
+
|
56
|
+
last_run = MetricValue.maximum(:end, :conditions => ["metric = '#{self.name}'"]) || Date.yesterday
|
57
|
+
|
58
|
+
while last_run < Date.today
|
59
|
+
start_date = (last_run + 1.day).beginning_of_day
|
60
|
+
end_date = start_date + 1.day - 1.second
|
61
|
+
value = @block.call(get_run_opts.merge(:start => start_date, :end => end_date))
|
62
|
+
|
63
|
+
MetricValue.create!(:start => start_date, :end => end_date, :value => value, :metric => self.name)
|
64
|
+
|
65
|
+
last_run = start_date
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
def get_run_opts
|
71
|
+
opts = {}
|
72
|
+
opts[:model] = @model_name.to_s.classify.constantize if @model_name
|
73
|
+
opts
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'rails/generators/base'
|
2
|
+
require 'rails/generators/migration'
|
3
|
+
require 'rails/generators/active_record'
|
4
|
+
|
5
|
+
module Bodhi
|
6
|
+
module Generators
|
7
|
+
class InstallGenerator < Rails::Generators::Base
|
8
|
+
include Rails::Generators::Migration
|
9
|
+
|
10
|
+
desc "Setup migrations and initializer for bodhi"
|
11
|
+
source_root File.expand_path("../templates", __FILE__)
|
12
|
+
|
13
|
+
def self.next_migration_number (dirname)
|
14
|
+
ActiveRecord::Generators::Base.next_migration_number (dirname)
|
15
|
+
end
|
16
|
+
|
17
|
+
def copy_files
|
18
|
+
copy_file 'bodhi.rb', 'config/initializers/bodhi.rb'
|
19
|
+
migration_template 'create_metric_values.rb',
|
20
|
+
"db/migrate/create_metric_values.rb"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class CreateMetricValues < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :metric_values do |t|
|
4
|
+
t.string :metric
|
5
|
+
t.datetime :start
|
6
|
+
t.datetime :end
|
7
|
+
t.float :value
|
8
|
+
|
9
|
+
end
|
10
|
+
add_index :metric_values, [:metric, :start], :unique => true, :name => 'index_metric_values_on_metric_and_start'
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.down
|
14
|
+
drop_table :metric_values
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Bodhi
|
4
|
+
describe Metric do
|
5
|
+
it "should calculate averages" do
|
6
|
+
m = Metric.average :dogs, :num_puppies
|
7
|
+
|
8
|
+
m.current.should == 6
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should calculate sums" do
|
12
|
+
m = Metric.sum :dogs, :num_puppies
|
13
|
+
|
14
|
+
m.current.should == 18
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should calculate minimums" do
|
18
|
+
m = Metric.minimum :dogs, :num_puppies
|
19
|
+
|
20
|
+
m.current.should == 2
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should calculate maximums" do
|
24
|
+
m = Metric.maximum :dogs, :num_puppies
|
25
|
+
|
26
|
+
m.current.should == 10
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/spec/metric_spec.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Bodhi
|
4
|
+
describe Metric do
|
5
|
+
it "accepts a block and and a name" do
|
6
|
+
m = Metric.define :my_metric do |run|
|
7
|
+
1
|
8
|
+
end
|
9
|
+
|
10
|
+
m.name.should == :my_metric
|
11
|
+
m.current.should == 1
|
12
|
+
end
|
13
|
+
|
14
|
+
it "can preload a model into a run" do
|
15
|
+
m = Metric.define :my_model_metric, :model_name => :dog do |run|
|
16
|
+
run[:model].count
|
17
|
+
end
|
18
|
+
|
19
|
+
m.current.should == 3 # defined in mock_model.rb
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
|
2
|
+
|
3
|
+
ActiveRecord::Schema.define(:version => 1) do
|
4
|
+
create_table :metric_values do |t|
|
5
|
+
t.string :metric
|
6
|
+
t.datetime :start
|
7
|
+
t.datetime :end
|
8
|
+
t.float :value
|
9
|
+
end
|
10
|
+
|
11
|
+
create_table :dogs do |m|
|
12
|
+
m.timestamps
|
13
|
+
m.string :name
|
14
|
+
m.string :breed
|
15
|
+
m.integer :num_puppies
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class Dog < ActiveRecord::Base
|
20
|
+
end
|
21
|
+
|
22
|
+
Dog.create!(:name => 'Sparky', :breed => 'Rotweiller', :num_puppies => 10, :created_at => 1.month.ago, :updated_at => 1.month.ago)
|
23
|
+
Dog.create!(:name => 'Bowser', :breed => 'Pug', :num_puppies => 6, :created_at => 1.week.ago)
|
24
|
+
Dog.create!(:name => 'Rex', :breed => 'Pug', :num_puppies => 2)
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Bodhi
|
4
|
+
describe Metric do
|
5
|
+
it "should persist to MetricValue when generate is called" do
|
6
|
+
m = Metric.define :dummy do
|
7
|
+
1
|
8
|
+
end
|
9
|
+
|
10
|
+
m.generate
|
11
|
+
|
12
|
+
MetricValue.where(:metric => 'dummy').count.should == 1
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should persist to MetricValue when generate_all is called" do
|
16
|
+
m1 = Metric.define :multi_dummy1 do
|
17
|
+
1
|
18
|
+
end
|
19
|
+
|
20
|
+
m2 = Metric.define :multi_dummy2 do
|
21
|
+
2
|
22
|
+
end
|
23
|
+
|
24
|
+
Metric.generate_all
|
25
|
+
|
26
|
+
MetricValue.where(:metric => 'multi_dummy1').count.should == 1
|
27
|
+
MetricValue.where(:metric => 'multi_dummy2').count.should == 1
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
metadata
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bodhi
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: 0.0.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Ryan Brunner
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2011-04-18 00:00:00 -04:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rspec
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
version: "0"
|
31
|
+
type: :development
|
32
|
+
version_requirements: *id001
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: sqlite3
|
35
|
+
prerelease: false
|
36
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
37
|
+
none: false
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 0
|
43
|
+
version: "0"
|
44
|
+
type: :development
|
45
|
+
version_requirements: *id002
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: activesupport
|
48
|
+
prerelease: false
|
49
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
segments:
|
55
|
+
- 0
|
56
|
+
version: "0"
|
57
|
+
type: :development
|
58
|
+
version_requirements: *id003
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: i18n
|
61
|
+
prerelease: false
|
62
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
segments:
|
68
|
+
- 0
|
69
|
+
version: "0"
|
70
|
+
type: :development
|
71
|
+
version_requirements: *id004
|
72
|
+
- !ruby/object:Gem::Dependency
|
73
|
+
name: activerecord
|
74
|
+
prerelease: false
|
75
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
76
|
+
none: false
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
segments:
|
81
|
+
- 0
|
82
|
+
version: "0"
|
83
|
+
type: :development
|
84
|
+
version_requirements: *id005
|
85
|
+
description: ""
|
86
|
+
email:
|
87
|
+
- ryan@ryanbrunner.com
|
88
|
+
executables: []
|
89
|
+
|
90
|
+
extensions: []
|
91
|
+
|
92
|
+
extra_rdoc_files: []
|
93
|
+
|
94
|
+
files:
|
95
|
+
- Gemfile
|
96
|
+
- Gemfile.lock
|
97
|
+
- README.markdown
|
98
|
+
- Rakefile
|
99
|
+
- bodhi.gemspec
|
100
|
+
- lib/generators/bodhi/install_generator.rb
|
101
|
+
- lib/generators/bodhi/templates/bodhi.rb
|
102
|
+
- lib/generators/bodhi/templates/create_metric_values.rb
|
103
|
+
- lib/bodhi.rb
|
104
|
+
- lib/bodhi/metric.rb
|
105
|
+
- lib/bodhi/version.rb
|
106
|
+
- lib/bodhi/definitions/aggregate.rb
|
107
|
+
- lib/bodhi/definitions/count.rb
|
108
|
+
- lib/bodhi/storage/metric_value.rb
|
109
|
+
- spec/support/mock_model.rb
|
110
|
+
- spec/support/persistence_spec.rb
|
111
|
+
- spec/aggregate_metrics_spec.rb
|
112
|
+
- spec/metric_spec.rb
|
113
|
+
- spec/spec_helper.rb
|
114
|
+
has_rdoc: true
|
115
|
+
homepage: ""
|
116
|
+
licenses: []
|
117
|
+
|
118
|
+
post_install_message:
|
119
|
+
rdoc_options: []
|
120
|
+
|
121
|
+
require_paths:
|
122
|
+
- lib
|
123
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
124
|
+
none: false
|
125
|
+
requirements:
|
126
|
+
- - ">="
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
segments:
|
129
|
+
- 0
|
130
|
+
version: "0"
|
131
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
132
|
+
none: false
|
133
|
+
requirements:
|
134
|
+
- - ">="
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
segments:
|
137
|
+
- 0
|
138
|
+
version: "0"
|
139
|
+
requirements: []
|
140
|
+
|
141
|
+
rubyforge_project: bodhi
|
142
|
+
rubygems_version: 1.3.7
|
143
|
+
signing_key:
|
144
|
+
specification_version: 3
|
145
|
+
summary: A simple, flexible DSL for generating reports.
|
146
|
+
test_files: []
|
147
|
+
|