process-metrics 0.13.0 → 0.14.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
- checksums.yaml.gz.sig +0 -0
- data/context/getting-started.md +14 -0
- data/lib/process/metrics/processor/linux.rb +89 -0
- data/lib/process/metrics/processor.rb +20 -0
- data/lib/process/metrics/version.rb +1 -1
- data/readme.md +4 -4
- data/releases.md +4 -0
- data.tar.gz.sig +0 -0
- metadata +2 -1
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 86b26a801c95a764b0f98139e25ad1ac12b455b1b44b664722d1ff189bce8be4
|
|
4
|
+
data.tar.gz: 7591aff04fdbc4e9b6eabdd42ac8bcdf6ffbeea605f812b1d00255a57cba49c5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1a688f8a4db31df31adbbc5d5513716785ff61047f0b010aba506064d4c981dc5582fe99784eef0d244f877643034325d0996a323cc91e3ee1d6e6caa0e0f8e9
|
|
7
|
+
data.tar.gz: 72d8c7499461b35deafd4af20ba6c065de44f76d8868971e3ab70795febbb2863df98f9cb06c1e82e94fc1cdc7867275d58e1e03f9aa9ea890d50c5a37cf05bb
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/context/getting-started.md
CHANGED
|
@@ -112,3 +112,17 @@ sample.utilization
|
|
|
112
112
|
```
|
|
113
113
|
|
|
114
114
|
Both interfaces use the same core-unit scale. A utilization of `0.5` means half of one core on average, while `2.0` means two cores were fully occupied. Utilization is therefore not limited to the range `0.0..1.0`.
|
|
115
|
+
|
|
116
|
+
## Processor Capacity
|
|
117
|
+
|
|
118
|
+
Use {ruby Process::Metrics::Processor.count} to get the number of processors available to the current process. On Linux, this takes CPU affinity into account.
|
|
119
|
+
|
|
120
|
+
Use {ruby Process::Metrics::Processor.quota} to get the available processor capacity as a `Float`. On Linux, it also takes cgroup v2 CPU bandwidth limits into account. On other systems, when no finite quota is configured, or when the quota cannot be determined, it returns {ruby Process::Metrics::Processor.count} as a `Float`.
|
|
121
|
+
|
|
122
|
+
``` ruby
|
|
123
|
+
Process::Metrics::Processor.count
|
|
124
|
+
# => 8
|
|
125
|
+
|
|
126
|
+
Process::Metrics::Processor.quota
|
|
127
|
+
# => 1.5
|
|
128
|
+
```
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Released under the MIT License.
|
|
4
|
+
# Copyright, 2026, by Samuel Williams.
|
|
5
|
+
|
|
6
|
+
module Process
|
|
7
|
+
module Metrics
|
|
8
|
+
class Processor
|
|
9
|
+
# @private
|
|
10
|
+
module Linux
|
|
11
|
+
DEFAULT_CGROUP_ROOT = "/sys/fs/cgroup"
|
|
12
|
+
DEFAULT_CGROUP_PATH = "/proc/self/cgroup"
|
|
13
|
+
|
|
14
|
+
class << self
|
|
15
|
+
# Read the effective processor quota for the current cgroup.
|
|
16
|
+
# @parameter cgroup_root [String] The root of the cgroup v2 filesystem.
|
|
17
|
+
# @parameter cgroup_path [String] The process cgroup membership file.
|
|
18
|
+
# @returns [Float | Nil] The smallest finite quota in the cgroup hierarchy, if available.
|
|
19
|
+
def quota(cgroup_root: DEFAULT_CGROUP_ROOT, cgroup_path: DEFAULT_CGROUP_PATH)
|
|
20
|
+
unless relative_path = current_path(cgroup_path)
|
|
21
|
+
return nil
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
root = File.expand_path(cgroup_root)
|
|
25
|
+
directory = File.expand_path(relative_path.delete_prefix("/"), root)
|
|
26
|
+
return nil unless directory == root || directory.start_with?("#{root}/")
|
|
27
|
+
|
|
28
|
+
quota = nil
|
|
29
|
+
|
|
30
|
+
loop do
|
|
31
|
+
if current = read_quota(directory)
|
|
32
|
+
quota = [quota, current].compact.min
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
break if directory == root
|
|
36
|
+
directory = File.dirname(directory)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
return quota
|
|
40
|
+
rescue Errno::EACCES, Errno::EINVAL, Errno::ENOENT, Errno::ENOTDIR, ArgumentError
|
|
41
|
+
return nil
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
def current_path(path)
|
|
47
|
+
File.foreach(path) do |line|
|
|
48
|
+
hierarchy, controllers, relative_path = line.strip.split(":", 3)
|
|
49
|
+
|
|
50
|
+
if hierarchy == "0" && controllers == "" && relative_path
|
|
51
|
+
return relative_path
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
return nil
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def read_quota(directory)
|
|
59
|
+
maximum, period = File.read(File.join(directory, "cpu.max")).split
|
|
60
|
+
return nil if maximum == "max" || !maximum || !period
|
|
61
|
+
|
|
62
|
+
maximum = Integer(maximum)
|
|
63
|
+
period = Integer(period)
|
|
64
|
+
return nil unless maximum.positive? && period.positive?
|
|
65
|
+
|
|
66
|
+
return maximum.to_f / period
|
|
67
|
+
rescue Errno::EACCES, Errno::EINVAL, Errno::ENOENT, Errno::ENOTDIR, ArgumentError
|
|
68
|
+
return nil
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# The processor capacity available to the current process.
|
|
74
|
+
# This takes cgroup v2 CPU bandwidth limits into account, and otherwise returns {count} as a `Float`.
|
|
75
|
+
# @returns [Float] The available processor capacity in core units.
|
|
76
|
+
def self.quota
|
|
77
|
+
count = self.count.to_f
|
|
78
|
+
|
|
79
|
+
if quota = Linux.quota
|
|
80
|
+
if quota < count
|
|
81
|
+
return quota
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
return count
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -3,10 +3,26 @@
|
|
|
3
3
|
# Released under the MIT License.
|
|
4
4
|
# Copyright, 2026, by Samuel Williams.
|
|
5
5
|
|
|
6
|
+
require "etc"
|
|
7
|
+
|
|
6
8
|
module Process
|
|
7
9
|
module Metrics
|
|
8
10
|
# Computes interval CPU utilization from cumulative process metrics.
|
|
9
11
|
class Processor
|
|
12
|
+
# The number of processors available to the current process.
|
|
13
|
+
# On Linux, this takes the process CPU affinity into account.
|
|
14
|
+
# @returns [Integer] The number of available processors.
|
|
15
|
+
def self.count
|
|
16
|
+
Etc.nprocessors
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# The processor capacity available to the current process.
|
|
20
|
+
# On Linux, this takes cgroup v2 CPU bandwidth limits into account. Otherwise, it returns {count} as a `Float`.
|
|
21
|
+
# @returns [Float] The available processor capacity in core units.
|
|
22
|
+
def self.quota
|
|
23
|
+
return self.count.to_f
|
|
24
|
+
end
|
|
25
|
+
|
|
10
26
|
# An immutable measurement of process CPU usage over an interval.
|
|
11
27
|
# @attribute [Integer] The process ID.
|
|
12
28
|
# @attribute [Float] The elapsed monotonic time in seconds.
|
|
@@ -79,3 +95,7 @@ module Process
|
|
|
79
95
|
end
|
|
80
96
|
end
|
|
81
97
|
end
|
|
98
|
+
|
|
99
|
+
if RUBY_PLATFORM.include?("linux")
|
|
100
|
+
require_relative "processor/linux"
|
|
101
|
+
end
|
data/readme.md
CHANGED
|
@@ -16,6 +16,10 @@ Please see the [project documentation](https://socketry.github.io/process-metric
|
|
|
16
16
|
|
|
17
17
|
Please see the [project releases](https://socketry.github.io/process-metrics/releases/index) for all releases.
|
|
18
18
|
|
|
19
|
+
### v0.14.0
|
|
20
|
+
|
|
21
|
+
- Add `Process::Metrics::Processor.count` and `.quota` for affinity-aware processor counts and cgroup v2-aware processor capacity.
|
|
22
|
+
|
|
19
23
|
### v0.13.0
|
|
20
24
|
|
|
21
25
|
- Normalize processor utilization to core units, where `1.0` represents one fully occupied CPU core, and restore Linux reporting.
|
|
@@ -56,10 +60,6 @@ Please see the [project releases](https://socketry.github.io/process-metrics/rel
|
|
|
56
60
|
|
|
57
61
|
- Be more proactive about returning nil if memory capture failed.
|
|
58
62
|
|
|
59
|
-
### v0.6.1
|
|
60
|
-
|
|
61
|
-
- Handle `Errno::ESRCH: No such process @ io_fillbuf - fd:xxx /proc/xxx/smaps_rollup` by ignoring it.
|
|
62
|
-
|
|
63
63
|
## Contributing
|
|
64
64
|
|
|
65
65
|
We welcome contributions to this project.
|
data/releases.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Releases
|
|
2
2
|
|
|
3
|
+
## v0.14.0
|
|
4
|
+
|
|
5
|
+
- Add `Process::Metrics::Processor.count` and `.quota` for affinity-aware processor counts and cgroup v2-aware processor capacity.
|
|
6
|
+
|
|
3
7
|
## v0.13.0
|
|
4
8
|
|
|
5
9
|
- Normalize processor utilization to core units, where `1.0` represents one fully occupied CPU core, and restore Linux reporting.
|
data.tar.gz.sig
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: process-metrics
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.14.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Samuel Williams
|
|
@@ -89,6 +89,7 @@ files:
|
|
|
89
89
|
- lib/process/metrics/memory/darwin.rb
|
|
90
90
|
- lib/process/metrics/memory/linux.rb
|
|
91
91
|
- lib/process/metrics/processor.rb
|
|
92
|
+
- lib/process/metrics/processor/linux.rb
|
|
92
93
|
- lib/process/metrics/version.rb
|
|
93
94
|
- license.md
|
|
94
95
|
- readme.md
|
metadata.gz.sig
CHANGED
|
Binary file
|