process-metrics 0.5.2 → 0.6.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/lib/process/metrics/command/summary.rb +22 -0
- data/lib/process/metrics/command/top.rb +2 -0
- data/lib/process/metrics/command.rb +3 -0
- data/lib/process/metrics/general.rb +13 -0
- data/lib/process/metrics/memory/darwin.rb +12 -1
- data/lib/process/metrics/memory/linux.rb +33 -0
- data/lib/process/metrics/memory.rb +4 -2
- data/lib/process/metrics/version.rb +3 -1
- data/readme.md +4 -0
- data/releases.md +4 -0
- data.tar.gz.sig +2 -3
- metadata +2 -2
- 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: ca29ce7e69894dd4f9f766caa5ee6055c1a25c06d1b764960ffe72c15dfb1958
|
|
4
|
+
data.tar.gz: 4723276718e25bc09053ba004357f33a720d3da342b384277f07b5a3eebe898e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b6548743e1120c91c17cf5aa6255bb14991c68ac7b28861325ea3376061e7a3da18f4d1bfc7762f83eb48e46f2e1ce792e1550e3fc16cae13254f5c8189e9650
|
|
7
|
+
data.tar.gz: 53cbcbabaef2f8d414e877eeb5b3d1dbc286f87cbb01ce4a6afee588527440e94c9ea144af4e13d5bb7f085971b2da91f373684bbc8076980cafe02c6aa8f7f6
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
|
@@ -12,6 +12,7 @@ require "console/terminal"
|
|
|
12
12
|
module Process
|
|
13
13
|
module Metrics
|
|
14
14
|
module Command
|
|
15
|
+
# Helper module for rendering horizontal progress bars using Unicode block characters.
|
|
15
16
|
module Bar
|
|
16
17
|
BLOCK = [
|
|
17
18
|
" ",
|
|
@@ -25,6 +26,10 @@ module Process
|
|
|
25
26
|
"█",
|
|
26
27
|
]
|
|
27
28
|
|
|
29
|
+
# Format a fractional value as a horizontal bar.
|
|
30
|
+
# @parameter value [Float] A value between 0.0 and 1.0 representing the fill level.
|
|
31
|
+
# @parameter width [Integer] The width of the bar in characters.
|
|
32
|
+
# @returns [String] A string of Unicode block characters representing the filled bar.
|
|
28
33
|
def self.format(value, width)
|
|
29
34
|
blocks = width * value
|
|
30
35
|
full_blocks = blocks.floor
|
|
@@ -38,6 +43,7 @@ module Process
|
|
|
38
43
|
end
|
|
39
44
|
end
|
|
40
45
|
|
|
46
|
+
# Command that displays a formatted summary of memory usage statistics for processes.
|
|
41
47
|
class Summary < Samovar::Command
|
|
42
48
|
self.description = "Display a summary of memory usage statistics."
|
|
43
49
|
|
|
@@ -48,6 +54,8 @@ module Process
|
|
|
48
54
|
option "--total-memory <integer>", "Set the total memory relative to the usage (MiB).", type: Integer
|
|
49
55
|
end
|
|
50
56
|
|
|
57
|
+
# Get the configured terminal for styled output.
|
|
58
|
+
# @returns [Console::Terminal] A terminal object with color/style definitions.
|
|
51
59
|
def terminal
|
|
52
60
|
terminal = Console::Terminal.for($stdout)
|
|
53
61
|
|
|
@@ -62,6 +70,9 @@ module Process
|
|
|
62
70
|
return terminal
|
|
63
71
|
end
|
|
64
72
|
|
|
73
|
+
# Format a processor utilization percentage with color-coded bar.
|
|
74
|
+
# @parameter value [Float] The CPU utilization percentage (0.0-100.0).
|
|
75
|
+
# @parameter terminal [Console::Terminal] The terminal to output styled text.
|
|
65
76
|
def format_processor_utilization(value, terminal)
|
|
66
77
|
if value > 80.0
|
|
67
78
|
intensity = :high
|
|
@@ -78,6 +89,10 @@ module Process
|
|
|
78
89
|
|
|
79
90
|
UNITS = ["KiB", "MiB", "GiB"]
|
|
80
91
|
|
|
92
|
+
# Format a memory size value in human-readable units.
|
|
93
|
+
# @parameter value [Numeric] The size value in kilobytes.
|
|
94
|
+
# @parameter units [Array(String)] The unit labels to use for scaling.
|
|
95
|
+
# @returns [String] A formatted string with value and unit (e.g., "512KiB", "1.5MiB").
|
|
81
96
|
def format_size(value, units: UNITS)
|
|
82
97
|
unit = 0
|
|
83
98
|
|
|
@@ -89,6 +104,10 @@ module Process
|
|
|
89
104
|
return "#{value.round(unit)}#{units[unit]}"
|
|
90
105
|
end
|
|
91
106
|
|
|
107
|
+
# Format a memory value with a horizontal bar showing utilization relative to total.
|
|
108
|
+
# @parameter value [Numeric] The memory value in kilobytes.
|
|
109
|
+
# @parameter total [Numeric] The total memory available in kilobytes.
|
|
110
|
+
# @parameter terminal [Console::Terminal] The terminal to output styled text.
|
|
92
111
|
def format_memory(value, total, terminal)
|
|
93
112
|
if value > (total * 0.8)
|
|
94
113
|
intensity = :high
|
|
@@ -103,6 +122,8 @@ module Process
|
|
|
103
122
|
terminal.print(formatted, intensity, "[", Bar.format(value / total.to_f, 60), "]", :reset)
|
|
104
123
|
end
|
|
105
124
|
|
|
125
|
+
# Get the total memory to use for percentage calculations.
|
|
126
|
+
# @returns [Integer] Total memory in kilobytes.
|
|
106
127
|
def total_memory
|
|
107
128
|
if total_memory = @options[:total_memory]
|
|
108
129
|
return total_memory * 1024
|
|
@@ -111,6 +132,7 @@ module Process
|
|
|
111
132
|
end
|
|
112
133
|
end
|
|
113
134
|
|
|
135
|
+
# Execute the summary command, capturing and displaying process metrics.
|
|
114
136
|
def call
|
|
115
137
|
# Validate required arguments: at least one of --pid or --ppid must be provided:
|
|
116
138
|
unless @options[:pid] || @options[:ppid]
|
|
@@ -11,6 +11,7 @@ require_relative "../version"
|
|
|
11
11
|
module Process
|
|
12
12
|
module Metrics
|
|
13
13
|
module Command
|
|
14
|
+
# Top-level command entry point for the process-metrics CLI.
|
|
14
15
|
class Top < Samovar::Command
|
|
15
16
|
self.description = "Collect memory usage statistics."
|
|
16
17
|
|
|
@@ -23,6 +24,7 @@ module Process
|
|
|
23
24
|
"summary" => Summary,
|
|
24
25
|
}, default: "summary"
|
|
25
26
|
|
|
27
|
+
# Execute the top command, dispatching to nested commands.
|
|
26
28
|
def call
|
|
27
29
|
if @options[:version]
|
|
28
30
|
puts "#{self.name} v#{VERSION}"
|
|
@@ -7,7 +7,10 @@ require_relative "command/top"
|
|
|
7
7
|
|
|
8
8
|
module Process
|
|
9
9
|
module Metrics
|
|
10
|
+
# @namespace
|
|
10
11
|
module Command
|
|
12
|
+
# Call the default command (Top).
|
|
13
|
+
# @parameter arguments [Array] Command-line arguments to pass through.
|
|
11
14
|
def self.call(*arguments)
|
|
12
15
|
Top.call(*arguments)
|
|
13
16
|
end
|
|
@@ -84,12 +84,20 @@ module Process
|
|
|
84
84
|
|
|
85
85
|
alias memory_usage total_size
|
|
86
86
|
|
|
87
|
+
# Recursively expand a set of child PIDs into a collection.
|
|
88
|
+
# @parameter children [Array<Integer>] The list of child process IDs to expand.
|
|
89
|
+
# @parameter hierarchy [Hash<Integer, Array<Integer>>] The parent-to-children process hierarchy.
|
|
90
|
+
# @parameter pids [Set<Integer>] The set to populate with process IDs.
|
|
87
91
|
def self.expand_children(children, hierarchy, pids)
|
|
88
92
|
children.each do |pid|
|
|
89
93
|
self.expand(pid, hierarchy, pids)
|
|
90
94
|
end
|
|
91
95
|
end
|
|
92
96
|
|
|
97
|
+
# Recursively expand a process and its descendants into a collection.
|
|
98
|
+
# @parameter pid [Integer] The process ID to expand.
|
|
99
|
+
# @parameter hierarchy [Hash<Integer, Array<Integer>>] The parent-to-children process hierarchy.
|
|
100
|
+
# @parameter pids [Set<Integer>] The set to populate with process IDs.
|
|
93
101
|
def self.expand(pid, hierarchy, pids)
|
|
94
102
|
unless pids.include?(pid)
|
|
95
103
|
pids << pid
|
|
@@ -100,6 +108,9 @@ module Process
|
|
|
100
108
|
end
|
|
101
109
|
end
|
|
102
110
|
|
|
111
|
+
# Build a parent-to-children process hierarchy from a set of processes.
|
|
112
|
+
# @parameter processes [Hash<Integer, General>] A hash mapping PIDs to General instances.
|
|
113
|
+
# @returns [Hash<Integer, Array<Integer>>] A hash mapping each parent PID to an array of child PIDs.
|
|
103
114
|
def self.build_tree(processes)
|
|
104
115
|
hierarchy = Hash.new{|h,k| h[k] = []}
|
|
105
116
|
|
|
@@ -112,6 +123,8 @@ module Process
|
|
|
112
123
|
return hierarchy
|
|
113
124
|
end
|
|
114
125
|
|
|
126
|
+
# Capture detailed memory metrics for each process in the given collection.
|
|
127
|
+
# @parameter processes [Hash<Integer, General>] A hash mapping PIDs to General instances.
|
|
115
128
|
def self.capture_memory(processes)
|
|
116
129
|
count = processes.size
|
|
117
130
|
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
module Process
|
|
7
7
|
module Metrics
|
|
8
|
+
# Darwin (macOS) implementation of memory metrics using vmmap.
|
|
8
9
|
class Memory::Darwin
|
|
9
10
|
VMMAP = "/usr/bin/vmmap"
|
|
10
11
|
|
|
@@ -25,7 +26,9 @@ module Process
|
|
|
25
26
|
end
|
|
26
27
|
end
|
|
27
28
|
|
|
28
|
-
# Parse a size string into kilobytes.
|
|
29
|
+
# Parse a size string from vmmap output into kilobytes.
|
|
30
|
+
# @parameter string [String | Nil] The size string (e.g., "4K", "1.5M", "2G").
|
|
31
|
+
# @returns [Integer] The size in kilobytes.
|
|
29
32
|
def self.parse_size(string)
|
|
30
33
|
return 0 unless string
|
|
31
34
|
|
|
@@ -93,14 +96,22 @@ module Process
|
|
|
93
96
|
|
|
94
97
|
if Memory::Darwin.supported?
|
|
95
98
|
class << Memory
|
|
99
|
+
# Whether memory capture is supported on this platform.
|
|
100
|
+
# @returns [Boolean] True if vmmap is available.
|
|
96
101
|
def supported?
|
|
97
102
|
return true
|
|
98
103
|
end
|
|
99
104
|
|
|
105
|
+
# Get total system memory size.
|
|
106
|
+
# @returns [Integer] Total memory in kilobytes.
|
|
100
107
|
def total_size
|
|
101
108
|
return Memory::Darwin.total_size
|
|
102
109
|
end
|
|
103
110
|
|
|
111
|
+
# Capture memory metrics for a process.
|
|
112
|
+
# @parameter pid [Integer] The process ID.
|
|
113
|
+
# @parameter options [Hash] Additional options (e.g., count for proportional estimates).
|
|
114
|
+
# @returns [Memory] A Memory instance with captured metrics.
|
|
104
115
|
def capture(...)
|
|
105
116
|
return Memory::Darwin.capture(...)
|
|
106
117
|
end
|
|
@@ -5,7 +5,28 @@
|
|
|
5
5
|
|
|
6
6
|
module Process
|
|
7
7
|
module Metrics
|
|
8
|
+
# Linux implementation of memory metrics using `/proc/[pid]/smaps` and `/proc/[pid]/stat`.
|
|
8
9
|
class Memory::Linux
|
|
10
|
+
# Extract minor/major page fault counters from `/proc/[pid]/stat` and assign to usage.
|
|
11
|
+
# @parameter pid [Integer] The process ID.
|
|
12
|
+
# @parameter usage [Memory] The Memory instance to populate with fault counters.
|
|
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
|
|
28
|
+
end
|
|
29
|
+
|
|
9
30
|
# @returns [Numeric] Total memory size in kilobytes.
|
|
10
31
|
def self.total_size
|
|
11
32
|
File.read("/proc/meminfo").each_line do |line|
|
|
@@ -49,6 +70,8 @@ module Process
|
|
|
49
70
|
end
|
|
50
71
|
|
|
51
72
|
usage.map_count += File.readlines("/proc/#{pid}/maps").size
|
|
73
|
+
# Also capture fault counters:
|
|
74
|
+
self.capture_faults(pid, usage)
|
|
52
75
|
rescue Errno::ENOENT => error
|
|
53
76
|
# Ignore.
|
|
54
77
|
end
|
|
@@ -79,6 +102,8 @@ module Process
|
|
|
79
102
|
usage.map_count += 1
|
|
80
103
|
end
|
|
81
104
|
end
|
|
105
|
+
# Also capture fault counters:
|
|
106
|
+
self.capture_faults(pid, usage)
|
|
82
107
|
rescue Errno::ENOENT => error
|
|
83
108
|
# Ignore.
|
|
84
109
|
end
|
|
@@ -94,14 +119,22 @@ module Process
|
|
|
94
119
|
|
|
95
120
|
if Memory::Linux.supported?
|
|
96
121
|
class << Memory
|
|
122
|
+
# Whether memory capture is supported on this platform.
|
|
123
|
+
# @returns [Boolean] True if /proc/[pid]/smaps or smaps_rollup is readable.
|
|
97
124
|
def supported?
|
|
98
125
|
return true
|
|
99
126
|
end
|
|
100
127
|
|
|
128
|
+
# Get total system memory size.
|
|
129
|
+
# @returns [Integer] Total memory in kilobytes.
|
|
101
130
|
def total_size
|
|
102
131
|
return Memory::Linux.total_size
|
|
103
132
|
end
|
|
104
133
|
|
|
134
|
+
# Capture memory metrics for a process.
|
|
135
|
+
# @parameter pid [Integer] The process ID.
|
|
136
|
+
# @parameter options [Hash] Additional options.
|
|
137
|
+
# @returns [Memory] A Memory instance with captured metrics.
|
|
105
138
|
def capture(...)
|
|
106
139
|
return Memory::Linux.capture(...)
|
|
107
140
|
end
|
|
@@ -8,7 +8,7 @@ require "json"
|
|
|
8
8
|
module Process
|
|
9
9
|
module Metrics
|
|
10
10
|
# Represents memory usage for a process, sizes are in kilobytes.
|
|
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
|
+
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, :minor_faults, :major_faults)
|
|
12
12
|
|
|
13
13
|
alias as_json to_h
|
|
14
14
|
|
|
@@ -27,8 +27,10 @@ module Process
|
|
|
27
27
|
self.private_clean_size + self.private_dirty_size
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
+
# Create a zero-initialized Memory instance.
|
|
31
|
+
# @returns [Memory] A new Memory object with all fields set to zero.
|
|
30
32
|
def self.zero
|
|
31
|
-
self.new(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
|
|
33
|
+
self.new(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
|
|
32
34
|
end
|
|
33
35
|
|
|
34
36
|
# Whether the memory usage can be captured on this system.
|
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.6.0
|
|
20
|
+
|
|
21
|
+
- 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).
|
|
22
|
+
|
|
19
23
|
### v0.5.1
|
|
20
24
|
|
|
21
25
|
- Fixed Linux memory usage capture to correctly read memory statistics.
|
data/releases.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Releases
|
|
2
2
|
|
|
3
|
+
## v0.6.0
|
|
4
|
+
|
|
5
|
+
- 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).
|
|
6
|
+
|
|
3
7
|
## v0.5.1
|
|
4
8
|
|
|
5
9
|
- Fixed Linux memory usage capture to correctly read memory statistics.
|
data.tar.gz.sig
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
/&CH�&�P��������>'k�vf'$xk&e�ɦ�Gָru���߭�B�nD-�ZU�y#c`Ԕ�A*�/���Ru��痴S:~�)rw)/דp��=���R�E� c�H_��/jdX$���A�9��,?6f�Ę�����<+ �BI�Pg����ZxN�T�:֔����Sw�f����Y��~>��}���+#do<�����ҩerV�S��C
|
|
1
|
+
\��1,��5��%��A�F��&|՝\,�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ƺ
|
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.6.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.
|
|
125
|
+
rubygems_version: 3.7.2
|
|
126
126
|
specification_version: 4
|
|
127
127
|
summary: Provide detailed OS-specific process metrics.
|
|
128
128
|
test_files: []
|
metadata.gz.sig
CHANGED
|
Binary file
|