rails_autoscale_agent 0.4.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9599e5eb723b8e92f13eb6f820ce7f49f6af5ae946146eb140f13e42a465625a
4
- data.tar.gz: 94eeec3ac6376605b5d0db1c8aa406c1f7101fddbf2f188e1cbb41c5f2f836bc
3
+ metadata.gz: 5d8c84bc0e74990ad310505abc8666c54de4de76d16c31c8435c495afc17dc8a
4
+ data.tar.gz: a46f8f5e0bb5c5683d10b175162fb4fb1911fbc5390ae80716054062c13604f7
5
5
  SHA512:
6
- metadata.gz: c8d33309ab62d23341bc707e8b5e5da5158e21885911fd0418a58c5880b4fe24a309cabf3cd08513382e18570e7c28f8ff2fa1bb7362f040aac8f3210fdf306e
7
- data.tar.gz: 41999dbec255f00d7f3369f97e81acae12c556b126050ea28a50816a8c91801a8dfa256cdfc14f8126c4ad175ecd9dc16fd3b8136aaf0c9805301a362cdf81de
6
+ metadata.gz: dc1afd33ac4589472ffea027d24b6ff0cc9ef8b91fcdc237191248c8245baeee7ead3550ec8c1826c0bcdd708cbb83fe91457c8240efead5fef94e9109daaad3
7
+ data.tar.gz: cd381c1dd165c3830fa22d412603a966b4ecff5ab04bf6d3b8fb846f4c3bc0cde324c0e1fd0b5964bab2a72500e7bc752b06cbd95bb1c40b1fba3abd2871ce54
@@ -1,10 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'rails_autoscale_agent/config'
4
+
3
5
  module RailsAutoscaleAgent
4
6
  module Logger
5
7
  def logger
6
8
  @logger ||= Config.instance.logger.tap do |logger|
7
9
  logger.extend(FakeTaggedLogging) unless logger.respond_to?(:tagged)
10
+ logger.extend(ConditionalDebugLogging)
8
11
  end
9
12
  end
10
13
 
@@ -14,5 +17,13 @@ module RailsAutoscaleAgent
14
17
  yield self
15
18
  end
16
19
  end
20
+
21
+ module ConditionalDebugLogging
22
+ def debug(*args)
23
+ # Rails logger defaults to DEBUG level in production, but I don't want
24
+ # to be chatty by default.
25
+ super if ENV['RAILS_AUTOSCALE_LOG_LEVEL'] == 'DEBUG'
26
+ end
27
+ end
17
28
  end
18
29
  end
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsAutoscaleAgent
4
- class Measurement < Struct.new(:time, :value)
5
- def initialize(time, value)
6
- super time.utc, value.to_i
4
+ class Measurement < Struct.new(:time, :value, :queue_name)
5
+ def initialize(time, value, queue_name = nil)
6
+ super time.utc, value.to_i, queue_name
7
7
  end
8
8
  end
9
9
  end
@@ -19,8 +19,6 @@ module RailsAutoscaleAgent
19
19
  config = Config.instance
20
20
  request = Request.new(env, config)
21
21
 
22
- logger.debug "Middleware entered - request_id=#{request.id} path=#{request.path} method=#{request.method} request_size=#{request.size}"
23
-
24
22
  store = Store.instance
25
23
  Reporter.start(config, store)
26
24
 
@@ -22,6 +22,12 @@ module RailsAutoscaleAgent
22
22
  result << measurement.time.to_i.to_s
23
23
  result << ','
24
24
  result << measurement.value.to_s
25
+
26
+ if measurement.queue_name
27
+ result << ','
28
+ result << measurement.queue_name
29
+ end
30
+
25
31
  result << "\n"
26
32
  end
27
33
  end
@@ -5,6 +5,7 @@ require 'rails_autoscale_agent/logger'
5
5
  require 'rails_autoscale_agent/autoscale_api'
6
6
  require 'rails_autoscale_agent/time_rounder'
7
7
  require 'rails_autoscale_agent/registration'
8
+ require 'rails_autoscale_agent/worker_adapters/sidekiq'
8
9
 
9
10
  # Reporter wakes up every minute to send metrics to the RailsAutoscale API
10
11
 
@@ -13,25 +14,34 @@ module RailsAutoscaleAgent
13
14
  include Singleton
14
15
  include Logger
15
16
 
17
+ WORKER_ADAPTERS = [
18
+ WorkerAdapters::Sidekiq.new,
19
+ ]
20
+
16
21
  def self.start(config, store)
17
- if config.api_base_url
18
- instance.start!(config, store) unless instance.running?
19
- else
20
- instance.logger.debug "Reporter not started: RAILS_AUTOSCALE_URL is not set"
21
- end
22
+ instance.start!(config, store) unless instance.started?
22
23
  end
23
24
 
24
25
  def start!(config, store)
25
- @running = true
26
+ @started = true
27
+ @worker_adapters = WORKER_ADAPTERS.select(&:enabled?)
28
+
29
+ if !config.api_base_url
30
+ logger.info "Reporter not started: RAILS_AUTOSCALE_URL is not set"
31
+ return
32
+ end
26
33
 
27
34
  Thread.new do
28
35
  logger.tagged 'RailsAutoscale' do
29
36
  register!(config)
30
37
 
31
38
  loop do
32
- sleep config.report_interval
39
+ # Stagger reporting to spread out reports from many processes
40
+ multiplier = 1 - (rand / 4) # between 0.75 and 1.0
41
+ sleep config.report_interval * multiplier
33
42
 
34
43
  begin
44
+ @worker_adapters.map { |a| a.collect!(store) }
35
45
  report!(config, store)
36
46
  rescue => ex
37
47
  # Exceptions in threads other than the main thread will fail silently
@@ -44,15 +54,15 @@ module RailsAutoscaleAgent
44
54
  end
45
55
  end
46
56
 
47
- def running?
48
- @running
57
+ def started?
58
+ @started
49
59
  end
50
60
 
51
61
  def report!(config, store)
52
62
  report = store.pop_report
53
63
 
54
64
  if report.measurements.any?
55
- logger.info "Reporting queue times for #{report.measurements.size} requests"
65
+ logger.info "Reporting #{report.measurements.size} measurements"
56
66
 
57
67
  params = report.to_params(config)
58
68
  result = AutoscaleApi.new(config.api_base_url).report_metrics!(params, report.to_csv)
@@ -76,7 +86,7 @@ module RailsAutoscaleAgent
76
86
  when AutoscaleApi::SuccessResponse
77
87
  config.report_interval = result.data['report_interval'] if result.data['report_interval']
78
88
  config.max_request_size = result.data['max_request_size'] if result.data['max_request_size']
79
- logger.info "Reporter starting, will report every #{config.report_interval} seconds"
89
+ logger.info "Reporter starting, will report every #{config.report_interval} seconds or so"
80
90
  when AutoscaleApi::FailureResponse
81
91
  logger.error "Reporter failed to register: #{result.failure_message}"
82
92
  end
@@ -24,16 +24,11 @@ module RailsAutoscaleAgent
24
24
 
25
25
  def queue_time
26
26
  if entered_queue_at
27
- if entered_queue_at < (Time.now - 60 * 10)
28
- # ignore unreasonable values
29
- logger.warn "request queued for more than 10 minutes... skipping collection"
30
- else
31
- queue_time = ((Time.now - entered_queue_at) * 1000).to_i
32
- queue_time = 0 if queue_time < 0
33
- logger.debug "Collected queue_time=#{queue_time}ms request_id=#{id} request_size=#{size}"
27
+ queue_time = ((Time.now - entered_queue_at) * 1000).to_i
28
+ queue_time = 0 if queue_time < 0
29
+ logger.debug "Collected queue_time=#{queue_time}ms request_id=#{id} request_size=#{size}"
34
30
 
35
- queue_time
36
- end
31
+ queue_time
37
32
  end
38
33
  end
39
34
  end
@@ -9,12 +9,14 @@ module RailsAutoscaleAgent
9
9
  class Store
10
10
  include Singleton
11
11
 
12
+ attr_reader :measurements
13
+
12
14
  def initialize
13
15
  @measurements = []
14
16
  end
15
17
 
16
- def push(value, time = Time.now)
17
- @measurements << Measurement.new(time, value)
18
+ def push(value, time = Time.now, queue_name = nil)
19
+ @measurements << Measurement.new(time, value, queue_name)
18
20
  end
19
21
 
20
22
  def pop_report
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsAutoscaleAgent
4
- VERSION = "0.4.1"
4
+ VERSION = "0.6.0"
5
5
  end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_autoscale_agent/logger'
4
+ require 'sidekiq/api'
5
+
6
+ module WorkerAdapters
7
+ class Sidekiq
8
+ include RailsAutoscaleAgent::Logger
9
+
10
+ def enabled?
11
+ defined?(::Sidekiq)
12
+ end
13
+
14
+ # TODO: specs
15
+ def collect!(store)
16
+ log_msg = String.new('Sidekiq latency ')
17
+
18
+ ::Sidekiq::Queue.all.each do |queue|
19
+ latency_ms = (queue.latency * 1000).ceil
20
+ store.push latency_ms, Time.now, queue.name
21
+ log_msg << "#{queue.name}=#{latency_ms} "
22
+ end
23
+
24
+ logger.debug log_msg
25
+ end
26
+ end
27
+ end
@@ -25,4 +25,5 @@ Gem::Specification.new do |spec|
25
25
  spec.add_development_dependency "webmock"
26
26
  spec.add_development_dependency "pry"
27
27
  spec.add_development_dependency "pry-byebug"
28
+ spec.add_development_dependency "sidekiq", "~> 5.0"
28
29
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_autoscale_agent
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam McCrea
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-01-21 00:00:00.000000000 Z
11
+ date: 2019-05-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -122,6 +122,20 @@ dependencies:
122
122
  - - ">="
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: sidekiq
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '5.0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '5.0'
125
139
  description:
126
140
  email:
127
141
  - adam@adamlogic.com
@@ -153,6 +167,7 @@ files:
153
167
  - lib/rails_autoscale_agent/store.rb
154
168
  - lib/rails_autoscale_agent/time_rounder.rb
155
169
  - lib/rails_autoscale_agent/version.rb
170
+ - lib/rails_autoscale_agent/worker_adapters/sidekiq.rb
156
171
  - log/.gitkeep
157
172
  - rails_autoscale_agent.gemspec
158
173
  homepage: https://github.com/adamlogic/rails_autoscale_agent