judoscale-ruby 1.4.1 → 1.5.1

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: b5ca5d8a39c5ebac4175cf82ee527e731b3d2ca749b54ad39c1fb7901cabbc16
4
- data.tar.gz: 3b33a3243e86bafbbe2f4c492a426ef12c45d46b14a34953e4fd4785a5884c9d
3
+ metadata.gz: 34e63423106d499e2a555bf9343d38224e1eeb1e4f2fa2177d532ff33df3de81
4
+ data.tar.gz: 7efed4c6de8f587dac09c10ede982a67f73aba88e6ffeb3275db19dc968f1df7
5
5
  SHA512:
6
- metadata.gz: 4fcb9704f24d532eda30e5c464428ae52bcdc1d41627da9c1d3408d9a04e099206c74d90c45456c676f33661805fa469cfa250313fbde9fce9fae6a2897ae75e
7
- data.tar.gz: f7a8c075e63febeb03473ddeb4f3c6601916ff4208bfd5d5cf69f90056291d9fea7d2d3b7cc6fbadb6ce0db43958a751f6ad1f7fefd4f596c5ae38b208199567
6
+ metadata.gz: 2858316d5ec92aaca9b448a30699fb64dae7a970a97bf3bd4e54437d5ed5877782efd2b2c698e7c45e5f1c122b652c6463d26e98349c248cf580869bea974aa6
7
+ data.tar.gz: 659d23cad27612aff9c3653890758a40a315eaea4e3d319cbb0d36ada38568a00168e13601220ef06dcec7ed49dec325accd1fb844924665e031d7e32bfd4fa4
data/Gemfile CHANGED
@@ -4,5 +4,6 @@ gemspec name: "judoscale-ruby"
4
4
 
5
5
  gem "rake", ">= 12.3.3"
6
6
  gem "minitest"
7
+ gem "minitest-stub-const"
7
8
  gem "webmock"
8
9
  gem "debug"
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- judoscale-ruby (1.4.1)
4
+ judoscale-ruby (1.5.1)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -18,6 +18,7 @@ GEM
18
18
  irb (1.6.2)
19
19
  reline (>= 0.3.0)
20
20
  minitest (5.17.0)
21
+ minitest-stub-const (0.6)
21
22
  public_suffix (5.0.1)
22
23
  rake (13.0.6)
23
24
  reline (0.3.2)
@@ -31,6 +32,7 @@ GEM
31
32
  PLATFORMS
32
33
  arm64-darwin-20
33
34
  arm64-darwin-21
35
+ arm64-darwin-22
34
36
  x86_64-darwin-21
35
37
  x86_64-linux
36
38
 
@@ -38,6 +40,7 @@ DEPENDENCIES
38
40
  debug
39
41
  judoscale-ruby!
40
42
  minitest
43
+ minitest-stub-const
41
44
  rake (>= 12.3.3)
42
45
  webmock
43
46
 
@@ -5,35 +5,14 @@ require "logger"
5
5
 
6
6
  module Judoscale
7
7
  class Config
8
- class RuntimeContainer
9
- # E.g.:
10
- # (Heroku) => "worker_fast", "3"
11
- # (Render) => "srv-cfa1es5a49987h4vcvfg", "5497f74465-m5wwr", "web" (or "worker", "pserv", "cron", "static")
12
- def initialize(service_name = nil, instance = nil, service_type = nil)
13
- @service_name = service_name
14
- @instance = instance
15
- @service_type = service_type
16
- end
17
-
18
- def to_s
19
- # heroku: 'worker_fast.5'
20
- # render: 'srv-cfa1es5a49987h4vcvfg.5497f74465-m5wwr'
21
- "#{@service_name}.#{@instance}"
22
- end
23
-
24
- def web?
25
- # NOTE: Heroku isolates 'web' as the required _name_ for its web process
26
- # type, Render exposes the actual service type more explicitly
27
- @service_name == "web" || @service_type == "web"
28
- end
29
-
8
+ class RuntimeContainer < String
30
9
  # Since Heroku exposes ordinal dyno 'numbers', we can tell if the current
31
10
  # instance is redundant (and thus skip collecting some metrics sometimes)
32
11
  # We don't have a means of determining that on Render though — so every
33
12
  # instance must be considered non-redundant
34
13
  def redundant_instance?
35
- instance_is_number = Integer(@instance, exception: false)
36
- instance_is_number && instance_is_number != 1
14
+ instance_number = split(".")[1].to_i
15
+ instance_number > 1
37
16
  end
38
17
  end
39
18
 
@@ -86,7 +65,7 @@ module Judoscale
86
65
  end
87
66
 
88
67
  attr_accessor :api_base_url, :report_interval_seconds,
89
- :max_request_size_bytes, :logger, :log_tag, :current_runtime_container
68
+ :max_request_size_bytes, :logger, :log_tag, :current_runtime_container, :allow_rake_tasks
90
69
  attr_reader :log_level
91
70
 
92
71
  def initialize
@@ -98,6 +77,7 @@ module Judoscale
98
77
  @log_tag = "Judoscale"
99
78
  @max_request_size_bytes = 100_000 # ignore request payloads over 100k since they skew the queue times
100
79
  @report_interval_seconds = 10
80
+ @allow_rake_tasks = []
101
81
 
102
82
  self.log_level = ENV["JUDOSCALE_LOG_LEVEL"] || ENV["RAILS_AUTOSCALE_LOG_LEVEL"]
103
83
  @logger = ::Logger.new($stdout)
@@ -106,14 +86,17 @@ module Judoscale
106
86
 
107
87
  if ENV["RENDER_INSTANCE_ID"]
108
88
  instance = ENV["RENDER_INSTANCE_ID"].delete_prefix(ENV["RENDER_SERVICE_ID"]).delete_prefix("-")
109
- @current_runtime_container = RuntimeContainer.new ENV["RENDER_SERVICE_ID"], instance, ENV["RENDER_SERVICE_TYPE"]
110
- @api_base_url ||= "https://adapter.judoscale.com/api/#{ENV["RENDER_SERVICE_ID"]}"
89
+ @current_runtime_container = RuntimeContainer.new instance
90
+ # Allow a custom API base URL to be set for Render (for testing)
91
+ @api_base_url ||= "https://adapter.judoscale.com/api"
92
+ @api_base_url += "/#{ENV["RENDER_SERVICE_ID"]}"
111
93
  elsif ENV["DYNO"]
112
- service_name, instance = ENV["DYNO"].split "."
113
- @current_runtime_container = RuntimeContainer.new service_name, instance
94
+ @current_runtime_container = RuntimeContainer.new ENV["DYNO"]
95
+ elsif (metadata_uri = ENV["ECS_CONTAINER_METADATA_URI"])
96
+ @current_runtime_container = RuntimeContainer.new(metadata_uri.split("/").last)
114
97
  else
115
98
  # unsupported platform? Don't want to leave @current_runtime_container nil though
116
- @current_runtime_container = RuntimeContainer.new
99
+ @current_runtime_container = RuntimeContainer.new("")
117
100
  end
118
101
  end
119
102
 
@@ -12,6 +12,12 @@ module Judoscale
12
12
  sql
13
13
  end
14
14
 
15
+ def self.table_exists?(table_name)
16
+ ::ActiveRecord::Base.connection.table_exists?(table_name)
17
+ rescue ActiveRecord::NoDatabaseError
18
+ false
19
+ end
20
+
15
21
  private
16
22
 
17
23
  def run_silently(&block)
@@ -9,7 +9,7 @@ module Judoscale
9
9
  include Judoscale::Logger
10
10
 
11
11
  def self.collect?(config)
12
- !config.current_runtime_container.redundant_instance? && adapter_config.enabled
12
+ super && !config.current_runtime_container.redundant_instance? && adapter_config.enabled
13
13
  end
14
14
 
15
15
  def self.adapter_name
@@ -3,11 +3,22 @@
3
3
  module Judoscale
4
4
  class MetricsCollector
5
5
  def self.collect?(config)
6
- true
6
+ in_rake_task = defined?(::Rake) && Rake.respond_to?(:application) && Rake.application.top_level_tasks.any?
7
+
8
+ !in_rake_task || in_whitelisted_rake_tasks?(config.allow_rake_tasks)
7
9
  end
8
10
 
9
11
  def collect
10
12
  []
11
13
  end
14
+
15
+ def self.in_whitelisted_rake_tasks?(allowed_rake_tasks)
16
+ # Get the tasks that were invoked from the command line.
17
+ tasks = Rake.application.top_level_tasks
18
+
19
+ allowed_rake_tasks.any? do |task_regex|
20
+ tasks.any? { |task| task =~ task_regex }
21
+ end
22
+ end
12
23
  end
13
24
  end
@@ -20,23 +20,25 @@ module Judoscale
20
20
  @pid = Process.pid
21
21
 
22
22
  if !config.api_base_url
23
- logger.debug "Reporter not started: JUDOSCALE_URL is not set"
23
+ logger.debug "Set api_base_url to enable metrics reporting"
24
24
  return
25
25
  end
26
26
 
27
- enabled_adapters = adapters.select { |adapter|
27
+ enabled_adapters, skipped_adapters = adapters.partition { |adapter|
28
+ # judoscale-ruby adapter does not have a metrics collector
28
29
  adapter.metrics_collector.nil? || adapter.metrics_collector.collect?(config)
29
30
  }
30
31
  metrics_collectors_classes = enabled_adapters.map(&:metrics_collector)
31
32
  metrics_collectors_classes.compact!
32
33
 
33
34
  if metrics_collectors_classes.empty?
34
- logger.debug "Reporter not started: no metrics need to be collected in this process"
35
+ adapters_msg = skipped_adapters.map(&:identifier).join(", ")
36
+ logger.debug "No metrics need to be collected (adapters: #{adapters_msg})"
35
37
  return
36
38
  end
37
39
 
38
40
  adapters_msg = enabled_adapters.map(&:identifier).join(", ")
39
- logger.info "Reporter starting, will report every #{config.report_interval_seconds} seconds or so. Adapters: [#{adapters_msg}]"
41
+ logger.info "Reporter starting, will report every ~#{config.report_interval_seconds} seconds (adapters: #{adapters_msg})"
40
42
 
41
43
  metrics_collectors = metrics_collectors_classes.map(&:new)
42
44
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Judoscale
4
- VERSION = "1.4.1"
4
+ VERSION = "1.5.1"
5
5
  end
@@ -5,12 +5,6 @@ require "judoscale/metrics_store"
5
5
 
6
6
  module Judoscale
7
7
  class WebMetricsCollector < MetricsCollector
8
- # NOTE: We collect metrics on all running web processes since they
9
- # all receive and handle requests independently
10
- def self.collect?(config)
11
- config.current_runtime_container.web?
12
- end
13
-
14
8
  def collect
15
9
  MetricsStore.instance.flush
16
10
  end
metadata CHANGED
@@ -1,18 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: judoscale-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.1
4
+ version: 1.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam McCrea
8
8
  - Carlos Antonio da Silva
9
9
  - Jon Sullivan
10
- autorequire:
10
+ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2023-05-04 00:00:00.000000000 Z
13
+ date: 2023-08-09 00:00:00.000000000 Z
14
14
  dependencies: []
15
- description:
15
+ description:
16
16
  email:
17
17
  - hello@judoscale.com
18
18
  executables: []
@@ -49,7 +49,7 @@ metadata:
49
49
  documentation_uri: https://judoscale.com/docs
50
50
  changelog_uri: https://github.com/judoscale/judoscale-ruby/blob/main/CHANGELOG.md
51
51
  source_code_uri: https://github.com/judoscale/judoscale-ruby
52
- post_install_message:
52
+ post_install_message:
53
53
  rdoc_options: []
54
54
  require_paths:
55
55
  - lib
@@ -64,8 +64,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
64
64
  - !ruby/object:Gem::Version
65
65
  version: '0'
66
66
  requirements: []
67
- rubygems_version: 3.2.32
68
- signing_key:
67
+ rubygems_version: 3.4.10
68
+ signing_key:
69
69
  specification_version: 4
70
70
  summary: This gem works with the Judoscale Heroku add-on to automatically scale your
71
71
  web and worker dynos.