tronprint 0.0.16 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
- Before you get started with Tronprint on ActiveRecord and you're using a
76
- relational database, (e.g., mysql) then you need to create the table
77
- Tronprint will use for storage. The easiest way to do this is add to
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
- Then, run `rake tronprint:moneta`.
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, Gemfile, app/views/trackings/_form.html.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
@@ -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
- adapter_underscored = options.delete :adapter
20
- adapter_underscored ||= 'pstore'
21
- adapter_underscored = adapter_underscored.to_s.downcase
21
+ self.adapter = options.delete :adapter
22
+ self.adapter ||= 'pstore'
23
+ self.adapter = self.adapter.to_s.downcase
22
24
  begin
23
- require "moneta/#{adapter_underscored}"
24
- klass = Moneta.const_get adapter_constant(adapter_underscored)
25
+ require "moneta/#{self.adapter}"
26
+ klass = Moneta.const_get adapter_constant
25
27
  rescue LoadError # Bundler hack
26
- require "moneta/adapters/#{adapter_underscored}"
27
- klass = Moneta::Adapters.const_get adapter_constant(adapter_underscored)
28
+ require "moneta/adapters/#{self.adapter}"
29
+ klass = Moneta::Adapters.const_get adapter_constant
28
30
  end
29
- args = adapter_underscored == 'memory' ? [] : [options]
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(adapter_underscored)
44
- case adapter_underscored
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
- adapter_underscored.split('_').map(&:capitalize).join('')
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
@@ -0,0 +1,13 @@
1
+ module Tronprint
2
+ class App
3
+ def initialize(app)
4
+ @app = app
5
+ end
6
+
7
+ def call(env)
8
+ Tronprint.traffic_monitor.increment
9
+
10
+ @app.call(env)
11
+ end
12
+ end
13
+ end
@@ -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
- emission_estimate.to_f
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
- emission_estimate.methodology
19
+ Tronprint.statistics.total_footprint_methodology
11
20
  end
12
21
 
13
- # The Carbon::EmissionEstimate object representing the
14
- # estimate processed by CM1.
15
- def emission_estimate
16
- @emission_estimate ||= Tronprint.emission_estimate
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
@@ -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.run # if Rails.env.production?
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 'Set up ActiveRecord datastore for Tronprint'
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,11 @@
1
+ module Tronprint
2
+ module StatisticsFormatter
3
+ def pounds_with_precision(number, precision = nil)
4
+ if precision.nil?
5
+ precision = number < 100 ? 4 : 0
6
+ end
7
+
8
+ number_with_precision(number * 2.2046, :precision => precision)
9
+ end
10
+ end
11
+ 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
@@ -1,3 +1,3 @@
1
1
  module Tronprint
2
- VERSION = "0.0.16"
2
+ VERSION = "1.0.0"
3
3
  end
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
- # Fetch the total amount of CPU time (in hours) used by the application.
76
- def total_duration
77
- aggregator[cpu_monitor.key] / 3600
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
- it 'should write statistics to an uninitailzed key' do
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 'should cumulatively update statistics' do
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
- let(:application) { Tronprint::Application.new }
5
-
6
- describe '#duration' do
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 'should write the elapsed time to the aggregate statistics' do
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 'should increment the toal recorded cpu time' do
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 'should return the total CPU time on the first run' do
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 'should return the amount of CPU time used since the last check' do
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 'should return the total user and system time of the process' do
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 'should return 0 by default' do
46
+ it 'returns 0 by default' do
47
47
  cpu_monitor.total_recorded_cpu_time.should == 0
48
48
  end
49
- it 'should return total recorded time' do
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 'should return the total footprint' do
13
- helper.stub!(:emission_estimate).and_return 89.4
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
+
@@ -8,39 +8,27 @@ describe Tronprint do
8
8
  end
9
9
 
10
10
  describe '.run' do
11
- it 'should start up each monitor' do
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 'should start the CPU monitor' do
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 'should return the CPU monitor instance' do
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 'should return the brighter_planet_key config option' do
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 'should return a configuration loaded from disk' do
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 'should return a default configuration if no config file exists' do
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 'should load a config file from cwd/config/tronprint.yml if it exists' do
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 'should return nil if no config file exists' do
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 'should return a default configuration' do
76
+ it 'returns a default configuration' do
89
77
  Tronprint.default_config.should be_an_instance_of(Hash)
90
78
  end
91
- it 'should set the brighter_planet_key if ENV["TRONPRINT_API_KEY"] is set' do
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 'should use MongoHQ if ENV["MONGOHQ_URL"] is set' do
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-02-03"
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 'sandbox'
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.3'
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
- prerelease: false
5
- segments:
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
- date: 2011-02-03 00:00:00 -05:00
18
- default_executable:
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
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: &id001 !ruby/object:Gem::Requirement
38
+ requirement: &2157409100 !ruby/object:Gem::Requirement
23
39
  none: false
24
- requirements:
25
- - - ">="
26
- - !ruby/object:Gem::Version
27
- segments:
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: *id001
33
- - !ruby/object:Gem::Dependency
46
+ version_requirements: *2157409100
47
+ - !ruby/object:Gem::Dependency
34
48
  name: bueller
35
- requirement: &id002 !ruby/object:Gem::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: *id002
48
- - !ruby/object:Gem::Dependency
57
+ version_requirements: *2157408560
58
+ - !ruby/object:Gem::Dependency
49
59
  name: rake
50
- requirement: &id003 !ruby/object:Gem::Requirement
60
+ requirement: &2157408040 !ruby/object:Gem::Requirement
51
61
  none: false
52
- requirements:
53
- - - ">="
54
- - !ruby/object:Gem::Version
55
- segments:
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: *id003
61
- - !ruby/object:Gem::Dependency
68
+ version_requirements: *2157408040
69
+ - !ruby/object:Gem::Dependency
62
70
  name: rspec
63
- requirement: &id004 !ruby/object:Gem::Requirement
71
+ requirement: &2157407300 !ruby/object:Gem::Requirement
64
72
  none: false
65
- requirements:
73
+ requirements:
66
74
  - - ~>
67
- - !ruby/object:Gem::Version
68
- segments:
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: *id004
75
- - !ruby/object:Gem::Dependency
79
+ version_requirements: *2157407300
80
+ - !ruby/object:Gem::Dependency
76
81
  name: sandbox
77
- requirement: &id005 !ruby/object:Gem::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
- segments:
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: *id005
88
- - !ruby/object:Gem::Dependency
101
+ version_requirements: *2157400260
102
+ - !ruby/object:Gem::Dependency
89
103
  name: carbon
90
- requirement: &id006 !ruby/object:Gem::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: *id006
103
- - !ruby/object:Gem::Dependency
112
+ version_requirements: *2157399320
113
+ - !ruby/object:Gem::Dependency
104
114
  name: i18n
105
- requirement: &id007 !ruby/object:Gem::Requirement
115
+ requirement: &2157397400 !ruby/object:Gem::Requirement
106
116
  none: false
107
- requirements:
108
- - - ">="
109
- - !ruby/object:Gem::Version
110
- segments:
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: *id007
116
- - !ruby/object:Gem::Dependency
123
+ version_requirements: *2157397400
124
+ - !ruby/object:Gem::Dependency
117
125
  name: dkastner-moneta
118
- requirement: &id008 !ruby/object:Gem::Requirement
126
+ requirement: &2157366380 !ruby/object:Gem::Requirement
119
127
  none: false
120
- requirements:
128
+ requirements:
121
129
  - - ~>
122
- - !ruby/object:Gem::Version
123
- segments:
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: *id008
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
- hash: 839406187484222147
184
- segments:
185
+ requirements:
186
+ - - ! '>='
187
+ - !ruby/object:Gem::Version
188
+ version: '0'
189
+ segments:
185
190
  - 0
186
- version: "0"
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
- hash: 839406187484222147
193
- segments:
194
+ requirements:
195
+ - - ! '>='
196
+ - !ruby/object:Gem::Version
197
+ version: '0'
198
+ segments:
194
199
  - 0
195
- version: "0"
200
+ hash: -3534616707855240394
196
201
  requirements: []
197
-
198
202
  rubyforge_project:
199
- rubygems_version: 1.3.7
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
-