yabeda-gvl_metrics 0.1.0 → 0.2.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: f265172814eb83a804e681355deef2db2dafbc7f37da386273eb7ce220b1b409
4
- data.tar.gz: 1cae20c48cf0478512afcd118945f58b9291da91c30014cdc546a0c4ba9b7a7c
3
+ metadata.gz: c8749669e68bbeda5b52d65280f39b68f008e23f7d043bb35a3cd993acd2ff5a
4
+ data.tar.gz: a7bb3003b69681c70b99e73be3330a694abd8036168c0a858678b47a8a3bbf95
5
5
  SHA512:
6
- metadata.gz: 69ab9b4aed9771456be0586d35c8d06430f556ffd272c774df2e3c1b624ed240772196f903224d1049232c045562b5f7d8f13c88f01e23040eee83e4d5731890
7
- data.tar.gz: 0b080cf1392f5acd4aa6472a4ecc3e3529be3ba56f5f7699cfbf76d84f14931f88ce0d452ba19c846c0853beb761058a584f24d271190b810a5d019e087e2d34
6
+ metadata.gz: 9ae994b9f1fdf4a6540024680ebaf90d05f36f5ca74238c853329217cd5184265a1e171d02df43ba975ad7e3e4c0e452013278250553514e7d59d8628c98cc07
7
+ data.tar.gz: 921f39479601ea69507705d6edfd3d40d2c7386869ca6e380a2a0b0fff034fbfdd06fb23560225eed300dace047dca93e1277e84d87faafd70ef4e7774d2a40b
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ### Added
4
+
5
+ - `hostname`, `pid`, `queue`, and `job_class` tags on all GVL metrics. `hostname`/`pid` identify the emitting process (`pid` is read per measurement so it stays correct under forking servers); `queue`/`job_class` segment Sidekiq metrics by the job's queue and class. All values are sourced locally — from within the process and from the data `gvl_metrics_middleware` already passes to the callback — with no `Sidekiq::ProcessSet`/Redis lookup. `queue` and `job_class` are empty for Rack.
6
+
3
7
  ## [0.1.0] - 2026-02-09
4
8
 
5
9
  - Initial release
data/README.md CHANGED
@@ -40,16 +40,32 @@ For non-Rails applications, call `configure!` directly after requiring the gem.
40
40
 
41
41
  ## Metrics
42
42
 
43
- All metrics are registered as Yabeda gauges in the `gvl_metrics` group with a `source` tag, reported in nanoseconds. Each gauge holds the value from the most recent request or job.
43
+ All metrics are registered as Yabeda gauges in the `gvl_metrics` group, reported in nanoseconds. Each gauge holds the value from the most recent request or job for a given set of tags.
44
44
 
45
45
  For metric definitions, see: https://github.com/speedshop/gvl_metrics_middleware?tab=readme-ov-file#available-metrics
46
46
 
47
- | Metric | Tag | Description |
48
- |--------|-----|-------------|
49
- | `gvl_metrics_total` | `source: "rack"` or `source: "sidekiq"` | Total time (running + io_wait + gvl_wait) |
50
- | `gvl_metrics_running` | `source: "rack"` or `source: "sidekiq"` | Time spent running Ruby code |
51
- | `gvl_metrics_io_wait` | `source: "rack"` or `source: "sidekiq"` | Time spent waiting on IO |
52
- | `gvl_metrics_gvl_wait` | `source: "rack"` or `source: "sidekiq"` | Time spent waiting on the GVL |
47
+ | Metric | Description |
48
+ |--------|-------------|
49
+ | `gvl_metrics_total` | Total time (running + io_wait + gvl_wait) |
50
+ | `gvl_metrics_running` | Time spent running Ruby code |
51
+ | `gvl_metrics_io_wait` | Time spent waiting on IO |
52
+ | `gvl_metrics_gvl_wait` | Time spent waiting on the GVL |
53
+
54
+ ### Tags
55
+
56
+ Every metric carries the following tags, so you can attribute GVL time to a specific process and, for Sidekiq, to the job that ran:
57
+
58
+ | Tag | Description |
59
+ |-----|-------------|
60
+ | `source` | `"rack"` or `"sidekiq"` |
61
+ | `hostname` | Host the process runs on (`ENV["DYNO"]` if set, otherwise `Socket.gethostname` — the same value Sidekiq reports for itself) |
62
+ | `pid` | Process ID. Read fresh on every measurement, so it stays correct under forking servers (e.g. Puma in cluster mode) |
63
+ | `queue` | Sidekiq only: the queue the job was pulled from. Empty for Rack. |
64
+ | `job_class` | Sidekiq only: the job's class name. Empty for Rack. |
65
+
66
+ The `hostname`, `pid`, `queue`, and `job_class` values are read locally from within the running process and from the data `gvl_metrics_middleware` already passes to the callback — there is no `Sidekiq::ProcessSet`/Redis lookup involved.
67
+
68
+ > **Cardinality:** `queue` and especially `job_class` multiply the number of time series per process (one series per `source`/`queue`/`job_class` combination), and `pid` produces a new series for every restart or redeploy. On apps with many job classes this can add up — keep an eye on your metrics backend's cardinality.
53
69
 
54
70
  ## Contributing
55
71
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Yabeda
4
4
  module GvlMetrics
5
- VERSION = "0.1.0"
5
+ VERSION = "0.2.0"
6
6
  end
7
7
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "socket"
4
+
3
5
  require "yabeda"
4
6
  require "gvl_metrics_middleware"
5
7
 
@@ -10,7 +12,7 @@ module Yabeda
10
12
  class Error < StandardError; end
11
13
 
12
14
  METRIC_GROUP = :gvl_metrics
13
- METRIC_TAGS = [:source].freeze
15
+ METRIC_TAGS = %i[source hostname pid queue job_class].freeze
14
16
 
15
17
  class << self
16
18
  def configure!(rack: defined?(::Rack), sidekiq: defined?(::Sidekiq))
@@ -39,26 +41,60 @@ module Yabeda
39
41
  GvlMetricsMiddleware.configure do |config|
40
42
  if rack
41
43
  config.rack do |total, running, io_wait, gvl_wait|
42
- record("rack", total, running, io_wait, gvl_wait)
44
+ record_rack(total, running, io_wait, gvl_wait)
43
45
  end
44
46
  end
45
47
 
46
48
  if sidekiq
47
- config.sidekiq do |total, running, io_wait, gvl_wait|
48
- record("sidekiq", total, running, io_wait, gvl_wait)
49
+ # gvl_metrics_middleware already hands the current job's queue and
50
+ # class to the callback as keyword arguments, so we can segment by
51
+ # them without any Sidekiq::ProcessSet/Redis lookup. They are given
52
+ # defaults so this stays compatible with any middleware version that
53
+ # does not send them.
54
+ config.sidekiq do |total, running, io_wait, gvl_wait, queue: nil, job_class: nil|
55
+ record_sidekiq(total, running, io_wait, gvl_wait, queue: queue, job_class: job_class)
49
56
  end
50
57
  end
51
58
  end
52
59
  end
53
60
 
54
- def record(source, total, running, io_wait, gvl_wait)
55
- tags = { source: source }
61
+ def record_rack(total, running, io_wait, gvl_wait)
62
+ write_metrics({ source: "rack", hostname: hostname, pid: ::Process.pid }, total, running, io_wait, gvl_wait)
63
+ end
64
+
65
+ def record_sidekiq(total, running, io_wait, gvl_wait, queue: nil, job_class: nil)
66
+ tags = {
67
+ source: "sidekiq",
68
+ hostname: hostname,
69
+ pid: ::Process.pid,
70
+ queue: queue.to_s,
71
+ job_class: job_class.to_s,
72
+ }
73
+
74
+ write_metrics(tags, total, running, io_wait, gvl_wait)
75
+ end
76
+
77
+ def write_metrics(tags, total, running, io_wait, gvl_wait)
78
+ # Every gauge is declared with the full METRIC_TAGS set, and exporters such
79
+ # as yabeda-prometheus reject a write that omits any declared tag. Default
80
+ # the tags a source does not set (queue/job_class for Rack) to an empty
81
+ # string so callers don't have to spell them out.
82
+ tags = { queue: "", job_class: "" }.merge(tags)
56
83
 
57
84
  Yabeda.gvl_metrics.total.set(tags, total)
58
85
  Yabeda.gvl_metrics.running.set(tags, running)
59
86
  Yabeda.gvl_metrics.io_wait.set(tags, io_wait)
60
87
  Yabeda.gvl_metrics.gvl_wait.set(tags, gvl_wait)
61
88
  end
89
+
90
+ # The host name does not change across a fork, so memoizing it (even if the
91
+ # value is inherited by a forked worker) is safe. The pid, which does change
92
+ # on fork, is read fresh on every call instead, so it stays correct under
93
+ # forking servers such as Puma in cluster mode. This mirrors how Sidekiq
94
+ # itself derives its hostname.
95
+ def hostname
96
+ @hostname ||= ENV["DYNO"] || Socket.gethostname
97
+ end
62
98
  end
63
99
  end
64
100
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yabeda-gvl_metrics
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nate Berkopec
@@ -77,7 +77,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
77
77
  - !ruby/object:Gem::Version
78
78
  version: '0'
79
79
  requirements: []
80
- rubygems_version: 4.0.3
80
+ rubygems_version: 4.0.12
81
81
  specification_version: 4
82
82
  summary: Yabeda plugin for exporting GVL metrics collected by gvl_metrics_middleware.
83
83
  test_files: []