harness 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +152 -2
- data/Rakefile +8 -0
- data/harness.gemspec +7 -0
- data/lib/harness/adapters/librato_adapter.rb +68 -0
- data/lib/harness/adapters/memory_adapter.rb +19 -0
- data/lib/harness/adapters/null_adapter.rb +11 -0
- data/lib/harness/consumer.rb +47 -0
- data/lib/harness/counter.rb +27 -0
- data/lib/harness/gauge.rb +21 -0
- data/lib/harness/instrumentation.rb +6 -0
- data/lib/harness/integration/action_controller.rb +9 -0
- data/lib/harness/integration/action_mailer.rb +10 -0
- data/lib/harness/integration/action_view.rb +10 -0
- data/lib/harness/integration/active_support.rb +9 -0
- data/lib/harness/measurement.rb +17 -0
- data/lib/harness/railtie.rb +36 -0
- data/lib/harness/tasks.rake +6 -0
- data/lib/harness/version.rb +1 -1
- data/lib/harness.rb +104 -1
- data/test/integration/counters_with_redis_test.rb +69 -0
- data/test/integration/instrumentation_test.rb +28 -0
- data/test/integration/integrations/action_controller_test.rb +51 -0
- data/test/integration/integrations/action_mailer_test.rb +22 -0
- data/test/integration/integrations/action_view_test.rb +22 -0
- data/test/integration/integrations/active_support_test.rb +40 -0
- data/test/integration/logging_test.rb +17 -0
- data/test/test_helper.rb +54 -0
- data/test/unit/adapters/librato_adapter_test.rb +176 -0
- data/test/unit/adapters/memory_adapter_test.rb +22 -0
- data/test/unit/counter_test.rb +55 -0
- data/test/unit/gauge_test.rb +53 -0
- data/test/unit/harness_test.rb +27 -0
- data/test/unit/measurement_test.rb +36 -0
- metadata +101 -10
data/README.md
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
# Harness
|
2
2
|
|
3
|
-
|
3
|
+
Harness connects measurements coming from `ActiveSupport::Notifications`
|
4
|
+
to external metric tracking services. Counters are stored locally with
|
5
|
+
redis before being sent to the service.
|
6
|
+
|
7
|
+
Currently Supported Services:
|
8
|
+
|
9
|
+
* Librato
|
4
10
|
|
5
11
|
## Installation
|
6
12
|
|
@@ -18,7 +24,151 @@ Or install it yourself as:
|
|
18
24
|
|
19
25
|
## Usage
|
20
26
|
|
21
|
-
|
27
|
+
In the metrics world there are two types of things: Gauges and Counters.
|
28
|
+
Gauges are time senstive and represent something at a specific point in
|
29
|
+
time. Counters keep track of things and should be increasing. Counters
|
30
|
+
can be reset back to zero. You can combine counters and/or gauges to
|
31
|
+
correlate data about your application.
|
32
|
+
|
33
|
+
Harness makes this process easily. Harness' primary goal it make it dead
|
34
|
+
simple to start measuring different parts of your application.
|
35
|
+
`ActiveSupport::Notifications` makes this very easy because it provides
|
36
|
+
measurements and implements the observer pattern.
|
37
|
+
|
38
|
+
## Tracking Things
|
39
|
+
|
40
|
+
I guess you read the `ActiveSupport::Notifications`
|
41
|
+
[documentation](http://api.rubyonrails.org/classes/ActiveSupport/Notifications.html)
|
42
|
+
before going any further or this will seems like php to you. Harness
|
43
|
+
hooks into your notifications and looks for `:gauge` or `:counter`
|
44
|
+
options. If either is present, it will be sent to the external service.
|
45
|
+
For example, you can track how long it's taking to do a specific thing:
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
class MyClass
|
49
|
+
def important_method(stuff)
|
50
|
+
ActiveSupport::Notifications.instrument "important_method.my_class", :gauge => true do
|
51
|
+
do_important_stuff
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
```
|
56
|
+
|
57
|
+
You can do the same with a counter. Counter values are automatically
|
58
|
+
stored in redis and incremented. This means you can simply pass
|
59
|
+
`:counter => true` in instrumentations if you'd like to count it. You
|
60
|
+
may also pass `:counter => 5` if you'd like to provide your own value.
|
61
|
+
This value is stored in redis so the next time `:counter => true` will
|
62
|
+
work correctly. You can reset all the counters back to zero by calling:
|
63
|
+
`Harness.reset_counters!`.
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
class MyClass
|
67
|
+
def important_method(stuff)
|
68
|
+
ActiveSupport::Notifications.instrument "important_method.my_class", :counter => true do
|
69
|
+
do_important_stuff
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
```
|
74
|
+
|
75
|
+
The instuments name will be sent as the name (`important_method.my_class`)
|
76
|
+
for that gauge or counter.
|
77
|
+
|
78
|
+
Harness will do all the extra work in sending these metrics to whatever
|
79
|
+
service you're using.
|
80
|
+
|
81
|
+
## Customzing
|
82
|
+
|
83
|
+
You can pash a hash to `:counter` or `:gauge` to initialize the
|
84
|
+
measurement your own way.
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
class MyClass
|
88
|
+
def important_method(stuff)
|
89
|
+
ActiveSupport::Notifications.instrument "important_method.my_class", :gauge => { :id => 'custom-id', :name => "My Measurement" } do
|
90
|
+
do_important_stuff
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
```
|
95
|
+
|
96
|
+
## One Off Gauges and Counters
|
97
|
+
|
98
|
+
You can instantiate `Harness::Counter` and `Harness::Guage` wherever you
|
99
|
+
want. Events from `ActiveSupport` are just converted to these classes
|
100
|
+
under the covers anyways. You can use these class if you want to take
|
101
|
+
peridocial measurements or tracking something that happens outside the
|
102
|
+
application.
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
gauge = Harness::Gauge.new
|
106
|
+
gauge.id = "foo.bar"
|
107
|
+
gauge.name = "Foo's Bar"
|
108
|
+
gauge.time # defaults to Time.now
|
109
|
+
gauge.value = readings_from_my_server
|
110
|
+
gauge.units = 'bytes'
|
111
|
+
gauge.log
|
112
|
+
|
113
|
+
counter = Harness::Counter.new
|
114
|
+
counter.id = "foo.bar"
|
115
|
+
counter.name = "# of Foo bars"
|
116
|
+
counter.time # defaults to Time.now
|
117
|
+
counter.value = read_total_users_in_database
|
118
|
+
counter.log
|
119
|
+
|
120
|
+
# Both class take an option hash
|
121
|
+
|
122
|
+
gauge = Harness::Guage.new :time => Time.now, :id => 'foo.bar'
|
123
|
+
counter = Harness::Counter.new :time => Time.now, :id => 'foo.bar'
|
124
|
+
```
|
125
|
+
|
126
|
+
## Configuration
|
127
|
+
|
128
|
+
```ruby
|
129
|
+
Harness.config.adapter = :librato
|
130
|
+
|
131
|
+
Harness.config.librato.email = 'example@example.com'
|
132
|
+
Harness.config.librato.token = 'your-api-key'
|
133
|
+
|
134
|
+
Harness.redis = Redis.new
|
135
|
+
```
|
136
|
+
|
137
|
+
## Rails Integration
|
138
|
+
|
139
|
+
Harness will automatically log metrics coming from `ActionPack`,
|
140
|
+
`ActiveRecord`, `ActiveSupport` and `ActionMailer`.
|
141
|
+
|
142
|
+
You can configure Harness from `application.rb`
|
143
|
+
|
144
|
+
```ruby
|
145
|
+
config.harness.adapter = :librato
|
146
|
+
config.librato.email = 'example@example.com'
|
147
|
+
config.librato.token = 'your-api-key'
|
148
|
+
```
|
149
|
+
|
150
|
+
Redis will be automatically configured if you `REDISTOGO_URL` or
|
151
|
+
`REDIS_URL` environment variables at set. They are wrapped in a
|
152
|
+
namespace so there will be no conflicts. If they are not present, the
|
153
|
+
default values are used. You can customize this in an initializer:
|
154
|
+
|
155
|
+
```ruby
|
156
|
+
# config/initializers/harness.rb
|
157
|
+
require 'erb'
|
158
|
+
|
159
|
+
file = Rails.root.join 'config', 'resque.yml'
|
160
|
+
config = YAML.load(ERB.new(File.read(Rails.root.join('config', 'resque.yml'))).result)
|
161
|
+
|
162
|
+
Harness.redis = Redis.new(:url => config[Rails.env])
|
163
|
+
```
|
164
|
+
|
165
|
+
`rake harness:reset_counters` is also added.
|
166
|
+
|
167
|
+
### Rails Environments
|
168
|
+
|
169
|
+
Measurements are completely ignored in the test env. They are processed
|
170
|
+
in development mode, but not sent to the external service. Everything is
|
171
|
+
logged in production.
|
22
172
|
|
23
173
|
## Contributing
|
24
174
|
|
data/Rakefile
CHANGED
data/harness.gemspec
CHANGED
@@ -14,4 +14,11 @@ Gem::Specification.new do |gem|
|
|
14
14
|
gem.name = "harness"
|
15
15
|
gem.require_paths = ["lib"]
|
16
16
|
gem.version = Harness::VERSION
|
17
|
+
|
18
|
+
gem.add_dependency "activesupport", "~> 3"
|
19
|
+
gem.add_dependency "redis"
|
20
|
+
gem.add_dependency "redis-namespace"
|
21
|
+
|
22
|
+
gem.add_development_dependency "simplecov"
|
23
|
+
gem.add_development_dependency "webmock"
|
17
24
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'uri'
|
3
|
+
require 'net/http'
|
4
|
+
|
5
|
+
module Harness
|
6
|
+
class LibratoAdapter
|
7
|
+
class Config
|
8
|
+
attr_accessor :email, :token
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.config
|
12
|
+
@config ||= Config.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.log_gauge(gauge)
|
16
|
+
raise Harness::LoggingError if gauge.id.length > 63
|
17
|
+
|
18
|
+
post({:gauges => [{
|
19
|
+
:name => sanitize(gauge.id),
|
20
|
+
:display_name => gauge.name,
|
21
|
+
:value => gauge.value,
|
22
|
+
:measure_time => gauge.time.to_i,
|
23
|
+
:source => gauge.source,
|
24
|
+
:attributes => { :display_units_short => gauge.units }
|
25
|
+
}]})
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.log_counter(counter)
|
29
|
+
raise Harness::LoggingError if counter.id.length > 63
|
30
|
+
|
31
|
+
post({:counters => [{
|
32
|
+
:name => sanitize(counter.id),
|
33
|
+
:display_name => counter.name,
|
34
|
+
:value => counter.value,
|
35
|
+
:measure_time => counter.time.to_i,
|
36
|
+
:source => counter.source,
|
37
|
+
:attributes => { :display_units_short => counter.units }
|
38
|
+
}]})
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
def self.post(params)
|
43
|
+
unless config.email && config.token
|
44
|
+
raise "Adapter not configured. Ensure email and token are set."
|
45
|
+
end
|
46
|
+
|
47
|
+
uri = URI.parse('https://metrics-api.librato.com/v1/metrics')
|
48
|
+
|
49
|
+
Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
|
50
|
+
request = Net::HTTP::Post.new uri.request_uri
|
51
|
+
|
52
|
+
request.basic_auth config.email, config.token
|
53
|
+
request['Content-Type'] = 'application/json'
|
54
|
+
request.body = params.to_json
|
55
|
+
|
56
|
+
response = http.request request
|
57
|
+
|
58
|
+
raise Harness::LoggingError, response.body unless response.code.to_i == 200
|
59
|
+
end
|
60
|
+
|
61
|
+
true
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.sanitize(name)
|
65
|
+
name.gsub(/\./, '-')
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Harness
|
2
|
+
class MemoryAdapter
|
3
|
+
def self.gauges
|
4
|
+
@gauges ||= []
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.counters
|
8
|
+
@counters ||= []
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.log_gauge(gauge)
|
12
|
+
gauges << gauge
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.log_counter(counter)
|
16
|
+
counters << counter
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Harness
|
2
|
+
class Consumer
|
3
|
+
def consume
|
4
|
+
Thread.new do
|
5
|
+
while measurement = queue.pop
|
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
|
+
ensure
|
20
|
+
mutex.synchronize { @finished = queue.empty? }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def finished?
|
27
|
+
@finished
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
def queue
|
32
|
+
Harness.queue
|
33
|
+
end
|
34
|
+
|
35
|
+
def adapter
|
36
|
+
Harness.config.adapter
|
37
|
+
end
|
38
|
+
|
39
|
+
def mutex
|
40
|
+
Harness.mutex
|
41
|
+
end
|
42
|
+
|
43
|
+
def logger
|
44
|
+
Harness.logger
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Harness
|
2
|
+
class Counter < Measurement
|
3
|
+
def self.from_event(event)
|
4
|
+
if event.payload[:counter].is_a? Hash
|
5
|
+
counter = new event.payload[:counter]
|
6
|
+
else
|
7
|
+
counter = new
|
8
|
+
end
|
9
|
+
|
10
|
+
counter.id ||= event.name
|
11
|
+
|
12
|
+
Harness.redis.sadd 'counters', counter.id
|
13
|
+
|
14
|
+
if event.payload[:counter].is_a? Fixnum
|
15
|
+
counter.value = event.payload[:counter]
|
16
|
+
end
|
17
|
+
|
18
|
+
if counter.value
|
19
|
+
Harness.redis.set counter.id, counter.value
|
20
|
+
else
|
21
|
+
counter.value = Harness.redis.incr(counter.id).to_i
|
22
|
+
end
|
23
|
+
|
24
|
+
counter
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Harness
|
2
|
+
class Gauge < Measurement
|
3
|
+
def initialize(attributes = {})
|
4
|
+
super
|
5
|
+
self.units ||= :ms
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.from_event(event)
|
9
|
+
if event.payload[:gauge].is_a? Hash
|
10
|
+
gauge = new event.payload[:gauge]
|
11
|
+
else
|
12
|
+
gauge = new
|
13
|
+
end
|
14
|
+
|
15
|
+
gauge.id ||= event.name
|
16
|
+
gauge.value = event.duration
|
17
|
+
|
18
|
+
gauge
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
events = %w(write_fragment read_fragment expire_fragment write_page expire_page process_action send_file)
|
2
|
+
|
3
|
+
regex = %r{#{events.join("|")}.action_controller}
|
4
|
+
|
5
|
+
ActiveSupport::Notifications.subscribe regex do |*args|
|
6
|
+
event = ActiveSupport::Notifications::Event.new(*args)
|
7
|
+
gauge = Harness::Gauge.from_event event
|
8
|
+
gauge.log
|
9
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
events = %w(render_template render_partial)
|
2
|
+
|
3
|
+
regex = %r{#{events.join("|")}.action_view}
|
4
|
+
|
5
|
+
ActiveSupport::Notifications.subscribe regex do |*args|
|
6
|
+
event = ActiveSupport::Notifications::Event.new(*args)
|
7
|
+
gauge = Harness::Gauge.from_event event
|
8
|
+
gauge.log
|
9
|
+
end
|
10
|
+
|
@@ -0,0 +1,9 @@
|
|
1
|
+
events = %w(cache_read cache_generate cache_fetch_hit cache_write cache_delete)
|
2
|
+
|
3
|
+
regex = %r{#{events.join("|")}.active_support}
|
4
|
+
|
5
|
+
ActiveSupport::Notifications.subscribe regex do |*args|
|
6
|
+
event = ActiveSupport::Notifications::Event.new(*args)
|
7
|
+
gauge = Harness::Gauge.from_event event
|
8
|
+
gauge.log
|
9
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Harness
|
2
|
+
class Measurement
|
3
|
+
attr_accessor :id, :name, :source, :time, :value, :units
|
4
|
+
|
5
|
+
def initialize(attributes = {})
|
6
|
+
attributes.each_pair do |name, value|
|
7
|
+
send "#{name}=", value
|
8
|
+
end
|
9
|
+
|
10
|
+
self.time ||= Time.now
|
11
|
+
end
|
12
|
+
|
13
|
+
def log
|
14
|
+
Harness.log self
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Harness
|
2
|
+
class Railtie < ::Rails::Railtie
|
3
|
+
config.harness = Harness.config
|
4
|
+
|
5
|
+
rake_tasks do
|
6
|
+
load "harness/tasks.rake"
|
7
|
+
end
|
8
|
+
|
9
|
+
initializer "harness.thread" do
|
10
|
+
Thread.abort_on_exception = Rails.env.development? || Rails.env.test?
|
11
|
+
end
|
12
|
+
|
13
|
+
initializer "harness.adapter" do |app|
|
14
|
+
case Rails.env
|
15
|
+
when 'development'
|
16
|
+
app.config.harness.adapter = :null
|
17
|
+
when 'test'
|
18
|
+
app.config.harness.adapter = :null
|
19
|
+
else
|
20
|
+
app.config.harness.adapter = :librato
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
initializer "harness.logger" do |app|
|
25
|
+
Harness.logger = Rails.logger
|
26
|
+
end
|
27
|
+
|
28
|
+
initializer "harness.redis" do
|
29
|
+
if existing_url = ENV['REDISTOGO_URL'] || ENV['REDIS_URL']
|
30
|
+
Harness.redis ||= Redis::Namespace.new('harness', :redis => Redis.connect(:url => existing_url))
|
31
|
+
else
|
32
|
+
Harness.redis ||= Redis::Namespace.new('harness', :redis => Redis.connect(:host => 'localhost', :port => '6379'))
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/harness/version.rb
CHANGED
data/lib/harness.rb
CHANGED
@@ -1,5 +1,108 @@
|
|
1
1
|
require "harness/version"
|
2
2
|
|
3
|
+
require 'thread'
|
4
|
+
|
5
|
+
require 'securerandom'
|
6
|
+
|
7
|
+
require 'redis'
|
8
|
+
require 'redis/namespace'
|
9
|
+
|
10
|
+
require 'active_support/notifications'
|
11
|
+
require 'active_support/core_ext/string'
|
12
|
+
|
3
13
|
module Harness
|
4
|
-
|
14
|
+
class LoggingError < RuntimeError ; end
|
15
|
+
|
16
|
+
class Config
|
17
|
+
attr_reader :adapter
|
18
|
+
attr_accessor :test_mode
|
19
|
+
|
20
|
+
def adapter=(val)
|
21
|
+
if val.is_a? Symbol
|
22
|
+
@adapter = "Harness::#{val.to_s.classify}Adapter".constantize
|
23
|
+
else
|
24
|
+
@adapter = val
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def method_missing(name, *args, &block)
|
29
|
+
begin
|
30
|
+
"Harness::#{name.to_s.classify}Adapter".constantize.config
|
31
|
+
rescue NameError
|
32
|
+
super
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.config
|
38
|
+
@config ||= Config.new
|
39
|
+
end
|
40
|
+
|
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
|
+
def self.log(measurement)
|
50
|
+
queue << measurement
|
51
|
+
wait if config.test_mode
|
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?
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.logger
|
63
|
+
@logger
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.logger=(logger)
|
67
|
+
@logger = logger
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.redis=(redis)
|
71
|
+
@redis = redis
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.redis
|
75
|
+
@redis
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.reset_counters!
|
79
|
+
redis.smembers('counters').each do |counter|
|
80
|
+
redis.set counter, -1
|
81
|
+
end
|
82
|
+
end
|
5
83
|
end
|
84
|
+
|
85
|
+
require 'harness/measurement'
|
86
|
+
require 'harness/counter'
|
87
|
+
require 'harness/gauge'
|
88
|
+
|
89
|
+
require 'harness/instrumentation'
|
90
|
+
|
91
|
+
require 'harness/consumer'
|
92
|
+
|
93
|
+
require 'harness/adapters/librato_adapter'
|
94
|
+
require 'harness/adapters/memory_adapter'
|
95
|
+
require 'harness/adapters/null_adapter'
|
96
|
+
|
97
|
+
require 'harness/integration/action_controller'
|
98
|
+
require 'harness/integration/action_view'
|
99
|
+
require 'harness/integration/action_mailer'
|
100
|
+
require 'harness/integration/active_support'
|
101
|
+
|
102
|
+
require 'harness/railtie' if defined?(Rails)
|
103
|
+
|
104
|
+
Harness.consumer.consume
|
105
|
+
|
106
|
+
require 'logger'
|
107
|
+
|
108
|
+
Harness.logger = Logger.new $stdout
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class CountersWithRedis < IntegrationTest
|
4
|
+
def test_stores_name_in_redis
|
5
|
+
instrument "event-counter", :counter => true
|
6
|
+
|
7
|
+
assert_includes redis.smembers('counters'), 'event-counter'
|
8
|
+
assert_equal 1, redis.get('event-counter').to_i
|
9
|
+
|
10
|
+
assert_counter_logged "event-counter"
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_increments_counter_each_instrument
|
14
|
+
instrument "event-counter", :counter => true
|
15
|
+
assert_counter_logged "event-counter"
|
16
|
+
counters.clear
|
17
|
+
|
18
|
+
assert_empty counters
|
19
|
+
instrument "event-counter", :counter => true
|
20
|
+
assert_counter_logged "event-counter"
|
21
|
+
|
22
|
+
assert_equal 2, counters.first.value
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_sets_given_value_in_redis_with_shortform
|
26
|
+
instrument "event-counter", :counter => 10
|
27
|
+
|
28
|
+
assert_equal 10, redis.get("event-counter").to_i
|
29
|
+
|
30
|
+
counters.clear
|
31
|
+
|
32
|
+
instrument "event-counter", :counter => true
|
33
|
+
assert_counter_logged 'event-counter'
|
34
|
+
|
35
|
+
assert_equal 11, counters.first.value
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_sets_given_value_in_redis_with_longform
|
39
|
+
instrument "event-counter", :counter => { :value => 10 }
|
40
|
+
|
41
|
+
assert_equal 10, redis.get("event-counter").to_i
|
42
|
+
|
43
|
+
counters.clear
|
44
|
+
|
45
|
+
instrument "event-counter", :counter => true
|
46
|
+
assert_counter_logged 'event-counter'
|
47
|
+
|
48
|
+
assert_equal 11, counters.first.value
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_resets_counters
|
52
|
+
instrument "event-counter", :counter => true
|
53
|
+
instrument "event-counter2", :counter => true
|
54
|
+
|
55
|
+
assert_equal 1, redis.get("event-counter").to_i
|
56
|
+
assert_equal 1, redis.get("event-counter2").to_i
|
57
|
+
|
58
|
+
Harness.reset_counters!
|
59
|
+
|
60
|
+
assert_equal -1, redis.get("event-counter").to_i
|
61
|
+
assert_equal -1, redis.get("event-counter2").to_i
|
62
|
+
|
63
|
+
counters.clear
|
64
|
+
instrument "event-counter", :counter => true
|
65
|
+
assert_counter_logged 'event-counter'
|
66
|
+
|
67
|
+
assert_equal 0, counters.first.value
|
68
|
+
end
|
69
|
+
end
|