harness 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|