judoscale-rails 1.10.0 → 1.11.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8126459482ea24a61ab251dc19235c8c52f3087d9104ff68d1442e4fb73d4698
4
- data.tar.gz: 3a25a9b8ced78ffdb8d21351085ccadfb533ecddda22b735b37c8d278977e88d
3
+ metadata.gz: 2c29391e2e1f325012b0a1597aa45800f4087bef039772e47bd2d06c91ea62ac
4
+ data.tar.gz: ed8f5d30b36a4241365a4cda20bc37960db8412f877af0a6d2848134ac6e30ff
5
5
  SHA512:
6
- metadata.gz: b23c16010590b9270a1b1369e95b64eac963993391dfeb415a7e37544d2c06e199d562014b4aa9226087a5ae34c38ae60ba43d59e9455efa60789e71bcc4046c
7
- data.tar.gz: a3af90edce5f9b7124dea6d4e599f2c1543f6655fe50cfe341ece06e15e9dd4738671f0886270fd2dd5f791165924018a3cd86da89c789ae4fab3cd861c81a8a
6
+ metadata.gz: c7ddebe2f73ba2f2848f7c998c9d03d452fba53dbf9149fee9240ae9d1a5db984a9c8a6187608bf5d38c0cf9a0f51fe832a2309d4317d01678b87c1bb47a657b
7
+ data.tar.gz: caecc435343f2db8606a20f2c22651f609103df1a21b93cbb080f6db886edb71843ddc68c4cb4f78ede83945ded3aa119564dd7c61faf11da5608355c3f099ad
@@ -3,12 +3,15 @@ require "judoscale/config"
3
3
  module Judoscale
4
4
  module Rails
5
5
  module Config
6
- attr_accessor :start_reporter_after_initialize, :rake_task_ignore_regex
6
+ attr_accessor :start_reporter_after_initialize, :rake_task_ignore_regex, :utilization_enabled, :utilization_interval
7
7
 
8
8
  def reset
9
9
  super
10
10
  @start_reporter_after_initialize = true
11
11
  @rake_task_ignore_regex = /assets:|db:/
12
+
13
+ @utilization_enabled = ENV["JUDOSCALE_UTILIZATION_ENABLED"] == "true"
14
+ @utilization_interval = (ENV["JUDOSCALE_UTILIZATION_INTERVAL"] || 1.0).to_f
12
15
  end
13
16
  end
14
17
 
@@ -1,15 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "rails"
4
- require "rails/railtie"
4
+ require "rails/engine"
5
5
  require "judoscale/request_middleware"
6
6
  require "judoscale/rails/config"
7
+ require "judoscale/rails/utilization_middleware"
7
8
  require "judoscale/logger"
8
9
  require "judoscale/reporter"
9
10
 
10
11
  module Judoscale
11
12
  module Rails
12
- class Railtie < ::Rails::Railtie
13
+ # Inherit from `Engine`, even though we use none its specific features (yet), so we can safely rely
14
+ # on `load_config_initializers` to setup our initializers and avoid loading `config/initializers/*`
15
+ # too early, otherwise we can run into initialization order conflicts with other libraries like
16
+ # `Sentry` and `Scout`, which patch Ruby classes in different ways (`prepend` vs `alias_method`),
17
+ # and may cause `stack level too deep` errors if they are loaded too early in the init process.
18
+ class Railtie < ::Rails::Engine
13
19
  include Judoscale::Logger
14
20
 
15
21
  def in_rails_console_or_runner?
@@ -27,14 +33,20 @@ module Judoscale
27
33
  ::Judoscale::Config.instance
28
34
  end
29
35
 
30
- initializer "Judoscale.logger" do |app|
36
+ initializer "judoscale.logger" do |app|
31
37
  judoscale_config.logger = ::Rails.logger
32
38
  end
33
39
 
34
- initializer "Judoscale.request_middleware" do |app|
40
+ initializer "judoscale.request_middleware" do |app|
35
41
  app.middleware.insert_before Rack::Runtime, RequestMiddleware
36
42
  end
37
43
 
44
+ initializer "judoscale.utilization_middleware", after: :load_config_initializers do |app|
45
+ if judoscale_config.utilization_enabled
46
+ app.middleware.insert_before RequestMiddleware, UtilizationMiddleware, interval: judoscale_config.utilization_interval
47
+ end
48
+ end
49
+
38
50
  config.after_initialize do
39
51
  if in_rails_console_or_runner?
40
52
  logger.debug "No reporting since we're in a Rails console or runner process"
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "singleton"
4
+ require "concurrent"
5
+ require "judoscale/metrics_store"
6
+
7
+ module Judoscale
8
+ module Rails
9
+ class UtilizationMiddleware
10
+ def initialize(app, interval:)
11
+ @app = app
12
+ @interval = interval
13
+ end
14
+
15
+ def call(env)
16
+ tracker = UtilizationTracker.instance
17
+ tracker.start!(interval: @interval)
18
+ tracker.incr
19
+
20
+ @app.call(env)
21
+ ensure
22
+ tracker.decr
23
+ end
24
+ end
25
+
26
+ class UtilizationTracker
27
+ include Singleton
28
+
29
+ def initialize
30
+ @active_request_counter = Concurrent::AtomicFixnum.new(0)
31
+ @thread_ref = Concurrent::AtomicReference.new(nil)
32
+ end
33
+
34
+ def start!(interval:)
35
+ @thread_ref.update do |current_thread|
36
+ next current_thread if current_thread&.alive?
37
+
38
+ Thread.new do
39
+ # Advise multi-threaded app servers to ignore this thread for the purposes of fork safety warnings.
40
+ Thread.current.thread_variable_set(:fork_safe, true)
41
+
42
+ loop do
43
+ sleep interval
44
+ track_current_state
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ def incr
51
+ @active_request_counter.increment
52
+ end
53
+
54
+ def decr
55
+ @active_request_counter.decrement
56
+ end
57
+
58
+ def track_current_state
59
+ active_requests = @active_request_counter.value
60
+ active_processes = (active_requests > 0) ? 1 : 0
61
+ time = Time.now.utc
62
+
63
+ MetricsStore.instance.tap do |store|
64
+ store.push :pu, active_processes, time # pu = process utilization
65
+ store.push :ru, active_requests, time # ru = request utilization
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
metadata CHANGED
@@ -1,16 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: judoscale-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.10.0
4
+ version: 1.11.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam McCrea
8
8
  - Carlos Antonio da Silva
9
9
  - Jon Sullivan
10
- autorequire:
11
10
  bindir: bin
12
11
  cert_chain: []
13
- date: 2025-02-17 00:00:00.000000000 Z
12
+ date: 1980-01-02 00:00:00.000000000 Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
15
  name: judoscale-ruby
@@ -18,14 +17,14 @@ dependencies:
18
17
  requirements:
19
18
  - - '='
20
19
  - !ruby/object:Gem::Version
21
- version: 1.10.0
20
+ version: 1.11.1
22
21
  type: :runtime
23
22
  prerelease: false
24
23
  version_requirements: !ruby/object:Gem::Requirement
25
24
  requirements:
26
25
  - - '='
27
26
  - !ruby/object:Gem::Version
28
- version: 1.10.0
27
+ version: 1.11.1
29
28
  - !ruby/object:Gem::Dependency
30
29
  name: railties
31
30
  requirement: !ruby/object:Gem::Requirement
@@ -40,7 +39,6 @@ dependencies:
40
39
  - - ">="
41
40
  - !ruby/object:Gem::Version
42
41
  version: '0'
43
- description:
44
42
  email:
45
43
  - hello@judoscale.com
46
44
  executables: []
@@ -51,6 +49,7 @@ files:
51
49
  - lib/judoscale/rails.rb
52
50
  - lib/judoscale/rails/config.rb
53
51
  - lib/judoscale/rails/railtie.rb
52
+ - lib/judoscale/rails/utilization_middleware.rb
54
53
  homepage: https://judoscale.com
55
54
  licenses:
56
55
  - MIT
@@ -60,7 +59,6 @@ metadata:
60
59
  documentation_uri: https://judoscale.com/docs
61
60
  changelog_uri: https://github.com/judoscale/judoscale-ruby/blob/main/CHANGELOG.md
62
61
  source_code_uri: https://github.com/judoscale/judoscale-ruby
63
- post_install_message:
64
62
  rdoc_options: []
65
63
  require_paths:
66
64
  - lib
@@ -75,8 +73,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
75
73
  - !ruby/object:Gem::Version
76
74
  version: '0'
77
75
  requirements: []
78
- rubygems_version: 3.5.22
79
- signing_key:
76
+ rubygems_version: 3.6.7
80
77
  specification_version: 4
81
78
  summary: Autoscaling for Ruby on Rails applications.
82
79
  test_files: []