process-metrics 0.6.0 → 0.7.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: ca29ce7e69894dd4f9f766caa5ee6055c1a25c06d1b764960ffe72c15dfb1958
4
- data.tar.gz: 4723276718e25bc09053ba004357f33a720d3da342b384277f07b5a3eebe898e
3
+ metadata.gz: 43c70d72392b299b8219b1bb1d5762de8d4ee116568ebd4ada928ba946d3ae96
4
+ data.tar.gz: d0c5a4ab4a3fd2935e95667fff758c20c87f14165776dec5b908f544cc24a590
5
5
  SHA512:
6
- metadata.gz: b6548743e1120c91c17cf5aa6255bb14991c68ac7b28861325ea3376061e7a3da18f4d1bfc7762f83eb48e46f2e1ce792e1550e3fc16cae13254f5c8189e9650
7
- data.tar.gz: 53cbcbabaef2f8d414e877eeb5b3d1dbc286f87cbb01ce4a6afee588527440e94c9ea144af4e13d5bb7f085971b2da91f373684bbc8076980cafe02c6aa8f7f6
6
+ metadata.gz: 91961040cacd7a310a28ab42b76ff4f73386bdbd77a36138b7e5e4a3704fed2e6184ad493629ad501e45473c0013bbe675a4c159d74efc723a1cdb138b1a1df7
7
+ data.tar.gz: 9de09390fbc96a7dc208914fd18aeed8d0380f49fb3bc4ab8bf33ec1e15dba671d48921eb71460a33aba779d409cd4180c7f811f42ff736ddd4bf48d2971958e
checksums.yaml.gz.sig CHANGED
Binary file
@@ -51,18 +51,18 @@ module Process
51
51
 
52
52
  # Capture memory usage for the given process IDs.
53
53
  def self.capture(pid, count: 1, **options)
54
- usage = Memory.zero
55
-
56
54
  IO.popen(["vmmap", pid.to_s], "r") do |io|
55
+ usage = Memory.zero
56
+
57
57
  io.each_line do |line|
58
58
  if match = LINE.match(line)
59
+ usage.map_count += 1
60
+
59
61
  virtual_size = parse_size(match[:virtual_size])
60
62
  resident_size = parse_size(match[:resident_size])
61
63
  dirty_size = parse_size(match[:dirty_size])
62
64
  swap_size = parse_size(match[:swap_size])
63
65
 
64
- # Update counts
65
- usage.map_count += 1
66
66
  usage.resident_size += resident_size
67
67
  usage.swap_size += swap_size
68
68
 
@@ -84,13 +84,21 @@ module Process
84
84
  end
85
85
  end
86
86
  end
87
+
88
+ if usage.map_count.zero?
89
+ # vmap might not fail, but also might not return any data.
90
+ return nil
91
+ end
92
+
93
+ # Darwin does not expose proportional memory usage, so we guess based on the number of processes. Yes, this is a terrible hack, but it's the most reasonable thing to do given the constraints:
94
+ usage.proportional_size = usage.resident_size / count
95
+ usage.proportional_swap_size = usage.swap_size / count
96
+
97
+ return usage
87
98
  end
88
-
89
- # Darwin does not expose proportional memory usage, so we guess based on the number of processes. Yes, this is a terrible hack, but it's the most reasonable thing to do given the constraints:
90
- usage.proportional_size = usage.resident_size / count
91
- usage.proportional_swap_size = usage.swap_size / count
92
-
93
- return usage
99
+ rescue Errno::ESRCH
100
+ # Process doesn't exist.
101
+ return nil
94
102
  end
95
103
  end
96
104
 
@@ -11,20 +11,16 @@ module Process
11
11
  # @parameter pid [Integer] The process ID.
12
12
  # @parameter usage [Memory] The Memory instance to populate with fault counters.
13
13
  def self.capture_faults(pid, usage)
14
- begin
15
- stat = File.read("/proc/#{pid}/stat")
16
- # The comm field can contain spaces and parentheses; find the closing ')':
17
- rparen_index = stat.rindex(")")
18
- return unless rparen_index
19
- fields = stat[(rparen_index+2)..-1].split(/\s+/)
20
- # proc(5): field 10=minflt, 12=majflt; our fields array is 0-indexed from field 3.
21
- usage.minor_faults = fields[10-3].to_i
22
- usage.major_faults = fields[12-3].to_i
23
- rescue Errno::ENOENT, Errno::EACCES
24
- # The process may have exited or permissions are insufficient; ignore.
25
- rescue => error
26
- # Be robust to unexpected formats; ignore errors silently.
27
- end
14
+ stat = File.read("/proc/#{pid}/stat")
15
+ # The comm field can contain spaces and parentheses; find the closing ')':
16
+ rparen_index = stat.rindex(")")
17
+ return unless rparen_index
18
+ fields = stat[(rparen_index+2)..-1].split(/\s+/)
19
+ # proc(5): field 10=minflt, 12=majflt; our fields array is 0-indexed from field 3.
20
+ usage.minor_faults = fields[10-3].to_i
21
+ usage.major_faults = fields[12-3].to_i
22
+ rescue
23
+ # Ignore.
28
24
  end
29
25
 
30
26
  # @returns [Numeric] Total memory size in kilobytes.
@@ -58,10 +54,10 @@ module Process
58
54
 
59
55
  # Capture memory usage for the given process IDs.
60
56
  def self.capture(pid, **options)
61
- usage = Memory.zero
62
-
63
- begin
64
- File.foreach("/proc/#{pid}/smaps_rollup") do |line|
57
+ File.open("/proc/#{pid}/smaps_rollup") do |file|
58
+ usage = Memory.zero
59
+
60
+ file.each_line do |line|
65
61
  if /(?<name>.*?):\s+(?<value>\d+) kB/ =~ line
66
62
  if key = SMAP[name]
67
63
  usage[key] += value.to_i
@@ -72,11 +68,12 @@ module Process
72
68
  usage.map_count += File.readlines("/proc/#{pid}/maps").size
73
69
  # Also capture fault counters:
74
70
  self.capture_faults(pid, usage)
75
- rescue Errno::ENOENT => error
76
- # Ignore.
71
+
72
+ return usage
77
73
  end
78
-
79
- return usage
74
+ rescue Errno::ENOENT, Errno::ESRCH
75
+ # Process doesn't exist.
76
+ return nil
80
77
  end
81
78
  elsif File.readable?("/proc/self/smaps")
82
79
  # Whether the memory usage can be captured on this system.
@@ -86,10 +83,10 @@ module Process
86
83
 
87
84
  # Capture memory usage for the given process IDs.
88
85
  def self.capture(pid, **options)
89
- usage = Memory.zero
90
-
91
- begin
92
- File.foreach("/proc/#{pid}/smaps") do |line|
86
+ File.open("/proc/#{pid}/smaps") do |file|
87
+ usage = Memory.zero
88
+
89
+ file.each_line do |line|
93
90
  # The format of this is fixed according to:
94
91
  # https://github.com/torvalds/linux/blob/351c8a09b00b5c51c8f58b016fffe51f87e2d820/fs/proc/task_mmu.c#L804-L814
95
92
  if /(?<name>.*?):\s+(?<value>\d+) kB/ =~ line
@@ -102,13 +99,15 @@ module Process
102
99
  usage.map_count += 1
103
100
  end
104
101
  end
102
+
105
103
  # Also capture fault counters:
106
104
  self.capture_faults(pid, usage)
107
- rescue Errno::ENOENT => error
108
- # Ignore.
105
+
106
+ return usage
109
107
  end
110
-
111
- return usage
108
+ rescue Errno::ENOENT, Errno::ESRCH
109
+ # Process doesn't exist.
110
+ return nil
112
111
  end
113
112
  else
114
113
  def self.supported?
@@ -7,6 +7,6 @@
7
7
  module Process
8
8
  # @namespace
9
9
  module Metrics
10
- VERSION = "0.6.0"
10
+ VERSION = "0.7.0"
11
11
  end
12
12
  end
data/readme.md CHANGED
@@ -16,6 +16,14 @@ 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.7.0
20
+
21
+ - Be more proactive about returning nil if memory capture failed.
22
+
23
+ ### v0.6.1
24
+
25
+ - Handle `Errno::ESRCH: No such process @ io_fillbuf - fd:xxx /proc/xxx/smaps_rollup` by ignoring it.
26
+
19
27
  ### v0.6.0
20
28
 
21
29
  - Add support for major and minor page faults on Linux: `Process::Metrics::Memory#major_faults` and `#minor_faults`. Unfortunately these metrics are not available on Darwin (macOS).
@@ -65,14 +73,6 @@ Please see the [project releases](https://socketry.github.io/process-metrics/rel
65
73
  - Fixed process metrics to exclude the `ps` command itself from measurements.
66
74
  - Fixed documentation formatting issues.
67
75
 
68
- ### v0.1.0
69
-
70
- - Initial release with support for process and memory metrics on Linux and Darwin (macOS).
71
- - Support for selecting processes based on PID or PPID (process group).
72
- - Implementation of memory statistics collection using `/proc` filesystem on Linux.
73
- - Better handling of process hierarchies.
74
- - Support for older Ruby versions.
75
-
76
76
  ## Contributing
77
77
 
78
78
  We welcome contributions to this project.
data/releases.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Releases
2
2
 
3
+ ## v0.7.0
4
+
5
+ - Be more proactive about returning nil if memory capture failed.
6
+
7
+ ## v0.6.1
8
+
9
+ - Handle `Errno::ESRCH: No such process @ io_fillbuf - fd:xxx /proc/xxx/smaps_rollup` by ignoring it.
10
+
3
11
  ## v0.6.0
4
12
 
5
13
  - Add support for major and minor page faults on Linux: `Process::Metrics::Memory#major_faults` and `#minor_faults`. Unfortunately these metrics are not available on Darwin (macOS).
data.tar.gz.sig CHANGED
@@ -1,2 +1 @@
1
- \��1,��5��%��AF��&|՝\,�J�:����!wA��x��^0`o>��iW�\D|
2
- �!���i�(�y���B��kJ>*�V��%��Jcy�`�/Uj=���?^��G�.��S���C]�j���ȃ���R%��7�|�VQU�S�p+�/����J+O ��&5�4ƺ
1
+ dj\�#c����6BX;n�k��M���E��Nk[J���t�lN,ԕ��jI��t��s�L�0���P?
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.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -122,7 +122,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
122
122
  - !ruby/object:Gem::Version
123
123
  version: '0'
124
124
  requirements: []
125
- rubygems_version: 3.7.2
125
+ rubygems_version: 3.6.9
126
126
  specification_version: 4
127
127
  summary: Provide detailed OS-specific process metrics.
128
128
  test_files: []
metadata.gz.sig CHANGED
Binary file