gvl_metrics_middleware 0.3.0 → 0.4.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: e9c303f29cd3924fceeeaa769037e69857a90f5b237c0ec10d5f94a412f5c03c
4
- data.tar.gz: 52c7a388c144debe25968379af1769d1f406214fe634961727589ca98784b78d
3
+ metadata.gz: 49d838fbb9b6654650f146cff085b6dc40a1569c07c6d2e03453007bcbab6a58
4
+ data.tar.gz: ebad112fc9f619e494b54a100551c74859d885446d2c70b93d1119b0324dc99f
5
5
  SHA512:
6
- metadata.gz: e83517c9c027b5329dcea41f6d051c1a2e5c685162a3057ee6c00294032289eb61aa8f444d4657284c9f6519d4e29458dcebd456f29018bd386a26b1cc4a9048
7
- data.tar.gz: 4a992b0675b6f32161d796f142e47c2b9232eb647bbbd7e0a64d324577794be882b5d7131dbaa24adbc74517c17dd9c3a95abaa1a6a642c5c68ec6c6ee5dd06d
6
+ metadata.gz: 33ba9dfbd6c8f8b8bccb3820d830d1e713e8bee067598035eb17d094b1e0040ffbbbd1ea68e9badafe78a09da3e258fec5ad45d2c468180e6256200582472e97
7
+ data.tar.gz: 6f0fafc8ba4e04a8834e7e0c79b98bfd4570f7c5a531863be30ed54ce0c8190aa66f6b8189167754115ec51d7fdb79362054a834bc3d509206e1a53d4fa58598
data/CHANGELOG.md CHANGED
@@ -1,10 +1,14 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.4.0] - 2026-06-19
4
+
5
+ - The Rack reporter now receives a `route:` keyword option: the request's route template — `"controller#action"` on Rails or the matched route on Sinatra (`nil` when no route matched). This lets reporters segment GVL metrics by endpoint (e.g. the CPU/IO ratio per action), mirroring the `queue`/`job_class` options the Sidekiq reporter already receives. Reporters defined as strict lambdas should accept the keyword (e.g. `->(total, running, io_wait, gvl_wait, **options) {}`); block-style reporters are unaffected.
6
+
3
7
  ## [0.3.0] - 2026-01-26
4
8
 
5
9
  - Add Ruby 4.0 support ([#25](https://github.com/speedshop/gvl_metrics_middleware/pull/25))
6
10
  - Add support for Sidekiq 5.2 ([#23](https://github.com/speedshop/gvl_metrics_middleware/pull/23))
7
- - Skip GVL measurement when no reporter is configured, improving performance ([#20](https://github.com/speedshop/gvl_metrics_middleware/pull/20))
11
+ - Skip GVL measurement when no reporter is configured, improving performance ([#21](https://github.com/speedshop/gvl_metrics_middleware/pull/21))
8
12
 
9
13
  ## [0.2.1] - 2025-11-14
10
14
 
data/README.md CHANGED
@@ -20,11 +20,14 @@ GvlMetricsMiddleware.configure do |config|
20
20
  # Optional: Set sampling rate (0.0 to 1.0, defaults to 0.01 for 1% sampling)
21
21
  config.sampling_rate = 0.1 # Sample 10% of requests/jobs
22
22
 
23
- config.rack do |total, running, io_wait, gvl_wait|
23
+ config.rack do |total, running, io_wait, gvl_wait, options|
24
+ # options[:route] is the request's route — "controller#action" on Rails or the
25
+ # matched route on Sinatra (nil when no route matched).
24
26
  # Your code here...
25
27
  end
26
28
 
27
- config.sidekiq do |total, running, io_wait, gvl_wait|
29
+ config.sidekiq do |total, running, io_wait, gvl_wait, options|
30
+ # options[:queue] and options[:job_class] describe the job.
28
31
  # Your code here...
29
32
  end
30
33
  end
@@ -38,11 +41,19 @@ GvlMetricsMiddleware.configure do |config|
38
41
  # Increase sampling from default 1% to 10% for more data
39
42
  config.sampling_rate = 0.1
40
43
 
41
- config.rack do |total, running, io_wait, gvl_wait|
44
+ config.rack do |total, running, io_wait, gvl_wait, options|
42
45
  NewRelic::Agent.record_metric("Custom/Rack/GVL/total", total)
43
46
  NewRelic::Agent.record_metric("Custom/Rack/GVL/running", running)
44
47
  NewRelic::Agent.record_metric("Custom/Rack/GVL/io_wait", io_wait)
45
48
  NewRelic::Agent.record_metric("Custom/Rack/GVL/gvl_wait", gvl_wait)
49
+
50
+ # Segment by route ("users#show" on Rails, "GET /users/:id" on Sinatra) to see
51
+ # the CPU/IO ratio per action:
52
+ route = options[:route]
53
+ if route
54
+ NewRelic::Agent.record_metric("Custom/Rack/GVL/#{route}/running", running)
55
+ NewRelic::Agent.record_metric("Custom/Rack/GVL/#{route}/io_wait", io_wait)
56
+ end
46
57
  end
47
58
 
48
59
  config.sidekiq do |total, running, io_wait, gvl_wait, options|
@@ -75,6 +86,13 @@ The `gvl_metrics_middleware` reports these metrics. All metrics are in nanosecon
75
86
  - **`io_wait`**: The time spent waiting for I/O after the thread released the GVL. Comes from `GVLTiming::Timer#idle_duration`.
76
87
  - **`gvl_wait`**: The time spent waiting to get the GVL. Comes from `GVLTiming::Timer#stalled_duration`.
77
88
 
89
+ ## Per-request context
90
+
91
+ Besides the four timing values, each callback receives a final `options` hash describing what was measured, so you can segment the metrics:
92
+
93
+ - **Rack** — `options[:route]`: the request's route *template*. On Rails this is the `"controller#action"` pair (e.g. `users#show`, `admin/users#index`); on Sinatra it is the matched route (e.g. `GET /users/:id`). It is `nil` when no route matched (404s, or a plain Rack app). Only the route template is used — never the raw path — so it stays low-cardinality.
94
+ - **Sidekiq** — `options[:queue]` and `options[:job_class]`: the queue the job ran on and its class name.
95
+
78
96
  ## Sampling
79
97
 
80
98
  By default, the middleware samples 1% of requests and jobs to keep overhead low. You can change this rate:
@@ -29,7 +29,7 @@ module GvlMetricsMiddleware
29
29
  end
30
30
 
31
31
  begin
32
- reporter.call(gvl_times.duration_ns, gvl_times.running_duration_ns, gvl_times.idle_duration_ns, gvl_times.stalled_duration_ns)
32
+ reporter.call(gvl_times.duration_ns, gvl_times.running_duration_ns, gvl_times.idle_duration_ns, gvl_times.stalled_duration_ns, route: route_for(env))
33
33
  rescue => exception
34
34
  GvlMetricsMiddleware.on_report_failure&.call("Rack", exception)
35
35
 
@@ -38,5 +38,24 @@ module GvlMetricsMiddleware
38
38
 
39
39
  response
40
40
  end
41
+
42
+ private
43
+
44
+ # The request's route template, passed to the reporter so it can segment GVL
45
+ # metrics by endpoint (for example, the CPU/IO ratio per action). On Rails it
46
+ # is the "controller#action" pair; on Sinatra it is the matched route. Only the
47
+ # route *template* is used -- never the raw path -- so it stays low-cardinality,
48
+ # and on Rails only :controller and :action are read (path_parameters also holds
49
+ # :id, :format, ...). Returns nil when no route matched (404s, or a plain Rack
50
+ # app), leaving any fallback to the reporter.
51
+ def route_for(env)
52
+ if (path_parameters = env["action_dispatch.request.path_parameters"]) # Rails
53
+ controller = path_parameters[:controller]
54
+ action = path_parameters[:action]
55
+ return "#{controller}##{action}" if controller && action
56
+ end
57
+
58
+ env["sinatra.route"] # Sinatra, e.g. "GET /users/:id"
59
+ end
41
60
  end
42
61
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GvlMetricsMiddleware
4
- VERSION = "0.3.0"
4
+ VERSION = "0.4.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gvl_metrics_middleware
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nate Berkopec
@@ -119,7 +119,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
119
119
  - !ruby/object:Gem::Version
120
120
  version: '0'
121
121
  requirements: []
122
- rubygems_version: 4.0.3
122
+ rubygems_version: 3.6.9
123
123
  specification_version: 4
124
124
  summary: Rack and Sidekiq middlewares for GVL metrics
125
125
  test_files: []