harness 0.9.1 → 1.0.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.
- 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
|