tronprint 0.0.16 → 1.0.0
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/README.rdoc +21 -7
- data/lib/tronprint/aggregator.rb +91 -11
- data/lib/tronprint/app.rb +13 -0
- data/lib/tronprint/rails/tronprint_helper.rb +33 -6
- data/lib/tronprint/rails.rb +9 -1
- data/lib/tronprint/rake_tasks/active_record.rb +1 -3
- data/lib/tronprint/statistics.rb +49 -0
- data/lib/tronprint/statistics_formatter.rb +11 -0
- data/lib/tronprint/traffic_monitor.rb +29 -0
- data/lib/tronprint/version.rb +1 -1
- data/lib/tronprint.rb +10 -12
- data/spec/tronprint/aggregator_spec.rb +86 -2
- data/spec/tronprint/application_spec.rb +3 -4
- data/spec/tronprint/cpu_monitor_spec.rb +7 -7
- data/spec/tronprint/rails/tronprint_helper_spec.rb +2 -2
- data/spec/tronprint/statistics_formatter_spec.rb +28 -0
- data/spec/tronprint/statistics_spec.rb +45 -0
- data/spec/tronprint/traffic_monitor_spec.rb +38 -0
- data/spec/tronprint_spec.rb +12 -34
- data/tronprint.gemspec +6 -3
- metadata +119 -113
- data/spec/tronprint/computer_spec.rb +0 -9
data/README.rdoc
CHANGED
@@ -43,6 +43,20 @@ In order to display your application's footprint, you can use Tronprint's
|
|
43
43
|
built-in view helper: TronprintHelper. Feel free to cache your footprint
|
44
44
|
to minimize the number of API requests made to CM1.
|
45
45
|
|
46
|
+
In whichever controller(s) that will use TronprintHelper (or in `ApplicationController`), simply require the helper:
|
47
|
+
|
48
|
+
class FoosController
|
49
|
+
helper TronprintHelper
|
50
|
+
end
|
51
|
+
|
52
|
+
==== Helper Methods
|
53
|
+
|
54
|
+
TronprintHelper comes with a few helper methods:
|
55
|
+
|
56
|
+
* footprint_badge - A badge that displays total footprint and current rate of emissions for your app.
|
57
|
+
* cm1_badge - Displays a CM1 badge
|
58
|
+
* footprint_methodology - A URL for a live methodology statement reporting how your total footprint was calculated. {Example}[http://carbon.brighterplanet.com/computations?duration=128372]
|
59
|
+
|
46
60
|
==== Heroku
|
47
61
|
|
48
62
|
Tronprint is available as a Heroku add-on. Add tronprint to your app, and
|
@@ -72,14 +86,14 @@ config/initializers/tronprint.rb:
|
|
72
86
|
|
73
87
|
Tronprint.aggregator_options = { :adapter => :active_record }
|
74
88
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
your Rakefile:
|
89
|
+
Tronprint automatically creates a storage table, `moneta_store` the next time your app
|
90
|
+
is run.
|
91
|
+
|
92
|
+
If you need to create the table manually, add to your Rakefile:
|
79
93
|
|
80
94
|
require 'tronprint/rake_tasks/active_record'
|
81
95
|
|
82
|
-
|
96
|
+
And run `rake tronprint:moneta`
|
83
97
|
|
84
98
|
=== Other Ruby Apps
|
85
99
|
|
@@ -89,7 +103,7 @@ When your application has started, all you have to do is make a call to
|
|
89
103
|
Tronprint.run. This starts up a thread that collects statistics at a
|
90
104
|
certain interval and stores the results in a key/value store.
|
91
105
|
|
92
|
-
To retrieve the footprint, make a call to Tronprint.emission_estimate. This
|
106
|
+
To retrieve the footprint, make a call to Tronprint.statistics.emission_estimate. This
|
93
107
|
returns an instance of {Carbon::EmissionEstimate}[http://rubydoc.info/gems/carbon/Carbon/EmissionEstimate].
|
94
108
|
It can be converted to a float for the amount in kilograms or other
|
95
109
|
methods, such as EmissionEstimate#methodology can provide a link to the
|
@@ -120,7 +134,7 @@ the options you would normally set in config/tronprint.yml.
|
|
120
134
|
== Examples
|
121
135
|
|
122
136
|
You can see an example Rails app using tronprint at http://github.com/brighterplanet/yaktrak.
|
123
|
-
Files of note: config/initializers/tronprint.rb
|
137
|
+
Files of note: `config/initializers/tronprint.rb`, `Gemfile`, `app/views/trackings/_form.html.rb`.
|
124
138
|
The live example is at http://yaktrak.org
|
125
139
|
|
126
140
|
== Note on Patches/Pull Requests
|
data/lib/tronprint/aggregator.rb
CHANGED
@@ -9,6 +9,8 @@ module Tronprint
|
|
9
9
|
# {moneta}[http://github.com/wycats/moneta] will work.
|
10
10
|
class Aggregator < Delegator
|
11
11
|
|
12
|
+
attr_accessor :adapter
|
13
|
+
|
12
14
|
# Initialize the Aggregator with the following options:
|
13
15
|
# +adapter+:: The underscore-ized name of the moneta class to use.
|
14
16
|
#
|
@@ -16,17 +18,17 @@ module Tronprint
|
|
16
18
|
# You'll have to read {moneda's source code}[https://github.com/wycats/moneta/tree/master/lib/moneta/adapters]
|
17
19
|
# for options needed by your desired adapter.
|
18
20
|
def initialize(options = {})
|
19
|
-
|
20
|
-
|
21
|
-
|
21
|
+
self.adapter = options.delete :adapter
|
22
|
+
self.adapter ||= 'pstore'
|
23
|
+
self.adapter = self.adapter.to_s.downcase
|
22
24
|
begin
|
23
|
-
require "moneta/#{
|
24
|
-
klass = Moneta.const_get adapter_constant
|
25
|
+
require "moneta/#{self.adapter}"
|
26
|
+
klass = Moneta.const_get adapter_constant
|
25
27
|
rescue LoadError # Bundler hack
|
26
|
-
require "moneta/adapters/#{
|
27
|
-
klass = Moneta::Adapters.const_get adapter_constant
|
28
|
+
require "moneta/adapters/#{self.adapter}"
|
29
|
+
klass = Moneta::Adapters.const_get adapter_constant
|
28
30
|
end
|
29
|
-
args =
|
31
|
+
args = self.adapter == 'memory' ? [] : [options]
|
30
32
|
instance = klass.new(*args)
|
31
33
|
__setobj__ instance # required in Ruby 1.8.7
|
32
34
|
super instance
|
@@ -40,19 +42,97 @@ module Tronprint
|
|
40
42
|
end
|
41
43
|
|
42
44
|
# The class name of the desired moneta adapter
|
43
|
-
def adapter_constant
|
44
|
-
case
|
45
|
+
def adapter_constant
|
46
|
+
case self.adapter
|
45
47
|
when 'pstore' then 'PStore'
|
46
48
|
when 'yaml' then 'YAML'
|
47
49
|
when 'mongodb' then 'MongoDB'
|
48
50
|
else
|
49
|
-
|
51
|
+
self.adapter.split('_').map(&:capitalize).join('')
|
50
52
|
end
|
51
53
|
end
|
52
54
|
|
53
55
|
# Increment the total statistic by the given +value+,
|
54
56
|
# specified by the given +key+.
|
55
57
|
def update(key, value)
|
58
|
+
update_total(key, value)
|
59
|
+
update_yearly(key, value)
|
60
|
+
update_monthly(key, value)
|
61
|
+
update_daily(key, value)
|
62
|
+
update_hourly(key, value)
|
63
|
+
end
|
64
|
+
|
65
|
+
def path(*args)
|
66
|
+
args.join('/')
|
67
|
+
end
|
68
|
+
|
69
|
+
def range_total(key, from, to)
|
70
|
+
raise "Invalid range" if from > to
|
71
|
+
total = 0
|
72
|
+
current = from
|
73
|
+
while current <= to
|
74
|
+
hourly_key = hourly_path(key, year(current), month(current), day(current), hour(current))
|
75
|
+
total += self[hourly_key].to_f
|
76
|
+
current = current + 3600
|
77
|
+
end
|
78
|
+
|
79
|
+
total
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def year(time)
|
85
|
+
time.year.to_s
|
86
|
+
end
|
87
|
+
def current_year
|
88
|
+
year(Time.now)
|
89
|
+
end
|
90
|
+
def month(time)
|
91
|
+
sprintf('%02d', time.month)
|
92
|
+
end
|
93
|
+
def current_month
|
94
|
+
month(Time.now)
|
95
|
+
end
|
96
|
+
def day(time)
|
97
|
+
sprintf('%02d', time.day)
|
98
|
+
end
|
99
|
+
def current_day
|
100
|
+
day(Time.now)
|
101
|
+
end
|
102
|
+
def hour(time)
|
103
|
+
sprintf('%02d', time.hour)
|
104
|
+
end
|
105
|
+
def current_hour
|
106
|
+
hour(Time.now)
|
107
|
+
end
|
108
|
+
|
109
|
+
def update_total(key, value)
|
110
|
+
update_entry key, value
|
111
|
+
end
|
112
|
+
|
113
|
+
def update_yearly(key, value)
|
114
|
+
update_entry path(key, 'by_date', current_year), value
|
115
|
+
end
|
116
|
+
|
117
|
+
def update_monthly(key, value)
|
118
|
+
update_entry path(key, 'by_date', current_year, current_month), value
|
119
|
+
end
|
120
|
+
|
121
|
+
def update_daily(key, value)
|
122
|
+
update_entry path(key, 'by_date', current_year, current_month, current_day), value
|
123
|
+
end
|
124
|
+
|
125
|
+
def hourly_path(key, year, month, day, hour)
|
126
|
+
path(key, 'by_date', year, month, day, hour)
|
127
|
+
end
|
128
|
+
def update_hourly(key, value)
|
129
|
+
update_entry hourly_path(key, current_year, current_month,
|
130
|
+
current_day, current_hour),
|
131
|
+
value
|
132
|
+
update_entry path(key, 'hourly', current_hour), value
|
133
|
+
end
|
134
|
+
|
135
|
+
def update_entry(key, value)
|
56
136
|
old_value = self[key]
|
57
137
|
new_value = old_value ? old_value + value : value
|
58
138
|
self[key] = new_value
|
@@ -1,19 +1,42 @@
|
|
1
|
+
require 'tronprint/statistics_formatter'
|
2
|
+
|
1
3
|
# Rails helper for displaying footprint data.
|
2
4
|
module TronprintHelper
|
5
|
+
include Tronprint::StatisticsFormatter
|
3
6
|
|
4
7
|
# The total amount of CO2e generated by the application.
|
5
8
|
def total_footprint
|
6
|
-
|
9
|
+
total_estimate.to_f
|
10
|
+
end
|
11
|
+
|
12
|
+
# The total amount of electricity used by the application.
|
13
|
+
def total_electricity
|
14
|
+
total_estimate.electricity_use.to_f
|
7
15
|
end
|
16
|
+
|
8
17
|
# A URL for the methodology statement of the emissions calculation.
|
9
18
|
def footprint_methodology
|
10
|
-
|
19
|
+
Tronprint.statistics.total_footprint_methodology
|
11
20
|
end
|
12
21
|
|
13
|
-
#
|
14
|
-
|
15
|
-
|
16
|
-
|
22
|
+
# An informational badge displaying total energy, footprint, CO2/minute
|
23
|
+
def footprint_badge
|
24
|
+
footprint = pounds_with_precision total_estimate
|
25
|
+
|
26
|
+
two_hr_emissions = Tronprint.statistics.
|
27
|
+
emission_estimate(Time.now - 7200, Time.now).to_f
|
28
|
+
rate = two_hr_emissions / 120 # kgs CO2 per minute over last 2 hours
|
29
|
+
rate = rate < 0.0001 ? "< 0.0001" : pounds_with_precision(rate)
|
30
|
+
|
31
|
+
text = <<-HTML
|
32
|
+
<p class="cm1-footprint">
|
33
|
+
<span class="cm1-total-footprint">Total footprint: #{total_electricity.to_i}W, #{footprint}lbs CO<sub>2</sub>e</span>
|
34
|
+
|
|
35
|
+
<span class="cm1-current-footprint">Current footprint: #{rate}lbs CO<sub>2</sub>e/min</span>
|
36
|
+
</p>
|
37
|
+
HTML
|
38
|
+
|
39
|
+
text.html_safe
|
17
40
|
end
|
18
41
|
|
19
42
|
# Let the world know that your app is powered by CM1
|
@@ -21,4 +44,8 @@ module TronprintHelper
|
|
21
44
|
%q{<script type="text/javascript" src="http://carbon.brighterplanet.com/badge.js"></script>}.
|
22
45
|
html_safe
|
23
46
|
end
|
47
|
+
|
48
|
+
def total_estimate
|
49
|
+
@total_estimate ||= Tronprint.statistics.emission_estimate
|
50
|
+
end
|
24
51
|
end
|
data/lib/tronprint/rails.rb
CHANGED
@@ -1,12 +1,20 @@
|
|
1
1
|
require 'rails'
|
2
2
|
require 'tronprint/rails/tronprint_helper'
|
3
|
+
require 'tronprint/app'
|
3
4
|
|
4
5
|
module Tronprint
|
5
6
|
|
6
7
|
# Rails plugin class.
|
7
8
|
class Railtie < Rails::Railtie
|
9
|
+
initializer 'tronprint.configure' do |app|
|
10
|
+
app.config.middleware.use Tronprint::App
|
11
|
+
end
|
12
|
+
|
8
13
|
config.after_initialize do
|
9
|
-
Tronprint.
|
14
|
+
if Tronprint.aggregator.adapter == 'active_record' && !Moneta::Adapters::ActiveRecord::Store.table_exists?
|
15
|
+
Tronprint.aggregator.migrate
|
16
|
+
end
|
17
|
+
Tronprint.run
|
10
18
|
end
|
11
19
|
|
12
20
|
generators do
|
@@ -1,5 +1,5 @@
|
|
1
1
|
namespace :tronprint do
|
2
|
-
desc '
|
2
|
+
desc 'Manually set up ActiveRecord datastore for Tronprint'
|
3
3
|
task :moneta => :environment do
|
4
4
|
adapter_options = Tronprint.aggregator_options
|
5
5
|
ar = Moneta::Adapters::ActiveRecord.new
|
@@ -7,5 +7,3 @@ namespace :tronprint do
|
|
7
7
|
puts 'Ensured that Moneta::Adapters::ActiveRecord::Store exists'
|
8
8
|
end
|
9
9
|
end
|
10
|
-
|
11
|
-
task 'db:migrate' => 'tronprint:moneta'
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Tronprint
|
2
|
+
# The Statistics class is your gateway to fetching statistics about
|
3
|
+
# the energy usage and footprint of your app.
|
4
|
+
class Statistics
|
5
|
+
|
6
|
+
attr_accessor :aggregator, :cpu_monitor
|
7
|
+
|
8
|
+
def initialize(aggregator, cpu_monitor)
|
9
|
+
self.aggregator = aggregator
|
10
|
+
self.cpu_monitor = cpu_monitor
|
11
|
+
end
|
12
|
+
|
13
|
+
# Fetch the total amount of CPU time (in hours) used by the application.
|
14
|
+
def total_duration
|
15
|
+
aggregator[cpu_monitor.key] / 3600
|
16
|
+
end
|
17
|
+
|
18
|
+
# Fetch total CPU time for a given range
|
19
|
+
def range_duration(from, to)
|
20
|
+
aggregator.range_total cpu_monitor.key, from, to
|
21
|
+
end
|
22
|
+
|
23
|
+
# Calculate emissions using aggregated data. A call is made to
|
24
|
+
# Brighter Planet's CM1 emission estimate service. Specifically,
|
25
|
+
# the call is made to the {computation emitter}[http://carbon.brighterplanet.com/models/computation]
|
26
|
+
def emission_estimate(from = nil, to = nil)
|
27
|
+
duration = from.nil? ? total_duration : range_duration(from, to)
|
28
|
+
|
29
|
+
app = Application.new :zip_code => Tronprint.zip_code, :duration => duration,
|
30
|
+
:brighter_planet_key => Tronprint.brighter_planet_key
|
31
|
+
app.emission_estimate
|
32
|
+
end
|
33
|
+
|
34
|
+
# The total amount of CO2e generated by the application.
|
35
|
+
def total_footprint
|
36
|
+
emission_estimate.to_f
|
37
|
+
end
|
38
|
+
|
39
|
+
# The total amount of electricity used by the application.
|
40
|
+
def total_electricity
|
41
|
+
emission_estimate.electricity_use.to_f
|
42
|
+
end
|
43
|
+
|
44
|
+
# A URL for the methodology statement of the total_footprint calculation.
|
45
|
+
def total_footprint_methodology
|
46
|
+
emission_estimate.methodology
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Tronprint
|
2
|
+
|
3
|
+
# Tronprint::CPUMonitor is a thread that monitors aggregate CPU usage.
|
4
|
+
class TrafficMonitor
|
5
|
+
attr_accessor :aggregator, :application_name
|
6
|
+
|
7
|
+
# Parameters:
|
8
|
+
# +aggregator+:: A Tronprint::Aggregator instance.
|
9
|
+
# +application_name+:: A unique application name.
|
10
|
+
def initialize(aggregator, application_name)
|
11
|
+
self.aggregator = aggregator
|
12
|
+
self.application_name = application_name
|
13
|
+
end
|
14
|
+
|
15
|
+
# The key used to store number of requests in the Aggregator.
|
16
|
+
def key
|
17
|
+
[application_name, 'requests'].join('/')
|
18
|
+
end
|
19
|
+
|
20
|
+
# Increment the total number of requests
|
21
|
+
def increment
|
22
|
+
aggregator.update key, 1
|
23
|
+
end
|
24
|
+
|
25
|
+
def requests
|
26
|
+
aggregator[key] || 0
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/tronprint/version.rb
CHANGED
data/lib/tronprint.rb
CHANGED
@@ -2,6 +2,8 @@ require 'yaml'
|
|
2
2
|
require 'tronprint/aggregator'
|
3
3
|
require 'tronprint/application'
|
4
4
|
require 'tronprint/cpu_monitor'
|
5
|
+
require 'tronprint/traffic_monitor'
|
6
|
+
require 'tronprint/statistics'
|
5
7
|
|
6
8
|
if defined?(Rails)
|
7
9
|
require 'tronprint/rails'
|
@@ -72,9 +74,14 @@ module Tronprint
|
|
72
74
|
@cpu_monitor ||= CPUMonitor.new aggregator, application_name
|
73
75
|
end
|
74
76
|
|
75
|
-
#
|
76
|
-
def
|
77
|
-
|
77
|
+
# The Tronprint::TrafficMonitor instance
|
78
|
+
def traffic_monitor
|
79
|
+
@traffic_monitor ||= TrafficMonitor.new aggregator, application_name
|
80
|
+
end
|
81
|
+
|
82
|
+
# The Tronprint::Statistics interface
|
83
|
+
def statistics
|
84
|
+
@statistics ||= Statistics.new aggregator, cpu_monitor
|
78
85
|
end
|
79
86
|
|
80
87
|
# The current configuration.
|
@@ -117,13 +124,4 @@ module Tronprint
|
|
117
124
|
}
|
118
125
|
@default_config
|
119
126
|
end
|
120
|
-
|
121
|
-
# Calculate emissions using aggregated data. A call is made to
|
122
|
-
# Brighter Planet's CM1 emission estimate service. Specifically,
|
123
|
-
# the call is made to the {computation emitter}[http://carbon.brighterplanet.com/models/computation]
|
124
|
-
def emission_estimate
|
125
|
-
app = Application.new :zip_code => zip_code, :duration => total_duration,
|
126
|
-
:brighter_planet_key => brighter_planet_key
|
127
|
-
app.emission_estimate
|
128
|
-
end
|
129
127
|
end
|
@@ -1,18 +1,102 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'sandbox'
|
3
|
+
require 'time'
|
4
|
+
require 'timecop'
|
3
5
|
|
4
6
|
describe Tronprint::Aggregator do
|
5
7
|
let(:aggregator) { Tronprint::Aggregator.new :adapter => :memory }
|
6
8
|
|
7
9
|
describe '#update' do
|
8
|
-
|
10
|
+
let(:now) { Time.parse('2011-06-02 13:45:12') }
|
11
|
+
before do
|
12
|
+
Timecop.freeze now
|
13
|
+
end
|
14
|
+
after do
|
15
|
+
Timecop.return
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'writes statistics to an uninitailzed key' do
|
9
19
|
aggregator.update('foo/bar', 22.1)
|
10
20
|
aggregator['foo/bar'].should == 22.1
|
11
21
|
end
|
12
|
-
it '
|
22
|
+
it 'cumulatively updates statistics' do
|
13
23
|
aggregator.update('foo/bar', 22.1)
|
14
24
|
aggregator.update('foo/bar', 44.2)
|
15
25
|
aggregator['foo/bar'].should be_within(0.01).of(66.3)
|
26
|
+
aggregator['foo/bar/by_date/2011'].should be_within(0.01).of(66.3)
|
27
|
+
aggregator['foo/bar/by_date/2011/06'].should be_within(0.01).of(66.3)
|
28
|
+
aggregator['foo/bar/by_date/2011/06/02'].should be_within(0.01).of(66.3)
|
29
|
+
aggregator['foo/bar/by_date/2011/06/02/13'].should be_within(0.01).of(66.3)
|
30
|
+
aggregator['foo/bar/hourly/13'].should be_within(0.01).of(66.3)
|
31
|
+
end
|
32
|
+
it 'stores by_date statistics in separate entries for each day, month, and year' do
|
33
|
+
aggregator.update('foo/bar', 22.1)
|
34
|
+
aggregator.update('foo/bar', 23.1)
|
35
|
+
aggregator['foo/bar/by_date/2011'].should be_within(0.01).of(45.2)
|
36
|
+
aggregator['foo/bar/by_date/2011/06'].should be_within(0.01).of(45.2)
|
37
|
+
aggregator['foo/bar/by_date/2011/06/02'].should be_within(0.01).of(45.2)
|
38
|
+
aggregator['foo/bar/by_date/2011/06/02/13'].should be_within(0.01).of(45.2)
|
39
|
+
aggregator['foo/bar/hourly/13'].should be_within(0.01).of(45.2)
|
40
|
+
|
41
|
+
Timecop.freeze Time.parse('2011-06-03 11:45:12')
|
42
|
+
aggregator.update('foo/bar', 33.1)
|
43
|
+
aggregator['foo/bar/by_date/2011'].should be_within(0.01).of(78.3)
|
44
|
+
aggregator['foo/bar/by_date/2011/06'].should be_within(0.01).of(78.3)
|
45
|
+
aggregator['foo/bar/by_date/2011/06/03'].should be_within(0.01).of(33.1)
|
46
|
+
aggregator['foo/bar/by_date/2011/06/03/11'].should be_within(0.01).of(33.1)
|
47
|
+
aggregator['foo/bar/hourly/11'].should be_within(0.01).of(33.1)
|
48
|
+
|
49
|
+
Timecop.freeze Time.parse('2011-05-03 11:45:12')
|
50
|
+
aggregator.update('foo/bar', 44.1)
|
51
|
+
aggregator['foo/bar/by_date/2011'].should be_within(0.01).of(122.4)
|
52
|
+
aggregator['foo/bar/by_date/2011/05'].should be_within(0.01).of(44.1)
|
53
|
+
aggregator['foo/bar/by_date/2011/06'].should be_within(0.01).of(78.3)
|
54
|
+
aggregator['foo/bar/by_date/2011/05/03'].should be_within(0.01).of(44.1)
|
55
|
+
aggregator['foo/bar/by_date/2011/05/03/11'].should be_within(0.01).of(44.1)
|
56
|
+
aggregator['foo/bar/hourly/11'].should be_within(0.01).of(77.2)
|
57
|
+
|
58
|
+
Timecop.freeze Time.parse('2012-05-03 00:45:12')
|
59
|
+
aggregator.update('foo/bar', 55.1)
|
60
|
+
aggregator['foo/bar/by_date/2012'].should be_within(0.01).of(55.1)
|
61
|
+
aggregator['foo/bar/by_date/2012/05'].should be_within(0.01).of(55.1)
|
62
|
+
aggregator['foo/bar/by_date/2012/05/03'].should be_within(0.01).of(55.1)
|
63
|
+
aggregator['foo/bar/by_date/2012/05/03/00'].should be_within(0.01).of(55.1)
|
64
|
+
aggregator['foo/bar/hourly/00'].should be_within(0.01).of(55.1)
|
65
|
+
|
66
|
+
Timecop.freeze Time.parse('2012-05-03 00:57:02')
|
67
|
+
aggregator.update('foo/bar', 55.1)
|
68
|
+
aggregator['foo/bar/by_date/2012'].should be_within(0.01).of(110.2)
|
69
|
+
aggregator['foo/bar/by_date/2012/05'].should be_within(0.01).of(110.2)
|
70
|
+
aggregator['foo/bar/by_date/2012/05/03'].should be_within(0.01).of(110.2)
|
71
|
+
aggregator['foo/bar/by_date/2012/05/03/00'].should be_within(0.01).of(110.2)
|
72
|
+
aggregator['foo/bar/hourly/00'].should be_within(0.01).of(110.2)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe '#range_total' do
|
77
|
+
before :each do
|
78
|
+
[
|
79
|
+
'2011-06-02 13:01:00','2011-06-02 14:01:00','2011-06-02 15:01:00',
|
80
|
+
'2011-06-02 16:01:00','2011-06-02 18:01:00','2011-06-02 19:01:00',
|
81
|
+
'2011-06-02 19:01:00','2011-06-02 20:01:00','2011-06-02 21:01:00',
|
82
|
+
].each do |time|
|
83
|
+
Timecop.freeze Time.parse(time)
|
84
|
+
aggregator.update('foozle', 1)
|
85
|
+
end
|
86
|
+
Timecop.return
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'returns a total for a given range' do
|
90
|
+
result = aggregator.range_total('foozle', Time.parse('2011-06-02 18:01:00'), Time.parse('2011-06-02 20:01:00'))
|
91
|
+
result.should == 4
|
92
|
+
end
|
93
|
+
it 'counts missing hours as 0' do
|
94
|
+
result = aggregator.range_total('foozle', Time.parse('2011-06-02 01:01:00'), Time.parse('2011-06-02 04:01:00'))
|
95
|
+
result.should == 0
|
96
|
+
end
|
97
|
+
it 'counts missing hours as 0 when a range has partial data' do
|
98
|
+
result = aggregator.range_total('foozle', Time.parse('2011-06-02 16:01:00'), Time.parse('2011-06-02 18:01:00'))
|
99
|
+
result.should == 2
|
16
100
|
end
|
17
101
|
end
|
18
102
|
end
|
@@ -1,10 +1,9 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Tronprint::Application do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
it 'reports emission esimates for application-related activity' do
|
5
|
+
app = Tronprint::Application.new :duration => 72831, :zip_code => 48915
|
6
|
+
app.should respond_to(:emission_estimate)
|
8
7
|
end
|
9
8
|
end
|
10
9
|
|
@@ -8,11 +8,11 @@ describe Tronprint::CPUMonitor do
|
|
8
8
|
before :each do
|
9
9
|
cpu_monitor.stub!(:elapsed_cpu_time).and_return 23.87
|
10
10
|
end
|
11
|
-
it '
|
11
|
+
it 'writes the elapsed time to the aggregate statistics' do
|
12
12
|
cpu_monitor.monitor
|
13
13
|
aggregator['my_app/application/cpu_time'].should == 23.87
|
14
14
|
end
|
15
|
-
it '
|
15
|
+
it 'increments the toal recorded cpu time' do
|
16
16
|
cpu_monitor.stub!(:elapsed_cpu_time).and_return 9.0
|
17
17
|
cpu_monitor.monitor
|
18
18
|
cpu_monitor.total_recorded_cpu_time.should == 9.0
|
@@ -23,12 +23,12 @@ describe Tronprint::CPUMonitor do
|
|
23
23
|
end
|
24
24
|
|
25
25
|
describe '#elapsed_cpu_time' do
|
26
|
-
it '
|
26
|
+
it 'returns the total CPU time on the first run' do
|
27
27
|
cpu_monitor.stub!(:total_recorded_cpu_time).and_return 0
|
28
28
|
cpu_monitor.stub!(:total_cpu_time).and_return 9.0
|
29
29
|
cpu_monitor.elapsed_cpu_time.should == 9.0
|
30
30
|
end
|
31
|
-
it '
|
31
|
+
it 'returns the amount of CPU time used since the last check' do
|
32
32
|
cpu_monitor.stub!(:total_recorded_cpu_time).and_return 23.0
|
33
33
|
cpu_monitor.stub!(:total_cpu_time).and_return 36.0
|
34
34
|
cpu_monitor.elapsed_cpu_time.should == 13.0
|
@@ -36,17 +36,17 @@ describe Tronprint::CPUMonitor do
|
|
36
36
|
end
|
37
37
|
|
38
38
|
describe '#total_cpu_time' do
|
39
|
-
it '
|
39
|
+
it 'returns the total user and system time of the process' do
|
40
40
|
Process.stub!(:times).and_return [10.1, 12.3]
|
41
41
|
cpu_monitor.total_cpu_time.should == 22.4
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
45
|
describe '#total_recorded_cpu_time' do
|
46
|
-
it '
|
46
|
+
it 'returns 0 by default' do
|
47
47
|
cpu_monitor.total_recorded_cpu_time.should == 0
|
48
48
|
end
|
49
|
-
it '
|
49
|
+
it 'returns total recorded time' do
|
50
50
|
cpu_monitor.total_recorded_cpu_time = 3
|
51
51
|
cpu_monitor.total_recorded_cpu_time.should == 3
|
52
52
|
end
|
@@ -9,8 +9,8 @@ describe TronprintHelper do
|
|
9
9
|
end
|
10
10
|
|
11
11
|
describe '#total_footprint' do
|
12
|
-
it '
|
13
|
-
|
12
|
+
it 'returns the total footprint' do
|
13
|
+
Tronprint.statistics.stub!(:emission_estimate).and_return mock(Object, :to_f => 89.4)
|
14
14
|
helper.total_footprint.should == 89.4
|
15
15
|
end
|
16
16
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'tronprint/statistics_formatter'
|
3
|
+
require 'action_view'
|
4
|
+
|
5
|
+
class StatisticsFormatterHarness
|
6
|
+
include ActionView::Helpers
|
7
|
+
include Tronprint::StatisticsFormatter
|
8
|
+
end
|
9
|
+
|
10
|
+
describe Tronprint::StatisticsFormatter do
|
11
|
+
let(:formatter) { StatisticsFormatterHarness.new }
|
12
|
+
|
13
|
+
describe '#pounds_with_precision' do
|
14
|
+
it 'converts kilograms to pounds' do
|
15
|
+
formatter.pounds_with_precision(1).should == '2.2046'
|
16
|
+
end
|
17
|
+
it 'uses a precision of 4 if the number is less than 100' do
|
18
|
+
formatter.pounds_with_precision(8).should == '17.6368'
|
19
|
+
end
|
20
|
+
it 'uses a precision of 4 if the number is 0' do
|
21
|
+
formatter.pounds_with_precision(0).should == '0.0000'
|
22
|
+
end
|
23
|
+
it 'uses a precision of 0 if the number is at least 100' do
|
24
|
+
formatter.pounds_with_precision(60).should == '132.2760'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Tronprint::Statistics do
|
4
|
+
let(:aggregator) { Tronprint::Aggregator.new :adapter => :memory }
|
5
|
+
let(:cpu_monitor) { mock Tronprint::CPUMonitor, :total_recorded_cpu_time => 27.2,
|
6
|
+
:key => 'myapp' }
|
7
|
+
let(:statistics) { Tronprint::Statistics.new aggregator, cpu_monitor }
|
8
|
+
|
9
|
+
before do
|
10
|
+
Tronprint.zip_code = 48915
|
11
|
+
Tronprint.brighter_planet_key = 'ABC123'
|
12
|
+
Tronprint.application_name = 'groove'
|
13
|
+
end
|
14
|
+
|
15
|
+
after do
|
16
|
+
aggregator.clear
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '#emission_estimate' do
|
20
|
+
it 'sends uses total duration if no range is given' do
|
21
|
+
statistics.stub!(:total_duration).and_return 28.7
|
22
|
+
Tronprint::Application.should_receive(:new).
|
23
|
+
with(:zip_code => 48915, :duration => 28.7, :brighter_planet_key => 'ABC123').
|
24
|
+
and_return mock(Object, :emission_estimate => nil)
|
25
|
+
statistics.emission_estimate
|
26
|
+
end
|
27
|
+
it 'sends a duration range if given' do
|
28
|
+
statistics.stub!(:range_duration).and_return 18.7
|
29
|
+
Tronprint::Application.should_receive(:new).
|
30
|
+
with(:zip_code => 48915, :duration => 18.7, :brighter_planet_key => 'ABC123').
|
31
|
+
and_return mock(Object, :emission_estimate => nil)
|
32
|
+
statistics.emission_estimate(Time.now - 7200, Time.now)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '#total_duration' do
|
37
|
+
it 'looks up the total for the application and return number of hours' do
|
38
|
+
mock_cpu = mock Tronprint::CPUMonitor, :key => 'groove/application/cpu_time'
|
39
|
+
statistics.instance_variable_set :@cpu_monitor, mock_cpu
|
40
|
+
statistics.aggregator.update 'groove/application/cpu_time', 5.0
|
41
|
+
statistics.total_duration.should be_within(0.00001).of(0.00138)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'timecop'
|
3
|
+
|
4
|
+
describe Tronprint::TrafficMonitor do
|
5
|
+
let(:aggregator) { Tronprint::Aggregator.new :adapter => :memory }
|
6
|
+
let(:traffic_monitor) { Tronprint::TrafficMonitor.new aggregator, 'my_app' }
|
7
|
+
|
8
|
+
describe '#increment' do
|
9
|
+
it 'increments the user count for each time slice' do
|
10
|
+
Timecop.freeze Time.parse('2011-06-02 13:23:01')
|
11
|
+
2.times { traffic_monitor.increment }
|
12
|
+
aggregator['my_app/requests'].should == 2
|
13
|
+
aggregator['my_app/requests/by_date/2011'].should == 2
|
14
|
+
aggregator['my_app/requests/by_date/2011/06'].should == 2
|
15
|
+
aggregator['my_app/requests/by_date/2011/06/02'].should == 2
|
16
|
+
aggregator['my_app/requests/by_date/2011/06/02/13'].should == 2
|
17
|
+
aggregator['my_app/requests/hourly/13'].should == 2
|
18
|
+
Timecop.return
|
19
|
+
end
|
20
|
+
it 'increments the toal recorded requests' do
|
21
|
+
traffic_monitor.increment
|
22
|
+
traffic_monitor.requests.should == 1
|
23
|
+
traffic_monitor.increment
|
24
|
+
traffic_monitor.requests.should == 2
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#requests' do
|
29
|
+
it 'returns 0 on the first run' do
|
30
|
+
traffic_monitor.requests.should == 0
|
31
|
+
end
|
32
|
+
it 'returns the total number of requests' do
|
33
|
+
aggregator['my_app/requests'] = 13
|
34
|
+
traffic_monitor.requests.should == 13
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
data/spec/tronprint_spec.rb
CHANGED
@@ -8,39 +8,27 @@ describe Tronprint do
|
|
8
8
|
end
|
9
9
|
|
10
10
|
describe '.run' do
|
11
|
-
it '
|
11
|
+
it 'starts up each monitor' do
|
12
12
|
Tronprint.should_receive :cpu_monitor
|
13
13
|
Tronprint.run
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
17
|
describe '.cpu_monitor' do
|
18
|
-
it '
|
18
|
+
it 'starts the CPU monitor' do
|
19
|
+
Tronprint.instance_variable_set :@cpu_monitor, nil
|
19
20
|
Tronprint::CPUMonitor.should_receive(:new).and_return mock_cpu
|
20
21
|
Tronprint.cpu_monitor
|
21
22
|
end
|
22
|
-
it '
|
23
|
+
it 'returns the CPU monitor instance' do
|
23
24
|
Tronprint.instance_variable_set :@cpu_monitor, nil
|
24
25
|
Tronprint::CPUMonitor.stub!(:new).and_return mock_cpu
|
25
26
|
Tronprint.cpu_monitor.should == mock_cpu
|
26
27
|
end
|
27
28
|
end
|
28
29
|
|
29
|
-
describe '.emission_estimate' do
|
30
|
-
it 'should send the zip code and total duration to the application' do
|
31
|
-
Tronprint.instance_variable_set(:@emission_estimate, nil)
|
32
|
-
Tronprint.zip_code = 48915
|
33
|
-
Tronprint.brighter_planet_key = 'ABC123'
|
34
|
-
Tronprint.stub!(:total_duration).and_return 28.7
|
35
|
-
Tronprint::Application.should_receive(:new).
|
36
|
-
with(:zip_code => 48915, :duration => 28.7, :brighter_planet_key => 'ABC123').
|
37
|
-
and_return mock(Object, :emission_estimate => nil)
|
38
|
-
Tronprint.emission_estimate
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
30
|
describe '.brighter_planet_key' do
|
43
|
-
it '
|
31
|
+
it 'returns the brighter_planet_key config option' do
|
44
32
|
Tronprint.instance_variable_set :@brighter_planet_key, nil
|
45
33
|
Tronprint.stub!(:config).and_return({ :brighter_planet_key => 'aaa' })
|
46
34
|
Tronprint.brighter_planet_key.should == 'aaa'
|
@@ -48,11 +36,11 @@ describe Tronprint do
|
|
48
36
|
end
|
49
37
|
|
50
38
|
describe '.config' do
|
51
|
-
it '
|
39
|
+
it 'returns a configuration loaded from disk' do
|
52
40
|
Tronprint.stub!(:load_config).and_return :foo => :bar
|
53
41
|
Tronprint.config.should include(:foo => :bar)
|
54
42
|
end
|
55
|
-
it '
|
43
|
+
it 'returns a default configuration if no config file exists' do
|
56
44
|
Tronprint.stub!(:default_config).and_return :foo => :bar
|
57
45
|
Tronprint.config.should include(:foo => :bar)
|
58
46
|
end
|
@@ -62,14 +50,14 @@ describe Tronprint do
|
|
62
50
|
before :each do
|
63
51
|
Tronprint.instance_variable_set :@loaded_config, nil
|
64
52
|
end
|
65
|
-
it '
|
53
|
+
it 'loads a config file from cwd/config/tronprint.yml if it exists' do
|
66
54
|
Dir.stub!(:pwd).and_return '/some/dir'
|
67
55
|
File.stub!(:exist?).and_return true
|
68
56
|
YAML.should_receive(:load_file).with('/some/dir/config/tronprint.yml').
|
69
57
|
and_return :my => :config
|
70
58
|
Tronprint.load_config.should == { :my => :config }
|
71
59
|
end
|
72
|
-
it '
|
60
|
+
it 'returns nil if no config file exists' do
|
73
61
|
Tronprint.instance_variable_set :@loaded_config, nil
|
74
62
|
Dir.stub!(:pwd).and_return '/some/dir'
|
75
63
|
File.stub!(:exist?).and_return false
|
@@ -85,27 +73,17 @@ describe Tronprint do
|
|
85
73
|
ENV['TRONPRINT_API_KEY'] = nil
|
86
74
|
ENV['MONGOHQ_URL'] = nil
|
87
75
|
end
|
88
|
-
it '
|
76
|
+
it 'returns a default configuration' do
|
89
77
|
Tronprint.default_config.should be_an_instance_of(Hash)
|
90
78
|
end
|
91
|
-
it '
|
79
|
+
it 'sets the brighter_planet_key if ENV["TRONPRINT_API_KEY"] is set' do
|
92
80
|
ENV['TRONPRINT_API_KEY'] = 'abc123'
|
93
81
|
Tronprint.default_config[:brighter_planet_key].should == 'abc123'
|
94
82
|
end
|
95
|
-
it '
|
83
|
+
it 'uses MongoHQ if ENV["MONGOHQ_URL"] is set' do
|
96
84
|
ENV['MONGOHQ_URL'] = 'mongodb://foo.com/bar'
|
97
85
|
Tronprint.default_config[:aggregator_options][:adapter].should == :mongodb
|
98
86
|
Tronprint.default_config[:aggregator_options][:uri].should == 'mongodb://foo.com/bar'
|
99
87
|
end
|
100
88
|
end
|
101
|
-
|
102
|
-
describe '.total_duration' do
|
103
|
-
it 'should look up the total for the application and return number of hours' do
|
104
|
-
mock_cpu = mock Tronprint::CPUMonitor, :key => 'groove/application/cpu_time'
|
105
|
-
Tronprint.instance_variable_set :@cpu_monitor, mock_cpu
|
106
|
-
Tronprint.application_name = 'groove'
|
107
|
-
Tronprint.aggregator.update 'groove/application/cpu_time', 5.0
|
108
|
-
Tronprint.total_duration.should be_within(0.00001).of(0.00138)
|
109
|
-
end
|
110
|
-
end
|
111
89
|
end
|
data/tronprint.gemspec
CHANGED
@@ -7,7 +7,7 @@ Gem::Specification.new do |s|
|
|
7
7
|
s.version = Tronprint::VERSION
|
8
8
|
|
9
9
|
s.authors = ['Derek Kastner']
|
10
|
-
s.date = "2011-
|
10
|
+
s.date = "2011-06-15"
|
11
11
|
s.description = %q{A gem for monitoring the carbon footprint of your ruby app}
|
12
12
|
s.email = %q{dkastner@gmail.com}
|
13
13
|
s.homepage = %q{http://github.com/brighterplanet/tronprint}
|
@@ -30,13 +30,16 @@ Gem::Specification.new do |s|
|
|
30
30
|
s.rubygems_version = %q{1.3.7}
|
31
31
|
s.summary = %q{Ruby process carbon footprinter}
|
32
32
|
|
33
|
+
s.add_development_dependency 'actionpack', '~> 3'
|
34
|
+
s.add_development_dependency 'activesupport', '~> 3'
|
33
35
|
s.add_development_dependency 'cucumber'
|
34
36
|
s.add_development_dependency 'bueller', '~> 0.0.2'
|
35
37
|
s.add_development_dependency 'rake'
|
36
38
|
s.add_development_dependency 'rspec', '~> 2.0'
|
37
|
-
s.add_development_dependency
|
39
|
+
s.add_development_dependency 'sandbox'
|
40
|
+
s.add_development_dependency 'timecop'
|
38
41
|
s.add_runtime_dependency 'carbon', '~> 1.0.3'
|
39
42
|
s.add_runtime_dependency 'i18n'
|
40
|
-
s.add_runtime_dependency 'dkastner-moneta', '~> 1.0.
|
43
|
+
s.add_runtime_dependency 'dkastner-moneta', '~> 1.0.5'
|
41
44
|
end
|
42
45
|
|
metadata
CHANGED
@@ -1,150 +1,156 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: tronprint
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
6
|
-
- 0
|
7
|
-
- 0
|
8
|
-
- 16
|
9
|
-
version: 0.0.16
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
10
6
|
platform: ruby
|
11
|
-
authors:
|
7
|
+
authors:
|
12
8
|
- Derek Kastner
|
13
9
|
autorequire:
|
14
10
|
bindir: bin
|
15
11
|
cert_chain: []
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
12
|
+
date: 2011-06-15 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: actionpack
|
16
|
+
requirement: &2157410400 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '3'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *2157410400
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: activesupport
|
27
|
+
requirement: &2157409500 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '3'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *2157409500
|
36
|
+
- !ruby/object:Gem::Dependency
|
21
37
|
name: cucumber
|
22
|
-
requirement: &
|
38
|
+
requirement: &2157409100 !ruby/object:Gem::Requirement
|
23
39
|
none: false
|
24
|
-
requirements:
|
25
|
-
- -
|
26
|
-
- !ruby/object:Gem::Version
|
27
|
-
|
28
|
-
- 0
|
29
|
-
version: "0"
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
30
44
|
type: :development
|
31
45
|
prerelease: false
|
32
|
-
version_requirements: *
|
33
|
-
- !ruby/object:Gem::Dependency
|
46
|
+
version_requirements: *2157409100
|
47
|
+
- !ruby/object:Gem::Dependency
|
34
48
|
name: bueller
|
35
|
-
requirement: &
|
49
|
+
requirement: &2157408560 !ruby/object:Gem::Requirement
|
36
50
|
none: false
|
37
|
-
requirements:
|
51
|
+
requirements:
|
38
52
|
- - ~>
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
segments:
|
41
|
-
- 0
|
42
|
-
- 0
|
43
|
-
- 2
|
53
|
+
- !ruby/object:Gem::Version
|
44
54
|
version: 0.0.2
|
45
55
|
type: :development
|
46
56
|
prerelease: false
|
47
|
-
version_requirements: *
|
48
|
-
- !ruby/object:Gem::Dependency
|
57
|
+
version_requirements: *2157408560
|
58
|
+
- !ruby/object:Gem::Dependency
|
49
59
|
name: rake
|
50
|
-
requirement: &
|
60
|
+
requirement: &2157408040 !ruby/object:Gem::Requirement
|
51
61
|
none: false
|
52
|
-
requirements:
|
53
|
-
- -
|
54
|
-
- !ruby/object:Gem::Version
|
55
|
-
|
56
|
-
- 0
|
57
|
-
version: "0"
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
58
66
|
type: :development
|
59
67
|
prerelease: false
|
60
|
-
version_requirements: *
|
61
|
-
- !ruby/object:Gem::Dependency
|
68
|
+
version_requirements: *2157408040
|
69
|
+
- !ruby/object:Gem::Dependency
|
62
70
|
name: rspec
|
63
|
-
requirement: &
|
71
|
+
requirement: &2157407300 !ruby/object:Gem::Requirement
|
64
72
|
none: false
|
65
|
-
requirements:
|
73
|
+
requirements:
|
66
74
|
- - ~>
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
|
69
|
-
- 2
|
70
|
-
- 0
|
71
|
-
version: "2.0"
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '2.0'
|
72
77
|
type: :development
|
73
78
|
prerelease: false
|
74
|
-
version_requirements: *
|
75
|
-
- !ruby/object:Gem::Dependency
|
79
|
+
version_requirements: *2157407300
|
80
|
+
- !ruby/object:Gem::Dependency
|
76
81
|
name: sandbox
|
77
|
-
requirement: &
|
82
|
+
requirement: &2157406680 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *2157406680
|
91
|
+
- !ruby/object:Gem::Dependency
|
92
|
+
name: timecop
|
93
|
+
requirement: &2157400260 !ruby/object:Gem::Requirement
|
78
94
|
none: false
|
79
|
-
requirements:
|
80
|
-
- -
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
|
83
|
-
- 0
|
84
|
-
version: "0"
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
85
99
|
type: :development
|
86
100
|
prerelease: false
|
87
|
-
version_requirements: *
|
88
|
-
- !ruby/object:Gem::Dependency
|
101
|
+
version_requirements: *2157400260
|
102
|
+
- !ruby/object:Gem::Dependency
|
89
103
|
name: carbon
|
90
|
-
requirement: &
|
104
|
+
requirement: &2157399320 !ruby/object:Gem::Requirement
|
91
105
|
none: false
|
92
|
-
requirements:
|
106
|
+
requirements:
|
93
107
|
- - ~>
|
94
|
-
- !ruby/object:Gem::Version
|
95
|
-
segments:
|
96
|
-
- 1
|
97
|
-
- 0
|
98
|
-
- 3
|
108
|
+
- !ruby/object:Gem::Version
|
99
109
|
version: 1.0.3
|
100
110
|
type: :runtime
|
101
111
|
prerelease: false
|
102
|
-
version_requirements: *
|
103
|
-
- !ruby/object:Gem::Dependency
|
112
|
+
version_requirements: *2157399320
|
113
|
+
- !ruby/object:Gem::Dependency
|
104
114
|
name: i18n
|
105
|
-
requirement: &
|
115
|
+
requirement: &2157397400 !ruby/object:Gem::Requirement
|
106
116
|
none: false
|
107
|
-
requirements:
|
108
|
-
- -
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
|
111
|
-
- 0
|
112
|
-
version: "0"
|
117
|
+
requirements:
|
118
|
+
- - ! '>='
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: '0'
|
113
121
|
type: :runtime
|
114
122
|
prerelease: false
|
115
|
-
version_requirements: *
|
116
|
-
- !ruby/object:Gem::Dependency
|
123
|
+
version_requirements: *2157397400
|
124
|
+
- !ruby/object:Gem::Dependency
|
117
125
|
name: dkastner-moneta
|
118
|
-
requirement: &
|
126
|
+
requirement: &2157366380 !ruby/object:Gem::Requirement
|
119
127
|
none: false
|
120
|
-
requirements:
|
128
|
+
requirements:
|
121
129
|
- - ~>
|
122
|
-
- !ruby/object:Gem::Version
|
123
|
-
|
124
|
-
- 1
|
125
|
-
- 0
|
126
|
-
- 3
|
127
|
-
version: 1.0.3
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: 1.0.5
|
128
132
|
type: :runtime
|
129
133
|
prerelease: false
|
130
|
-
version_requirements: *
|
134
|
+
version_requirements: *2157366380
|
131
135
|
description: A gem for monitoring the carbon footprint of your ruby app
|
132
136
|
email: dkastner@gmail.com
|
133
137
|
executables: []
|
134
|
-
|
135
138
|
extensions: []
|
136
|
-
|
137
|
-
extra_rdoc_files:
|
139
|
+
extra_rdoc_files:
|
138
140
|
- LICENSE
|
139
141
|
- README.rdoc
|
140
|
-
files:
|
142
|
+
files:
|
141
143
|
- lib/tronprint/aggregator.rb
|
144
|
+
- lib/tronprint/app.rb
|
142
145
|
- lib/tronprint/application.rb
|
143
146
|
- lib/tronprint/cpu_monitor.rb
|
144
147
|
- lib/tronprint/rails/generator.rb
|
145
148
|
- lib/tronprint/rails/tronprint_helper.rb
|
146
149
|
- lib/tronprint/rails.rb
|
147
150
|
- lib/tronprint/rake_tasks/active_record.rb
|
151
|
+
- lib/tronprint/statistics.rb
|
152
|
+
- lib/tronprint/statistics_formatter.rb
|
153
|
+
- lib/tronprint/traffic_monitor.rb
|
148
154
|
- lib/tronprint/version.rb
|
149
155
|
- lib/tronprint.rb
|
150
156
|
- .document
|
@@ -159,55 +165,55 @@ files:
|
|
159
165
|
- spec/spec_helper.rb
|
160
166
|
- spec/tronprint/aggregator_spec.rb
|
161
167
|
- spec/tronprint/application_spec.rb
|
162
|
-
- spec/tronprint/computer_spec.rb
|
163
168
|
- spec/tronprint/cpu_monitor_spec.rb
|
164
169
|
- spec/tronprint/rails/tronprint_helper_spec.rb
|
170
|
+
- spec/tronprint/statistics_formatter_spec.rb
|
171
|
+
- spec/tronprint/statistics_spec.rb
|
172
|
+
- spec/tronprint/traffic_monitor_spec.rb
|
165
173
|
- spec/tronprint_spec.rb
|
166
174
|
- features/step_definitions/tronprint_steps.rb
|
167
175
|
- features/support/env.rb
|
168
176
|
- features/tronprint.feature
|
169
|
-
has_rdoc: true
|
170
177
|
homepage: http://github.com/brighterplanet/tronprint
|
171
178
|
licenses: []
|
172
|
-
|
173
179
|
post_install_message:
|
174
180
|
rdoc_options: []
|
175
|
-
|
176
|
-
require_paths:
|
181
|
+
require_paths:
|
177
182
|
- lib
|
178
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
183
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
179
184
|
none: false
|
180
|
-
requirements:
|
181
|
-
- -
|
182
|
-
- !ruby/object:Gem::Version
|
183
|
-
|
184
|
-
segments:
|
185
|
+
requirements:
|
186
|
+
- - ! '>='
|
187
|
+
- !ruby/object:Gem::Version
|
188
|
+
version: '0'
|
189
|
+
segments:
|
185
190
|
- 0
|
186
|
-
|
187
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
191
|
+
hash: -3534616707855240394
|
192
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
188
193
|
none: false
|
189
|
-
requirements:
|
190
|
-
- -
|
191
|
-
- !ruby/object:Gem::Version
|
192
|
-
|
193
|
-
segments:
|
194
|
+
requirements:
|
195
|
+
- - ! '>='
|
196
|
+
- !ruby/object:Gem::Version
|
197
|
+
version: '0'
|
198
|
+
segments:
|
194
199
|
- 0
|
195
|
-
|
200
|
+
hash: -3534616707855240394
|
196
201
|
requirements: []
|
197
|
-
|
198
202
|
rubyforge_project:
|
199
|
-
rubygems_version: 1.
|
203
|
+
rubygems_version: 1.8.5
|
200
204
|
signing_key:
|
201
205
|
specification_version: 3
|
202
206
|
summary: Ruby process carbon footprinter
|
203
|
-
test_files:
|
207
|
+
test_files:
|
204
208
|
- spec/spec.opts
|
205
209
|
- spec/spec_helper.rb
|
206
210
|
- spec/tronprint/aggregator_spec.rb
|
207
211
|
- spec/tronprint/application_spec.rb
|
208
|
-
- spec/tronprint/computer_spec.rb
|
209
212
|
- spec/tronprint/cpu_monitor_spec.rb
|
210
213
|
- spec/tronprint/rails/tronprint_helper_spec.rb
|
214
|
+
- spec/tronprint/statistics_formatter_spec.rb
|
215
|
+
- spec/tronprint/statistics_spec.rb
|
216
|
+
- spec/tronprint/traffic_monitor_spec.rb
|
211
217
|
- spec/tronprint_spec.rb
|
212
218
|
- features/step_definitions/tronprint_steps.rb
|
213
219
|
- features/support/env.rb
|
@@ -1,9 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Tronprint::Application do
|
4
|
-
it 'should report emission esimates for application-related activity' do
|
5
|
-
app = Tronprint::Application.new :duration => 72831, :zip_code => 48915
|
6
|
-
app.should respond_to(:emission_estimate)
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|