judoscale-ruby 1.10.0 → 1.11.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a4bc0aac7fb199da1e1e4602136b9c3c9bf5a9210861893172e1a33988a1c60a
4
- data.tar.gz: 1fd02e843f7d67331a8d843e70931c4b32c84310d299b8a5f12b6a3effdff4af
3
+ metadata.gz: 92983f008bba242830346f573d60a9c7302c794cac38afbc0e78b359e4dd09e2
4
+ data.tar.gz: 0c7971f58dab5fa1c17b43e14f25db639d5d81b2b0b2dc60e123e6951f0f645c
5
5
  SHA512:
6
- metadata.gz: c88289dafeb2033b5bbbcdb90f5ff2e68520d7ce0a446af958632c3551e433f6eeea0c7ec531687d1acd03275ebdb954463e3a6edcc71ba6638ea13672ae3d1b
7
- data.tar.gz: 828b3bebf4c5823a83448698d83b939b620f57d6111ace29bd046a81e9735ab30dbfcfbf0d79169fdc95381ec79298b55f7d20c91809cd1041f7350780aa4c3a
6
+ metadata.gz: f5452b651fe1582de5c6ae1c96f78738b30d2090635df3701a1e8d987f19ac0c6d9cb6a408cafcea62e0208616a5a11680919cb42695ef01023887980a4fa71c
7
+ data.tar.gz: c63a089e0f391605166f7c65b2b0afd457bb05fde10a7c9cd1a1cf67641f67721f5a08f5005c38b8057ac4a7877738917506b2e724ff40a728263613f70f6888
@@ -35,8 +35,8 @@ module Judoscale
35
35
  @queue_filter = DEFAULT_QUEUE_FILTER
36
36
 
37
37
  # Support for deprecated legacy env var configs.
38
- @max_queues = (ENV["RAILS_AUTOSCALE_MAX_QUEUES"] || 20).to_i
39
- self.track_busy_jobs = ENV["RAILS_AUTOSCALE_LONG_JOBS"] == "true"
38
+ @max_queues = (ENV["JUDOSCALE_MAX_QUEUES"] || ENV["RAILS_AUTOSCALE_MAX_QUEUES"] || 20).to_i
39
+ self.track_busy_jobs = (ENV["JUDOSCALE_LONG_JOBS"] || ENV["RAILS_AUTOSCALE_LONG_JOBS"]) == "true"
40
40
  end
41
41
 
42
42
  def track_busy_jobs=(value)
@@ -16,39 +16,12 @@ module Judoscale
16
16
  @request_start_header = env["HTTP_X_REQUEST_START"]
17
17
  end
18
18
 
19
- def ignore?
20
- @config.ignore_large_requests? && @size > @config.max_request_size_bytes
21
- end
22
-
23
- def started_at
24
- if @request_start_header
25
- # There are several variants of this header. We handle these:
26
- # - whole milliseconds (Heroku)
27
- # - whole microseconds (???)
28
- # - whole nanoseconds (Render)
29
- # - fractional seconds (NGINX)
30
- # - preceeding "t=" (NGINX)
31
- value = @request_start_header.gsub(/[^0-9.]/, "").to_f
32
-
33
- # `value` could be seconds, milliseconds, microseconds or nanoseconds.
34
- # We use some arbitrary cutoffs to determine which one it is.
35
-
36
- if value > NANOSECONDS_CUTOFF
37
- Time.at(value / 1_000_000_000.0)
38
- elsif value > MICROSECONDS_CUTOFF
39
- Time.at(value / 1_000_000.0)
40
- elsif value > MILLISECONDS_CUTOFF
41
- Time.at(value / 1000.0)
42
- else
43
- Time.at(value)
44
- end
45
- end
19
+ def track_queue_time?
20
+ @request_start_header && !ignore_large_request?
46
21
  end
47
22
 
48
23
  def queue_time(now = Time.now)
49
- return if started_at.nil?
50
-
51
- queue_time = ((now - started_at) * 1000).to_i
24
+ queue_time = ((now.utc - started_at.utc) * 1000).to_i
52
25
 
53
26
  # Subtract the time Puma spent waiting on the request body, i.e. the network time. It's irrelevant to
54
27
  # capacity-related queue time. Without this, slow clients and large request payloads will skew queue time.
@@ -57,5 +30,42 @@ module Judoscale
57
30
  # Safeguard against negative queue times (should not happen in practice)
58
31
  (queue_time > 0) ? queue_time : 0
59
32
  end
33
+
34
+ def elapsed_time
35
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
36
+ response = yield
37
+ finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)
38
+
39
+ elapsed = ((finish - start) * 1000).to_i
40
+ [elapsed, response]
41
+ end
42
+
43
+ private
44
+
45
+ def ignore_large_request?
46
+ @config.ignore_large_requests? && @size > @config.max_request_size_bytes
47
+ end
48
+
49
+ def started_at
50
+ # There are several variants of this header. We handle these:
51
+ # - whole milliseconds (Heroku)
52
+ # - whole microseconds (???)
53
+ # - whole nanoseconds (Render)
54
+ # - fractional seconds (NGINX)
55
+ # - preceeding "t=" (NGINX)
56
+ value = @request_start_header.gsub(/[^0-9.]/, "").to_f
57
+
58
+ # `value` could be seconds, milliseconds, microseconds or nanoseconds.
59
+ # We use some arbitrary cutoffs to determine which one it is.
60
+ if value > NANOSECONDS_CUTOFF
61
+ Time.at(value / 1_000_000_000.0)
62
+ elsif value > MICROSECONDS_CUTOFF
63
+ Time.at(value / 1_000_000.0)
64
+ elsif value > MILLISECONDS_CUTOFF
65
+ Time.at(value / 1000.0)
66
+ else
67
+ Time.at(value)
68
+ end
69
+ end
60
70
  end
61
71
  end
@@ -15,30 +15,33 @@ module Judoscale
15
15
 
16
16
  def call(env)
17
17
  request_metrics = RequestMetrics.new(env)
18
+ store = MetricsStore.instance
19
+ time = Time.now.utc
18
20
 
19
- unless request_metrics.ignore?
20
- queue_time = request_metrics.queue_time
21
+ if request_metrics.track_queue_time?
22
+ queue_time = request_metrics.queue_time(time)
21
23
  network_time = request_metrics.network_time
22
- end
23
-
24
- Reporter.start
25
-
26
- if queue_time
27
- store = MetricsStore.instance
28
24
 
29
25
  # NOTE: Expose queue time to the app
30
26
  env["judoscale.queue_time"] = queue_time
31
- store.push :qt, queue_time
27
+ store.push :qt, queue_time, time
32
28
 
33
29
  unless network_time.zero?
34
30
  env["judoscale.network_time"] = network_time
35
- store.push :nt, network_time
31
+ store.push :nt, network_time, time
36
32
  end
37
33
 
38
34
  logger.debug "Request queue_time=#{queue_time}ms network_time=#{network_time}ms request_id=#{request_metrics.request_id} size=#{request_metrics.size}"
39
35
  end
40
36
 
41
- @app.call(env)
37
+ Reporter.start
38
+
39
+ app_time, response = request_metrics.elapsed_time do
40
+ @app.call(env)
41
+ end
42
+ store.push :at, app_time, time
43
+
44
+ response
42
45
  end
43
46
  end
44
47
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Judoscale
4
- VERSION = "1.10.0"
4
+ VERSION = "1.11.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: judoscale-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.10.0
4
+ version: 1.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam McCrea
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2025-02-17 00:00:00.000000000 Z
13
+ date: 2025-04-28 00:00:00.000000000 Z
14
14
  dependencies: []
15
15
  description:
16
16
  email: