harness 0.9.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +2 -0
- data/README.md +108 -323
- data/harness.gemspec +3 -12
- data/lib/harness.rb +69 -68
- data/lib/harness/async_queue.rb +29 -0
- data/lib/harness/fake_collector.rb +40 -0
- data/lib/harness/instrumentation.rb +21 -6
- data/lib/harness/null_collector.rb +23 -0
- data/lib/harness/subscription.rb +7 -0
- data/lib/harness/sync_queue.rb +14 -0
- data/lib/harness/version.rb +1 -1
- data/test/acceptance_test.rb +20 -0
- data/test/active_support_notifications_test.rb +93 -0
- data/test/async_queue_test.rb +14 -0
- data/test/instrumentation_test.rb +54 -0
- data/test/null_collector_test.rb +29 -0
- data/test/test_helper.rb +38 -34
- metadata +21 -196
- data/lib/harness/adapters/librato_adapter.rb +0 -90
- data/lib/harness/adapters/memory_adapter.rb +0 -27
- data/lib/harness/adapters/null_adapter.rb +0 -11
- data/lib/harness/adapters/stathat_adapter.rb +0 -75
- data/lib/harness/adapters/statsd_adapter.rb +0 -50
- data/lib/harness/consumer.rb +0 -35
- data/lib/harness/counter.rb +0 -29
- data/lib/harness/gauge.rb +0 -23
- data/lib/harness/integration/action_controller.rb +0 -9
- data/lib/harness/integration/action_mailer.rb +0 -9
- data/lib/harness/integration/action_view.rb +0 -9
- data/lib/harness/integration/active_model_serializers.rb +0 -9
- data/lib/harness/integration/active_support.rb +0 -9
- data/lib/harness/integration/sidekiq.rb +0 -47
- data/lib/harness/job.rb +0 -23
- data/lib/harness/measurement.rb +0 -43
- data/lib/harness/queues/delayed_job_queue.rb +0 -7
- data/lib/harness/queues/resque_queue.rb +0 -29
- data/lib/harness/queues/sidekiq_queue.rb +0 -31
- data/lib/harness/queues/synchronous_queue.rb +0 -18
- data/lib/harness/railtie.rb +0 -71
- data/lib/harness/tasks.rake +0 -6
- data/test/integration/counters_with_redis_test.rb +0 -67
- data/test/integration/instrumentation_test.rb +0 -50
- data/test/integration/integrations/action_controller_test.rb +0 -51
- data/test/integration/integrations/action_mailer_test.rb +0 -22
- data/test/integration/integrations/action_view_test.rb +0 -32
- data/test/integration/integrations/active_model_serializers_test.rb +0 -22
- data/test/integration/integrations/active_support_test.rb +0 -41
- data/test/integration/integrations/sidekiq_test.rb +0 -54
- data/test/integration/logging_test.rb +0 -17
- data/test/integration/queues/delayed_job_test.rb +0 -59
- data/test/integration/queues/resque_test.rb +0 -24
- data/test/integration/queues/sidekiq_test.rb +0 -34
- data/test/integration/railtie_test.rb +0 -26
- data/test/unit/adapters/librato_adapter_test.rb +0 -169
- data/test/unit/adapters/memory_adapter_test.rb +0 -22
- data/test/unit/adapters/stathat_adapter_test.rb +0 -144
- data/test/unit/adapters/statsd_adapter_test.rb +0 -74
- data/test/unit/counter_test.rb +0 -84
- data/test/unit/gauge_test.rb +0 -93
- data/test/unit/harness_test.rb +0 -39
- data/test/unit/measurement_test.rb +0 -76
@@ -1,90 +0,0 @@
|
|
1
|
-
require 'uri'
|
2
|
-
require 'net/http'
|
3
|
-
|
4
|
-
module Harness
|
5
|
-
class LibratoAdapter
|
6
|
-
class NameTooLong < Harness::LoggingError
|
7
|
-
def to_s
|
8
|
-
"Name cannot be more than 63 characters long"
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
class Config
|
13
|
-
attr_accessor :email, :token
|
14
|
-
end
|
15
|
-
|
16
|
-
def self.config
|
17
|
-
@config ||= Config.new
|
18
|
-
end
|
19
|
-
|
20
|
-
def log_gauge(gauge)
|
21
|
-
raise NameTooLong if gauge.id.length > 63
|
22
|
-
|
23
|
-
post({:gauges => [{
|
24
|
-
:name => sanitize(gauge.id),
|
25
|
-
:display_name => gauge.name,
|
26
|
-
:value => gauge.value,
|
27
|
-
:measure_time => gauge.time.to_i,
|
28
|
-
:source => gauge.source,
|
29
|
-
:attributes => { :display_units_short => gauge.units }
|
30
|
-
}]})
|
31
|
-
end
|
32
|
-
|
33
|
-
def log_counter(counter)
|
34
|
-
raise NameTooLong if counter.id.length > 63
|
35
|
-
|
36
|
-
post({:counters => [{
|
37
|
-
:name => sanitize(counter.id),
|
38
|
-
:display_name => counter.name,
|
39
|
-
:value => counter.value,
|
40
|
-
:measure_time => counter.time.to_i,
|
41
|
-
:source => counter.source,
|
42
|
-
:attributes => { :display_units_short => counter.units }
|
43
|
-
}]})
|
44
|
-
end
|
45
|
-
|
46
|
-
private
|
47
|
-
def post(params)
|
48
|
-
unless config.email && config.token
|
49
|
-
raise "Adapter not configured. Ensure email and token are set."
|
50
|
-
end
|
51
|
-
|
52
|
-
uri = URI.parse('https://metrics-api.librato.com/v1/metrics')
|
53
|
-
|
54
|
-
Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
|
55
|
-
request = Net::HTTP::Post.new uri.request_uri
|
56
|
-
|
57
|
-
request.basic_auth config.email, config.token
|
58
|
-
request['Content-Type'] = 'application/json'
|
59
|
-
request.body = MultiJson.dump params
|
60
|
-
|
61
|
-
response = http.request request
|
62
|
-
|
63
|
-
if response.code.to_i != 200
|
64
|
-
text = %Q{
|
65
|
-
Server Said: #{response.body}
|
66
|
-
Sent: #{params.inspect}
|
67
|
-
}
|
68
|
-
|
69
|
-
raise Harness::LoggingError, text
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
true
|
74
|
-
end
|
75
|
-
|
76
|
-
def config
|
77
|
-
self.class.config
|
78
|
-
end
|
79
|
-
|
80
|
-
def sanitize(name)
|
81
|
-
if Harness.config.namespace
|
82
|
-
key = "#{name}.#{Harness.config.namespace}"
|
83
|
-
else
|
84
|
-
key = name
|
85
|
-
end
|
86
|
-
|
87
|
-
key.gsub('/', '.')
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
@@ -1,27 +0,0 @@
|
|
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 log_gauge(gauge)
|
12
|
-
gauges << gauge
|
13
|
-
end
|
14
|
-
|
15
|
-
def log_counter(counter)
|
16
|
-
counters << counter
|
17
|
-
end
|
18
|
-
|
19
|
-
def counters
|
20
|
-
self.class.counters
|
21
|
-
end
|
22
|
-
|
23
|
-
def gauges
|
24
|
-
self.class.gauges
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
@@ -1,75 +0,0 @@
|
|
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
|
@@ -1,50 +0,0 @@
|
|
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/consumer.rb
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
module Harness
|
2
|
-
class Consumer
|
3
|
-
def consume
|
4
|
-
Thread.new do
|
5
|
-
while measurement = queue.pop
|
6
|
-
begin
|
7
|
-
ensure
|
8
|
-
mutex.synchronize { @finished = queue.empty? }
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
def finished?
|
15
|
-
@finished
|
16
|
-
end
|
17
|
-
|
18
|
-
private
|
19
|
-
def queue
|
20
|
-
Harness.queue
|
21
|
-
end
|
22
|
-
|
23
|
-
def adapter
|
24
|
-
Harness.config.adapter
|
25
|
-
end
|
26
|
-
|
27
|
-
def mutex
|
28
|
-
Harness.mutex
|
29
|
-
end
|
30
|
-
|
31
|
-
def logger
|
32
|
-
Harness.logger
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
data/lib/harness/counter.rb
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
require 'securerandom'
|
2
|
-
|
3
|
-
module Harness
|
4
|
-
class Counter < Measurement
|
5
|
-
def self.from_event(event)
|
6
|
-
if event.payload[:counter].is_a? Hash
|
7
|
-
counter = new event.payload[:counter]
|
8
|
-
elsif event.payload[:counter].is_a?(Symbol) || event.payload[:counter].is_a?(String)
|
9
|
-
counter = new :id => event.payload[:counter].to_s
|
10
|
-
else
|
11
|
-
counter = new
|
12
|
-
end
|
13
|
-
|
14
|
-
counter.id ||= event.name
|
15
|
-
|
16
|
-
if event.payload[:counter].is_a? Fixnum
|
17
|
-
counter.value = event.payload[:counter]
|
18
|
-
end
|
19
|
-
|
20
|
-
if counter.value
|
21
|
-
Harness.redis.set "counters/#{counter.id}", counter.value
|
22
|
-
else
|
23
|
-
counter.value = Harness.redis.incr("counters/#{counter.id}").to_i
|
24
|
-
end
|
25
|
-
|
26
|
-
counter
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
data/lib/harness/gauge.rb
DELETED
@@ -1,23 +0,0 @@
|
|
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
|
-
elsif event.payload[:gauge].is_a?(Symbol) || event.payload[:gauge].is_a?(String)
|
12
|
-
gauge = new :id => event.payload[:gauge].to_s
|
13
|
-
else
|
14
|
-
gauge = new
|
15
|
-
end
|
16
|
-
|
17
|
-
gauge.id ||= event.name
|
18
|
-
gauge.value ||= event.duration
|
19
|
-
|
20
|
-
gauge
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,9 +0,0 @@
|
|
1
|
-
events = %w(write_fragment read_fragment expire_fragment write_page expire_page process_action send_file)
|
2
|
-
|
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
|
-
end
|
@@ -1,9 +0,0 @@
|
|
1
|
-
events = %w(render_template render_partial)
|
2
|
-
|
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
|
-
end
|
@@ -1,9 +0,0 @@
|
|
1
|
-
events = %w(serializable_hash associations)
|
2
|
-
|
3
|
-
events.each do |name|
|
4
|
-
ActiveSupport::Notifications.subscribe %r{^#{name}.*\.serializer$} do |*args|
|
5
|
-
event = ActiveSupport::Notifications::Event.new(*args)
|
6
|
-
gauge = Harness::Gauge.from_event event
|
7
|
-
gauge.log
|
8
|
-
end
|
9
|
-
end
|
@@ -1,9 +0,0 @@
|
|
1
|
-
events = %w(cache_read cache_generate cache_fetch_hit cache_write cache_delete)
|
2
|
-
|
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
|
-
end
|
@@ -1,47 +0,0 @@
|
|
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
|