harness 0.1.2 → 0.2.14
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.md +72 -3
- data/harness.gemspec +2 -0
- data/lib/harness/adapters/librato_adapter.rb +15 -2
- data/lib/harness/consumer.rb +0 -12
- data/lib/harness/counter.rb +5 -1
- data/lib/harness/gauge.rb +1 -1
- data/lib/harness/instrumentation.rb +4 -2
- data/lib/harness/integration/action_controller.rb +6 -6
- data/lib/harness/integration/action_mailer.rb +6 -7
- data/lib/harness/integration/action_view.rb +6 -7
- data/lib/harness/integration/active_support.rb +6 -6
- data/lib/harness/integration/sidekiq.rb +47 -0
- data/lib/harness/job.rb +23 -0
- data/lib/harness/measurement.rb +21 -0
- data/lib/harness/meter.rb +55 -0
- data/lib/harness/queues/resque_queue.rb +29 -0
- data/lib/harness/queues/sidekiq_queue.rb +29 -0
- data/lib/harness/queues/syncronous_queue.rb +13 -0
- data/lib/harness/railtie.rb +22 -4
- data/lib/harness/version.rb +1 -1
- data/lib/harness.rb +23 -28
- data/test/integration/counters_with_redis_test.rb +22 -3
- data/test/integration/instrumentation_test.rb +22 -0
- data/test/integration/integrations/action_view_test.rb +13 -3
- data/test/integration/integrations/sidekiq_test.rb +54 -0
- data/test/integration/meter_test.rb +32 -0
- data/test/integration/queues/resque_test.rb +24 -0
- data/test/integration/queues/sidekiq_test.rb +34 -0
- data/test/test_helper.rb +13 -4
- data/test/unit/adapters/librato_adapter_test.rb +7 -14
- data/test/unit/counter_test.rb +10 -0
- data/test/unit/gauge_test.rb +10 -0
- data/test/unit/harness_test.rb +12 -0
- data/test/unit/measurement_test.rb +33 -0
- data/test/unit/meter_test.rb +0 -0
- metadata +50 -12
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
|
-
|
|
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', '
|
|
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
|
@@ -55,14 +55,27 @@ module Harness
|
|
|
55
55
|
|
|
56
56
|
response = http.request request
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
unless response.code.to_i == 200
|
|
59
|
+
text = %Q{
|
|
60
|
+
Server Said: #{response.body}
|
|
61
|
+
Sent: #{params.inspect}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
raise Harness::LoggingError, text
|
|
65
|
+
end
|
|
59
66
|
end
|
|
60
67
|
|
|
61
68
|
true
|
|
62
69
|
end
|
|
63
70
|
|
|
64
71
|
def self.sanitize(name)
|
|
65
|
-
|
|
72
|
+
if Harness.config.namespace
|
|
73
|
+
key = "#{name}.#{Harness.config.namespace}"
|
|
74
|
+
else
|
|
75
|
+
key = name
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
key.gsub('/', '.')
|
|
66
79
|
end
|
|
67
80
|
end
|
|
68
81
|
end
|
data/lib/harness/consumer.rb
CHANGED
|
@@ -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
|
data/lib/harness/counter.rb
CHANGED
|
@@ -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?
|
|
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?
|
|
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
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
ActiveSupport::Notifications.subscribe %r{.+} do |*args|
|
|
2
2
|
event = ActiveSupport::Notifications::Event.new(*args)
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
unless event.payload[:exception]
|
|
5
|
+
Harness::Gauge.from_event(event).log if event.payload[:gauge]
|
|
6
|
+
Harness::Counter.from_event(event).log if event.payload[:counter]
|
|
7
|
+
end
|
|
6
8
|
end
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
events = %w(write_fragment read_fragment expire_fragment write_page expire_page process_action send_file)
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
ActiveSupport::Notifications.
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
events.each do |name|
|
|
4
|
+
ActiveSupport::Notifications.subscribe "#{name}.action_controller" do |*args|
|
|
5
|
+
event = ActiveSupport::Notifications::Event.new(*args)
|
|
6
|
+
gauge = Harness::Gauge.from_event event
|
|
7
|
+
gauge.log
|
|
8
|
+
end
|
|
9
9
|
end
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
events = %w(receive deliver)
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
ActiveSupport::Notifications.
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
events.each do |name|
|
|
4
|
+
ActiveSupport::Notifications.subscribe "#{name}.action_mailer" do |*args|
|
|
5
|
+
event = ActiveSupport::Notifications::Event.new(*args)
|
|
6
|
+
gauge = Harness::Gauge.from_event event
|
|
7
|
+
gauge.log
|
|
8
|
+
end
|
|
9
9
|
end
|
|
10
|
-
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
events = %w(render_template render_partial)
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
ActiveSupport::Notifications.
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
events.each do |name|
|
|
4
|
+
ActiveSupport::Notifications.subscribe "#{name}.action_view" do |*args|
|
|
5
|
+
event = ActiveSupport::Notifications::Event.new(*args)
|
|
6
|
+
gauge = Harness::Gauge.from_event event
|
|
7
|
+
gauge.log
|
|
8
|
+
end
|
|
9
9
|
end
|
|
10
|
-
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
events = %w(cache_read cache_generate cache_fetch_hit cache_write cache_delete)
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
ActiveSupport::Notifications.
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
events.each do |name|
|
|
4
|
+
ActiveSupport::Notifications.subscribe "#{name}.active_support" do |*args|
|
|
5
|
+
event = ActiveSupport::Notifications::Event.new(*args)
|
|
6
|
+
gauge = Harness::Gauge.from_event event
|
|
7
|
+
gauge.log
|
|
8
|
+
end
|
|
9
9
|
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module Sidekiq
|
|
2
|
+
module Middleware
|
|
3
|
+
module Server
|
|
4
|
+
class HarnessInstrumentation
|
|
5
|
+
def call(worker_class, item, queue)
|
|
6
|
+
if instrument? worker_class
|
|
7
|
+
logger.debug "Instrumenting: #{worker_class.inspect}"
|
|
8
|
+
|
|
9
|
+
options = {}
|
|
10
|
+
options[:gauge] = "#{worker_class.class.to_s.underscore}.sidekiq"
|
|
11
|
+
options[:counter] = "#{worker_class.class.to_s.pluralize.underscore}.sidekiq"
|
|
12
|
+
|
|
13
|
+
ActiveSupport::Notifications.instrument "#{worker_class.class.to_s.underscore}.sidekiq", options do
|
|
14
|
+
yield
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
ActiveSupport::Notifications.instrument "job.sidekiq", :counter => true
|
|
18
|
+
else
|
|
19
|
+
logger.debug "Skipped Instrumenting: #{worker_class.inspect}"
|
|
20
|
+
yield
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
def instrument?(worker_class)
|
|
26
|
+
if worker_class.is_a? Harness::SidekiqQueue::SendCounter
|
|
27
|
+
false
|
|
28
|
+
elsif worker_class.is_a? Harness::SidekiqQueue::SendGauge
|
|
29
|
+
false
|
|
30
|
+
else
|
|
31
|
+
worker_class.to_s !~ /^harness/i
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def logger
|
|
36
|
+
Sidekiq.logger
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
Sidekiq.configure_server do |config|
|
|
44
|
+
config.server_middleware do |chain|
|
|
45
|
+
chain.add Sidekiq::Middleware::Server::HarnessInstrumentation
|
|
46
|
+
end
|
|
47
|
+
end
|
data/lib/harness/job.rb
ADDED
|
@@ -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
|
data/lib/harness/measurement.rb
CHANGED
|
@@ -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
|
data/lib/harness/railtie.rb
CHANGED
|
@@ -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,27 @@ 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
|
+
Harness.config.queue = Harness::SyncronousQueue
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
initializer "harness.queue.production" do |app|
|
|
37
|
+
use_real_queue = Rails.env != 'development' && Rails.env != 'test'
|
|
38
|
+
|
|
39
|
+
if defined?(Resque::Job) && use_real_queue
|
|
40
|
+
require 'harness/queues/resque_queue'
|
|
41
|
+
Harness.config.queue = :resque
|
|
42
|
+
elsif defined?(Sidekiq::Worker) && use_real_queue
|
|
43
|
+
require 'harness/queues/sidekiq_queue'
|
|
44
|
+
Harness.config.queue = :sidekiq
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
initializer "harness.sidekiq" do |app|
|
|
49
|
+
if defined? Sidekiq::Worker
|
|
50
|
+
require 'harness/integration/sidekiq'
|
|
51
|
+
end
|
|
52
|
+
end
|
|
35
53
|
end
|
|
36
54
|
end
|
data/lib/harness/version.rb
CHANGED
data/lib/harness.rb
CHANGED
|
@@ -2,32 +2,42 @@ 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 :
|
|
19
|
+
attr_reader :adapter, :queue
|
|
20
|
+
attr_accessor :namespace
|
|
19
21
|
|
|
20
22
|
def adapter=(val)
|
|
21
23
|
if val.is_a? Symbol
|
|
22
|
-
@adapter = "Harness::#{val.to_s.
|
|
24
|
+
@adapter = "Harness::#{val.to_s.camelize}Adapter".constantize
|
|
23
25
|
else
|
|
24
26
|
@adapter = val
|
|
25
27
|
end
|
|
26
28
|
end
|
|
27
29
|
|
|
30
|
+
def queue=(val)
|
|
31
|
+
if val.is_a? Symbol
|
|
32
|
+
@queue= "Harness::#{val.to_s.camelize}Queue".constantize
|
|
33
|
+
else
|
|
34
|
+
@queue= val
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
28
38
|
def method_missing(name, *args, &block)
|
|
29
39
|
begin
|
|
30
|
-
"Harness::#{name.to_s.
|
|
40
|
+
"Harness::#{name.to_s.camelize}Adapter".constantize.config
|
|
31
41
|
rescue NameError
|
|
32
42
|
super
|
|
33
43
|
end
|
|
@@ -38,25 +48,8 @@ module Harness
|
|
|
38
48
|
@config ||= Config.new
|
|
39
49
|
end
|
|
40
50
|
|
|
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
51
|
def self.log(measurement)
|
|
50
|
-
queue
|
|
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?
|
|
52
|
+
config.queue.push measurement
|
|
60
53
|
end
|
|
61
54
|
|
|
62
55
|
def self.logger
|
|
@@ -77,7 +70,8 @@ module Harness
|
|
|
77
70
|
|
|
78
71
|
def self.reset_counters!
|
|
79
72
|
redis.smembers('counters').each do |counter|
|
|
80
|
-
redis.set counter,
|
|
73
|
+
redis.set counter, 0
|
|
74
|
+
redis.del "meters/#{counter}"
|
|
81
75
|
end
|
|
82
76
|
end
|
|
83
77
|
end
|
|
@@ -85,10 +79,13 @@ end
|
|
|
85
79
|
require 'harness/measurement'
|
|
86
80
|
require 'harness/counter'
|
|
87
81
|
require 'harness/gauge'
|
|
82
|
+
require 'harness/meter'
|
|
88
83
|
|
|
89
84
|
require 'harness/instrumentation'
|
|
90
85
|
|
|
91
|
-
require 'harness/
|
|
86
|
+
require 'harness/job'
|
|
87
|
+
|
|
88
|
+
require 'harness/queues/syncronous_queue'
|
|
92
89
|
|
|
93
90
|
require 'harness/adapters/librato_adapter'
|
|
94
91
|
require 'harness/adapters/memory_adapter'
|
|
@@ -101,8 +98,6 @@ require 'harness/integration/active_support'
|
|
|
101
98
|
|
|
102
99
|
require 'harness/railtie' if defined?(Rails)
|
|
103
100
|
|
|
104
|
-
Harness.consumer.consume
|
|
105
|
-
|
|
106
101
|
require 'logger'
|
|
107
102
|
|
|
108
103
|
Harness.logger = Logger.new $stdout
|
|
@@ -57,13 +57,32 @@ class CountersWithRedis < IntegrationTest
|
|
|
57
57
|
|
|
58
58
|
Harness.reset_counters!
|
|
59
59
|
|
|
60
|
-
assert_equal
|
|
61
|
-
assert_equal
|
|
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
|
|
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
|
|
@@ -25,4 +25,26 @@ class ActiveSupportTestCase < IntegrationTest
|
|
|
25
25
|
assert_counter_logged "test-counter"
|
|
26
26
|
assert_gauge_logged "test-gauge"
|
|
27
27
|
end
|
|
28
|
+
|
|
29
|
+
def test_does_not_log_counter_on_exception
|
|
30
|
+
begin
|
|
31
|
+
ActiveSupport::Notifications.instrument "counter_test.harness", :counter => true do |args|
|
|
32
|
+
raise
|
|
33
|
+
end
|
|
34
|
+
rescue
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
refute_counter_logged "counter_test.harness"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def test_does_not_log_gauge_on_exception
|
|
41
|
+
begin
|
|
42
|
+
ActiveSupport::Notifications.instrument "gauge_test.harness", :gauge => true do |args|
|
|
43
|
+
raise
|
|
44
|
+
end
|
|
45
|
+
rescue
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
refute_gauge_logged "gauge_test.harness"
|
|
49
|
+
end
|
|
28
50
|
end
|
|
@@ -13,10 +13,20 @@ class ActionViewIntegration < IntegrationTest
|
|
|
13
13
|
assert_gauge_logged "render_partial.action_view"
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
+
def test_skips_internal_partial_events
|
|
17
|
+
instrument "!render_partial"
|
|
18
|
+
|
|
19
|
+
refute_gauge_logged "!render_partial.action_view"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def test_skips_internal_template_events
|
|
23
|
+
instrument "!render_template"
|
|
24
|
+
|
|
25
|
+
refute_gauge_logged "!render_template.action_view"
|
|
26
|
+
end
|
|
27
|
+
|
|
16
28
|
private
|
|
17
29
|
def instrument(event)
|
|
18
|
-
ActiveSupport::Notifications.instrument "#{event}.action_view"
|
|
19
|
-
# nada
|
|
20
|
-
end
|
|
30
|
+
ActiveSupport::Notifications.instrument "#{event}.action_view"
|
|
21
31
|
end
|
|
22
32
|
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
require 'sidekiq'
|
|
3
|
+
require 'harness/integration/sidekiq'
|
|
4
|
+
|
|
5
|
+
class SidekiqIntegrationTest < IntegrationTest
|
|
6
|
+
def middleware
|
|
7
|
+
Sidekiq::Middleware::Server::HarnessInstrumentation.new
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def tests_logs_job_performance_stats
|
|
11
|
+
middleware.call("report", nil, nil) { }
|
|
12
|
+
|
|
13
|
+
assert_gauge_logged "report.sidekiq"
|
|
14
|
+
assert_counter_logged "reports.sidekiq"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def tests_logs_a_counter_of_all_jobs
|
|
18
|
+
middleware.call("reports", nil, nil) { }
|
|
19
|
+
|
|
20
|
+
assert_counter_logged "job.sidekiq"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def test_ignores_harness_jobs
|
|
24
|
+
middleware.call("Harness::SidekiqQueue::SendCounter", nil, nil) { }
|
|
25
|
+
|
|
26
|
+
assert_empty counters
|
|
27
|
+
assert_empty gauges
|
|
28
|
+
|
|
29
|
+
middleware.call("Harness::SidekiqQueue::SendGauge", nil, nil) { }
|
|
30
|
+
|
|
31
|
+
assert_empty counters
|
|
32
|
+
assert_empty gauges
|
|
33
|
+
|
|
34
|
+
middleware.call(Harness::SidekiqQueue::SendCounter, nil, nil) { }
|
|
35
|
+
|
|
36
|
+
assert_empty counters
|
|
37
|
+
assert_empty gauges
|
|
38
|
+
|
|
39
|
+
middleware.call(Harness::SidekiqQueue::SendGauge, nil, nil) { }
|
|
40
|
+
|
|
41
|
+
assert_empty counters
|
|
42
|
+
assert_empty gauges
|
|
43
|
+
|
|
44
|
+
middleware.call(Harness::SidekiqQueue::SendCounter.new, nil, nil) { }
|
|
45
|
+
|
|
46
|
+
assert_empty counters
|
|
47
|
+
assert_empty gauges
|
|
48
|
+
|
|
49
|
+
middleware.call(Harness::SidekiqQueue::SendGauge.new, nil, nil) { }
|
|
50
|
+
|
|
51
|
+
assert_empty counters
|
|
52
|
+
assert_empty gauges
|
|
53
|
+
end
|
|
54
|
+
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
|
|
@@ -34,6 +35,14 @@ class IntegrationTest < MiniTest::Unit::TestCase
|
|
|
34
35
|
refute_empty counters.select {|c| c.name = name }, "Expected #{counters.inspect} to contain a #{name} result"
|
|
35
36
|
end
|
|
36
37
|
|
|
38
|
+
def refute_gauge_logged(name)
|
|
39
|
+
assert_empty gauges.select {|g| g.name = name }, "No gauge expected to be logged"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def refute_counter_logged(name)
|
|
43
|
+
assert_empty counters.select {|c| c.name = name }, "No counter expected to be logged"
|
|
44
|
+
end
|
|
45
|
+
|
|
37
46
|
def gauges
|
|
38
47
|
Harness::MemoryAdapter.gauges
|
|
39
48
|
end
|
|
@@ -21,13 +21,7 @@ class LibratoAdapterTest < MiniTest::Unit::TestCase
|
|
|
21
21
|
|
|
22
22
|
Harness::LibratoAdapter.config.email = email
|
|
23
23
|
Harness::LibratoAdapter.config.token = token
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def teardown
|
|
27
|
-
WebMock.reset!
|
|
28
|
-
|
|
29
|
-
Harness::LibratoAdapter.config.email = nil
|
|
30
|
-
Harness::LibratoAdapter.config.token = nil
|
|
24
|
+
Harness.config.namespace = nil
|
|
31
25
|
end
|
|
32
26
|
|
|
33
27
|
def test_gauge_is_logged
|
|
@@ -50,12 +44,12 @@ class LibratoAdapterTest < MiniTest::Unit::TestCase
|
|
|
50
44
|
assert_requested expected_request
|
|
51
45
|
end
|
|
52
46
|
|
|
53
|
-
def
|
|
54
|
-
|
|
47
|
+
def test_gauge_is_logged_with_namespace
|
|
48
|
+
Harness.config.namespace = :foo
|
|
55
49
|
|
|
56
50
|
json = {
|
|
57
51
|
:gauges => [{
|
|
58
|
-
:name => "
|
|
52
|
+
:name => "#{@gauge.id}.foo",
|
|
59
53
|
:display_name => @gauge.name,
|
|
60
54
|
:value => @gauge.value,
|
|
61
55
|
:measure_time => @gauge.time.to_i,
|
|
@@ -72,7 +66,6 @@ class LibratoAdapterTest < MiniTest::Unit::TestCase
|
|
|
72
66
|
assert_requested expected_request
|
|
73
67
|
end
|
|
74
68
|
|
|
75
|
-
|
|
76
69
|
def test_logging_gague_raises_an_exception
|
|
77
70
|
stub_request(:post, %r{metrics}).to_return(:status => 500, :body => "message")
|
|
78
71
|
|
|
@@ -118,12 +111,12 @@ class LibratoAdapterTest < MiniTest::Unit::TestCase
|
|
|
118
111
|
assert_requested expected_request
|
|
119
112
|
end
|
|
120
113
|
|
|
121
|
-
def
|
|
122
|
-
|
|
114
|
+
def test_counter_is_logged_with_namespace
|
|
115
|
+
Harness.config.namespace = :foo
|
|
123
116
|
|
|
124
117
|
json = {
|
|
125
118
|
:counters => [{
|
|
126
|
-
:name => "
|
|
119
|
+
:name => "#{@counter.id}.foo",
|
|
127
120
|
:display_name => @counter.name,
|
|
128
121
|
:value => @counter.value,
|
|
129
122
|
:measure_time => @counter.time.to_i,
|
data/test/unit/counter_test.rb
CHANGED
|
@@ -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
|
data/test/unit/gauge_test.rb
CHANGED
|
@@ -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
|
|
data/test/unit/harness_test.rb
CHANGED
|
@@ -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.
|
|
4
|
+
version: 0.2.14
|
|
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-
|
|
12
|
+
date: 2012-05-16 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: activesupport
|
|
16
|
-
requirement: &
|
|
16
|
+
requirement: &70133381445980 !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: *
|
|
24
|
+
version_requirements: *70133381445980
|
|
25
25
|
- !ruby/object:Gem::Dependency
|
|
26
26
|
name: redis
|
|
27
|
-
requirement: &
|
|
27
|
+
requirement: &70133381445320 !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: *
|
|
35
|
+
version_requirements: *70133381445320
|
|
36
36
|
- !ruby/object:Gem::Dependency
|
|
37
37
|
name: redis-namespace
|
|
38
|
-
requirement: &
|
|
38
|
+
requirement: &70133381444680 !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: *
|
|
46
|
+
version_requirements: *70133381444680
|
|
47
47
|
- !ruby/object:Gem::Dependency
|
|
48
48
|
name: simplecov
|
|
49
|
-
requirement: &
|
|
49
|
+
requirement: &70133381443920 !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: *
|
|
57
|
+
version_requirements: *70133381443920
|
|
58
58
|
- !ruby/object:Gem::Dependency
|
|
59
59
|
name: webmock
|
|
60
|
-
requirement: &
|
|
60
|
+
requirement: &70133381443020 !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: *
|
|
68
|
+
version_requirements: *70133381443020
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: resque
|
|
71
|
+
requirement: &70133381441920 !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: *70133381441920
|
|
80
|
+
- !ruby/object:Gem::Dependency
|
|
81
|
+
name: sidekiq
|
|
82
|
+
requirement: &70133381441440 !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: *70133381441440
|
|
69
91
|
description: ''
|
|
70
92
|
email:
|
|
71
93
|
- me@broadcastingadam.com
|
|
@@ -91,7 +113,13 @@ 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/integration/sidekiq.rb
|
|
117
|
+
- lib/harness/job.rb
|
|
94
118
|
- lib/harness/measurement.rb
|
|
119
|
+
- lib/harness/meter.rb
|
|
120
|
+
- lib/harness/queues/resque_queue.rb
|
|
121
|
+
- lib/harness/queues/sidekiq_queue.rb
|
|
122
|
+
- lib/harness/queues/syncronous_queue.rb
|
|
95
123
|
- lib/harness/railtie.rb
|
|
96
124
|
- lib/harness/tasks.rake
|
|
97
125
|
- lib/harness/version.rb
|
|
@@ -101,7 +129,11 @@ files:
|
|
|
101
129
|
- test/integration/integrations/action_mailer_test.rb
|
|
102
130
|
- test/integration/integrations/action_view_test.rb
|
|
103
131
|
- test/integration/integrations/active_support_test.rb
|
|
132
|
+
- test/integration/integrations/sidekiq_test.rb
|
|
104
133
|
- test/integration/logging_test.rb
|
|
134
|
+
- test/integration/meter_test.rb
|
|
135
|
+
- test/integration/queues/resque_test.rb
|
|
136
|
+
- test/integration/queues/sidekiq_test.rb
|
|
105
137
|
- test/test_helper.rb
|
|
106
138
|
- test/unit/adapters/librato_adapter_test.rb
|
|
107
139
|
- test/unit/adapters/memory_adapter_test.rb
|
|
@@ -109,6 +141,7 @@ files:
|
|
|
109
141
|
- test/unit/gauge_test.rb
|
|
110
142
|
- test/unit/harness_test.rb
|
|
111
143
|
- test/unit/measurement_test.rb
|
|
144
|
+
- test/unit/meter_test.rb
|
|
112
145
|
homepage: ''
|
|
113
146
|
licenses: []
|
|
114
147
|
post_install_message:
|
|
@@ -140,7 +173,11 @@ test_files:
|
|
|
140
173
|
- test/integration/integrations/action_mailer_test.rb
|
|
141
174
|
- test/integration/integrations/action_view_test.rb
|
|
142
175
|
- test/integration/integrations/active_support_test.rb
|
|
176
|
+
- test/integration/integrations/sidekiq_test.rb
|
|
143
177
|
- test/integration/logging_test.rb
|
|
178
|
+
- test/integration/meter_test.rb
|
|
179
|
+
- test/integration/queues/resque_test.rb
|
|
180
|
+
- test/integration/queues/sidekiq_test.rb
|
|
144
181
|
- test/test_helper.rb
|
|
145
182
|
- test/unit/adapters/librato_adapter_test.rb
|
|
146
183
|
- test/unit/adapters/memory_adapter_test.rb
|
|
@@ -148,3 +185,4 @@ test_files:
|
|
|
148
185
|
- test/unit/gauge_test.rb
|
|
149
186
|
- test/unit/harness_test.rb
|
|
150
187
|
- test/unit/measurement_test.rb
|
|
188
|
+
- test/unit/meter_test.rb
|