server_metrics 1.0.0 → 1.0.1

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.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 1.0.1
2
+
3
+ * Grouping kthreadd's children together under the comm "kthreadd"
4
+
1
5
  ## 0.1.0
2
6
 
3
7
  * Optimization for collecting processes on Linux
@@ -47,17 +47,7 @@ class ServerMetrics::Processes
47
47
 
48
48
  def run
49
49
  @processes = calculate_processes # returns a hash
50
- top_memory = get_top_processes(:memory, 10) # returns an array
51
- top_cpu = get_top_processes(:cpu, 10) # returns an array
52
-
53
- # combine the two and index by cmd. The indexing process will remove duplicates
54
- result = (top_cpu + top_memory).inject(Hash.new) {|temp_hash,process_hash| temp_hash[process_hash[:cmd]] = process_hash; temp_hash }
55
-
56
- # An alternate approach is to return an array with two separate arrays. More explicit, but more verbose.
57
- #{
58
- # :top_memory => get_top_processes(:memory, 10),
59
- # :top_cpu => get_top_processes(:cpu, 10)
60
- #}
50
+ @processes.keys.inject(@processes) { |processes, key| processes[key][:cmd] = key; processes }
61
51
  end
62
52
 
63
53
  # called from run(). This method lists all the processes running on the server, groups them by command,
@@ -121,13 +111,6 @@ class ServerMetrics::Processes
121
111
  grouped
122
112
  end
123
113
 
124
- # Can only be called after @processes is set. Based on @processes, calcuates the top {num} processes, as ordered by {order_by}.
125
- # Returns an array of hashes:
126
- # [{:cmd=>"ruby", :cpu=>30.0, :memory=>100, :uid=>1,:cmdlines=>[]}, {:cmd => ...} ]
127
- def get_top_processes(order_by, num)
128
- @processes.map { |key, hash| {:cmd => key}.merge(hash) }.sort { |a, b| a[order_by] <=> b[order_by] }.reverse[0...num]
129
- end
130
-
131
114
  # Relies on the /proc directory (/proc/timer_list). We need this because the process CPU utilization is measured in jiffies.
132
115
  # In order to calculate the process' % usage of total CPU resources, we need to know how many jiffies have passed.
133
116
  # Unfortunately, jiffies isn't a fixed value (it can vary between 100 and 250 per second), so we need to calculate it ourselves.
@@ -20,6 +20,21 @@ module SysLite
20
20
 
21
21
  # @mem_total = IO.read("/proc/meminfo")[/MemTotal.*/].split[1].to_i * 1024 rescue nil
22
22
  # @boot_time = IO.read("/proc/stat")[/btime.*/].split.last.to_i rescue nil
23
+
24
+ # Handles a special case on Ubuntu - kthreadd generates many children (200+).
25
+ # These are aggregated together and reported as a single process, kthreadd.
26
+ #
27
+ # Examples child process names:
28
+ #
29
+ # watchdog/5
30
+ # kworker/10:1
31
+ # kworker/10:1H
32
+ # ksoftirqd/8
33
+ # migration/10
34
+ # scsi_eh_2
35
+ # flush-9:2
36
+ # kswapd0
37
+ @kthreadd = nil # the ProcTableStruct representing kthreadd
23
38
 
24
39
  @fields = [
25
40
  'cmdline', # Complete command line
@@ -107,7 +122,6 @@ module SysLite
107
122
  def self.ps(pid=nil)
108
123
  array = block_given? ? nil : []
109
124
  struct = nil
110
-
111
125
  raise TypeError unless pid.is_a?(Fixnum) if pid
112
126
 
113
127
  Dir.foreach("/proc"){ |file|
@@ -172,9 +186,10 @@ module SysLite
172
186
  stat = stat.split
173
187
 
174
188
  struct.pid = stat[0].to_i
175
- struct.comm = stat[1].tr('()','') # Remove parens
189
+ # Remove parens. Note this could be overwritten in #get_comm_group_name.
190
+ struct.comm = stat[1].tr('()','')
176
191
  # struct.state = stat[2]
177
- # struct.ppid = stat[3].to_i
192
+ struct.ppid = stat[3].to_i
178
193
  # struct.pgrp = stat[4].to_i
179
194
  # struct.session = stat[5].to_i
180
195
  # struct.tty_nr = stat[6].to_i
@@ -233,7 +248,18 @@ module SysLite
233
248
  # Manually calculate CPU and memory usage
234
249
  # struct.pctcpu = get_pctcpu(struct.utime, struct.starttime)
235
250
  # struct.pctmem = get_pctmem(struct.rss)
236
-
251
+
252
+ # don't report kthreadd chidren individually - aggregate into the parent.
253
+ if kthreadd_child?(struct.ppid)
254
+ @kthreadd.utime += struct.utime
255
+ @kthreadd.stime += struct.stime
256
+ @kthreadd.rss += struct.rss
257
+ next
258
+ elsif struct.comm == 'kthreadd'
259
+ @kthreadd = struct
260
+ next
261
+ end
262
+
237
263
  struct.freeze # This is read-only data
238
264
 
239
265
  if block_given?
@@ -243,7 +269,12 @@ module SysLite
243
269
  end
244
270
  }
245
271
 
246
- pid ? struct : array
272
+ if pid
273
+ struct
274
+ else
275
+ array << @kthreadd if @kthreadd # not added when iterating.
276
+ array
277
+ end
247
278
  end
248
279
 
249
280
  # Returns an array of fields that each ProcTableStruct will contain. This
@@ -261,6 +292,11 @@ module SysLite
261
292
  end
262
293
 
263
294
  private
295
+
296
+ # True if the process's parent process id is kthreadd.
297
+ def self.kthreadd_child?(ppid)
298
+ @kthreadd and @kthreadd.pid == ppid
299
+ end
264
300
 
265
301
  # Calculate the percentage of memory usage for the given process.
266
302
  #
@@ -1,3 +1,3 @@
1
1
  module ServerMetrics
2
- VERSION = "1.0.0"
2
+ VERSION = "1.0.1"
3
3
  end
data/test/test_basics.rb CHANGED
@@ -84,7 +84,7 @@ class TestBasics < Test::Unit::TestCase
84
84
  p.instance_variable_set '@last_run', last_run
85
85
  p.instance_variable_set '@last_process_list', "bogus value"
86
86
 
87
- assert_equal({:last_run=>last_run,:last_jiffies=>nil,:last_process_list=>"bogus value"}, p.to_hash)
87
+ assert_equal({ :last_run => last_run, :last_jiffies => nil, :last_process_list => "bogus value" }, p.to_hash)
88
88
  end
89
89
 
90
90
  def test_processes_from_hash
@@ -151,4 +151,4 @@ class TestBasics < Test::Unit::TestCase
151
151
  end
152
152
  end
153
153
 
154
- end
154
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: server_metrics
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2014-01-13 00:00:00.000000000 Z
14
+ date: 2014-01-14 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: sys-proctable