harness 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -8,6 +8,39 @@ Currently Supported Services:
8
8
 
9
9
  * Librato
10
10
 
11
+ Current Features:
12
+
13
+ * Track counters over time (# of registered users)
14
+ * Read time specific values (# time to cache something)
15
+ * Build meters on top of counters (# requests per second)
16
+ * Sidekiq integration
17
+ * Resque integration
18
+ * Rails integration
19
+ * Capture and log all measurements coming out of Rails
20
+
21
+ **Crash Course**
22
+
23
+ ```ruby
24
+ class ComplicatedClass
25
+ def hard_work
26
+ # Automatically track how long each of these calls takes so they can
27
+ # tracked and compared over time.
28
+ ActiveSupport::Notifications.instrument "hard_work", :gauge => true do
29
+ # do hard_work
30
+ end
31
+ end
32
+
33
+ def register_user
34
+ # Automatically track the total # of registered users you have.
35
+ # As well, as be able to take measurements of users created in a
36
+ # specific interval
37
+ ActiveSupport::Notifications.instrument "register_user", :counter => true do
38
+ # register_user
39
+ end
40
+ end
41
+ end
42
+ ```
43
+
11
44
  ## Installation
12
45
 
13
46
  Add this line to your application's Gemfile:
@@ -28,7 +61,8 @@ In the metrics world there are two types of things: Gauges and Counters.
28
61
  Gauges are time senstive and represent something at a specific point in
29
62
  time. Counters keep track of things and should be increasing. Counters
30
63
  can be reset back to zero. You can combine counters and/or gauges to
31
- correlate data about your application.
64
+ correlate data about your application. Meters monitor counters. They
65
+ allow you look at rates of counters (read: counters per second).
32
66
 
33
67
  Harness makes this process easily. Harness' primary goal it make it dead
34
68
  simple to start measuring different parts of your application.
@@ -78,7 +112,30 @@ for that gauge or counter.
78
112
  Harness will do all the extra work in sending these metrics to whatever
79
113
  service you're using.
80
114
 
81
- ## Customzing
115
+ Once you the counters are you are instrumented, then you can meter them.
116
+ Meters allow you take arbitary readings of counter rates. The results
117
+ return a gauge so they can be logged as well.
118
+
119
+ ```ruby
120
+ # Define a counter
121
+ class MyClass
122
+ def important_method(stuff)
123
+ ActiveSupport::Notifications.instrument "important_method.my_class", :counter => true do
124
+ do_important_stuff
125
+ end
126
+ end
127
+ end
128
+
129
+ # Now you can meter it
130
+ meter = Harnes::Meter.new('important_method.my_class')
131
+ meter.per_second # returns a gauge
132
+ meter.per_second.value # if you just want the number
133
+ meter.per(1.hour).value # You can use your own interval
134
+ meter.per_minute
135
+ meter.per_hour
136
+ ```
137
+
138
+ ## Customizing
82
139
 
83
140
  You can pash a hash to `:counter` or `:gauge` to initialize the
84
141
  measurement your own way.
@@ -157,7 +214,7 @@ default values are used. You can customize this in an initializer:
157
214
  require 'erb'
158
215
 
159
216
  file = Rails.root.join 'config', 'resque.yml'
160
- config = YAML.load(ERB.new(File.read(Rails.root.join('config', 'resque.yml'))).result)
217
+ config = YAML.load(ERB.new(File.read(Rails.root.join('config', 'redis.yml'))).result)
161
218
 
162
219
  Harness.redis = Redis.new(:url => config[Rails.env])
163
220
  ```
@@ -170,6 +227,18 @@ Measurements are completely ignored in the test env. They are processed
170
227
  in development mode, but not sent to the external service. Everything is
171
228
  logged in production.
172
229
 
230
+ ### Background Processing
231
+
232
+ Harness integrates automatically with Resque or Sidekiq. This is because
233
+ reporting measurements can take time and add unncessary overhead to the
234
+ response time. If neither of these libraries are present, measurements
235
+ **will be posted in realtime.** You can set your own queue by
236
+ specifiying a class like so:
237
+
238
+ ```ruby
239
+ Harness.config.queue = MyCustomQueue
240
+ ```
241
+
173
242
  ## Contributing
174
243
 
175
244
  1. Fork it
data/harness.gemspec CHANGED
@@ -21,4 +21,6 @@ Gem::Specification.new do |gem|
21
21
 
22
22
  gem.add_development_dependency "simplecov"
23
23
  gem.add_development_dependency "webmock"
24
+ gem.add_development_dependency "resque"
25
+ gem.add_development_dependency "sidekiq"
24
26
  end
data/lib/harness.rb CHANGED
@@ -2,32 +2,41 @@ require "harness/version"
2
2
 
3
3
  require 'thread'
4
4
 
5
- require 'securerandom'
6
-
7
5
  require 'redis'
8
6
  require 'redis/namespace'
9
7
 
10
8
  require 'active_support/notifications'
11
9
  require 'active_support/core_ext/string'
10
+ require 'active_support/core_ext/hash/keys'
11
+ require 'active_support/core_ext/numeric'
12
+ require 'active_support/core_ext/integer'
12
13
 
13
14
  module Harness
14
15
  class LoggingError < RuntimeError ; end
16
+ class NoCounter < RuntimeError ; end
15
17
 
16
18
  class Config
17
- attr_reader :adapter
18
- attr_accessor :syncronous
19
+ attr_reader :adapter, :queue
19
20
 
20
21
  def adapter=(val)
21
22
  if val.is_a? Symbol
22
- @adapter = "Harness::#{val.to_s.classify}Adapter".constantize
23
+ @adapter = "Harness::#{val.to_s.camelize}Adapter".constantize
23
24
  else
24
25
  @adapter = val
25
26
  end
26
27
  end
27
28
 
29
+ def queue=(val)
30
+ if val.is_a? Symbol
31
+ @queue= "Harness::#{val.to_s.camelize}Queue".constantize
32
+ else
33
+ @queue= val
34
+ end
35
+ end
36
+
28
37
  def method_missing(name, *args, &block)
29
38
  begin
30
- "Harness::#{name.to_s.classify}Adapter".constantize.config
39
+ "Harness::#{name.to_s.camelize}Adapter".constantize.config
31
40
  rescue NameError
32
41
  super
33
42
  end
@@ -38,25 +47,8 @@ module Harness
38
47
  @config ||= Config.new
39
48
  end
40
49
 
41
- def self.queue
42
- @queue ||= Queue.new
43
- end
44
-
45
- def self.consumer
46
- Thread.current["#{object_id}_harness_consumer_"] ||= Consumer.new
47
- end
48
-
49
50
  def self.log(measurement)
50
- queue << measurement
51
- wait if config.syncronous
52
- end
53
-
54
- def self.mutex
55
- @mutex ||= Mutex.new
56
- end
57
-
58
- def self.wait
59
- sleep 0.01 until consumer.finished? && queue.empty?
51
+ config.queue.push measurement
60
52
  end
61
53
 
62
54
  def self.logger
@@ -77,7 +69,8 @@ module Harness
77
69
 
78
70
  def self.reset_counters!
79
71
  redis.smembers('counters').each do |counter|
80
- redis.set counter, -1
72
+ redis.set counter, 0
73
+ redis.del "meters/#{counter}"
81
74
  end
82
75
  end
83
76
  end
@@ -85,10 +78,13 @@ end
85
78
  require 'harness/measurement'
86
79
  require 'harness/counter'
87
80
  require 'harness/gauge'
81
+ require 'harness/meter'
88
82
 
89
83
  require 'harness/instrumentation'
90
84
 
91
- require 'harness/consumer'
85
+ require 'harness/job'
86
+
87
+ require 'harness/queues/syncronous_queue'
92
88
 
93
89
  require 'harness/adapters/librato_adapter'
94
90
  require 'harness/adapters/memory_adapter'
@@ -101,8 +97,6 @@ require 'harness/integration/active_support'
101
97
 
102
98
  require 'harness/railtie' if defined?(Rails)
103
99
 
104
- Harness.consumer.consume
105
-
106
100
  require 'logger'
107
101
 
108
102
  Harness.logger = Logger.new $stdout
@@ -4,18 +4,6 @@ module Harness
4
4
  Thread.new do
5
5
  while measurement = queue.pop
6
6
  begin
7
- logger.debug "[Harness] Processing Measurement: #{measurement.inspect}"
8
-
9
- case measurement.class.to_s.demodulize.underscore.to_sym
10
- when :gauge
11
- adapter.log_gauge measurement
12
- when :counter
13
- adapter.log_counter measurement
14
- end
15
- rescue LoggingError => ex
16
- logger.debug "[Harness] Logging measurement failed! Server Said: #{ex}"
17
- logger.debug ex.backtrace.join("\n")
18
- logger.warn "[Harness] Could not post measurement! Enable debug logging to see full errors"
19
7
  ensure
20
8
  mutex.synchronize { @finished = queue.empty? }
21
9
  end
@@ -1,9 +1,11 @@
1
+ require 'securerandom'
2
+
1
3
  module Harness
2
4
  class Counter < Measurement
3
5
  def self.from_event(event)
4
6
  if event.payload[:counter].is_a? Hash
5
7
  counter = new event.payload[:counter]
6
- elsif event.payload[:counter].is_a? Symbol
8
+ elsif event.payload[:counter].is_a?(Symbol) || event.payload[:counter].is_a?(String)
7
9
  counter = new :id => event.payload[:counter].to_s
8
10
  else
9
11
  counter = new
@@ -23,6 +25,8 @@ module Harness
23
25
  counter.value = Harness.redis.incr(counter.id).to_i
24
26
  end
25
27
 
28
+ Harness.redis.zadd "meters/#{counter.id}", counter.time.to_f, counter.value
29
+
26
30
  counter
27
31
  end
28
32
  end
data/lib/harness/gauge.rb CHANGED
@@ -8,7 +8,7 @@ module Harness
8
8
  def self.from_event(event)
9
9
  if event.payload[:gauge].is_a? Hash
10
10
  gauge = new event.payload[:gauge]
11
- elsif event.payload[:gauge].is_a? Symbol
11
+ elsif event.payload[:gauge].is_a?(Symbol) || event.payload[:gauge].is_a?(String)
12
12
  gauge = new :id => event.payload[:gauge].to_s
13
13
  else
14
14
  gauge = new
@@ -0,0 +1,23 @@
1
+ module Harness
2
+ class Job
3
+ def log(measurement)
4
+ logger.debug "[Harness] Processing Measurement: #{measurement.inspect}"
5
+
6
+ case measurement.class.to_s.demodulize.underscore.to_sym
7
+ when :gauge
8
+ adapter.log_gauge measurement
9
+ when :counter
10
+ adapter.log_counter measurement
11
+ end
12
+ end
13
+
14
+ private
15
+ def logger
16
+ Harness.logger
17
+ end
18
+
19
+ def adapter
20
+ Harness.config.adapter
21
+ end
22
+ end
23
+ end
@@ -10,8 +10,29 @@ module Harness
10
10
  self.time ||= Time.now
11
11
  end
12
12
 
13
+ def time=(value)
14
+ if value.is_a? String
15
+ @time = DateTime.parse value
16
+ elsif value.is_a? Fixnum
17
+ @time = Time.at value
18
+ else
19
+ @time = value
20
+ end
21
+ end
22
+
13
23
  def log
14
24
  Harness.log self
15
25
  end
26
+
27
+ def attributes
28
+ {
29
+ :id => id,
30
+ :name => name,
31
+ :source => source,
32
+ :time => time,
33
+ :units => units,
34
+ :value => value
35
+ }
36
+ end
16
37
  end
17
38
  end
@@ -0,0 +1,55 @@
1
+ module Harness
2
+ class Meter
3
+ def initialize(name)
4
+ @name = name
5
+
6
+ raise Harness::NoCounter, "#{@name} is not being metered" unless redis.exists key
7
+ end
8
+
9
+ def per_second
10
+ per 1.second
11
+ end
12
+
13
+ def per_minute
14
+ per 1.minute
15
+ end
16
+
17
+ def per_hour
18
+ per 1.hour
19
+ end
20
+
21
+ def per(rate, base = Time.now)
22
+ gauge = Gauge.new :value => redis.zcount(key, base.to_f - rate, base.to_f)
23
+
24
+ if words = rate_in_words(rate)
25
+ gauge.name = "#{@name} per #{words}"
26
+ gauge.id = "#{@name}-per-#{words}"
27
+ else
28
+ gauge.id = "#{@name} gauge"
29
+ end
30
+
31
+ gauge.time = Time.now
32
+
33
+ gauge
34
+ end
35
+
36
+ private
37
+ def key
38
+ "meters/#{@name}"
39
+ end
40
+
41
+ def redis
42
+ Harness.redis
43
+ end
44
+
45
+ def rate_in_words(rate)
46
+ if rate < 1.minute
47
+ "second"
48
+ elsif rate >= 1.minute && rate < 1.hour
49
+ "minute"
50
+ elsif rate >= 1.hour && rate < 1.day
51
+ "hour"
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,29 @@
1
+ module Harness
2
+ class ResqueQueue
3
+ class SendGauge < Job
4
+ @queue = :high
5
+
6
+ def self.perform(attributes)
7
+ gauge = Gauge.new attributes
8
+ new.log gauge
9
+ end
10
+ end
11
+
12
+ class SendCounter < Job
13
+ @queue = :high
14
+
15
+ def self.perform(attributes)
16
+ counter = Counter.new attributes
17
+ new.log counter
18
+ end
19
+ end
20
+
21
+ def self.push(measurement)
22
+ if measurement.is_a? Gauge
23
+ Resque.enqueue SendGauge, measurement.attributes
24
+ elsif measurement.is_a? Counter
25
+ Resque.enqueue SendCounter, measurement.attributes
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+ module Harness
2
+ class SidekiqQueue
3
+ class SendGauge < Job
4
+ include Sidekiq::Worker
5
+
6
+ def perform(attributes)
7
+ gauge = Gauge.new attributes
8
+ log gauge
9
+ end
10
+ end
11
+
12
+ class SendCounter < Job
13
+ include Sidekiq::Worker
14
+
15
+ def perform(attributes)
16
+ counter = Counter.new attributes
17
+ log counter
18
+ end
19
+ end
20
+
21
+ def self.push(measurement)
22
+ if measurement.is_a? Gauge
23
+ SendGauge.perform_async measurement.attributes
24
+ elsif measurement.is_a? Counter
25
+ SendCounter.perform_async measurement.attributes
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,13 @@
1
+ module Harness
2
+ class SyncronousQueue
3
+ def self.push(measurement)
4
+ begin
5
+ Harness::Job.new.log(measurement)
6
+ rescue LoggingError => ex
7
+ logger.debug "[Harness] Logging measurement failed! Server Said: #{ex}"
8
+ logger.debug ex.backtrace.join("\n")
9
+ logger.warn "[Harness] Could not post measurement! Enable debug logging to see full errors"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -6,10 +6,6 @@ module Harness
6
6
  load "harness/tasks.rake"
7
7
  end
8
8
 
9
- initializer "harness.thread" do
10
- Thread.abort_on_exception = Rails.env.development? || Rails.env.test?
11
- end
12
-
13
9
  initializer "harness.adapter" do |app|
14
10
  case Rails.env
15
11
  when 'development'
@@ -32,5 +28,17 @@ module Harness
32
28
  Harness.redis ||= Redis::Namespace.new('harness', :redis => Redis.connect(:host => 'localhost', :port => '6379'))
33
29
  end
34
30
  end
31
+
32
+ initializer "harness.queue" do
33
+ if defined? Resque
34
+ require 'harness/queues/resque_queue'
35
+ Harness.config.queue = :resque
36
+ elsif defined? Sidekiq
37
+ require 'harness/queues/sidekiq_queue'
38
+ Harness.config.queue = :sidekiq
39
+ else
40
+ Harness.config.queue = Harness::SyncronousQueue
41
+ end
42
+ end
35
43
  end
36
44
  end
@@ -1,3 +1,3 @@
1
1
  module Harness
2
- VERSION = "0.1.2"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -57,13 +57,32 @@ class CountersWithRedis < IntegrationTest
57
57
 
58
58
  Harness.reset_counters!
59
59
 
60
- assert_equal -1, redis.get("event-counter").to_i
61
- assert_equal -1, redis.get("event-counter2").to_i
60
+ assert_equal 0, redis.get("event-counter").to_i
61
+ assert_equal 0, redis.get("event-counter2").to_i
62
62
 
63
63
  counters.clear
64
64
  instrument "event-counter", :counter => true
65
65
  assert_counter_logged 'event-counter'
66
66
 
67
- assert_equal 0, counters.first.value
67
+ assert_equal 1, counters.first.value
68
+ assert_equal 1, redis.get("event-counter").to_i
69
+ end
70
+
71
+ def test_resets_counters_resets_meters
72
+ instrument "event-counter", :counter => true
73
+
74
+ assert_equal 1, redis.get("event-counter").to_i
75
+ assert_equal 1, redis.zcard("meters/event-counter").to_i
76
+
77
+ Harness.reset_counters!
78
+
79
+ assert_equal 0, redis.get("event-counter").to_i
80
+ assert_equal 0, redis.zcard("meters/event-counter").to_i
81
+ end
82
+
83
+ def test_counting_updates_sorted_set_in_redis
84
+ instrument "event-counter", :counter => true
85
+
86
+ assert_equal 1, redis.zcard("meters/event-counter")
68
87
  end
69
88
  end
@@ -0,0 +1,32 @@
1
+ require 'test_helper'
2
+
3
+ class CountersWithRedis < IntegrationTest
4
+ def test_counters_can_act_like_gauges
5
+ 50.times { instrument "event-counter", :counter => true }
6
+
7
+ meter = Harness::Meter.new 'event-counter'
8
+ assert_equal 50, meter.per_second.value
9
+ assert_equal 50, meter.per_minute.value
10
+ assert_equal 50, meter.per_hour.value
11
+ end
12
+
13
+ def tests_raises_an_error_when_no_such_counter
14
+ assert_raises Harness::NoCounter do
15
+ Harness::Meter.new 'unknown-counter'
16
+ end
17
+ end
18
+
19
+ def test_rates_return_gauges
20
+ 50.times { instrument "event-counter", :counter => true }
21
+
22
+ meter = Harness::Meter.new 'event-counter'
23
+
24
+ gauge = meter.per_second
25
+
26
+ assert_kind_of Harness::Gauge, gauge
27
+
28
+ assert_equal "event-counter-per-second", gauge.id
29
+ assert_equal "event-counter per second", gauge.name
30
+ assert_kind_of Time, gauge.time
31
+ end
32
+ end
@@ -0,0 +1,24 @@
1
+ require 'test_helper'
2
+ require 'harness/queues/resque_queue'
3
+
4
+ class ResqueTest < IntegrationTest
5
+ def setup
6
+ super
7
+ Resque.inline = true
8
+ Harness.config.queue = :resque
9
+ end
10
+
11
+ def test_a_gauge_is_logged
12
+ instrument "test-gauge", :gauge => true
13
+
14
+ assert_gauge_logged "test-gauge"
15
+ end
16
+
17
+ def test_a_counter_is_logged
18
+ instrument "test-counter", :counter => true
19
+
20
+ assert_counter_logged "test-counter"
21
+
22
+ assert_equal 1, counters.first.value
23
+ end
24
+ end
@@ -0,0 +1,34 @@
1
+ require 'test_helper'
2
+ require 'harness/queues/sidekiq_queue'
3
+ require 'sidekiq/testing'
4
+
5
+ class SidekiqTest < IntegrationTest
6
+ def setup
7
+ super
8
+ Harness.config.queue = :sidekiq
9
+ end
10
+
11
+ def test_a_gauge_is_logged
12
+ instrument "test-gauge", :gauge => true
13
+
14
+ refute_empty Harness::SidekiqQueue::SendGauge.jobs
15
+
16
+ args = Harness::SidekiqQueue::SendGauge.jobs.first['args'].first
17
+ Harness::SidekiqQueue::SendGauge.new.perform args
18
+
19
+ assert_gauge_logged "test-gauge"
20
+ end
21
+
22
+ def test_a_counter_is_logged
23
+ instrument "test-counter", :counter => true
24
+
25
+ refute_empty Harness::SidekiqQueue::SendCounter.jobs
26
+
27
+ args = Harness::SidekiqQueue::SendCounter.jobs.first['args'].first
28
+ Harness::SidekiqQueue::SendCounter.new.perform args
29
+
30
+ assert_counter_logged "test-counter"
31
+
32
+ assert_equal 1, counters.first.value
33
+ end
34
+ end
data/test/test_helper.rb CHANGED
@@ -1,6 +1,9 @@
1
1
  require 'simplecov'
2
2
  SimpleCov.start
3
3
 
4
+ require 'resque'
5
+ require 'sidekiq'
6
+
4
7
  require 'harness'
5
8
 
6
9
  require 'minitest/unit'
@@ -11,10 +14,6 @@ require 'webmock/minitest'
11
14
 
12
15
  WebMock.disable_net_connect!
13
16
 
14
- Thread.abort_on_exception = true
15
-
16
- Harness.config.syncronous = true
17
-
18
17
  Harness.logger = Logger.new '/dev/null'
19
18
 
20
19
  Harness.redis = Redis::Namespace.new 'harness-test', :redis => Redis.connect(:host => 'localhost', :port => '6379')
@@ -22,6 +21,8 @@ Harness.redis = Redis::Namespace.new 'harness-test', :redis => Redis.connect(:ho
22
21
  class IntegrationTest < MiniTest::Unit::TestCase
23
22
  def setup
24
23
  Harness.config.adapter = :memory
24
+ Harness.config.queue = :syncronous
25
+
25
26
  gauges.clear ; counters.clear
26
27
  redis.flushall
27
28
  end
@@ -59,6 +59,16 @@ class CounterTest < MiniTest::Unit::TestCase
59
59
 
60
60
  counter = Harness::Counter.from_event event
61
61
 
62
+ assert_equal 'foo', counter.id
63
+ end
64
+
65
+ def test_sets_id_from_payload_if_string
66
+ base = Time.now
67
+
68
+ event = ActiveSupport::Notifications::Event.new "name", base - 1, Time.now, nil, :counter => 'foo'
69
+
70
+ counter = Harness::Counter.from_event event
71
+
62
72
  assert_equal 'foo', counter.id
63
73
  end
64
74
  end
@@ -55,6 +55,16 @@ class GaugeTest < MiniTest::Unit::TestCase
55
55
  assert_equal 'foo', gauge.id
56
56
  end
57
57
 
58
+ def test_sets_id_from_payload_if_string
59
+ base = Time.now
60
+
61
+ event = ActiveSupport::Notifications::Event.new "name", base - 1, Time.now, nil, :gauge => 'foo'
62
+
63
+ gauge = Harness::Gauge.from_event event
64
+
65
+ assert_equal 'foo', gauge.id
66
+ end
67
+
58
68
  def test_initializes_time_if_not_set
59
69
  gauge = Harness::Gauge.new
60
70
 
@@ -13,6 +13,18 @@ class HarnessModuleTest < MiniTest::Unit::TestCase
13
13
  assert_equal Harness::MemoryAdapter, Harness.config.adapter
14
14
  end
15
15
 
16
+ def test_can_set_the_queue_with_a_symbol
17
+ Harness.config.queue = :syncronous
18
+
19
+ assert_equal Harness::SyncronousQueue, Harness.config.queue
20
+ end
21
+
22
+ def test_can_set_the_queue_with_a_class
23
+ Harness.config.adapter = Harness::SyncronousQueue
24
+
25
+ assert_equal Harness::SyncronousQueue, Harness.config.queue
26
+ end
27
+
16
28
  def test_uses_method_missing_to_configure_adapters
17
29
  Harness.config.librato.email = 'foo'
18
30
 
@@ -33,4 +33,37 @@ class MeasurementTest < MiniTest::Unit::TestCase
33
33
  def test_initializes_time
34
34
  assert @measurement.time
35
35
  end
36
+
37
+ def test_can_take_a_string_time
38
+ @measurement.time = "2010-10-1T15:15:15Z"
39
+
40
+ assert_equal DateTime.parse("2010-10-1T15:15:15Z"), @measurement.time
41
+ end
42
+
43
+ def test_can_take_an_integer_time
44
+ time = Time.now
45
+
46
+ @measurement.time = time.to_i
47
+
48
+ assert_equal time.to_i, @measurement.time.to_i
49
+ end
50
+
51
+ def test_can_take_a_time
52
+ time = Time.now
53
+
54
+ @measurement.time = time
55
+
56
+ assert_equal time, @measurement.time
57
+ end
58
+
59
+ def test_attributes
60
+ hash = @measurement.attributes
61
+
62
+ assert hash.has_key?(:id)
63
+ assert hash.has_key?(:name)
64
+ assert hash.has_key?(:source)
65
+ assert hash.has_key?(:time)
66
+ assert hash.has_key?(:units)
67
+ assert hash.has_key?(:value)
68
+ end
36
69
  end
File without changes
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: harness
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-10 00:00:00.000000000 Z
12
+ date: 2012-04-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
16
- requirement: &70328784097540 !ruby/object:Gem::Requirement
16
+ requirement: &70140998559480 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '3'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70328784097540
24
+ version_requirements: *70140998559480
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: redis
27
- requirement: &70328784097120 !ruby/object:Gem::Requirement
27
+ requirement: &70140998559060 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70328784097120
35
+ version_requirements: *70140998559060
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: redis-namespace
38
- requirement: &70328784096660 !ruby/object:Gem::Requirement
38
+ requirement: &70140998558600 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70328784096660
46
+ version_requirements: *70140998558600
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: simplecov
49
- requirement: &70328784096240 !ruby/object:Gem::Requirement
49
+ requirement: &70140998558180 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70328784096240
57
+ version_requirements: *70140998558180
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: webmock
60
- requirement: &70328784095820 !ruby/object:Gem::Requirement
60
+ requirement: &70140998557760 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,7 +65,29 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70328784095820
68
+ version_requirements: *70140998557760
69
+ - !ruby/object:Gem::Dependency
70
+ name: resque
71
+ requirement: &70140998557340 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *70140998557340
80
+ - !ruby/object:Gem::Dependency
81
+ name: sidekiq
82
+ requirement: &70140998556920 !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: *70140998556920
69
91
  description: ''
70
92
  email:
71
93
  - me@broadcastingadam.com
@@ -91,7 +113,12 @@ files:
91
113
  - lib/harness/integration/action_mailer.rb
92
114
  - lib/harness/integration/action_view.rb
93
115
  - lib/harness/integration/active_support.rb
116
+ - lib/harness/job.rb
94
117
  - lib/harness/measurement.rb
118
+ - lib/harness/meter.rb
119
+ - lib/harness/queues/resque_queue.rb
120
+ - lib/harness/queues/sidekiq_queue.rb
121
+ - lib/harness/queues/syncronous_queue.rb
95
122
  - lib/harness/railtie.rb
96
123
  - lib/harness/tasks.rake
97
124
  - lib/harness/version.rb
@@ -102,6 +129,9 @@ files:
102
129
  - test/integration/integrations/action_view_test.rb
103
130
  - test/integration/integrations/active_support_test.rb
104
131
  - test/integration/logging_test.rb
132
+ - test/integration/meter_test.rb
133
+ - test/integration/queues/resque_test.rb
134
+ - test/integration/queues/sidekiq_test.rb
105
135
  - test/test_helper.rb
106
136
  - test/unit/adapters/librato_adapter_test.rb
107
137
  - test/unit/adapters/memory_adapter_test.rb
@@ -109,6 +139,7 @@ files:
109
139
  - test/unit/gauge_test.rb
110
140
  - test/unit/harness_test.rb
111
141
  - test/unit/measurement_test.rb
142
+ - test/unit/meter_test.rb
112
143
  homepage: ''
113
144
  licenses: []
114
145
  post_install_message:
@@ -121,12 +152,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
121
152
  - - ! '>='
122
153
  - !ruby/object:Gem::Version
123
154
  version: '0'
155
+ segments:
156
+ - 0
157
+ hash: 3488499753103101951
124
158
  required_rubygems_version: !ruby/object:Gem::Requirement
125
159
  none: false
126
160
  requirements:
127
161
  - - ! '>='
128
162
  - !ruby/object:Gem::Version
129
163
  version: '0'
164
+ segments:
165
+ - 0
166
+ hash: 3488499753103101951
130
167
  requirements: []
131
168
  rubyforge_project:
132
169
  rubygems_version: 1.8.11
@@ -141,6 +178,9 @@ test_files:
141
178
  - test/integration/integrations/action_view_test.rb
142
179
  - test/integration/integrations/active_support_test.rb
143
180
  - test/integration/logging_test.rb
181
+ - test/integration/meter_test.rb
182
+ - test/integration/queues/resque_test.rb
183
+ - test/integration/queues/sidekiq_test.rb
144
184
  - test/test_helper.rb
145
185
  - test/unit/adapters/librato_adapter_test.rb
146
186
  - test/unit/adapters/memory_adapter_test.rb
@@ -148,3 +188,4 @@ test_files:
148
188
  - test/unit/gauge_test.rb
149
189
  - test/unit/harness_test.rb
150
190
  - test/unit/measurement_test.rb
191
+ - test/unit/meter_test.rb