process-metrics 0.1.1 → 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: f6eef8073c3bde206609e197c710ff0a3a7b5bb100b9e7e3081ceb1a3cafad4d
4
- data.tar.gz: 8861bf2052c3cd39bc0e1d75682538efdce0c6bc6bbb444a44a4a12a8bbc23bd
3
+ metadata.gz: 7cec50409b679c3cb38ad2951f012f9ec80ebd932af96a27aa8e443724b6f08b
4
+ data.tar.gz: e93c274723c0a744b9b27d38f20e7ca7c430b33ad804d55f706d3ceda30b95b8
5
5
  SHA512:
6
- metadata.gz: 48118f047e6b37cae47ab65b5486c63009efc60379eeaf984bb0076e0a2890ff3be3e4ee6ded12d32dc3e18b805bb04564c590ad6233bef666b8238e88de76d4
7
- data.tar.gz: 21c7a27dc3494df5a7ae7fa830af1bfe8d7989b388534e0b7b6bac1bd4416168a927e7efcfe13faba5abb369ec6ae51181d039f294b614166096a46ad88797b0
6
+ metadata.gz: c81cee9bea7a96472e8e649f6695fafeff89d6c129c0fbc967f4fecac94a5e52818225992d9cce94e75c43abbed8877c1a5da186f14aae3cc56d085c1651c2f2
7
+ data.tar.gz: 72694d4aa9dd22d9b9f3ec82bd66586119c1fc6be7edb278c5263279004b551c0a1d8b7364ab5877d503828d904aab9f58206d72fbec65b5d59ce518e01a36f3
data/README.md CHANGED
@@ -133,6 +133,18 @@ pp metrics
133
133
  # ... snip ...
134
134
  ```
135
135
 
136
+ ### Metrics
137
+
138
+ On some platforms (currently only Linux), additional memory metrics are captured.
139
+
140
+ #### Proportional Set Size
141
+
142
+ The total private memory usage + shared memory usage divided by the number of processes sharing said data.
143
+
144
+ #### Unique Set Size
145
+
146
+ The total private memory usage.
147
+
136
148
  ## Contributing
137
149
 
138
150
  1. Fork it
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Copyright, 2020, by Samuel G. D. Williams. <http://www.codeotaku.com>
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
23
+
24
+ require_relative '../lib/process/metrics/command'
25
+
26
+ begin
27
+ Process::Metrics::Command.call
28
+ rescue Interrupt
29
+ end
@@ -0,0 +1,31 @@
1
+ # Copyright, 2017, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require_relative 'command/top'
22
+
23
+ module Process
24
+ module Metrics
25
+ module Command
26
+ def self.call(*arguments)
27
+ Top.call(*arguments)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,177 @@
1
+ # Copyright, 2020, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require 'samovar'
22
+
23
+ require_relative '../general'
24
+
25
+ require 'console/terminal'
26
+
27
+ module Process
28
+ module Metrics
29
+ module Command
30
+ module Bar
31
+ BLOCK = [
32
+ " ",
33
+ "▏",
34
+ "▎",
35
+ "▍",
36
+ "▌",
37
+ "▋",
38
+ "▊",
39
+ "▉",
40
+ "█",
41
+ ]
42
+
43
+ def self.format(value, width)
44
+ blocks = width * value
45
+ full_blocks = blocks.floor
46
+ partial_block = ((blocks - full_blocks) * BLOCK.size).floor
47
+
48
+ if partial_block.zero?
49
+ BLOCK.last * full_blocks
50
+ else
51
+ "#{BLOCK.last * full_blocks}#{BLOCK[partial_block]}"
52
+ end.ljust(width)
53
+ end
54
+ end
55
+
56
+ class Summary < Samovar::Command
57
+ self.description = "Display a summary of memory usage statistics."
58
+
59
+ options do
60
+ option '--pid <integer>', "Report on a single process id.", type: Integer, required: true
61
+ option '-p/--ppid <integer>', "Report on all children of this process id.", type: Integer, required: true
62
+
63
+ option '--memory-scale <integer>', "Scale maximum memory usage to the specified amount (MiB).", type: Integer, default: 512
64
+ end
65
+
66
+ def terminal
67
+ terminal = Console::Terminal.for($stdout)
68
+
69
+ # terminal[:pid] = terminal.style(:blue)
70
+ terminal[:command] = terminal.style(nil, nil, :bold)
71
+ terminal[:key] = terminal.style(:cyan)
72
+
73
+ terminal[:low] = terminal.style(:green)
74
+ terminal[:medium] = terminal.style(:yellow)
75
+ terminal[:high] = terminal.style(:red)
76
+
77
+ return terminal
78
+ end
79
+
80
+ def format_pcpu(value, terminal)
81
+ if value > 80.0
82
+ intensity = :high
83
+ elsif value > 50.0
84
+ intensity = :medium
85
+ else
86
+ intensity = :low
87
+ end
88
+
89
+ formatted = "%5.1f%% " % value
90
+
91
+ terminal.print(formatted.rjust(10), intensity, "[", Bar.format(value / 100.0, 60), "]", :reset)
92
+ end
93
+
94
+ UNITS = ["KiB", "MiB", "GiB"]
95
+
96
+ def format_size(value, units: UNITS)
97
+ unit = 0
98
+
99
+ while value > 1024.0 && unit < units.size
100
+ value /= 1024.0
101
+ unit += 1
102
+ end
103
+
104
+ return "#{value.round(unit)}#{units[unit]}"
105
+ end
106
+
107
+ def format_memory_usage(value, terminal, scale: @options[:memory_scale])
108
+ if value > (1024.0 * scale * 0.8)
109
+ intensity = :high
110
+ elsif value > (1024.0 * scale * 0.5)
111
+ intensity = :medium
112
+ else
113
+ intensity = :low
114
+ end
115
+
116
+ formatted = (format_size(value) + ' ').rjust(10)
117
+
118
+ terminal.print(formatted, intensity, "[", Bar.format(value / (1024.0 * scale), 60), "]", :reset)
119
+ end
120
+
121
+ def call
122
+ terminal = self.terminal
123
+
124
+ summary = Process::Metrics::General.capture(pid: @options[:pid], ppid: @options[:ppid])
125
+
126
+ format_memory_usage = self.method(:format_memory_usage).curry
127
+ memory_usage = 0
128
+ proportional = true
129
+
130
+ summary.each do |pid, general|
131
+ terminal.print_line(:pid, pid, :reset, " ", :command, general[:command])
132
+
133
+ terminal.print(:key, "Processor Usage: ".rjust(20), :reset)
134
+ format_pcpu(general.pcpu, terminal)
135
+ terminal.print_line
136
+
137
+ if memory = general.memory
138
+ memory_usage += memory.proportional_size
139
+
140
+ terminal.print_line(
141
+ :key, "Memory (PSS): ".rjust(20), :reset,
142
+ format_memory_usage[memory.proportional_size]
143
+ )
144
+
145
+ terminal.print_line(
146
+ :key, "Private (USS): ".rjust(20), :reset,
147
+ format_memory_usage[memory.unique_size]
148
+ )
149
+ else
150
+ memory_usage += general.rsz
151
+ proportional = false
152
+
153
+ terminal.print_line(
154
+ :key, "Memory (RSS): ".rjust(20), :reset,
155
+ format_memory_usage[general.rsz]
156
+ )
157
+ end
158
+ end
159
+
160
+ terminal.print_line("Summary")
161
+
162
+ if proportional
163
+ terminal.print_line(
164
+ :key, "Memory (PSS): ".rjust(20), :reset,
165
+ format_memory_usage[memory_usage]
166
+ )
167
+ else
168
+ terminal.print_line(
169
+ :key, "Memory (RSS): ".rjust(20), :reset,
170
+ format_memory_usage[memory_usage]
171
+ )
172
+ end
173
+ end
174
+ end
175
+ end
176
+ end
177
+ end
@@ -0,0 +1,53 @@
1
+ # Copyright, 2020, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require 'samovar'
22
+
23
+ require_relative 'summary'
24
+ require_relative '../version'
25
+
26
+ module Process
27
+ module Metrics
28
+ module Command
29
+ class Top < Samovar::Command
30
+ self.description = "Collect memory usage statistics."
31
+
32
+ options do
33
+ option '-h/--help', "Print out help information."
34
+ option '-v/--version', "Print out the application version."
35
+ end
36
+
37
+ nested :command, {
38
+ 'summary' => Summary,
39
+ }, default: 'summary'
40
+
41
+ def call
42
+ if @options[:version]
43
+ puts "#{self.name} v#{VERSION}"
44
+ elsif @options[:help]
45
+ self.print_usage
46
+ else
47
+ @command.call
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -49,86 +49,131 @@ module Process
49
49
  pcpu: ->(value){value.to_f},
50
50
  time: self.method(:duration),
51
51
  vsz: ->(value){value.to_i},
52
- rss: ->(value){value.to_i},
52
+ rsz: ->(value){value.to_i},
53
53
  etime: self.method(:duration),
54
54
  command: ->(value){value},
55
55
  }
56
56
 
57
- def self.set(ids)
58
- Set.new(Array(ids))
59
- end
60
-
61
- def self.expand_children(children, hierarchy, pids)
62
- children.each do |pid|
63
- self.expand(pid, hierarchy, pids)
57
+ class General < Struct.new(:pid, :ppid, :pgid, :pcpu, :vsz, :rsz, :time, :etime, :command, :memory)
58
+ def as_json
59
+ {
60
+ pid: self.pid,
61
+ ppid: self.ppid,
62
+ pgid: self.pgid,
63
+ pcpu: self.pcpu,
64
+ vsz: self.vsz,
65
+ rsz: self.rsz,
66
+ time: self.time,
67
+ etime: self.etime,
68
+ command: self.command,
69
+ memory: self.memory&.as_json,
70
+ }
64
71
  end
65
- end
66
-
67
- def self.expand(pid, hierarchy, pids)
68
- unless pids.include?(pid)
69
- pids << pid
70
-
71
- if children = hierarchy.fetch(pid, nil)
72
- self.expand_children(children, hierarchy, pids)
73
- end
74
- end
75
- end
76
-
77
- def self.capture(pid: nil, ppid: nil, ps: PS, fields: FIELDS)
78
- input, output = IO.pipe
79
72
 
80
- arguments = [ps]
81
-
82
- if pid && ppid.nil?
83
- arguments.push("-p", Array(pid).join(','))
84
- else
85
- arguments.push("ax")
73
+ def to_json(*arguments)
74
+ as_json.to_json(*arguments)
86
75
  end
87
76
 
88
- arguments.push("-o", fields.keys.join(','))
89
-
90
- ps_pid = Process.spawn(*arguments, out: output, pgroup: true)
91
-
92
- output.close
77
+ def memory_usage
78
+ if self.memory
79
+ self.memory.proportional_size
80
+ else
81
+ self.rsz
82
+ end
83
+ end
93
84
 
94
- header, *lines = input.readlines.map(&:strip)
85
+ def self.expand_children(children, hierarchy, pids)
86
+ children.each do |pid|
87
+ self.expand(pid, hierarchy, pids)
88
+ end
89
+ end
95
90
 
96
- processes = lines.map do |line|
97
- fields.
98
- zip(line.split(/\s+/, fields.size)).
99
- map{|(key, type), value| [key, type.call(value)]}.
100
- to_h
91
+ def self.expand(pid, hierarchy, pids)
92
+ unless pids.include?(pid)
93
+ pids << pid
94
+
95
+ if children = hierarchy.fetch(pid, nil)
96
+ self.expand_children(children, hierarchy, pids)
97
+ end
98
+ end
101
99
  end
102
100
 
103
- if ppid
104
- pids = Set.new
101
+ def self.build_tree(processes)
105
102
  hierarchy = Hash.new{|h,k| h[k] = []}
106
103
 
107
- processes.each do |process|
108
- unless process[:pid] == ps_pid
109
- hierarchy[process[:ppid]] << process[:pid]
104
+ processes.each_value do |process|
105
+ if ppid = process.ppid
106
+ hierarchy[ppid] << process.pid
110
107
  end
111
108
  end
112
109
 
113
- self.expand_children(Array(pid), hierarchy, pids)
114
- self.expand_children(Array(ppid), hierarchy, pids)
115
-
116
- processes.select! do |process|
117
- pids.include?(process[:pid])
110
+ return hierarchy
111
+ end
112
+
113
+ def self.capture_memory(processes)
114
+ processes.each do |pid, process|
115
+ process.memory = Memory.capture(Array(pid))
118
116
  end
119
117
  end
120
118
 
121
- if Memory.supported?
122
- processes.each do |process|
123
- if pid = process[:pid]
124
- process[:memory] = Memory.capture(Array(process[:pid]))
119
+ def self.capture(pid: nil, ppid: nil, ps: PS, fields: FIELDS)
120
+ input, output = IO.pipe
121
+
122
+ arguments = [ps]
123
+
124
+ if pid && ppid.nil?
125
+ arguments.push("-p", Array(pid).join(','))
126
+ else
127
+ arguments.push("ax")
128
+ end
129
+
130
+ arguments.push("-o", fields.keys.join(','))
131
+
132
+ ps_pid = Process.spawn(*arguments, out: output, pgroup: true)
133
+
134
+ output.close
135
+
136
+ header, *lines = input.readlines.map(&:strip)
137
+
138
+ processes = {}
139
+
140
+ lines.map do |line|
141
+ record = fields.
142
+ zip(line.split(/\s+/, fields.size)).
143
+ map{|(key, type), value| type.call(value)}
144
+
145
+ instance = self.new(*record)
146
+
147
+ processes[instance.pid] = instance
148
+ end
149
+
150
+ if ppid
151
+ pids = Set.new
152
+
153
+ hierarchy = self.build_tree(processes)
154
+
155
+ self.expand_children(Array(pid), hierarchy, pids)
156
+ self.expand_children(Array(ppid), hierarchy, pids)
157
+
158
+ processes.select! do |pid, process|
159
+ if pid != ps_pid
160
+ pids.include?(pid)
161
+ end
125
162
  end
126
163
  end
164
+
165
+ if Memory.supported?
166
+ self.capture_memory(processes)
167
+
168
+ # if pid
169
+ # self.compute_summary(pid, processes)
170
+ # end
171
+ end
172
+
173
+ return processes
174
+ ensure
175
+ Process.wait(ps_pid) if ps_pid
127
176
  end
128
-
129
- return processes
130
- ensure
131
- Process.wait(ps_pid) if ps_pid
132
177
  end
133
178
  end
134
179
  end
@@ -22,28 +22,40 @@
22
22
 
23
23
  module Process
24
24
  module Metrics
25
- module Memory
25
+ class Memory < Struct.new(:map_count, :total_size, :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)
26
+
27
+ alias as_json to_h
28
+
29
+ def to_json(*arguments)
30
+ as_json.to_json(*arguments)
31
+ end
32
+
33
+ # The unique set size, the size of completely private (unshared) data.
34
+ def unique_size
35
+ self.private_clean_size + self.private_dirty_size
36
+ end
37
+
26
38
  if File.readable?('/proc/self/smaps')
27
39
  def self.supported?
28
40
  true
29
41
  end
30
42
 
31
43
  MAP = {
32
- "Size" => :total,
33
- "Rss" => :rss,
34
- "Pss" => :pss,
35
- "Shared_Clean" => :shared_clean,
36
- "Shared_Dirty" => :shared_dirty,
37
- "Private_Clean" => :private_clean,
38
- "Private_Dirty" => :private_dirty,
39
- "Referenced" => :referenced,
40
- "Anonymous" => :anonymous,
41
- "Swap" => :swap,
42
- "SwapPss" => :swap_pss,
44
+ "Size" => :total_size,
45
+ "Rss" => :resident_size,
46
+ "Pss" => :proportional_size,
47
+ "Shared_Clean" => :shared_clean_size,
48
+ "Shared_Dirty" => :shared_dirty_size,
49
+ "Private_Clean" => :private_clean_size,
50
+ "Private_Dirty" => :private_dirty_size,
51
+ "Referenced" => :referenced_size,
52
+ "Anonymous" => :anonymous_size,
53
+ "Swap" => :swap_size,
54
+ "SwapPss" => :proportional_swap_size,
43
55
  }
44
56
 
45
57
  def self.capture(pids)
46
- usage = Hash.new{|h,k| h[k] = 0}
58
+ usage = self.new(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
47
59
 
48
60
  pids.each do |pid|
49
61
  if lines = File.readlines("/proc/#{pid}/smaps")
@@ -57,13 +69,13 @@ module Process
57
69
  elsif /VmFlags:\s+(?<flags>.*)/ =~ line
58
70
  # It should be possible to extract the number of fibers and each fiber's memory usage.
59
71
  # flags = flags.split(/\s+/)
60
- usage[:maps] += 1
72
+ usage.map_count += 1
61
73
  end
62
74
  end
63
75
  end
64
76
  end
65
77
 
66
- return usage.freeze
78
+ return usage
67
79
  end
68
80
  else
69
81
  def self.supported?
@@ -71,6 +83,7 @@ module Process
71
83
  end
72
84
 
73
85
  def self.capture(pids)
86
+ return self.new
74
87
  end
75
88
  end
76
89
  end
@@ -22,6 +22,6 @@
22
22
 
23
23
  module Process
24
24
  module Metrics
25
- VERSION = "0.1.1"
25
+ VERSION = "0.2.0"
26
26
  end
27
27
  end
@@ -23,6 +23,8 @@ Gem::Specification.new do |spec|
23
23
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
24
24
  spec.require_paths = ["lib"]
25
25
 
26
+ spec.add_dependency "console", "~> 1.8"
27
+
26
28
  spec.add_development_dependency "covered"
27
29
  spec.add_development_dependency "bundler"
28
30
  spec.add_development_dependency "rake", "~> 12.0"
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: process-metrics
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-12-30 00:00:00.000000000 Z
11
+ date: 2020-02-01 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: console
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.8'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.8'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: covered
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -70,8 +84,7 @@ description:
70
84
  email:
71
85
  - samuel.williams@oriontransfer.co.nz
72
86
  executables:
73
- - console
74
- - setup
87
+ - process-metrics
75
88
  extensions: []
76
89
  extra_rdoc_files: []
77
90
  files:
@@ -81,9 +94,11 @@ files:
81
94
  - Gemfile
82
95
  - README.md
83
96
  - Rakefile
84
- - bin/console
85
- - bin/setup
97
+ - bin/process-metrics
86
98
  - lib/process/metrics.rb
99
+ - lib/process/metrics/command.rb
100
+ - lib/process/metrics/command/summary.rb
101
+ - lib/process/metrics/command/top.rb
87
102
  - lib/process/metrics/general.rb
88
103
  - lib/process/metrics/memory.rb
89
104
  - lib/process/metrics/version.rb
@@ -108,7 +123,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
108
123
  - !ruby/object:Gem::Version
109
124
  version: '0'
110
125
  requirements: []
111
- rubygems_version: 3.0.6
126
+ rubygems_version: 3.1.2
112
127
  signing_key:
113
128
  specification_version: 4
114
129
  summary: Provide detailed OS-specific process metrics.
@@ -1,14 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "bundler/setup"
4
- require "process/metrics"
5
-
6
- # You can add fixtures and/or initialization code here to make experimenting
7
- # with your gem easier. You can also use a different console, if you like.
8
-
9
- # (If you use this, don't forget to add pry to your Gemfile!)
10
- # require "pry"
11
- # Pry.start
12
-
13
- require "irb"
14
- IRB.start(__FILE__)
data/bin/setup DELETED
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here