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 +4 -4
- data/CHANGELOG.md +5 -1
- data/README.md +21 -3
- data/lib/gvl_metrics_middleware/rack.rb +20 -1
- data/lib/gvl_metrics_middleware/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 49d838fbb9b6654650f146cff085b6dc40a1569c07c6d2e03453007bcbab6a58
|
|
4
|
+
data.tar.gz: ebad112fc9f619e494b54a100551c74859d885446d2c70b93d1119b0324dc99f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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 ([#
|
|
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
|
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.
|
|
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:
|
|
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: []
|