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.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -0
  3. data/README.md +108 -323
  4. data/harness.gemspec +3 -12
  5. data/lib/harness.rb +69 -68
  6. data/lib/harness/async_queue.rb +29 -0
  7. data/lib/harness/fake_collector.rb +40 -0
  8. data/lib/harness/instrumentation.rb +21 -6
  9. data/lib/harness/null_collector.rb +23 -0
  10. data/lib/harness/subscription.rb +7 -0
  11. data/lib/harness/sync_queue.rb +14 -0
  12. data/lib/harness/version.rb +1 -1
  13. data/test/acceptance_test.rb +20 -0
  14. data/test/active_support_notifications_test.rb +93 -0
  15. data/test/async_queue_test.rb +14 -0
  16. data/test/instrumentation_test.rb +54 -0
  17. data/test/null_collector_test.rb +29 -0
  18. data/test/test_helper.rb +38 -34
  19. metadata +21 -196
  20. data/lib/harness/adapters/librato_adapter.rb +0 -90
  21. data/lib/harness/adapters/memory_adapter.rb +0 -27
  22. data/lib/harness/adapters/null_adapter.rb +0 -11
  23. data/lib/harness/adapters/stathat_adapter.rb +0 -75
  24. data/lib/harness/adapters/statsd_adapter.rb +0 -50
  25. data/lib/harness/consumer.rb +0 -35
  26. data/lib/harness/counter.rb +0 -29
  27. data/lib/harness/gauge.rb +0 -23
  28. data/lib/harness/integration/action_controller.rb +0 -9
  29. data/lib/harness/integration/action_mailer.rb +0 -9
  30. data/lib/harness/integration/action_view.rb +0 -9
  31. data/lib/harness/integration/active_model_serializers.rb +0 -9
  32. data/lib/harness/integration/active_support.rb +0 -9
  33. data/lib/harness/integration/sidekiq.rb +0 -47
  34. data/lib/harness/job.rb +0 -23
  35. data/lib/harness/measurement.rb +0 -43
  36. data/lib/harness/queues/delayed_job_queue.rb +0 -7
  37. data/lib/harness/queues/resque_queue.rb +0 -29
  38. data/lib/harness/queues/sidekiq_queue.rb +0 -31
  39. data/lib/harness/queues/synchronous_queue.rb +0 -18
  40. data/lib/harness/railtie.rb +0 -71
  41. data/lib/harness/tasks.rake +0 -6
  42. data/test/integration/counters_with_redis_test.rb +0 -67
  43. data/test/integration/instrumentation_test.rb +0 -50
  44. data/test/integration/integrations/action_controller_test.rb +0 -51
  45. data/test/integration/integrations/action_mailer_test.rb +0 -22
  46. data/test/integration/integrations/action_view_test.rb +0 -32
  47. data/test/integration/integrations/active_model_serializers_test.rb +0 -22
  48. data/test/integration/integrations/active_support_test.rb +0 -41
  49. data/test/integration/integrations/sidekiq_test.rb +0 -54
  50. data/test/integration/logging_test.rb +0 -17
  51. data/test/integration/queues/delayed_job_test.rb +0 -59
  52. data/test/integration/queues/resque_test.rb +0 -24
  53. data/test/integration/queues/sidekiq_test.rb +0 -34
  54. data/test/integration/railtie_test.rb +0 -26
  55. data/test/unit/adapters/librato_adapter_test.rb +0 -169
  56. data/test/unit/adapters/memory_adapter_test.rb +0 -22
  57. data/test/unit/adapters/stathat_adapter_test.rb +0 -144
  58. data/test/unit/adapters/statsd_adapter_test.rb +0 -74
  59. data/test/unit/counter_test.rb +0 -84
  60. data/test/unit/gauge_test.rb +0 -93
  61. data/test/unit/harness_test.rb +0 -39
  62. 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,11 +0,0 @@
1
- module Harness
2
- class NullAdapter
3
- def log_gauge(gauge)
4
-
5
- end
6
-
7
- def log_counter(counter)
8
-
9
- end
10
- end
11
- 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
@@ -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
@@ -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(receive deliver)
2
-
3
- events.each do |name|
4
- ActiveSupport::Notifications.subscribe "#{name}.action_mailer" 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