server_metrics 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
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