process-metrics 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/bin/process-metrics +1 -1
- data/lib/process/metrics/command/summary.rb +34 -27
- data/lib/process/metrics/command/top.rb +8 -8
- data/lib/process/metrics/command.rb +2 -2
- data/lib/process/metrics/general.rb +32 -20
- data/lib/process/metrics/memory/darwin.rb +100 -0
- data/lib/process/metrics/memory/linux.rb +98 -0
- data/lib/process/metrics/memory.rb +17 -81
- data/lib/process/metrics/version.rb +1 -1
- data/license.md +1 -1
- data/readme.md +3 -3
- data.tar.gz.sig +0 -0
- metadata +12 -15
- metadata.gz.sig +2 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 42d11b0f2e725706c447c1b4cfa3f15a961f759fb8cacf0ef0d238338c3be6ab
|
4
|
+
data.tar.gz: 80468efcb1b3eab151f8fcf0d054d93d11dcd90127ec70a6ad63e5fc10b68f89
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5c765d57991e1a15e8c966ea1497234dae6e8e98cdd8e2463cefe1caf046770b1930b01b68b202b7ace9d802ad6d0577dfbb3cfef48a1d23abc3013ea5a48580
|
7
|
+
data.tar.gz: 8c2bf4692a659037dc8167ad7f3349beb300e4bf021ee97b8ed3bf645cc83eaeefa19ae6ef5aee62855d781f7782ab9750d3999ca21982b865c24afbb65a0be5
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/bin/process-metrics
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Released under the MIT License.
|
4
|
-
# Copyright, 2020-
|
4
|
+
# Copyright, 2020-2025, by Samuel Williams.
|
5
5
|
|
6
|
-
require
|
6
|
+
require "samovar"
|
7
7
|
|
8
|
-
require_relative
|
8
|
+
require_relative "../general"
|
9
9
|
|
10
|
-
require
|
10
|
+
require "console/terminal"
|
11
11
|
|
12
12
|
module Process
|
13
13
|
module Metrics
|
@@ -42,10 +42,8 @@ module Process
|
|
42
42
|
self.description = "Display a summary of memory usage statistics."
|
43
43
|
|
44
44
|
options do
|
45
|
-
option
|
46
|
-
option
|
47
|
-
|
48
|
-
option '--memory-scale <integer>', "Scale maximum memory usage to the specified amount (MiB).", type: Integer, default: 512
|
45
|
+
option "--pid <integer>", "Report on a single process id.", type: Integer, required: true
|
46
|
+
option "-p/--ppid <integer>", "Report on all children of this process id.", type: Integer, required: true
|
49
47
|
end
|
50
48
|
|
51
49
|
def terminal
|
@@ -89,18 +87,18 @@ module Process
|
|
89
87
|
return "#{value.round(unit)}#{units[unit]}"
|
90
88
|
end
|
91
89
|
|
92
|
-
def format_memory_usage(value,
|
93
|
-
if value > (
|
90
|
+
def format_memory_usage(value, total, terminal)
|
91
|
+
if value > (total * 0.8)
|
94
92
|
intensity = :high
|
95
|
-
elsif value > (
|
93
|
+
elsif value > (total * 0.5)
|
96
94
|
intensity = :medium
|
97
95
|
else
|
98
96
|
intensity = :low
|
99
97
|
end
|
100
98
|
|
101
|
-
formatted = (format_size(value) +
|
99
|
+
formatted = (format_size(value) + " ").rjust(10)
|
102
100
|
|
103
|
-
terminal.print(formatted, intensity, "[", Bar.format(value /
|
101
|
+
terminal.print(formatted, intensity, "[", Bar.format(value / total.to_f, 60), "]", :reset)
|
104
102
|
end
|
105
103
|
|
106
104
|
def call
|
@@ -111,6 +109,15 @@ module Process
|
|
111
109
|
format_memory_usage = self.method(:format_memory_usage).curry
|
112
110
|
shared_memory_usage = 0
|
113
111
|
private_memory_usage = 0
|
112
|
+
total_memory_usage = 0
|
113
|
+
|
114
|
+
summary.each do |pid, general|
|
115
|
+
if memory = general.memory
|
116
|
+
total_memory_usage += memory.proportional_size + memory.unique_size
|
117
|
+
else
|
118
|
+
total_memory_usage += general.resident_size
|
119
|
+
end
|
120
|
+
end
|
114
121
|
|
115
122
|
proportional = true
|
116
123
|
|
@@ -126,21 +133,21 @@ module Process
|
|
126
133
|
private_memory_usage += memory.unique_size
|
127
134
|
|
128
135
|
terminal.print_line(
|
129
|
-
:key, "Memory
|
130
|
-
format_memory_usage[memory.proportional_size]
|
136
|
+
:key, "Shared Memory: ".rjust(20), :reset,
|
137
|
+
format_memory_usage[memory.proportional_size, total_memory_usage]
|
131
138
|
)
|
132
139
|
|
133
140
|
terminal.print_line(
|
134
|
-
:key, "Private
|
135
|
-
format_memory_usage[memory.unique_size]
|
141
|
+
:key, "Private Memory: ".rjust(20), :reset,
|
142
|
+
format_memory_usage[memory.unique_size, total_memory_usage]
|
136
143
|
)
|
137
144
|
else
|
138
|
-
shared_memory_usage += general.
|
145
|
+
shared_memory_usage += general.resident_size
|
139
146
|
proportional = false
|
140
147
|
|
141
148
|
terminal.print_line(
|
142
|
-
:key, "Memory
|
143
|
-
format_memory_usage[general.
|
149
|
+
:key, "Memory: ".rjust(20), :reset,
|
150
|
+
format_memory_usage[general.resident_size, total_memory_usage]
|
144
151
|
)
|
145
152
|
end
|
146
153
|
end
|
@@ -149,24 +156,24 @@ module Process
|
|
149
156
|
|
150
157
|
if proportional
|
151
158
|
terminal.print_line(
|
152
|
-
:key, "Memory
|
153
|
-
format_memory_usage[shared_memory_usage]
|
159
|
+
:key, "Shared Memory: ".rjust(20), :reset,
|
160
|
+
format_memory_usage[shared_memory_usage, total_memory_usage]
|
154
161
|
)
|
155
162
|
|
156
163
|
terminal.print_line(
|
157
|
-
:key, "Memory
|
158
|
-
format_memory_usage[private_memory_usage]
|
164
|
+
:key, "Private Memory: ".rjust(20), :reset,
|
165
|
+
format_memory_usage[private_memory_usage, total_memory_usage]
|
159
166
|
)
|
160
167
|
else
|
161
168
|
terminal.print_line(
|
162
|
-
:key, "Memory
|
163
|
-
format_memory_usage[memory_usage]
|
169
|
+
:key, "Memory: ".rjust(20), :reset,
|
170
|
+
format_memory_usage[memory_usage, total_memory_usage]
|
164
171
|
)
|
165
172
|
end
|
166
173
|
|
167
174
|
terminal.print_line(
|
168
175
|
:key, "Memory (Total): ".rjust(20), :reset,
|
169
|
-
format_memory_usage[shared_memory_usage + private_memory_usage]
|
176
|
+
format_memory_usage[shared_memory_usage + private_memory_usage, total_memory_usage]
|
170
177
|
)
|
171
178
|
end
|
172
179
|
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Released under the MIT License.
|
4
|
-
# Copyright, 2020-
|
4
|
+
# Copyright, 2020-2025, by Samuel Williams.
|
5
5
|
|
6
|
-
require
|
6
|
+
require "samovar"
|
7
7
|
|
8
|
-
require_relative
|
9
|
-
require_relative
|
8
|
+
require_relative "summary"
|
9
|
+
require_relative "../version"
|
10
10
|
|
11
11
|
module Process
|
12
12
|
module Metrics
|
@@ -15,13 +15,13 @@ module Process
|
|
15
15
|
self.description = "Collect memory usage statistics."
|
16
16
|
|
17
17
|
options do
|
18
|
-
option
|
19
|
-
option
|
18
|
+
option "-h/--help", "Print out help information."
|
19
|
+
option "-v/--version", "Print out the application version."
|
20
20
|
end
|
21
21
|
|
22
22
|
nested :command, {
|
23
|
-
|
24
|
-
}, default:
|
23
|
+
"summary" => Summary,
|
24
|
+
}, default: "summary"
|
25
25
|
|
26
26
|
def call
|
27
27
|
if @options[:version]
|
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Released under the MIT License.
|
4
|
-
# Copyright, 2020-
|
4
|
+
# Copyright, 2020-2025, by Samuel Williams.
|
5
5
|
|
6
|
-
require_relative
|
6
|
+
require_relative "command/top"
|
7
7
|
|
8
8
|
module Process
|
9
9
|
module Metrics
|
@@ -1,21 +1,38 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Released under the MIT License.
|
4
|
-
# Copyright, 2019-
|
4
|
+
# Copyright, 2019-2025, by Samuel Williams.
|
5
5
|
|
6
|
-
require_relative
|
7
|
-
require
|
8
|
-
require
|
6
|
+
require_relative "memory"
|
7
|
+
require "set"
|
8
|
+
require "json"
|
9
9
|
|
10
10
|
module Process
|
11
11
|
module Metrics
|
12
12
|
PS = "ps"
|
13
13
|
|
14
|
+
DURATION = /\A
|
15
|
+
(?:(?<days>\d+)-)? # Optional days (e.g., '2-')
|
16
|
+
(?:(?<hours>\d+):)? # Optional hours (e.g., '1:')
|
17
|
+
(?<minutes>\d{1,2}): # Minutes (always present, 1 or 2 digits)
|
18
|
+
(?<seconds>\d{2}) # Seconds (exactly 2 digits)
|
19
|
+
(?:\.(?<fraction>\d{1,2}))? # Optional fraction of a second (e.g., '.27')
|
20
|
+
\z/x
|
21
|
+
|
22
|
+
|
14
23
|
# Parse a duration string into seconds.
|
15
24
|
# According to the linux manual page specifications.
|
16
25
|
def self.duration(value)
|
17
|
-
if
|
18
|
-
|
26
|
+
if match = DURATION.match(value)
|
27
|
+
days = match[:days].to_i
|
28
|
+
hours = match[:hours].to_i
|
29
|
+
minutes = match[:minutes].to_i
|
30
|
+
seconds = match[:seconds].to_i
|
31
|
+
fraction = match[:fraction].to_i
|
32
|
+
|
33
|
+
return days * 24 * 60 * 60 + hours * 60 * 60 + minutes * 60 + seconds + fraction / 100.0
|
34
|
+
else
|
35
|
+
return 0.0
|
19
36
|
end
|
20
37
|
end
|
21
38
|
|
@@ -25,10 +42,10 @@ module Process
|
|
25
42
|
ppid: ->(value){value.to_i}, # Parent Process ID
|
26
43
|
pgid: ->(value){value.to_i}, # Process Group ID
|
27
44
|
pcpu: ->(value){value.to_f}, # Percentage CPU
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
etime: self.method(:duration), # Elapsed Time
|
45
|
+
vsz: ->(value){value.to_i}, # Virtual Size (KiB)
|
46
|
+
rss: ->(value){value.to_i}, # Resident Size (KiB)
|
47
|
+
time: self.method(:duration), # CPU Time (seconds)
|
48
|
+
etime: self.method(:duration), # Elapsed Time (seconds)
|
32
49
|
command: ->(value){value}, # Command (name of the process)
|
33
50
|
}
|
34
51
|
|
@@ -56,7 +73,7 @@ module Process
|
|
56
73
|
as_json.to_json(*arguments)
|
57
74
|
end
|
58
75
|
|
59
|
-
# The
|
76
|
+
# The total size of the process in memory, in kilobytes.
|
60
77
|
def total_size
|
61
78
|
if memory = self.memory
|
62
79
|
memory.proportional_size
|
@@ -105,18 +122,18 @@ module Process
|
|
105
122
|
#
|
106
123
|
# @parameter pid [Integer] The process ID to capture.
|
107
124
|
# @parameter ppid [Integer] The parent process ID to capture.
|
108
|
-
def self.capture(pid: nil, ppid: nil, ps: PS)
|
125
|
+
def self.capture(pid: nil, ppid: nil, ps: PS, memory: Memory.supported?)
|
109
126
|
input, output = IO.pipe
|
110
127
|
|
111
128
|
arguments = [ps]
|
112
129
|
|
113
130
|
if pid && ppid.nil?
|
114
|
-
arguments.push("-p", Array(pid).join(
|
131
|
+
arguments.push("-p", Array(pid).join(","))
|
115
132
|
else
|
116
133
|
arguments.push("ax")
|
117
134
|
end
|
118
135
|
|
119
|
-
arguments.push("-o", FIELDS.keys.join(
|
136
|
+
arguments.push("-o", FIELDS.keys.join(","))
|
120
137
|
|
121
138
|
ps_pid = Process.spawn(*arguments, out: output, pgroup: true)
|
122
139
|
|
@@ -130,7 +147,6 @@ module Process
|
|
130
147
|
record = FIELDS.
|
131
148
|
zip(line.split(/\s+/, FIELDS.size)).
|
132
149
|
map{|(key, type), value| type.call(value)}
|
133
|
-
|
134
150
|
instance = self.new(*record)
|
135
151
|
|
136
152
|
processes[instance.process_id] = instance
|
@@ -151,12 +167,8 @@ module Process
|
|
151
167
|
end
|
152
168
|
end
|
153
169
|
|
154
|
-
if
|
170
|
+
if memory
|
155
171
|
self.capture_memory(processes)
|
156
|
-
|
157
|
-
# if pid
|
158
|
-
# self.compute_summary(pid, processes)
|
159
|
-
# end
|
160
172
|
end
|
161
173
|
|
162
174
|
return processes
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2025, by Samuel Williams.
|
5
|
+
|
6
|
+
module Process
|
7
|
+
module Metrics
|
8
|
+
class Memory::Darwin
|
9
|
+
VMMAP = "/usr/bin/vmmap"
|
10
|
+
|
11
|
+
# Whether the memory usage can be captured on this system.
|
12
|
+
def self.supported?
|
13
|
+
File.executable?(VMMAP)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Parse a size string into kilobytes.
|
17
|
+
def self.parse_size(string)
|
18
|
+
return 0 unless string
|
19
|
+
|
20
|
+
case string.strip
|
21
|
+
when /([\d\.]+)K/i then ($1.to_f).round
|
22
|
+
when /([\d\.]+)M/i then ($1.to_f * 1024).round
|
23
|
+
when /([\d\.]+)G/i then ($1.to_f * 1024 * 1024).round
|
24
|
+
else (string.to_f / 1024).ceil
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
LINE = /\A
|
29
|
+
\s*
|
30
|
+
(?<region_name>.+?)\s+
|
31
|
+
(?<start_address>[0-9a-fA-F]+)-(?<end_address>[0-9a-fA-F]+)\s+
|
32
|
+
\[\s*(?<virtual_size>[\d\.]+[KMG]?)\s+(?<resident_size>[\d\.]+[KMG]?)\s+(?<dirty_size>[\d\.]+[KMG]?)\s+(?<swap_size>[\d\.]+[KMG]?)\s*\]\s+
|
33
|
+
(?<permissions>[rwx\-\/]+)\s+
|
34
|
+
SM=(?<sharing_mode>\w+)
|
35
|
+
/x
|
36
|
+
|
37
|
+
# Capture memory usage for the given process IDs.
|
38
|
+
def self.capture(pids)
|
39
|
+
usage = Memory.zero
|
40
|
+
|
41
|
+
pids.each do |pid|
|
42
|
+
IO.popen(["vmmap", pid.to_s], "r") do |io|
|
43
|
+
io.each_line do |line|
|
44
|
+
if match = LINE.match(line)
|
45
|
+
virtual_size = parse_size(match[:virtual_size])
|
46
|
+
resident_size = parse_size(match[:resident_size])
|
47
|
+
dirty_size = parse_size(match[:dirty_size])
|
48
|
+
swap_size = parse_size(match[:swap_size])
|
49
|
+
|
50
|
+
# puts [match[:region_name], virtual_size, resident_size, dirty_size, swap_size, match[:permissions], match[:sharing_mode]].join(",")
|
51
|
+
|
52
|
+
# Update counts
|
53
|
+
usage.map_count += 1
|
54
|
+
usage.resident_size += resident_size
|
55
|
+
usage.swap_size += swap_size
|
56
|
+
|
57
|
+
# Private vs. Shared memory
|
58
|
+
# COW=copy_on_write PRV=private NUL=empty ALI=aliased
|
59
|
+
# SHM=shared ZER=zero_filled S/A=shared_alias
|
60
|
+
case match[:sharing_mode]
|
61
|
+
when "PRV"
|
62
|
+
usage.private_clean_size += resident_size - dirty_size
|
63
|
+
usage.private_dirty_size += dirty_size
|
64
|
+
when "COW", "SHM"
|
65
|
+
usage.shared_clean_size += resident_size - dirty_size
|
66
|
+
usage.shared_dirty_size += dirty_size
|
67
|
+
end
|
68
|
+
|
69
|
+
# Anonymous memory: no region detail path or special names
|
70
|
+
if match[:region_name] =~ /MALLOC|VM_ALLOCATE|Stack|STACK|anonymous/
|
71
|
+
usage.anonymous_size += resident_size
|
72
|
+
end
|
73
|
+
# else
|
74
|
+
# puts "Failed to match line: #{line}"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# On Darwin, we cannot compute the proportional size, so we just set it to the resident size.
|
81
|
+
usage.proportional_size = usage.resident_size
|
82
|
+
usage.proportional_swap_size = usage.swap_size
|
83
|
+
|
84
|
+
return usage
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
if Memory::Darwin.supported?
|
89
|
+
class << Memory
|
90
|
+
def supported?
|
91
|
+
return true
|
92
|
+
end
|
93
|
+
|
94
|
+
def capture(pids)
|
95
|
+
return Memory::Darwin.capture(pids)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2025, by Samuel Williams.
|
5
|
+
|
6
|
+
module Process
|
7
|
+
module Metrics
|
8
|
+
class Memory::Linux
|
9
|
+
# The fields that will be extracted from the `smaps` data.
|
10
|
+
SMAP = {
|
11
|
+
"Rss" => :resident_size,
|
12
|
+
"Pss" => :proportional_size,
|
13
|
+
"Shared_Clean" => :shared_clean_size,
|
14
|
+
"Shared_Dirty" => :shared_dirty_size,
|
15
|
+
"Private_Clean" => :private_clean_size,
|
16
|
+
"Private_Dirty" => :private_dirty_size,
|
17
|
+
"Referenced" => :referenced_size,
|
18
|
+
"Anonymous" => :anonymous_size,
|
19
|
+
"Swap" => :swap_size,
|
20
|
+
"SwapPss" => :proportional_swap_size,
|
21
|
+
}
|
22
|
+
|
23
|
+
if File.readable?("/proc/self/smaps_rollup")
|
24
|
+
# Whether the memory usage can be captured on this system.
|
25
|
+
def self.supported?
|
26
|
+
true
|
27
|
+
end
|
28
|
+
|
29
|
+
# Capture memory usage for the given process IDs.
|
30
|
+
def self.capture(pids)
|
31
|
+
usage = Memory.zero
|
32
|
+
|
33
|
+
pids.each do |pid|
|
34
|
+
File.foreach("/proc/#{pid}/smaps_rollup") do |line|
|
35
|
+
if /(?<name>.*?):\s+(?<value>\d+) kB/ =~ line
|
36
|
+
if key = SMAP[name]
|
37
|
+
usage[key] += value.to_i
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
usage.map_count += File.readlines("/proc/#{pid}/maps").size
|
43
|
+
rescue Errno::ENOENT => error
|
44
|
+
# Ignore.
|
45
|
+
end
|
46
|
+
|
47
|
+
return usage
|
48
|
+
end
|
49
|
+
elsif File.readable?("/proc/self/smaps")
|
50
|
+
# Whether the memory usage can be captured on this system.
|
51
|
+
def self.supported?
|
52
|
+
true
|
53
|
+
end
|
54
|
+
|
55
|
+
# Capture memory usage for the given process IDs.
|
56
|
+
def self.capture(pids)
|
57
|
+
usage = Memory.zero
|
58
|
+
|
59
|
+
pids.each do |pid|
|
60
|
+
File.foreach("/proc/#{pid}/smaps") do |line|
|
61
|
+
# The format of this is fixed according to:
|
62
|
+
# https://github.com/torvalds/linux/blob/351c8a09b00b5c51c8f58b016fffe51f87e2d820/fs/proc/task_mmu.c#L804-L814
|
63
|
+
if /(?<name>.*?):\s+(?<value>\d+) kB/ =~ line
|
64
|
+
if key = SMAP[name]
|
65
|
+
usage[key] += value.to_i
|
66
|
+
end
|
67
|
+
elsif /VmFlags:\s+(?<flags>.*)/ =~ line
|
68
|
+
# It should be possible to extract the number of fibers and each fiber's memory usage.
|
69
|
+
# flags = flags.split(/\s+/)
|
70
|
+
usage.map_count += 1
|
71
|
+
end
|
72
|
+
end
|
73
|
+
rescue Errno::ENOENT => error
|
74
|
+
# Ignore.
|
75
|
+
end
|
76
|
+
|
77
|
+
return usage
|
78
|
+
end
|
79
|
+
else
|
80
|
+
def self.supported?
|
81
|
+
false
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
if Memory::Linux.supported?
|
87
|
+
class << Memory
|
88
|
+
def supported?
|
89
|
+
return true
|
90
|
+
end
|
91
|
+
|
92
|
+
def capture(pids)
|
93
|
+
return Memory::Linux.capture(pids)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -1,12 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Released under the MIT License.
|
4
|
-
# Copyright, 2019-
|
4
|
+
# Copyright, 2019-2025, by Samuel Williams.
|
5
5
|
|
6
|
-
require
|
6
|
+
require "json"
|
7
7
|
|
8
8
|
module Process
|
9
9
|
module Metrics
|
10
|
+
# Represents memory usage for a process, sizes are in kilobytes.
|
10
11
|
class Memory < Struct.new(:map_count, :resident_size, :proportional_size, :shared_clean_size, :shared_dirty_size, :private_clean_size, :private_dirty_size, :referenced_size, :anonymous_size, :swap_size, :proportional_swap_size)
|
11
12
|
|
12
13
|
alias as_json to_h
|
@@ -26,87 +27,22 @@ module Process
|
|
26
27
|
self.private_clean_size + self.private_dirty_size
|
27
28
|
end
|
28
29
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
"Referenced" => :referenced_size,
|
38
|
-
"Anonymous" => :anonymous_size,
|
39
|
-
"Swap" => :swap_size,
|
40
|
-
"SwapPss" => :proportional_swap_size,
|
41
|
-
}
|
30
|
+
def self.zero
|
31
|
+
self.new(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Whether the memory usage can be captured on this system.
|
35
|
+
def self.supported?
|
36
|
+
false
|
37
|
+
end
|
42
38
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
true
|
47
|
-
end
|
48
|
-
|
49
|
-
# Capture memory usage for the given process IDs.
|
50
|
-
def self.capture(pids)
|
51
|
-
usage = self.new(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
|
52
|
-
|
53
|
-
pids.each do |pid|
|
54
|
-
File.foreach("/proc/#{pid}/smaps_rollup") do |line|
|
55
|
-
if /(?<name>.*?):\s+(?<value>\d+) kB/ =~ line
|
56
|
-
if key = MAP[name]
|
57
|
-
usage[key] += value.to_i
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
usage.map_count += File.readlines("/proc/#{pid}/maps").size
|
63
|
-
rescue Errno::ENOENT => error
|
64
|
-
# Ignore.
|
65
|
-
end
|
66
|
-
|
67
|
-
return usage
|
68
|
-
end
|
69
|
-
elsif File.readable?('/proc/self/smaps')
|
70
|
-
# Whether the memory usage can be captured on this system.
|
71
|
-
def self.supported?
|
72
|
-
true
|
73
|
-
end
|
74
|
-
|
75
|
-
# Capture memory usage for the given process IDs.
|
76
|
-
def self.capture(pids)
|
77
|
-
usage = self.new(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
|
78
|
-
|
79
|
-
pids.each do |pid|
|
80
|
-
File.foreach("/proc/#{pid}/smaps") do |line|
|
81
|
-
# The format of this is fixed according to:
|
82
|
-
# https://github.com/torvalds/linux/blob/351c8a09b00b5c51c8f58b016fffe51f87e2d820/fs/proc/task_mmu.c#L804-L814
|
83
|
-
if /(?<name>.*?):\s+(?<value>\d+) kB/ =~ line
|
84
|
-
if key = MAP[name]
|
85
|
-
usage[key] += value.to_i
|
86
|
-
end
|
87
|
-
elsif /VmFlags:\s+(?<flags>.*)/ =~ line
|
88
|
-
# It should be possible to extract the number of fibers and each fiber's memory usage.
|
89
|
-
# flags = flags.split(/\s+/)
|
90
|
-
usage.map_count += 1
|
91
|
-
end
|
92
|
-
end
|
93
|
-
rescue Errno::ENOENT => error
|
94
|
-
# Ignore.
|
95
|
-
end
|
96
|
-
|
97
|
-
return usage
|
98
|
-
end
|
99
|
-
else
|
100
|
-
# Whether the memory usage can be captured on this system.
|
101
|
-
def self.supported?
|
102
|
-
false
|
103
|
-
end
|
104
|
-
|
105
|
-
# Capture memory usage for the given process IDs.
|
106
|
-
def self.capture(pids)
|
107
|
-
return self.new
|
108
|
-
end
|
39
|
+
# Capture memory usage for the given process IDs.
|
40
|
+
def self.capture(pids)
|
41
|
+
return nil
|
109
42
|
end
|
110
43
|
end
|
111
44
|
end
|
112
45
|
end
|
46
|
+
|
47
|
+
require_relative "memory/linux"
|
48
|
+
require_relative "memory/darwin"
|
data/license.md
CHANGED
data/readme.md
CHANGED
@@ -24,8 +24,8 @@ We welcome contributions to this project.
|
|
24
24
|
|
25
25
|
### Developer Certificate of Origin
|
26
26
|
|
27
|
-
|
27
|
+
In order to protect users of this project, we require all contributors to comply with the [Developer Certificate of Origin](https://developercertificate.org/). This ensures that all contributions are properly licensed and attributed.
|
28
28
|
|
29
|
-
###
|
29
|
+
### Community Guidelines
|
30
30
|
|
31
|
-
This project is
|
31
|
+
This project is best served by a collaborative and respectful environment. Treat each other professionally, respect differing viewpoints, and engage constructively. Harassment, discrimination, or harmful behavior is not tolerated. Communicate clearly, listen actively, and support one another. If any issues arise, please inform the project maintainers.
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: process-metrics
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
8
8
|
- Adam Daniels
|
9
|
-
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain:
|
12
11
|
- |
|
@@ -38,7 +37,7 @@ cert_chain:
|
|
38
37
|
Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
|
39
38
|
voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
|
40
39
|
-----END CERTIFICATE-----
|
41
|
-
date:
|
40
|
+
date: 2025-02-21 00:00:00.000000000 Z
|
42
41
|
dependencies:
|
43
42
|
- !ruby/object:Gem::Dependency
|
44
43
|
name: console
|
@@ -55,35 +54,33 @@ dependencies:
|
|
55
54
|
- !ruby/object:Gem::Version
|
56
55
|
version: '1.8'
|
57
56
|
- !ruby/object:Gem::Dependency
|
58
|
-
name:
|
57
|
+
name: json
|
59
58
|
requirement: !ruby/object:Gem::Requirement
|
60
59
|
requirements:
|
61
60
|
- - "~>"
|
62
61
|
- !ruby/object:Gem::Version
|
63
|
-
version: '2
|
62
|
+
version: '2'
|
64
63
|
type: :runtime
|
65
64
|
prerelease: false
|
66
65
|
version_requirements: !ruby/object:Gem::Requirement
|
67
66
|
requirements:
|
68
67
|
- - "~>"
|
69
68
|
- !ruby/object:Gem::Version
|
70
|
-
version: '2
|
69
|
+
version: '2'
|
71
70
|
- !ruby/object:Gem::Dependency
|
72
|
-
name:
|
71
|
+
name: samovar
|
73
72
|
requirement: !ruby/object:Gem::Requirement
|
74
73
|
requirements:
|
75
74
|
- - "~>"
|
76
75
|
- !ruby/object:Gem::Version
|
77
|
-
version: '2'
|
76
|
+
version: '2.1'
|
78
77
|
type: :runtime
|
79
78
|
prerelease: false
|
80
79
|
version_requirements: !ruby/object:Gem::Requirement
|
81
80
|
requirements:
|
82
81
|
- - "~>"
|
83
82
|
- !ruby/object:Gem::Version
|
84
|
-
version: '2'
|
85
|
-
description:
|
86
|
-
email:
|
83
|
+
version: '2.1'
|
87
84
|
executables:
|
88
85
|
- process-metrics
|
89
86
|
extensions: []
|
@@ -96,6 +93,8 @@ files:
|
|
96
93
|
- lib/process/metrics/command/top.rb
|
97
94
|
- lib/process/metrics/general.rb
|
98
95
|
- lib/process/metrics/memory.rb
|
96
|
+
- lib/process/metrics/memory/darwin.rb
|
97
|
+
- lib/process/metrics/memory/linux.rb
|
99
98
|
- lib/process/metrics/version.rb
|
100
99
|
- license.md
|
101
100
|
- readme.md
|
@@ -106,7 +105,6 @@ metadata:
|
|
106
105
|
documentation_uri: https://socketry.github.io/process-metrics/
|
107
106
|
funding_uri: https://github.com/sponsors/ioquatix
|
108
107
|
source_code_uri: https://github.com/socketry/process-metrics.git
|
109
|
-
post_install_message:
|
110
108
|
rdoc_options: []
|
111
109
|
require_paths:
|
112
110
|
- lib
|
@@ -114,15 +112,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
114
112
|
requirements:
|
115
113
|
- - ">="
|
116
114
|
- !ruby/object:Gem::Version
|
117
|
-
version: '
|
115
|
+
version: '3.1'
|
118
116
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
119
117
|
requirements:
|
120
118
|
- - ">="
|
121
119
|
- !ruby/object:Gem::Version
|
122
120
|
version: '0'
|
123
121
|
requirements: []
|
124
|
-
rubygems_version: 3.
|
125
|
-
signing_key:
|
122
|
+
rubygems_version: 3.6.2
|
126
123
|
specification_version: 4
|
127
124
|
summary: Provide detailed OS-specific process metrics.
|
128
125
|
test_files: []
|
metadata.gz.sig
CHANGED
@@ -1,3 +1,2 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
&&�{ _��Wl����J҂�5H��жѨ�v��~\G�Y͇���',<�X��Z���S��I��Y|�Ѳ
|
1
|
+
<�)wGZ��5�e�ݹ���qؿc��<��ˡR��v/�H��5 #^�� r��0����ٽB2k���G��WBc_=*Y���>[�|��J�����[Q���j�]pY02jr�ʨ`�Q�+6��?�C�h%3J��R����&�A����� o'4$aƁpK�Q�4���v(�ގ������u=�f���h,(�� ���6��33�ӷo�
|
2
|
+
ig�kH(��#�0�nš�a�f����Ҙ(��i��C�Î\p�����Na��<�J+?N�:���ќ�>V-q�"��D ��`�K��z$!�W��N��N����Q�(��(D[\D������9`8u�NDK㏼Z����RNXn�~n
|