rails_autoscale_agent 0.7.0 → 0.10.2
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/.vscode/tasks.json +85 -0
- data/CHANGELOG.md +115 -0
- data/Gemfile +13 -1
- data/README.md +65 -17
- data/lib/rails_autoscale_agent/autoscale_api.rb +13 -4
- data/lib/rails_autoscale_agent/config.rb +29 -8
- data/lib/rails_autoscale_agent/logger.rb +28 -14
- data/lib/rails_autoscale_agent/measurement.rb +5 -3
- data/lib/rails_autoscale_agent/middleware.rb +8 -13
- data/lib/rails_autoscale_agent/railtie.rb +4 -0
- data/lib/rails_autoscale_agent/registration.rb +4 -2
- data/lib/rails_autoscale_agent/report.rb +7 -9
- data/lib/rails_autoscale_agent/reporter.rb +37 -23
- data/lib/rails_autoscale_agent/request.rb +29 -15
- data/lib/rails_autoscale_agent/store.rb +7 -2
- data/lib/rails_autoscale_agent/version.rb +1 -1
- data/lib/rails_autoscale_agent/worker_adapters/delayed_job.rb +97 -0
- data/lib/rails_autoscale_agent/worker_adapters/que.rb +71 -0
- data/lib/rails_autoscale_agent/worker_adapters/resque.rb +50 -0
- data/lib/rails_autoscale_agent/worker_adapters/sidekiq.rb +69 -18
- data/rails_autoscale_agent.gemspec +1 -10
- metadata +14 -135
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails_autoscale_agent/logger'
|
4
|
+
|
5
|
+
module RailsAutoscaleAgent
|
6
|
+
module WorkerAdapters
|
7
|
+
class Que
|
8
|
+
include RailsAutoscaleAgent::Logger
|
9
|
+
include Singleton
|
10
|
+
|
11
|
+
attr_writer :queues
|
12
|
+
|
13
|
+
def queues
|
14
|
+
# Track the known queues so we can continue reporting on queues that don't
|
15
|
+
# have enqueued jobs at the time of reporting.
|
16
|
+
# Assume a "default" queue so we always report *something*, even when nothing
|
17
|
+
# is enqueued.
|
18
|
+
@queues ||= Set.new(['default'])
|
19
|
+
end
|
20
|
+
|
21
|
+
def enabled?
|
22
|
+
if defined?(::Que)
|
23
|
+
logger.info "Que enabled (#{::ActiveRecord::Base.default_timezone})"
|
24
|
+
true
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def collect!(store)
|
29
|
+
log_msg = String.new
|
30
|
+
t = Time.now.utc
|
31
|
+
sql = <<~SQL
|
32
|
+
SELECT queue, min(run_at)
|
33
|
+
FROM que_jobs
|
34
|
+
WHERE finished_at IS NULL
|
35
|
+
AND expired_at IS NULL
|
36
|
+
AND error_count = 0
|
37
|
+
GROUP BY 1
|
38
|
+
SQL
|
39
|
+
|
40
|
+
run_at_by_queue = Hash[select_rows(sql)]
|
41
|
+
|
42
|
+
# Don't collect worker metrics if there are unreasonable number of queues
|
43
|
+
if run_at_by_queue.size > 50
|
44
|
+
logger.debug "Skipping Que metrics - #{run_at_by_queue.size} queues"
|
45
|
+
return
|
46
|
+
end
|
47
|
+
|
48
|
+
self.queues |= run_at_by_queue.keys
|
49
|
+
|
50
|
+
queues.each do |queue|
|
51
|
+
run_at = run_at_by_queue[queue]
|
52
|
+
run_at = DateTime.parse(run_at) if run_at.is_a?(String)
|
53
|
+
latency_ms = run_at ? ((t - run_at)*1000).ceil : 0
|
54
|
+
latency_ms = 0 if latency_ms < 0
|
55
|
+
|
56
|
+
store.push latency_ms, t, queue
|
57
|
+
log_msg << "que.#{queue}=#{latency_ms} "
|
58
|
+
end
|
59
|
+
|
60
|
+
logger.debug log_msg unless log_msg.empty?
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def select_rows(sql)
|
66
|
+
# This ensures the agent doesn't hold onto a DB connection any longer than necessary
|
67
|
+
ActiveRecord::Base.connection_pool.with_connection { |c| c.select_rows(sql) }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails_autoscale_agent/logger'
|
4
|
+
|
5
|
+
module RailsAutoscaleAgent
|
6
|
+
module WorkerAdapters
|
7
|
+
class Resque
|
8
|
+
include RailsAutoscaleAgent::Logger
|
9
|
+
include Singleton
|
10
|
+
|
11
|
+
attr_writer :queues
|
12
|
+
|
13
|
+
def queues
|
14
|
+
@queues ||= ['default']
|
15
|
+
end
|
16
|
+
|
17
|
+
def enabled?
|
18
|
+
require 'resque'
|
19
|
+
logger.info "Resque enabled"
|
20
|
+
true
|
21
|
+
rescue LoadError
|
22
|
+
false
|
23
|
+
end
|
24
|
+
|
25
|
+
def collect!(store)
|
26
|
+
log_msg = String.new
|
27
|
+
current_queues = ::Resque.queues
|
28
|
+
|
29
|
+
# Don't collect worker metrics if there are unreasonable number of queues
|
30
|
+
if current_queues.size > 50
|
31
|
+
logger.debug "Skipping Resque metrics - #{current_queues.size} queues"
|
32
|
+
return
|
33
|
+
end
|
34
|
+
|
35
|
+
# Ensure we continue to collect metrics for known queue names, even when nothing is
|
36
|
+
# enqueued at the time. Without this, it will appears that the agent is no longer reporting.
|
37
|
+
self.queues |= current_queues
|
38
|
+
|
39
|
+
queues.each do |queue|
|
40
|
+
next if queue.nil? || queue.empty?
|
41
|
+
depth = ::Resque.size(queue)
|
42
|
+
store.push depth, Time.now, queue, :qd
|
43
|
+
log_msg << "resque-qd.#{queue}=#{depth} "
|
44
|
+
end
|
45
|
+
|
46
|
+
logger.debug log_msg
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -2,28 +2,79 @@
|
|
2
2
|
|
3
3
|
require 'rails_autoscale_agent/logger'
|
4
4
|
|
5
|
-
module
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
5
|
+
module RailsAutoscaleAgent
|
6
|
+
module WorkerAdapters
|
7
|
+
class Sidekiq
|
8
|
+
include RailsAutoscaleAgent::Logger
|
9
|
+
include Singleton
|
10
|
+
|
11
|
+
attr_writer :queues
|
12
|
+
|
13
|
+
def enabled?
|
14
|
+
require 'sidekiq/api'
|
15
|
+
|
16
|
+
log_msg = String.new("Sidekiq enabled")
|
17
|
+
log_msg << " with long-running job support" if track_long_running_jobs?
|
18
|
+
logger.info log_msg
|
19
|
+
|
20
|
+
true
|
21
|
+
rescue LoadError
|
22
|
+
false
|
23
|
+
end
|
24
|
+
|
25
|
+
def collect!(store)
|
26
|
+
log_msg = String.new
|
27
|
+
queues_by_name = ::Sidekiq::Queue.all.each_with_object({}) do |queue, obj|
|
28
|
+
obj[queue.name] = queue
|
29
|
+
end
|
30
|
+
|
31
|
+
# Don't collect worker metrics if there are unreasonable number of queues
|
32
|
+
if queues_by_name.size > 50
|
33
|
+
logger.debug "Skipping Sidekiq metrics - #{queues_by_name.size} queues"
|
34
|
+
return
|
35
|
+
end
|
15
36
|
|
16
|
-
|
17
|
-
|
18
|
-
|
37
|
+
# Ensure we continue to collect metrics for known queue names, even when nothing is
|
38
|
+
# enqueued at the time. Without this, it will appear that the agent is no longer reporting.
|
39
|
+
queues.each do |queue_name|
|
40
|
+
queues_by_name[queue_name] ||= ::Sidekiq::Queue.new(queue_name)
|
41
|
+
end
|
42
|
+
self.queues = queues_by_name.keys
|
19
43
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
44
|
+
if track_long_running_jobs?
|
45
|
+
busy_counts = Hash.new { |h,k| h[k] = 0}
|
46
|
+
::Sidekiq::Workers.new.each do |pid, tid, work|
|
47
|
+
busy_counts[work.dig('payload', 'queue')] += 1
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
queues_by_name.each do |queue_name, queue|
|
52
|
+
latency_ms = (queue.latency * 1000).ceil
|
53
|
+
depth = queue.size
|
54
|
+
|
55
|
+
store.push latency_ms, Time.now, queue.name, :qt
|
56
|
+
store.push depth, Time.now, queue.name, :qd
|
57
|
+
log_msg << "sidekiq-qt.#{queue.name}=#{latency_ms} sidekiq-qd.#{queue.name}=#{depth} "
|
58
|
+
|
59
|
+
if track_long_running_jobs?
|
60
|
+
busy_count = busy_counts[queue.name]
|
61
|
+
store.push busy_count, Time.now, queue.name, :busy
|
62
|
+
log_msg << "sidekiq-busy.#{queue.name}=#{busy_count} "
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
logger.debug log_msg
|
24
67
|
end
|
25
68
|
|
26
|
-
|
69
|
+
private
|
70
|
+
|
71
|
+
def queues
|
72
|
+
@queues ||= ['default']
|
73
|
+
end
|
74
|
+
|
75
|
+
def track_long_running_jobs?
|
76
|
+
Config.instance.track_long_running_jobs
|
77
|
+
end
|
27
78
|
end
|
28
79
|
end
|
29
80
|
end
|
@@ -16,14 +16,5 @@ Gem::Specification.new do |spec|
|
|
16
16
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
17
|
spec.require_paths = ["lib"]
|
18
18
|
|
19
|
-
spec.
|
20
|
-
|
21
|
-
spec.add_development_dependency "bundler", "~> 2.0"
|
22
|
-
spec.add_development_dependency "rake", "~> 10.0"
|
23
|
-
spec.add_development_dependency "rspec", "~> 3.0"
|
24
|
-
spec.add_development_dependency "vcr", "~> 3.0"
|
25
|
-
spec.add_development_dependency "webmock"
|
26
|
-
spec.add_development_dependency "pry"
|
27
|
-
spec.add_development_dependency "pry-byebug"
|
28
|
-
spec.add_development_dependency "sidekiq", "~> 5.0"
|
19
|
+
spec.required_ruby_version = '>= 2.5'
|
29
20
|
end
|
metadata
CHANGED
@@ -1,142 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails_autoscale_agent
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam McCrea
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
12
|
-
dependencies:
|
13
|
-
|
14
|
-
name: activesupport
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '3.2'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '3.2'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: bundler
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '2.0'
|
34
|
-
type: :development
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '2.0'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: rake
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '10.0'
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '10.0'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: rspec
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - "~>"
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '3.0'
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - "~>"
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '3.0'
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: vcr
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - "~>"
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '3.0'
|
76
|
-
type: :development
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - "~>"
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '3.0'
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: webmock
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - ">="
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '0'
|
90
|
-
type: :development
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - ">="
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '0'
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
|
-
name: pry
|
99
|
-
requirement: !ruby/object:Gem::Requirement
|
100
|
-
requirements:
|
101
|
-
- - ">="
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: '0'
|
104
|
-
type: :development
|
105
|
-
prerelease: false
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
107
|
-
requirements:
|
108
|
-
- - ">="
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
version: '0'
|
111
|
-
- !ruby/object:Gem::Dependency
|
112
|
-
name: pry-byebug
|
113
|
-
requirement: !ruby/object:Gem::Requirement
|
114
|
-
requirements:
|
115
|
-
- - ">="
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
version: '0'
|
118
|
-
type: :development
|
119
|
-
prerelease: false
|
120
|
-
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
requirements:
|
122
|
-
- - ">="
|
123
|
-
- !ruby/object:Gem::Version
|
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'
|
139
|
-
description:
|
11
|
+
date: 2021-01-12 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description:
|
140
14
|
email:
|
141
15
|
- adam@adamlogic.com
|
142
16
|
executables: []
|
@@ -147,6 +21,8 @@ files:
|
|
147
21
|
- ".rspec"
|
148
22
|
- ".ruby-version"
|
149
23
|
- ".travis.yml"
|
24
|
+
- ".vscode/tasks.json"
|
25
|
+
- CHANGELOG.md
|
150
26
|
- Gemfile
|
151
27
|
- LICENSE.txt
|
152
28
|
- README.md
|
@@ -167,6 +43,9 @@ files:
|
|
167
43
|
- lib/rails_autoscale_agent/store.rb
|
168
44
|
- lib/rails_autoscale_agent/time_rounder.rb
|
169
45
|
- lib/rails_autoscale_agent/version.rb
|
46
|
+
- lib/rails_autoscale_agent/worker_adapters/delayed_job.rb
|
47
|
+
- lib/rails_autoscale_agent/worker_adapters/que.rb
|
48
|
+
- lib/rails_autoscale_agent/worker_adapters/resque.rb
|
170
49
|
- lib/rails_autoscale_agent/worker_adapters/sidekiq.rb
|
171
50
|
- log/.gitkeep
|
172
51
|
- rails_autoscale_agent.gemspec
|
@@ -174,7 +53,7 @@ homepage: https://github.com/adamlogic/rails_autoscale_agent
|
|
174
53
|
licenses:
|
175
54
|
- MIT
|
176
55
|
metadata: {}
|
177
|
-
post_install_message:
|
56
|
+
post_install_message:
|
178
57
|
rdoc_options: []
|
179
58
|
require_paths:
|
180
59
|
- lib
|
@@ -182,15 +61,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
182
61
|
requirements:
|
183
62
|
- - ">="
|
184
63
|
- !ruby/object:Gem::Version
|
185
|
-
version: '
|
64
|
+
version: '2.5'
|
186
65
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
187
66
|
requirements:
|
188
67
|
- - ">="
|
189
68
|
- !ruby/object:Gem::Version
|
190
69
|
version: '0'
|
191
70
|
requirements: []
|
192
|
-
rubygems_version: 3.
|
193
|
-
signing_key:
|
71
|
+
rubygems_version: 3.1.4
|
72
|
+
signing_key:
|
194
73
|
specification_version: 4
|
195
74
|
summary: This gem works with the Rails Autoscale Heroku add-on to automatically scale
|
196
75
|
your web dynos.
|