yabeda-rack-queue 0.1.0 → 0.2.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: 21cab04c6429f2f935c1f25dd635a57bef7b6f619775a06ee15c678cad907bc8
4
- data.tar.gz: 2b0aedeb8ab33fe5c2380942c71221b64a743c2eb7999ba2ecd153ca4703820f
3
+ metadata.gz: a2460b8b476ceba45cccd0edd32320f133780bc01681d08bcf5fb162b7dd0cf4
4
+ data.tar.gz: 3b69c898a813804c2f8194fa9e5a84cf1508c1d3df2eb52096683e1b4612d09d
5
5
  SHA512:
6
- metadata.gz: 177604e2d5e1fc330c66a074dcae18c33ed42a49afca78755e91f75675b67b04451e1d27813ec3040375f2040e221a1aa20e8348b2b17e3e9e8d70cc71b12acc
7
- data.tar.gz: 6a90ef452a54f42dd2e916ca6ef528b24cbe97993bc2dc6f0d19f767aeb1fc54bf942c37a82017d559656c57035c85ca6929107d91898f7759a3a67d6e6b9650
6
+ metadata.gz: 7b34b7083e9afb7c53825d8fd2645d74d36f4b6e9551885546de59f19d836199eb9cf3abc2a4a504d9844a52b468d157c1e6c1a3b7c1df62436b2286b1199271
7
+ data.tar.gz: c82d59eb210d12595a0c53a4330d004d0d7d4667fdb71101d0b2c2e4a017bc78b77f91ed312ceb6fae8bc68d2d28fb3ee6c7c761eb5020ffbedfc937af6b9788
data/CHANGELOG.md ADDED
@@ -0,0 +1,22 @@
1
+ # Changelog
2
+
3
+ ## 0.2.1 - 2026-06-29
4
+
5
+ ### Fixed
6
+
7
+ - Keep requests flowing if rack queue metric reporting fails, logging the error instead.
8
+ - Load `yabeda/railtie` when Rails appears after Yabeda was already required.
9
+
10
+ ## 0.2.0 - 2026-03-09
11
+
12
+ ### Changed
13
+
14
+ - Renamed the histogram metric from `rack_queue_duration` to `duration` inside the `rack_queue` group.
15
+ - The Yabeda accessor is now `Yabeda.rack_queue.duration`.
16
+ - Adapters that prepend the group name, such as Prometheus, now expose the metric as `rack_queue_duration_seconds` instead of `rack_queue_rack_queue_duration_seconds`.
17
+
18
+ ## 0.1.0 - 2026-03-08
19
+
20
+ ### Added
21
+
22
+ - Initial release.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- yabeda-rack-queue (0.1.0)
4
+ yabeda-rack-queue (0.2.1)
5
5
  yabeda (>= 0.14, < 1.0)
6
6
 
7
7
  GEM
@@ -114,7 +114,7 @@ CHECKSUMS
114
114
  unicode-display_width (3.2.0) sha256=0cdd96b5681a5949cdbc2c55e7b420facae74c4aaf9a9815eee1087cb1853c42
115
115
  unicode-emoji (4.2.0) sha256=519e69150f75652e40bf736106cfbc8f0f73aa3fb6a65afe62fefa7f80b0f80f
116
116
  yabeda (0.14.0) sha256=bc517bf22d692ebd80a29fc9fd2246c257aaf92d10b2735a775e2419351a43bf
117
- yabeda-rack-queue (0.1.0)
117
+ yabeda-rack-queue (0.2.1)
118
118
 
119
119
  BUNDLED WITH
120
120
  4.0.3
data/README.md CHANGED
@@ -12,7 +12,7 @@ High queue time means your app is too busy. It cannot take new requests. That is
12
12
 
13
13
  Load balancers can add a header to each request. The header records when the request arrived. Common headers are `X-Request-Start` and `X-Queue-Start`.
14
14
 
15
- This middleware reads that header. It subtracts the header's timestamp from the current time. Then it reports that value as `rack_queue.rack_queue_duration`.
15
+ This middleware reads that header. It subtracts the header's timestamp from the current time. Then it reports that value as `rack_queue.duration`.
16
16
 
17
17
  > [!NOTE]
18
18
  > If neither header is present, no measurement is taken. The request passes through unchanged.
@@ -55,14 +55,16 @@ config.middleware.use Yabeda::Rack::Queue::Middleware
55
55
 
56
56
  | Name | Group | Type | Unit |
57
57
  |------|-------|------|------|
58
- | `rack_queue_duration` | `rack_queue` | histogram | seconds |
58
+ | `duration` | `rack_queue` | histogram | seconds |
59
59
 
60
60
  Access it in code:
61
61
 
62
62
  ```ruby
63
- Yabeda.rack_queue.rack_queue_duration
63
+ Yabeda.rack_queue.duration
64
64
  ```
65
65
 
66
+ With adapters that prepend the group name, such as Prometheus, this becomes `rack_queue_duration_seconds`.
67
+
66
68
  Histogram buckets: 1 ms, 5 ms, 10 ms, 25 ms, 50 ms, 100 ms, 250 ms, 500 ms, 1 s, 2.5 s, 5 s, 10 s, 30 s, 60 s.
67
69
 
68
70
  ## Header formats
@@ -93,7 +95,6 @@ The middleware accepts these keyword arguments:
93
95
  | Argument | Default | Purpose |
94
96
  |----------|---------|---------|
95
97
  | `reporter:` | `YabedaReporter.new` | Writes the value to Yabeda. |
96
- | `parser:` | `HeaderTimestampParser.new` | Parses the header timestamp. |
97
98
  | `logger:` | stderr | Gets warning messages. |
98
99
  | `clock:` | `Process.clock_gettime(CLOCK_REALTIME)` | Returns current time in seconds. |
99
100
 
data/SPEC.md CHANGED
@@ -21,7 +21,7 @@ Linting uses standardrb.
21
21
 
22
22
  | Name | Type | Group | Unit | Description |
23
23
  |------|------|-------|------|-------------|
24
- | `rack_queue_duration` | histogram | `rack_queue` | seconds | Time a request waited in the upstream queue before reaching the application |
24
+ | `duration` | histogram | `rack_queue` | seconds | Time a request waited in the upstream queue before reaching the application |
25
25
 
26
26
  ### Histogram Buckets
27
27
 
@@ -2,9 +2,13 @@
2
2
 
3
3
  require "yabeda"
4
4
 
5
+ # Yabeda only loads its Railtie if Rails exists when Yabeda is first required.
6
+ # Puma plugins can require Yabeda before Rails, so retry when this gem loads.
7
+ require "yabeda/railtie" if defined?(::Rails::Railtie)
8
+
5
9
  Yabeda.configure do
6
10
  group :rack_queue do
7
- histogram :rack_queue_duration,
11
+ histogram :duration,
8
12
  comment: "Time a request waited in the upstream queue before reaching the application",
9
13
  unit: :seconds,
10
14
  buckets: [0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10, 30, 60]
@@ -9,7 +9,7 @@ module Yabeda
9
9
  end
10
10
 
11
11
  class YabedaReporter
12
- def observe(value) = Yabeda.rack_queue.rack_queue_duration.measure({}, value)
12
+ def observe(value) = Yabeda.rack_queue.duration.measure({}, value)
13
13
  end
14
14
 
15
15
  def initialize(app, reporter: YabedaReporter.new, logger: nil, clock: nil)
@@ -32,6 +32,8 @@ module Yabeda
32
32
  start = @parser.parse(env["HTTP_X_REQUEST_START"], now: now) ||
33
33
  @parser.parse(env["HTTP_X_QUEUE_START"], now: now)
34
34
  report_queue_time(env, now, start) if start
35
+ rescue => error
36
+ @logger.warn("rack queue metric failed: #{error.class}: #{error.message}")
35
37
  end
36
38
 
37
39
  def report_queue_time(env, now, request_start)
@@ -3,7 +3,7 @@
3
3
  module Yabeda
4
4
  module Rack
5
5
  module Queue
6
- VERSION = "0.1.0"
6
+ VERSION = "0.2.1"
7
7
  end
8
8
  end
9
9
  end
@@ -55,7 +55,7 @@ class PumaIntegrationTest < Minitest::Test
55
55
  super
56
56
  end
57
57
 
58
- def test_records_rack_queue_duration_histogram_via_yabeda_on_real_http_request
58
+ def test_records_duration_histogram_via_yabeda_on_real_http_request
59
59
  requested_queue_time_seconds = 0.12
60
60
  request_start_ms = ((Time.now.to_f - requested_queue_time_seconds) * 1_000).to_i
61
61
  uri = URI("http://127.0.0.1:#{@server.port}/")
@@ -66,7 +66,7 @@ class PumaIntegrationTest < Minitest::Test
66
66
 
67
67
  assert_equal "200", response.code
68
68
 
69
- metric = Yabeda.rack_queue.rack_queue_duration
69
+ metric = Yabeda.rack_queue.duration
70
70
  measured = Yabeda::TestAdapter.instance.histograms.fetch(metric).fetch({})
71
71
 
72
72
  assert_kind_of Float, measured
@@ -3,10 +3,11 @@
3
3
  require "test_helper"
4
4
 
5
5
  class MetricTest < Minitest::Test
6
- def test_registers_rack_queue_duration_histogram_with_required_metadata
7
- metric = Yabeda.rack_queue.rack_queue_duration
6
+ def test_registers_duration_histogram_with_required_metadata
7
+ metric = Yabeda.rack_queue.duration
8
8
 
9
9
  assert_instance_of Yabeda::Histogram, metric
10
+ assert_equal :duration, metric.name
10
11
  assert_equal :rack_queue, metric.group
11
12
  assert_equal :seconds, metric.unit
12
13
  assert_equal "Time a request waited in the upstream queue before reaching the application", metric.comment
@@ -14,6 +14,12 @@ class CapturingReporter
14
14
  end
15
15
  end
16
16
 
17
+ class FailingReporter
18
+ def observe(_value)
19
+ raise NoMethodError, "undefined method `rack_queue' for Yabeda:Module"
20
+ end
21
+ end
22
+
17
23
  class CapturingLogger
18
24
  attr_reader :warnings
19
25
 
@@ -144,6 +150,21 @@ class MiddlewareTest < Minitest::Test
144
150
  assert_empty @reporter.values
145
151
  end
146
152
 
153
+ def test_metric_reporting_errors_are_logged_and_do_not_break_request
154
+ middleware = Yabeda::Rack::Queue::Middleware.new(
155
+ @app,
156
+ reporter: FailingReporter.new,
157
+ clock: @clock,
158
+ logger: @logger
159
+ )
160
+
161
+ result = middleware.call("HTTP_X_REQUEST_START" => "t=1699999999.9")
162
+
163
+ assert_same @response, result
164
+ assert_equal 1, @app.called_count
165
+ assert_includes @logger.warnings.join("\n"), "rack queue metric failed: NoMethodError"
166
+ end
167
+
147
168
  def test_drops_negative_queue_times_and_logs_warning
148
169
  @middleware.call("HTTP_X_REQUEST_START" => "t=1700000000.1")
149
170
 
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+ require "open3"
5
+ require "rbconfig"
6
+
7
+ class RailtieTest < Minitest::Test
8
+ def test_loads_yabeda_railtie_when_rails_appears_after_yabeda
9
+ script = <<~RUBY
10
+ require "bundler/setup"
11
+ require "yabeda"
12
+
13
+ module Rails
14
+ class Railtie
15
+ def self.config
16
+ @config ||= Config.new
17
+ end
18
+
19
+ class Config
20
+ def after_initialize
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ require "yabeda/rack/queue"
27
+
28
+ abort "Yabeda::Rails::Railtie was not loaded" unless defined?(Yabeda::Rails::Railtie)
29
+ RUBY
30
+
31
+ stdout, stderr, status = Open3.capture3("bundle", "exec", RbConfig.ruby, "-Ilib", "-e", script)
32
+
33
+ assert status.success?, [stdout, stderr].join("\n")
34
+ end
35
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yabeda-rack-queue
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nate Berkopec
@@ -147,6 +147,7 @@ extensions: []
147
147
  extra_rdoc_files: []
148
148
  files:
149
149
  - ".gitignore"
150
+ - CHANGELOG.md
150
151
  - Gemfile
151
152
  - Gemfile.lock
152
153
  - LICENSE.txt
@@ -166,6 +167,7 @@ files:
166
167
  - test/yabeda/rack/queue/metric_test.rb
167
168
  - test/yabeda/rack/queue/middleware_performance_test.rb
168
169
  - test/yabeda/rack/queue/middleware_test.rb
170
+ - test/yabeda/rack/queue/railtie_test.rb
169
171
  - yabeda-rack-queue.gemspec
170
172
  homepage: https://github.com/speedshop/yabeda-rack-queue
171
173
  licenses:
@@ -190,7 +192,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
190
192
  - !ruby/object:Gem::Version
191
193
  version: '0'
192
194
  requirements: []
193
- rubygems_version: 4.0.3
195
+ rubygems_version: 4.0.10
194
196
  specification_version: 4
195
197
  summary: Yabeda middleware for HTTP request queue duration
196
198
  test_files: []