harness 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/README.md +80 -19
- data/harness.gemspec +4 -0
- data/lib/harness.rb +6 -9
- data/lib/harness/adapters/librato_adapter.rb +8 -4
- data/lib/harness/adapters/memory_adapter.rb +10 -2
- data/lib/harness/adapters/null_adapter.rb +2 -2
- data/lib/harness/adapters/stathat_adapter.rb +75 -0
- data/lib/harness/adapters/statsd_adapter.rb +50 -0
- data/lib/harness/gauge.rb +1 -1
- data/lib/harness/queues/delayed_job_queue.rb +7 -0
- data/lib/harness/queues/resque_queue.rb +1 -1
- data/lib/harness/queues/sidekiq_queue.rb +1 -1
- data/lib/harness/queues/{syncronous_queue.rb → synchronous_queue.rb} +7 -2
- data/lib/harness/railtie.rb +12 -12
- data/lib/harness/version.rb +1 -1
- data/test/integration/integrations/active_support_test.rb +1 -0
- data/test/integration/queues/delayed_job_test.rb +59 -0
- data/test/integration/railtie_test.rb +4 -0
- data/test/test_helper.rb +4 -2
- data/test/unit/adapters/librato_adapter_test.rb +2 -2
- data/test/unit/adapters/memory_adapter_test.rb +1 -1
- data/test/unit/adapters/stathat_adapter_test.rb +143 -0
- data/test/unit/adapters/statsd_adapter_test.rb +73 -0
- data/test/unit/gauge_test.rb +10 -0
- data/test/unit/harness_test.rb +9 -9
- metadata +146 -24
- data/test/unit/meter_test.rb +0 -0
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -7,6 +7,8 @@ redis before being sent to the service.
|
|
7
7
|
Currently Supported Services:
|
8
8
|
|
9
9
|
* Librato
|
10
|
+
* Statsd (thanks to fluxlux)
|
11
|
+
* Stathat
|
10
12
|
|
11
13
|
Current Features:
|
12
14
|
|
@@ -45,20 +47,26 @@ end
|
|
45
47
|
|
46
48
|
Add this line to your application's Gemfile:
|
47
49
|
|
48
|
-
|
50
|
+
```
|
51
|
+
gem 'harness'
|
52
|
+
```
|
49
53
|
|
50
54
|
And then execute:
|
51
55
|
|
52
|
-
|
56
|
+
```
|
57
|
+
$ bundle
|
58
|
+
```
|
53
59
|
|
54
60
|
Or install it yourself as:
|
55
61
|
|
56
|
-
|
62
|
+
```
|
63
|
+
$ gem install harness
|
64
|
+
```
|
57
65
|
|
58
66
|
## Usage
|
59
67
|
|
60
68
|
In the metrics world there are two types of things: Gauges and Counters.
|
61
|
-
Gauges are time
|
69
|
+
Gauges are time sensitive and represent something at a specific point in
|
62
70
|
time. Counters keep track of things and should be increasing. Counters
|
63
71
|
can be reset back to zero. You can combine counters and/or gauges to
|
64
72
|
correlate data about your application. Meters monitor counters. They
|
@@ -94,7 +102,14 @@ stored in redis and incremented. This means you can simply pass
|
|
94
102
|
may also pass `:counter => 5` if you'd like to provide your own value.
|
95
103
|
This value is stored in redis so the next time `:counter => true` will
|
96
104
|
work correctly. You can reset all the counters back to zero by calling:
|
97
|
-
`Harness.reset_counters!`.
|
105
|
+
`Harness.reset_counters!`.
|
106
|
+
|
107
|
+
**NOTE**: You should use the bundled rake task to reset counters with
|
108
|
+
a cron job. This will prevent unbounded growth of this metadata. You
|
109
|
+
can call `rake harness:reset_counters` to do this. You should call
|
110
|
+
this rake task at whatever your longest measurable interval is. Here's
|
111
|
+
an example: You log gauges every 12 hours. You should reset the
|
112
|
+
counters every 12 hours. This issue is discussed [here](https://github.com/twinturbo/harness/issues/15).
|
98
113
|
|
99
114
|
```ruby
|
100
115
|
class MyClass
|
@@ -106,14 +121,25 @@ class MyClass
|
|
106
121
|
end
|
107
122
|
```
|
108
123
|
|
109
|
-
The
|
124
|
+
The instruments name will be sent as the name (`important_method.my_class`)
|
110
125
|
for that gauge or counter.
|
111
126
|
|
127
|
+
Note that `ActiveSupport::Notifications.instrument` doesn't require
|
128
|
+
a block. This can be useful when you are taking an instant measurement.
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
class MyClass
|
132
|
+
def important_method(stuff)
|
133
|
+
ActiveSupport::Notifications.instrument "important_method.my_class", :counter => true
|
134
|
+
end
|
135
|
+
end
|
136
|
+
```
|
137
|
+
|
112
138
|
Harness will do all the extra work in sending these metrics to whatever
|
113
139
|
service you're using.
|
114
140
|
|
115
141
|
Once you the counters are you are instrumented, then you can meter them.
|
116
|
-
Meters allow you take
|
142
|
+
Meters allow you take arbitrary readings of counter rates. The results
|
117
143
|
return a gauge so they can be logged as well.
|
118
144
|
|
119
145
|
```ruby
|
@@ -137,13 +163,18 @@ meter.per_hour
|
|
137
163
|
|
138
164
|
## Customizing
|
139
165
|
|
140
|
-
You can
|
166
|
+
You can pass a hash to `:counter` or `:gauge` to initialize the
|
141
167
|
measurement your own way.
|
142
168
|
|
169
|
+
If you pass a value attribute to a gauge, it will be the value
|
170
|
+
sent instead of the duration of the block.
|
171
|
+
|
143
172
|
```ruby
|
144
173
|
class MyClass
|
145
174
|
def important_method(stuff)
|
146
|
-
ActiveSupport::Notifications.instrument "important_method.my_class",
|
175
|
+
ActiveSupport::Notifications.instrument "important_method.my_class",
|
176
|
+
:gauge => { :id => 'custom-id', :name => "My Measurement",
|
177
|
+
:value => my_current_val, :units => 'cogs' } do
|
147
178
|
do_important_stuff
|
148
179
|
end
|
149
180
|
end
|
@@ -152,10 +183,10 @@ end
|
|
152
183
|
|
153
184
|
## One Off Gauges and Counters
|
154
185
|
|
155
|
-
You can instantiate `Harness::Counter` and `Harness::
|
186
|
+
You can instantiate `Harness::Counter` and `Harness::Gauge` wherever you
|
156
187
|
want. Events from `ActiveSupport` are just converted to these classes
|
157
188
|
under the covers anyways. You can use these class if you want to take
|
158
|
-
|
189
|
+
periodic measurements or tracking something that happens outside the
|
159
190
|
application.
|
160
191
|
|
161
192
|
```ruby
|
@@ -174,21 +205,51 @@ counter.time # defaults to Time.now
|
|
174
205
|
counter.value = read_total_users_in_database
|
175
206
|
counter.log
|
176
207
|
|
177
|
-
|
208
|
+
### Both classes take an option hash
|
178
209
|
|
179
|
-
gauge = Harness::
|
210
|
+
gauge = Harness::Gauge.new :time => Time.now, :id => 'foo.bar'
|
180
211
|
counter = Harness::Counter.new :time => Time.now, :id => 'foo.bar'
|
181
212
|
```
|
182
213
|
|
183
214
|
## Configuration
|
184
215
|
|
216
|
+
### Librato
|
185
217
|
```ruby
|
186
218
|
Harness.config.adapter = :librato
|
187
219
|
|
188
220
|
Harness.config.librato.email = 'example@example.com'
|
189
221
|
Harness.config.librato.token = 'your-api-key'
|
190
222
|
|
191
|
-
|
223
|
+
```
|
224
|
+
|
225
|
+
### StatsD
|
226
|
+
|
227
|
+
Harness does **not** configure StatsD for you. It uses the StatsD class
|
228
|
+
under the covers. If you've already configured that in your own way, great.
|
229
|
+
If not, you can use the configuration proxy as described below. You
|
230
|
+
must also add `statsd-instrument` to your `Gemfile`. This is a soft
|
231
|
+
dependency that is not installed for you.
|
232
|
+
|
233
|
+
```ruby
|
234
|
+
Harness.config.adapter = :statsd
|
235
|
+
|
236
|
+
# Harness.config.statsd is a proxy for the StatsD class
|
237
|
+
Harness.config.statsd.host = 'localhost'
|
238
|
+
Harness.config.statsd.port = '8080'
|
239
|
+
Harness.config.statsd.default_sample_rate = 0.1
|
240
|
+
Harness.config.statsd.logger = Rails.logger
|
241
|
+
|
242
|
+
# You can assign your own StatsD implementation
|
243
|
+
# by setting the "backend" attribute
|
244
|
+
Harness.config.statsd.backend = CustomStatsD
|
245
|
+
```
|
246
|
+
|
247
|
+
### Stathat
|
248
|
+
|
249
|
+
```ruby
|
250
|
+
Harness.config.adapter = :stathat
|
251
|
+
|
252
|
+
Harness.config.stathat.ezkey = 'example@example.com'
|
192
253
|
```
|
193
254
|
|
194
255
|
## Rails Integration
|
@@ -209,8 +270,8 @@ You can configure Harness from `application.rb`
|
|
209
270
|
|
210
271
|
```ruby
|
211
272
|
config.harness.adapter = :librato
|
212
|
-
config.librato.email = 'example@example.com'
|
213
|
-
config.librato.token = 'your-api-key'
|
273
|
+
config.harness.librato.email = 'example@example.com'
|
274
|
+
config.harness.librato.token = 'your-api-key'
|
214
275
|
```
|
215
276
|
|
216
277
|
Redis will be automatically configured if you `REDISTOGO_URL` or
|
@@ -225,7 +286,7 @@ require 'erb'
|
|
225
286
|
file = Rails.root.join 'config', 'resque.yml'
|
226
287
|
config = YAML.load(ERB.new(File.read(Rails.root.join('config', 'redis.yml'))).result)
|
227
288
|
|
228
|
-
Harness.redis = Redis.new(:url => config[Rails.env])
|
289
|
+
Harness.redis = Redis::Namespace.new('harness', :redis => Redis.connect(:url => config[Rails.env]))
|
229
290
|
```
|
230
291
|
|
231
292
|
`rake harness:reset_counters` is also added.
|
@@ -239,10 +300,10 @@ logged in production.
|
|
239
300
|
### Background Processing
|
240
301
|
|
241
302
|
Harness integrates automatically with Resque or Sidekiq. This is because
|
242
|
-
reporting measurements can take time and add
|
303
|
+
reporting measurements can take time and add unnecessary overhead to the
|
243
304
|
response time. If neither of these libraries are present, measurements
|
244
305
|
**will be posted in realtime.** You can set your own queue by
|
245
|
-
|
306
|
+
specifying a class like so:
|
246
307
|
|
247
308
|
```ruby
|
248
309
|
Harness.config.queue = MyCustomQueue
|
data/harness.gemspec
CHANGED
@@ -23,6 +23,10 @@ Gem::Specification.new do |gem|
|
|
23
23
|
gem.add_development_dependency "webmock"
|
24
24
|
gem.add_development_dependency "resque"
|
25
25
|
gem.add_development_dependency "sidekiq"
|
26
|
+
gem.add_development_dependency "delayed_job_active_record"
|
26
27
|
gem.add_development_dependency "active_model_serializers"
|
27
28
|
gem.add_development_dependency "rails"
|
29
|
+
gem.add_development_dependency "sqlite3"
|
30
|
+
gem.add_development_dependency "minitest"
|
31
|
+
gem.add_development_dependency "statsd-instrument"
|
28
32
|
end
|
data/lib/harness.rb
CHANGED
@@ -26,7 +26,7 @@ module Harness
|
|
26
26
|
|
27
27
|
def adapter=(val)
|
28
28
|
if val.is_a? Symbol
|
29
|
-
@adapter = "Harness::#{val.to_s.camelize}Adapter".constantize
|
29
|
+
@adapter = "Harness::#{val.to_s.camelize}Adapter".constantize.new
|
30
30
|
else
|
31
31
|
@adapter = val
|
32
32
|
end
|
@@ -34,9 +34,9 @@ module Harness
|
|
34
34
|
|
35
35
|
def queue=(val)
|
36
36
|
if val.is_a? Symbol
|
37
|
-
@queue= "Harness::#{val.to_s.camelize}Queue".constantize
|
37
|
+
@queue = "Harness::#{val.to_s.camelize}Queue".constantize.new
|
38
38
|
else
|
39
|
-
@queue= val
|
39
|
+
@queue = val
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
@@ -90,16 +90,13 @@ require 'harness/instrumentation'
|
|
90
90
|
|
91
91
|
require 'harness/job'
|
92
92
|
|
93
|
-
require 'harness/queues/
|
93
|
+
require 'harness/queues/synchronous_queue'
|
94
94
|
|
95
95
|
require 'harness/adapters/librato_adapter'
|
96
96
|
require 'harness/adapters/memory_adapter'
|
97
97
|
require 'harness/adapters/null_adapter'
|
98
|
-
|
99
|
-
require 'harness/
|
100
|
-
require 'harness/integration/action_view'
|
101
|
-
require 'harness/integration/action_mailer'
|
102
|
-
require 'harness/integration/active_support'
|
98
|
+
require 'harness/adapters/statsd_adapter'
|
99
|
+
require 'harness/adapters/stathat_adapter'
|
103
100
|
|
104
101
|
require 'harness/railtie' if defined?(Rails)
|
105
102
|
|
@@ -12,7 +12,7 @@ module Harness
|
|
12
12
|
@config ||= Config.new
|
13
13
|
end
|
14
14
|
|
15
|
-
def
|
15
|
+
def log_gauge(gauge)
|
16
16
|
raise Harness::LoggingError if gauge.id.length > 63
|
17
17
|
|
18
18
|
post({:gauges => [{
|
@@ -25,7 +25,7 @@ module Harness
|
|
25
25
|
}]})
|
26
26
|
end
|
27
27
|
|
28
|
-
def
|
28
|
+
def log_counter(counter)
|
29
29
|
raise Harness::LoggingError if counter.id.length > 63
|
30
30
|
|
31
31
|
post({:counters => [{
|
@@ -39,7 +39,7 @@ module Harness
|
|
39
39
|
end
|
40
40
|
|
41
41
|
private
|
42
|
-
def
|
42
|
+
def post(params)
|
43
43
|
unless config.email && config.token
|
44
44
|
raise "Adapter not configured. Ensure email and token are set."
|
45
45
|
end
|
@@ -68,7 +68,11 @@ module Harness
|
|
68
68
|
true
|
69
69
|
end
|
70
70
|
|
71
|
-
def
|
71
|
+
def config
|
72
|
+
self.class.config
|
73
|
+
end
|
74
|
+
|
75
|
+
def sanitize(name)
|
72
76
|
if Harness.config.namespace
|
73
77
|
key = "#{name}.#{Harness.config.namespace}"
|
74
78
|
else
|
@@ -8,12 +8,20 @@ module Harness
|
|
8
8
|
@counters ||= []
|
9
9
|
end
|
10
10
|
|
11
|
-
def
|
11
|
+
def log_gauge(gauge)
|
12
12
|
gauges << gauge
|
13
13
|
end
|
14
14
|
|
15
|
-
def
|
15
|
+
def log_counter(counter)
|
16
16
|
counters << counter
|
17
17
|
end
|
18
|
+
|
19
|
+
def counters
|
20
|
+
self.class.counters
|
21
|
+
end
|
22
|
+
|
23
|
+
def gauges
|
24
|
+
self.class.gauges
|
25
|
+
end
|
18
26
|
end
|
19
27
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'net/http'
|
3
|
+
|
4
|
+
module Harness
|
5
|
+
class StathatAdapter
|
6
|
+
class Config
|
7
|
+
attr_accessor :ezkey
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.config
|
11
|
+
@config ||= Config.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def log_gauge(gauge)
|
15
|
+
raise Harness::LoggingError if gauge.id.length > 255
|
16
|
+
|
17
|
+
post({
|
18
|
+
:stat => sanitize(gauge.id),
|
19
|
+
:value => gauge.value,
|
20
|
+
})
|
21
|
+
end
|
22
|
+
|
23
|
+
def log_counter(counter)
|
24
|
+
raise Harness::LoggingError if counter.id.length > 255
|
25
|
+
|
26
|
+
post({
|
27
|
+
:stat => sanitize(counter.id),
|
28
|
+
:count => counter.value,
|
29
|
+
})
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def post(params)
|
35
|
+
unless config.ezkey
|
36
|
+
raise "Adapter not configured. Ensure ezkey is set."
|
37
|
+
end
|
38
|
+
|
39
|
+
uri = URI.parse('https://api.stathat.com/ez')
|
40
|
+
|
41
|
+
Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
|
42
|
+
request = Net::HTTP::Post.new uri.request_uri
|
43
|
+
|
44
|
+
request.set_form_data params.merge(:ezkey => config.ezkey)
|
45
|
+
|
46
|
+
response = http.request request
|
47
|
+
|
48
|
+
unless response.code.to_i == 200
|
49
|
+
text = %Q{
|
50
|
+
Server Said: #{response.body}
|
51
|
+
Sent: #{params.inspect}
|
52
|
+
}
|
53
|
+
|
54
|
+
raise Harness::LoggingError, text
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
true
|
59
|
+
end
|
60
|
+
|
61
|
+
def config
|
62
|
+
self.class.config
|
63
|
+
end
|
64
|
+
|
65
|
+
def sanitize(name)
|
66
|
+
if Harness.config.namespace
|
67
|
+
key = "#{name}.#{Harness.config.namespace}"
|
68
|
+
else
|
69
|
+
key = name
|
70
|
+
end
|
71
|
+
|
72
|
+
key.gsub('/', '.')
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'statsd-instrument'
|
2
|
+
|
3
|
+
module Harness
|
4
|
+
class StatsdAdapter
|
5
|
+
class Config
|
6
|
+
delegate :host, :port, :default_sample_rate, :mode, :logger, :to => :backend
|
7
|
+
delegate :host=, :port=, :default_sample_rate=, :mode=, :logger=, :to => :backend
|
8
|
+
|
9
|
+
def backend=(value)
|
10
|
+
@backend = value
|
11
|
+
end
|
12
|
+
|
13
|
+
def backend
|
14
|
+
@backend ||= StatsD
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.config
|
19
|
+
@config ||= Config.new
|
20
|
+
end
|
21
|
+
|
22
|
+
def log_gauge(gauge)
|
23
|
+
validate!
|
24
|
+
backend.gauge sanitize(gauge.id), gauge.value
|
25
|
+
end
|
26
|
+
|
27
|
+
def log_counter(counter)
|
28
|
+
validate!
|
29
|
+
backend.increment sanitize(counter.id), counter.value
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
def validate!
|
34
|
+
raise "Adapter not configured. Ensure host and port are set." unless config.host and config.port
|
35
|
+
end
|
36
|
+
|
37
|
+
def sanitize(name)
|
38
|
+
key = Harness.config.namespace ? "#{Harness.config.namespace}.#{name}" : name
|
39
|
+
key.gsub(%r{[^a-z0-9]}, '.')
|
40
|
+
end
|
41
|
+
|
42
|
+
def backend
|
43
|
+
config.backend
|
44
|
+
end
|
45
|
+
|
46
|
+
def config
|
47
|
+
self.class.config
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/harness/gauge.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Harness
|
2
|
-
class
|
3
|
-
def
|
2
|
+
class SynchronousQueue
|
3
|
+
def push(measurement)
|
4
4
|
begin
|
5
5
|
Harness::Job.new.log(measurement)
|
6
6
|
rescue LoggingError => ex
|
@@ -9,5 +9,10 @@ module Harness
|
|
9
9
|
logger.warn "[Harness] Could not post measurement! Enable debug logging to see full errors"
|
10
10
|
end
|
11
11
|
end
|
12
|
+
|
13
|
+
private
|
14
|
+
def logger
|
15
|
+
Harness.logger
|
16
|
+
end
|
12
17
|
end
|
13
18
|
end
|
data/lib/harness/railtie.rb
CHANGED
@@ -12,29 +12,26 @@ module Harness
|
|
12
12
|
# Custom instrumentation can be turned on as follows
|
13
13
|
# See files in lib/harness/integration for available integrations
|
14
14
|
#
|
15
|
-
# config.harness.
|
16
|
-
# config.harness.
|
15
|
+
# config.harness.instrument.sidekiq = true
|
16
|
+
# config.harness.instrument.active_model_serializers = true
|
17
17
|
|
18
18
|
rake_tasks do
|
19
19
|
load "harness/tasks.rake"
|
20
20
|
end
|
21
21
|
|
22
22
|
initializer "harness.adapter" do |app|
|
23
|
-
case Rails.env
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
else
|
29
|
-
app.config.harness.adapter = :librato
|
30
|
-
end
|
23
|
+
app.config.harness.adapter ||= case Rails.env
|
24
|
+
when 'development' then :null
|
25
|
+
when 'test' then :null
|
26
|
+
else :librato
|
27
|
+
end
|
31
28
|
end
|
32
29
|
|
33
30
|
initializer "harness.logger" do |app|
|
34
31
|
Harness.logger = Rails.logger
|
35
32
|
end
|
36
33
|
|
37
|
-
initializer "harness.redis" do
|
34
|
+
initializer "harness.redis" do
|
38
35
|
if existing_url = ENV['REDISTOGO_URL'] || ENV['REDIS_URL']
|
39
36
|
Harness.redis ||= Redis::Namespace.new('harness', :redis => Redis.connect(:url => existing_url))
|
40
37
|
else
|
@@ -43,7 +40,7 @@ module Harness
|
|
43
40
|
end
|
44
41
|
|
45
42
|
initializer "harness.queue" do
|
46
|
-
Harness.config.queue =
|
43
|
+
Harness.config.queue = :synchronous
|
47
44
|
end
|
48
45
|
|
49
46
|
initializer "harness.queue.production" do |app|
|
@@ -55,6 +52,9 @@ module Harness
|
|
55
52
|
elsif defined?(Sidekiq::Worker) && use_real_queue
|
56
53
|
require 'harness/queues/sidekiq_queue'
|
57
54
|
Harness.config.queue = :sidekiq
|
55
|
+
elsif defined?(Delayed::Worker) && use_real_queue
|
56
|
+
require 'harness/queues/delayed_job_queue'
|
57
|
+
Harness.config.queue = :delayed_job
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
data/lib/harness/version.rb
CHANGED
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'harness/queues/delayed_job_queue'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
class DelayedJobTest < IntegrationTest
|
6
|
+
def setup
|
7
|
+
super
|
8
|
+
|
9
|
+
tmp = File.expand_path('../../../tmp', __FILE__)
|
10
|
+
db = File.join(tmp, 'db.sqlite3')
|
11
|
+
|
12
|
+
FileUtils.mkdir_p tmp
|
13
|
+
FileUtils.rm_f db
|
14
|
+
|
15
|
+
ActiveRecord::Base.establish_connection(
|
16
|
+
:adapter => "sqlite3",
|
17
|
+
:database => db
|
18
|
+
)
|
19
|
+
|
20
|
+
Class.new(ActiveRecord::Migration) do
|
21
|
+
def self.up
|
22
|
+
suppress_messages do
|
23
|
+
create_table :delayed_jobs, :force => true do |table|
|
24
|
+
table.integer :priority, :default => 0 # Allows some jobs to jump to the front of the queue
|
25
|
+
table.integer :attempts, :default => 0 # Provides for retries, but still fail eventually.
|
26
|
+
table.text :handler # YAML-encoded string of the object that will do work
|
27
|
+
table.text :last_error # reason for last failure (See Note below)
|
28
|
+
table.datetime :run_at # When to run. Could be Time.zone.now for immediately, or sometime in the future.
|
29
|
+
table.datetime :locked_at # Set when a client is working on this object
|
30
|
+
table.datetime :failed_at # Set when all retries have failed (actually, by default, the record is deleted instead)
|
31
|
+
table.string :locked_by # Who is working on this object (if locked)
|
32
|
+
table.string :queue # The name of the queue this job is in
|
33
|
+
table.timestamps
|
34
|
+
end
|
35
|
+
|
36
|
+
add_index :delayed_jobs, [:priority, :run_at], :name => 'delayed_jobs_priority'
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end.up
|
40
|
+
|
41
|
+
Delayed::Worker.delay_jobs = false
|
42
|
+
|
43
|
+
Harness.config.queue = :delayed_job
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_a_gauge_is_logged
|
47
|
+
instrument "test-gauge", :gauge => true
|
48
|
+
|
49
|
+
assert_gauge_logged "test-gauge"
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_a_counter_is_logged
|
53
|
+
instrument "test-counter", :counter => true
|
54
|
+
|
55
|
+
assert_counter_logged "test-counter"
|
56
|
+
|
57
|
+
assert_equal 1, counters.first.value
|
58
|
+
end
|
59
|
+
end
|
@@ -19,4 +19,8 @@ class RailtieTest < MiniTest::Unit::TestCase
|
|
19
19
|
assert app.config.harness.instrument.action_view
|
20
20
|
refute app.config.harness.instrument.active_support
|
21
21
|
end
|
22
|
+
|
23
|
+
def test_configures_queue
|
24
|
+
assert_kind_of Harness::SynchronousQueue, app.config.harness.queue
|
25
|
+
end
|
22
26
|
end
|
data/test/test_helper.rb
CHANGED
@@ -5,6 +5,8 @@ SimpleCov.start
|
|
5
5
|
|
6
6
|
require 'resque'
|
7
7
|
require 'sidekiq'
|
8
|
+
require 'delayed_job_active_record'
|
9
|
+
require 'sqlite3'
|
8
10
|
|
9
11
|
require 'harness'
|
10
12
|
|
@@ -23,7 +25,7 @@ Harness.redis = Redis::Namespace.new 'harness-test', :redis => Redis.connect(:ho
|
|
23
25
|
class IntegrationTest < MiniTest::Unit::TestCase
|
24
26
|
def setup
|
25
27
|
Harness.config.adapter = :memory
|
26
|
-
Harness.config.queue = :
|
28
|
+
Harness.config.queue = :synchronous
|
27
29
|
|
28
30
|
gauges.clear ; counters.clear
|
29
31
|
redis.flushall
|
@@ -58,7 +60,7 @@ class IntegrationTest < MiniTest::Unit::TestCase
|
|
58
60
|
end
|
59
61
|
|
60
62
|
def instrument(name, data = {})
|
61
|
-
ActiveSupport::Notifications.instrument name, data do
|
63
|
+
ActiveSupport::Notifications.instrument name, data do
|
62
64
|
# nothing
|
63
65
|
end
|
64
66
|
end
|
@@ -2,7 +2,7 @@ require 'test_helper'
|
|
2
2
|
|
3
3
|
class LibratoAdapterTest < MiniTest::Unit::TestCase
|
4
4
|
def setup
|
5
|
-
@adapter = Harness::LibratoAdapter
|
5
|
+
@adapter = Harness::LibratoAdapter.new
|
6
6
|
|
7
7
|
@gauge = Harness::Gauge.new
|
8
8
|
@gauge.id = "fake-gauge"
|
@@ -66,7 +66,7 @@ class LibratoAdapterTest < MiniTest::Unit::TestCase
|
|
66
66
|
assert_requested expected_request
|
67
67
|
end
|
68
68
|
|
69
|
-
def
|
69
|
+
def test_logging_gauge_raises_an_exception
|
70
70
|
stub_request(:post, %r{metrics}).to_return(:status => 500, :body => "message")
|
71
71
|
|
72
72
|
assert_raises Harness::LoggingError do
|
@@ -0,0 +1,143 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class StathatAdapterTest < MiniTest::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@adapter = Harness::StathatAdapter.new
|
6
|
+
|
7
|
+
@gauge = Harness::Gauge.new
|
8
|
+
@gauge.id = "fake-gauge"
|
9
|
+
@gauge.name = "Fake Gauge"
|
10
|
+
@gauge.source = "minitest"
|
11
|
+
@gauge.time = Time.now
|
12
|
+
@gauge.value = "55"
|
13
|
+
|
14
|
+
@counter = Harness::Counter.new
|
15
|
+
@counter.id = "fake-counter"
|
16
|
+
@counter.name = "Fake Counter"
|
17
|
+
@counter.source = "minitest"
|
18
|
+
@counter.time = Time.now
|
19
|
+
@counter.value = "55"
|
20
|
+
@counter.units = :bytes
|
21
|
+
|
22
|
+
Harness::StathatAdapter.config.ezkey = token
|
23
|
+
Harness.config.namespace = nil
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_gauge_is_logged
|
27
|
+
args = {
|
28
|
+
:stat => @gauge.id,
|
29
|
+
:ezkey => token,
|
30
|
+
:value => @gauge.value,
|
31
|
+
}
|
32
|
+
|
33
|
+
expected_request = stub_request(:post, "https://api.stathat.com/ez").
|
34
|
+
with(:body => args, :headers => {'Content-Type'=>'application/x-www-form-urlencoded'}).
|
35
|
+
to_return(:status => 200)
|
36
|
+
|
37
|
+
assert @adapter.log_gauge(@gauge)
|
38
|
+
assert_requested expected_request
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_gauge_is_logged_with_namespace
|
42
|
+
Harness.config.namespace = :foo
|
43
|
+
|
44
|
+
args = {
|
45
|
+
:stat => "#{@gauge.id}.foo",
|
46
|
+
:ezkey => token,
|
47
|
+
:value => @gauge.value,
|
48
|
+
}
|
49
|
+
|
50
|
+
expected_request = stub_request(:post, "https://api.stathat.com/ez").
|
51
|
+
with(:body => args, :headers => {'Content-Type'=>'application/x-www-form-urlencoded'}).
|
52
|
+
to_return(:status => 200)
|
53
|
+
|
54
|
+
assert @adapter.log_gauge(@gauge)
|
55
|
+
assert_requested expected_request
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_logging_gauge_raises_an_exception
|
59
|
+
stub_request(:post, %r{stathat}).to_return(:status => 500, :body => "message")
|
60
|
+
|
61
|
+
assert_raises Harness::LoggingError do
|
62
|
+
@adapter.log_gauge @gauge
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_logging_gauge_raises_an_exception_when_id_is_too_long
|
67
|
+
@gauge.id = "f" * 256
|
68
|
+
|
69
|
+
assert_raises Harness::LoggingError do
|
70
|
+
@adapter.log_gauge @gauge
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_logging_gauge_raises_an_exception_when_not_configured
|
75
|
+
Harness::StathatAdapter.config.ezkey = nil
|
76
|
+
|
77
|
+
assert_raises RuntimeError do
|
78
|
+
@adapter.log_gauge @gauge
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_counter_is_logged
|
83
|
+
args = {
|
84
|
+
:stat => @counter.id,
|
85
|
+
:ezkey => token,
|
86
|
+
:count => @counter.value,
|
87
|
+
}
|
88
|
+
|
89
|
+
expected_request = stub_request(:post, "https://api.stathat.com/ez").
|
90
|
+
with(:body => args, :headers => {'Content-Type'=>'application/x-www-form-urlencoded'}).
|
91
|
+
to_return(:status => 200)
|
92
|
+
|
93
|
+
assert @adapter.log_counter(@counter)
|
94
|
+
assert_requested expected_request
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_counter_is_logged_with_namespace
|
98
|
+
Harness.config.namespace = :foo
|
99
|
+
|
100
|
+
args = {
|
101
|
+
:stat => "#{@counter.id}.foo",
|
102
|
+
:ezkey => token,
|
103
|
+
:count => @counter.value,
|
104
|
+
}
|
105
|
+
|
106
|
+
expected_request = stub_request(:post, "https://api.stathat.com/ez").
|
107
|
+
with(:body => args, :headers => {'Content-Type'=>'application/x-www-form-urlencoded'}).
|
108
|
+
to_return(:status => 200)
|
109
|
+
|
110
|
+
assert @adapter.log_counter(@counter)
|
111
|
+
assert_requested expected_request
|
112
|
+
end
|
113
|
+
|
114
|
+
def test_logging_counter_raises_an_exception
|
115
|
+
stub_request(:post, %r{stathat}).to_return(:status => 500, :body => "message")
|
116
|
+
|
117
|
+
assert_raises Harness::LoggingError do
|
118
|
+
@adapter.log_counter @counter
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def test_logging_counter_raises_an_exception_when_not_configured
|
123
|
+
Harness::StathatAdapter.config.ezkey = nil
|
124
|
+
|
125
|
+
assert_raises RuntimeError do
|
126
|
+
@adapter.log_counter @counter
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_logging_counter_raises_an_exception_when_id_is_too_long
|
131
|
+
@counter.id = "f" * 256
|
132
|
+
|
133
|
+
assert_raises Harness::LoggingError do
|
134
|
+
@adapter.log_counter @counter
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
private
|
139
|
+
|
140
|
+
def token
|
141
|
+
'example@example.com'
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
class StatsdAdapterTest < MiniTest::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
@adapter = Harness::StatsdAdapter.new
|
7
|
+
|
8
|
+
@gauge = Harness::Gauge.new
|
9
|
+
@gauge.id = "fake-gauge"
|
10
|
+
@gauge.name = "Fake Gauge"
|
11
|
+
@gauge.source = "minitest"
|
12
|
+
@gauge.time = Time.now
|
13
|
+
@gauge.value = 55
|
14
|
+
|
15
|
+
@counter = Harness::Counter.new
|
16
|
+
@counter.id = "fake-counter"
|
17
|
+
@counter.name = "Fake Counter"
|
18
|
+
@counter.source = "minitest"
|
19
|
+
@counter.time = Time.now
|
20
|
+
@counter.value = 1337
|
21
|
+
@counter.units = :bytes
|
22
|
+
Harness.config.namespace = nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_gauge_is_logged
|
26
|
+
mock_backend = MiniTest::Mock.new
|
27
|
+
mock_backend.expect :host, 'foo'
|
28
|
+
mock_backend.expect :port, 'bar'
|
29
|
+
|
30
|
+
Harness::StatsdAdapter.config.backend = mock_backend
|
31
|
+
mock_backend.expect :gauge, true, [String, 55]
|
32
|
+
|
33
|
+
assert @adapter.log_gauge(@gauge)
|
34
|
+
assert mock_backend.verify
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_logging_gauge_raises_an_exception_when_not_configured
|
38
|
+
mock_backend = MiniTest::Mock.new
|
39
|
+
mock_backend.expect :host, nil
|
40
|
+
mock_backend.expect :port, nil
|
41
|
+
|
42
|
+
Harness::StatsdAdapter.config.backend = mock_backend
|
43
|
+
mock_backend.expect :gauge, true, [String, 55]
|
44
|
+
|
45
|
+
assert_raises RuntimeError do
|
46
|
+
@adapter.log_gauge @gauge
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_counter_is_logged
|
51
|
+
mock_backend = MiniTest::Mock.new
|
52
|
+
mock_backend.expect :host, 'foo'
|
53
|
+
mock_backend.expect :port, 'bar'
|
54
|
+
|
55
|
+
Harness::StatsdAdapter.config.backend = mock_backend
|
56
|
+
mock_backend.expect :increment, true, [String, 1337]
|
57
|
+
|
58
|
+
assert @adapter.log_counter(@counter)
|
59
|
+
assert mock_backend.verify
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_logging_counter_raises_an_exception_when_not_configured
|
63
|
+
mock_backend = MiniTest::Mock.new
|
64
|
+
mock_backend.expect :host, nil
|
65
|
+
mock_backend.expect :port, nil
|
66
|
+
|
67
|
+
Harness::StatsdAdapter.config.backend = mock_backend
|
68
|
+
|
69
|
+
assert_raises RuntimeError do
|
70
|
+
@adapter.log_counter @counter
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/test/unit/gauge_test.rb
CHANGED
@@ -65,6 +65,16 @@ class GaugeTest < MiniTest::Unit::TestCase
|
|
65
65
|
assert_equal 'foo', gauge.id
|
66
66
|
end
|
67
67
|
|
68
|
+
def test_sets_value_from_payload_if_number
|
69
|
+
base = Time.now
|
70
|
+
|
71
|
+
event = ActiveSupport::Notifications::Event.new "name", base - 1, Time.now, nil, :gauge => {value: 42}
|
72
|
+
|
73
|
+
gauge = Harness::Gauge.from_event event
|
74
|
+
|
75
|
+
assert_equal 42, gauge.value
|
76
|
+
end
|
77
|
+
|
68
78
|
def test_initializes_time_if_not_set
|
69
79
|
gauge = Harness::Gauge.new
|
70
80
|
|
data/test/unit/harness_test.rb
CHANGED
@@ -4,25 +4,25 @@ class HarnessModuleTest < MiniTest::Unit::TestCase
|
|
4
4
|
def test_can_set_the_adapter_with_a_symbol
|
5
5
|
Harness.config.adapter = :memory
|
6
6
|
|
7
|
-
|
7
|
+
assert_kind_of Harness::MemoryAdapter, Harness.config.adapter
|
8
8
|
end
|
9
9
|
|
10
|
-
def
|
11
|
-
Harness.config.adapter = Harness::MemoryAdapter
|
10
|
+
def test_can_set_the_adapter_with_an_adapter_instance
|
11
|
+
Harness.config.adapter = Harness::MemoryAdapter.new
|
12
12
|
|
13
|
-
|
13
|
+
assert_kind_of Harness::MemoryAdapter, Harness.config.adapter
|
14
14
|
end
|
15
15
|
|
16
16
|
def test_can_set_the_queue_with_a_symbol
|
17
|
-
Harness.config.queue = :
|
17
|
+
Harness.config.queue = :synchronous
|
18
18
|
|
19
|
-
|
19
|
+
assert_kind_of Harness::SynchronousQueue, Harness.config.queue
|
20
20
|
end
|
21
21
|
|
22
|
-
def
|
23
|
-
Harness.config.
|
22
|
+
def test_can_set_the_queue_with_a_queue_instance
|
23
|
+
Harness.config.queue = Harness::SynchronousQueue.new
|
24
24
|
|
25
|
-
|
25
|
+
assert_kind_of Harness::SynchronousQueue, Harness.config.queue
|
26
26
|
end
|
27
27
|
|
28
28
|
def test_uses_method_missing_to_configure_adapters
|
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.4.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-
|
12
|
+
date: 2012-11-20 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,15 @@ dependencies:
|
|
21
21
|
version: '3'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '3'
|
25
30
|
- !ruby/object:Gem::Dependency
|
26
31
|
name: redis
|
27
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
28
33
|
none: false
|
29
34
|
requirements:
|
30
35
|
- - ! '>='
|
@@ -32,10 +37,15 @@ dependencies:
|
|
32
37
|
version: '0'
|
33
38
|
type: :runtime
|
34
39
|
prerelease: false
|
35
|
-
version_requirements:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
36
46
|
- !ruby/object:Gem::Dependency
|
37
47
|
name: redis-namespace
|
38
|
-
requirement:
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
39
49
|
none: false
|
40
50
|
requirements:
|
41
51
|
- - ! '>='
|
@@ -43,10 +53,15 @@ dependencies:
|
|
43
53
|
version: '0'
|
44
54
|
type: :runtime
|
45
55
|
prerelease: false
|
46
|
-
version_requirements:
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
47
62
|
- !ruby/object:Gem::Dependency
|
48
63
|
name: simplecov
|
49
|
-
requirement:
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
50
65
|
none: false
|
51
66
|
requirements:
|
52
67
|
- - ! '>='
|
@@ -54,10 +69,15 @@ dependencies:
|
|
54
69
|
version: '0'
|
55
70
|
type: :development
|
56
71
|
prerelease: false
|
57
|
-
version_requirements:
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
58
78
|
- !ruby/object:Gem::Dependency
|
59
79
|
name: webmock
|
60
|
-
requirement:
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
61
81
|
none: false
|
62
82
|
requirements:
|
63
83
|
- - ! '>='
|
@@ -65,10 +85,15 @@ dependencies:
|
|
65
85
|
version: '0'
|
66
86
|
type: :development
|
67
87
|
prerelease: false
|
68
|
-
version_requirements:
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
69
94
|
- !ruby/object:Gem::Dependency
|
70
95
|
name: resque
|
71
|
-
requirement:
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
72
97
|
none: false
|
73
98
|
requirements:
|
74
99
|
- - ! '>='
|
@@ -76,10 +101,31 @@ dependencies:
|
|
76
101
|
version: '0'
|
77
102
|
type: :development
|
78
103
|
prerelease: false
|
79
|
-
version_requirements:
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
80
110
|
- !ruby/object:Gem::Dependency
|
81
111
|
name: sidekiq
|
82
|
-
requirement:
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: delayed_job_active_record
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
83
129
|
none: false
|
84
130
|
requirements:
|
85
131
|
- - ! '>='
|
@@ -87,10 +133,15 @@ dependencies:
|
|
87
133
|
version: '0'
|
88
134
|
type: :development
|
89
135
|
prerelease: false
|
90
|
-
version_requirements:
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ! '>='
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
91
142
|
- !ruby/object:Gem::Dependency
|
92
143
|
name: active_model_serializers
|
93
|
-
requirement:
|
144
|
+
requirement: !ruby/object:Gem::Requirement
|
94
145
|
none: false
|
95
146
|
requirements:
|
96
147
|
- - ! '>='
|
@@ -98,10 +149,63 @@ dependencies:
|
|
98
149
|
version: '0'
|
99
150
|
type: :development
|
100
151
|
prerelease: false
|
101
|
-
version_requirements:
|
152
|
+
version_requirements: !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
154
|
+
requirements:
|
155
|
+
- - ! '>='
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '0'
|
102
158
|
- !ruby/object:Gem::Dependency
|
103
159
|
name: rails
|
104
|
-
requirement:
|
160
|
+
requirement: !ruby/object:Gem::Requirement
|
161
|
+
none: false
|
162
|
+
requirements:
|
163
|
+
- - ! '>='
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '0'
|
166
|
+
type: :development
|
167
|
+
prerelease: false
|
168
|
+
version_requirements: !ruby/object:Gem::Requirement
|
169
|
+
none: false
|
170
|
+
requirements:
|
171
|
+
- - ! '>='
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
- !ruby/object:Gem::Dependency
|
175
|
+
name: sqlite3
|
176
|
+
requirement: !ruby/object:Gem::Requirement
|
177
|
+
none: false
|
178
|
+
requirements:
|
179
|
+
- - ! '>='
|
180
|
+
- !ruby/object:Gem::Version
|
181
|
+
version: '0'
|
182
|
+
type: :development
|
183
|
+
prerelease: false
|
184
|
+
version_requirements: !ruby/object:Gem::Requirement
|
185
|
+
none: false
|
186
|
+
requirements:
|
187
|
+
- - ! '>='
|
188
|
+
- !ruby/object:Gem::Version
|
189
|
+
version: '0'
|
190
|
+
- !ruby/object:Gem::Dependency
|
191
|
+
name: minitest
|
192
|
+
requirement: !ruby/object:Gem::Requirement
|
193
|
+
none: false
|
194
|
+
requirements:
|
195
|
+
- - ! '>='
|
196
|
+
- !ruby/object:Gem::Version
|
197
|
+
version: '0'
|
198
|
+
type: :development
|
199
|
+
prerelease: false
|
200
|
+
version_requirements: !ruby/object:Gem::Requirement
|
201
|
+
none: false
|
202
|
+
requirements:
|
203
|
+
- - ! '>='
|
204
|
+
- !ruby/object:Gem::Version
|
205
|
+
version: '0'
|
206
|
+
- !ruby/object:Gem::Dependency
|
207
|
+
name: statsd-instrument
|
208
|
+
requirement: !ruby/object:Gem::Requirement
|
105
209
|
none: false
|
106
210
|
requirements:
|
107
211
|
- - ! '>='
|
@@ -109,7 +213,12 @@ dependencies:
|
|
109
213
|
version: '0'
|
110
214
|
type: :development
|
111
215
|
prerelease: false
|
112
|
-
version_requirements:
|
216
|
+
version_requirements: !ruby/object:Gem::Requirement
|
217
|
+
none: false
|
218
|
+
requirements:
|
219
|
+
- - ! '>='
|
220
|
+
- !ruby/object:Gem::Version
|
221
|
+
version: '0'
|
113
222
|
description: ''
|
114
223
|
email:
|
115
224
|
- me@broadcastingadam.com
|
@@ -127,6 +236,8 @@ files:
|
|
127
236
|
- lib/harness/adapters/librato_adapter.rb
|
128
237
|
- lib/harness/adapters/memory_adapter.rb
|
129
238
|
- lib/harness/adapters/null_adapter.rb
|
239
|
+
- lib/harness/adapters/stathat_adapter.rb
|
240
|
+
- lib/harness/adapters/statsd_adapter.rb
|
130
241
|
- lib/harness/consumer.rb
|
131
242
|
- lib/harness/counter.rb
|
132
243
|
- lib/harness/gauge.rb
|
@@ -140,9 +251,10 @@ files:
|
|
140
251
|
- lib/harness/job.rb
|
141
252
|
- lib/harness/measurement.rb
|
142
253
|
- lib/harness/meter.rb
|
254
|
+
- lib/harness/queues/delayed_job_queue.rb
|
143
255
|
- lib/harness/queues/resque_queue.rb
|
144
256
|
- lib/harness/queues/sidekiq_queue.rb
|
145
|
-
- lib/harness/queues/
|
257
|
+
- lib/harness/queues/synchronous_queue.rb
|
146
258
|
- lib/harness/railtie.rb
|
147
259
|
- lib/harness/tasks.rake
|
148
260
|
- lib/harness/version.rb
|
@@ -156,17 +268,19 @@ files:
|
|
156
268
|
- test/integration/integrations/sidekiq_test.rb
|
157
269
|
- test/integration/logging_test.rb
|
158
270
|
- test/integration/meter_test.rb
|
271
|
+
- test/integration/queues/delayed_job_test.rb
|
159
272
|
- test/integration/queues/resque_test.rb
|
160
273
|
- test/integration/queues/sidekiq_test.rb
|
161
274
|
- test/integration/railtie_test.rb
|
162
275
|
- test/test_helper.rb
|
163
276
|
- test/unit/adapters/librato_adapter_test.rb
|
164
277
|
- test/unit/adapters/memory_adapter_test.rb
|
278
|
+
- test/unit/adapters/stathat_adapter_test.rb
|
279
|
+
- test/unit/adapters/statsd_adapter_test.rb
|
165
280
|
- test/unit/counter_test.rb
|
166
281
|
- test/unit/gauge_test.rb
|
167
282
|
- test/unit/harness_test.rb
|
168
283
|
- test/unit/measurement_test.rb
|
169
|
-
- test/unit/meter_test.rb
|
170
284
|
homepage: ''
|
171
285
|
licenses: []
|
172
286
|
post_install_message:
|
@@ -179,15 +293,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
179
293
|
- - ! '>='
|
180
294
|
- !ruby/object:Gem::Version
|
181
295
|
version: '0'
|
296
|
+
segments:
|
297
|
+
- 0
|
298
|
+
hash: -4565454551887677115
|
182
299
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
183
300
|
none: false
|
184
301
|
requirements:
|
185
302
|
- - ! '>='
|
186
303
|
- !ruby/object:Gem::Version
|
187
304
|
version: '0'
|
305
|
+
segments:
|
306
|
+
- 0
|
307
|
+
hash: -4565454551887677115
|
188
308
|
requirements: []
|
189
309
|
rubyforge_project:
|
190
|
-
rubygems_version: 1.8.
|
310
|
+
rubygems_version: 1.8.24
|
191
311
|
signing_key:
|
192
312
|
specification_version: 3
|
193
313
|
summary: ''
|
@@ -202,14 +322,16 @@ test_files:
|
|
202
322
|
- test/integration/integrations/sidekiq_test.rb
|
203
323
|
- test/integration/logging_test.rb
|
204
324
|
- test/integration/meter_test.rb
|
325
|
+
- test/integration/queues/delayed_job_test.rb
|
205
326
|
- test/integration/queues/resque_test.rb
|
206
327
|
- test/integration/queues/sidekiq_test.rb
|
207
328
|
- test/integration/railtie_test.rb
|
208
329
|
- test/test_helper.rb
|
209
330
|
- test/unit/adapters/librato_adapter_test.rb
|
210
331
|
- test/unit/adapters/memory_adapter_test.rb
|
332
|
+
- test/unit/adapters/stathat_adapter_test.rb
|
333
|
+
- test/unit/adapters/statsd_adapter_test.rb
|
211
334
|
- test/unit/counter_test.rb
|
212
335
|
- test/unit/gauge_test.rb
|
213
336
|
- test/unit/harness_test.rb
|
214
337
|
- test/unit/measurement_test.rb
|
215
|
-
- test/unit/meter_test.rb
|
data/test/unit/meter_test.rb
DELETED
File without changes
|