neutrino_client 0.0.3 → 0.0.5

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.
@@ -10,11 +10,10 @@ module Neutrino
10
10
  property :group
11
11
  property :type
12
12
  property :name
13
- property :value
13
+ property :values
14
14
  property :display_options
15
15
 
16
16
  def metric_id
17
- raise StandardError.new("Requires name and hostname") unless name && hostname
18
17
  Digest::MD5.hexdigest("#{name}#{hostname}")
19
18
  end
20
19
 
@@ -23,15 +22,19 @@ module Neutrino
23
22
  end
24
23
 
25
24
  def to_h
25
+ raise StandardError.new("Requires name") unless name
26
+ raise StandardError.new("Requires values") unless values
27
+ raise StandardError.new("Requires hostname") unless hostname
26
28
  {
27
29
  :metadata => (base_metadata || {}).merge({
28
30
  :name => self.name,
29
31
  :group => self.group,
30
- :type => self.type
32
+ :type => self.type,
33
+ :hostname => self.hostname
31
34
  }),
32
35
  :display_options => self.display_options,
33
36
  :name => self.metric_id,
34
- :value => self.value
37
+ :values => self.values || {}
35
38
  }
36
39
  end
37
40
  end
@@ -8,7 +8,7 @@ module Neutrino
8
8
  def initialize(opts={})
9
9
  super(opts)
10
10
  configure
11
- # query
11
+ query
12
12
  end
13
13
 
14
14
  def self.execute_and_parse(command)
@@ -16,9 +16,16 @@ module Neutrino
16
16
  stdout.read.strip
17
17
  end
18
18
  result = {}
19
- output.split("\n").each do |line|
19
+ Log.debug("#{command} outputs #{output}")
20
+ output.to_s.split("\n").each do |line|
20
21
  whole_line, key, value = line.match(/(\S*) (.*)/).to_a
21
- key_parts = key.split(/\.|_/)
22
+ key = line.strip if key.nil? # Can be nil if no value is specified
23
+ key_parts = nil
24
+ if key.match("graph_")
25
+ key_parts = key.split(/_/)
26
+ else
27
+ key_parts = key.split(/\./)
28
+ end
22
29
  if key_parts.length == 2
23
30
  result[key_parts.first] ||= {}
24
31
  result[key_parts.first][key_parts.last] = value
@@ -26,6 +33,7 @@ module Neutrino
26
33
  result[key_parts.first] = value
27
34
  end
28
35
  end
36
+ Log.debug("#{command} output is parsed as #{result.inspect}")
29
37
  result
30
38
  end
31
39
 
@@ -44,14 +52,22 @@ module Neutrino
44
52
  self.base_metadata["group"] = plugin_configuration["graph"]["category"]
45
53
  self.base_metadata["type"] = plugin_configuration["graph"]["vlabel"]
46
54
  self.base_metadata["name"] = plugin_configuration["graph"]["title"]
55
+ self.name = plugin_configuration["graph"]["title"]
47
56
  end
48
57
  end
49
58
 
50
59
  def query
51
60
  plugin_query = MuninMetric.query_plugin(self.munin_plugin_path)
52
61
  begin
53
- self.value = plugin_query.to_a.first[1]["value"]
54
- rescue
62
+ values_hash = {}
63
+ plugin_query.to_a.each do |metric|
64
+ name = metric[0]
65
+ val = metric[1]["value"]
66
+ values_hash[name] = val.nil? ? nil : val.to_f
67
+ end
68
+ self.values = values_hash
69
+ rescue => e
70
+ Log.debug("Error querying munin: #{e}")
55
71
  end
56
72
  end
57
73
 
@@ -6,60 +6,46 @@ module Neutrino
6
6
 
7
7
  def self.record(metric)
8
8
  Log.info("Recording: #{metric.to_json}")
9
- HTTParty.post('http://neutrino2.heroku.com/record', :body => metric.to_json)
10
- # `curl --silent -X POST -H 'Content-Type: application/json' -d '#{metric.to_json}' http://neutrino2.heroku.com/record`
9
+ response = HTTParty.post('http://neutrino2.heroku.com/record', :body => metric.to_h)
10
+ Log.debug "Response: body=#{response.body} code=#{response.code} message=#{response.message} headers=#{response.headers.inspect}"
11
11
  end
12
12
 
13
13
  def self.get_metrics
14
14
  ms = [
15
- ShellMetric.new({
16
- :name => "CPU Steal",
17
- :command => "iostat | grep -A1 avg-cpu | tail -1 | awk '{print $5}'",
18
- :group => "system",
19
- :type => "CPU"
20
- }),
21
15
  ShellMetric.new({
22
16
  :name => "User CPU",
23
- :command => "iostat | grep -A1 avg-cpu | tail -1 | awk '{print $1}'",
17
+ :commands => {:user => "iostat | grep -A1 avg-cpu | tail -1 | awk '{print $1}'"},
24
18
  :group => "system",
25
19
  :type => "CPU",
26
20
  :display_options => {:min => 0, :max => 1}
27
21
  }),
28
22
  ShellMetric.new({
29
23
  :name => "Idle CPU",
30
- :command => "iostat | grep -A1 avg-cpu | tail -1 | awk '{print $6}'",
24
+ :commands => {:idle => "iostat | grep -A1 avg-cpu | tail -1 | awk '{print $6}'"},
31
25
  :group => "system",
32
26
  :type => "CPU",
33
27
  :display_options => {:min => 0, :max => 100}
34
28
  }),
35
29
  ShellMetric.new({
36
30
  :name => "Free Memory",
37
- :command => "cat /proc/meminfo | grep 'MemFree' | awk '{print $2}'",
31
+ :commands => {:free => "cat /proc/meminfo | grep 'MemFree' | awk '{print $2}'"},
38
32
  :group => "system",
39
33
  :type => 'memory'
40
34
  # :display_options => {:min => 0, :max => ShellMetric.execute("cat /proc/meminfo | grep 'MemTotal' | awk '{print $2}'")}
41
35
  }),
42
- ShellMetric.new({
43
- :name => "Load Avg (1m)",
44
- :command => "cat /proc/loadavg | awk '{print $1}'",
45
- :group => "system",
46
- :type => 'load'
47
- }),
48
- ShellMetric.new({
49
- :name => "Load Avg (5m)",
50
- :command => "cat /proc/loadavg | awk '{print $2}'",
51
- :group => "system",
52
- :type => 'load'
53
- }),
54
36
  ShellMetric.new({
55
37
  :name => "Load Avg (15m)",
56
- :command => "cat /proc/loadavg | awk '{print $3}'",
38
+ :commands => {
39
+ "1_min" => "cat /proc/loadavg | awk '{print $1}'",
40
+ "5_min" => "cat /proc/loadavg | awk '{print $2}'",
41
+ "15_min" => "cat /proc/loadavg | awk '{print $3}'",
42
+ },
57
43
  :group => "system",
58
44
  :type => 'load'
59
45
  }),
60
46
  ShellMetric.new({
61
47
  :name => "Process Count",
62
- :command => "ps aux | wc -l",
48
+ :commands => {:processes => "ps aux | wc -l"},
63
49
  :group => "system",
64
50
  :type => 'process'
65
51
  })
@@ -72,11 +58,7 @@ module Neutrino
72
58
  get_metrics.each do |m|
73
59
  m.hostname = `hostname`.strip
74
60
  m.base_metadata = Config.metadata
75
- begin
76
- Reporter.record(m)
77
- rescue StandardError => e
78
- Log.warn("Error running '#{m.name}': #{e}")
79
- end
61
+ Reporter.record(m)
80
62
  end
81
63
  end
82
64
  end
@@ -3,20 +3,28 @@ require 'open3'
3
3
  module Neutrino
4
4
  module Client
5
5
  class ShellMetric < Metric
6
- property :command
6
+ property :commands
7
+
8
+ def initialize(opts={})
9
+ super(opts)
10
+ query
11
+ end
7
12
 
8
13
  def self.execute(command)
9
14
  parsed_value = Open3.popen3(command) do |stdin, stdout, stderr, wait_thr|
10
15
  stdout.read.strip
11
16
  end
12
- raise StandardError.new("Could not parse a value from \"#{command}\". Got '#{parsed_value}'") if parsed_value.nil? || parsed_value == ""
17
+ Log.debug("'#{command}' outputs '#{parsed_value}'")
18
+ Log.warn("'#{command}' outputs '#{parsed_value}'") if parsed_value.nil? || parsed_value.empty?
13
19
  return parsed_value
14
20
  end
15
21
 
16
- def value
17
- v = ShellMetric.execute(self.command)
18
- Log.debug("#{self.command} returns '#{v}'")
19
- v
22
+ def query
23
+ values_hash = {}
24
+ self.commands.each_pair do |name, cmd|
25
+ values_hash[name] = ShellMetric.execute(cmd)
26
+ end
27
+ self.values = values_hash
20
28
  end
21
29
  end
22
30
  end
@@ -1,5 +1,5 @@
1
1
  module Neutrino
2
2
  module Client
3
- VERSION = "0.0.3"
3
+ VERSION = "0.0.5"
4
4
  end
5
5
  end
@@ -1,4 +1,4 @@
1
- require "neutrino/client"
1
+ require "lib/neutrino/client"
2
2
  require "test/unit"
3
3
 
4
4
  module Neutrino
@@ -1,4 +1,4 @@
1
- require "neutrino/client"
1
+ require "lib/neutrino/client"
2
2
  require "test/unit"
3
3
 
4
4
  module Neutrino
@@ -1,4 +1,4 @@
1
- require "neutrino/client"
1
+ require "lib/neutrino/client"
2
2
  require "test/unit"
3
3
  require 'mocha'
4
4
 
@@ -17,7 +17,7 @@ module Neutrino
17
17
  def test_metric_attributes
18
18
  attrs = {
19
19
  :name => "Load Avg (15m)",
20
- :value => 747,
20
+ :values => {:myval => 747},
21
21
  :group => "system",
22
22
  :type => 'load',
23
23
  :display_options => {:width => 100}
@@ -26,7 +26,8 @@ module Neutrino
26
26
  assert_equal metric.group, attrs[:group]
27
27
  assert_equal metric.type, attrs[:type]
28
28
  assert_equal metric.name, attrs[:name]
29
- assert_equal metric.value, attrs[:value]
29
+ assert_equal metric.values, attrs[:values]
30
+ assert_equal metric.values[:myval], attrs[:values][:myval]
30
31
  assert_equal metric.display_options, attrs[:display_options]
31
32
  end
32
33
 
@@ -51,16 +52,6 @@ module Neutrino
51
52
  assert_equal metric.metric_id, Digest::MD5.hexdigest("#{name}#{hostname}")
52
53
  end
53
54
 
54
- def test_metric_id_raises_without_hostname
55
- metric = Metric.new(:name => "a_metric")
56
- assert_raises(StandardError){ metric.metric_id }
57
- end
58
-
59
- def test_metric_id_raises_without_hostname
60
- metric = Metric.new(:hostname => "a_metric.com")
61
- assert_raises(StandardError){ metric.metric_id }
62
- end
63
-
64
55
  def test_to_json_calls_to_h
65
56
  metric = Metric.new(:hostname => "a_metric.com", :name => "asdf")
66
57
  metric.expects(:to_h)
@@ -70,7 +61,7 @@ module Neutrino
70
61
  def test_metric_to_h
71
62
  attrs = {
72
63
  :name => "Load Avg (15m)",
73
- :value => 0.11,
64
+ :values => {:bval => 0.11},
74
65
  :group => "system",
75
66
  :type => 'load',
76
67
  :display_options => {:width => 100}
@@ -84,10 +75,46 @@ module Neutrino
84
75
  assert_equal result[:metadata][:name], attrs[:name]
85
76
  assert_equal result[:metadata][:group], attrs[:group]
86
77
  assert_equal result[:metadata][:type], attrs[:type]
78
+ assert_equal result[:metadata][:hostname], metric.hostname
87
79
  assert_equal result[:display_options], attrs[:display_options]
88
- assert_equal result[:value], attrs[:value]
80
+ assert_equal result[:values][:bval], 0.11
89
81
  assert_equal result[:name], metric.metric_id
90
82
  end
83
+
84
+ def test_metric_to_h_raises_without_hostname
85
+ attrs = {
86
+ :name => "Load Avg (15m)",
87
+ :values => {:bval => 0.11},
88
+ :group => "system",
89
+ :type => 'load',
90
+ :display_options => {:width => 100}
91
+ }
92
+ metric = Metric.new(attrs)
93
+ assert_raises(StandardError){ metric.to_h }
94
+ end
95
+
96
+ def test_metric_to_h_raises_without_name
97
+ attrs = {
98
+ :values => {:bval => 0.11},
99
+ :group => "system",
100
+ :type => 'load',
101
+ :display_options => {:width => 100}
102
+ }
103
+ metric = Metric.new(attrs)
104
+ assert_raises(StandardError){ metric.to_h }
105
+ end
106
+
107
+ def test_metric_to_h_raises_without_values
108
+ attrs = {
109
+ :name => "Load Avg (15m)",
110
+ :group => "system",
111
+ :type => 'load',
112
+ :display_options => {:width => 100}
113
+ }
114
+ metric = Metric.new(attrs)
115
+ assert_raises(StandardError){ metric.to_h }
116
+ end
117
+
91
118
  end
92
119
  end
93
120
  end
@@ -1,4 +1,4 @@
1
- require "neutrino/client"
1
+ require "lib/neutrino/client"
2
2
  require "test/unit"
3
3
  require 'mocha'
4
4
 
@@ -11,6 +11,7 @@ module Neutrino
11
11
 
12
12
  def test_properties
13
13
  path = "/path/to/plugin"
14
+ Open3.stubs(:popen3)
14
15
  m = MuninMetric.new(:munin_plugin_path => path)
15
16
  assert_equal m.munin_plugin_path, path
16
17
  end
@@ -42,8 +43,9 @@ module Neutrino
42
43
  assert_equal m["load"]["value"], "0.17"
43
44
  end
44
45
 
45
- def test_configure
46
+ def test_configuring_sets_base_metadata
46
47
  path = "/some_plugin"
48
+ Open3.stubs(:popen3).with("#{path}")
47
49
  Open3.expects(:popen3).with("#{path} config").returns("graph_title Load average\ngraph_args --base 1000 -l 0\ngraph_vlabel load\ngraph_scale no\ngraph_category system\nload.label load\nload.warning 10\nload.critical 120\ngraph_info The load average of the machine describes how many processes are in the run-queue (scheduled to run \"immediately\").\nload.info Average load for the five minutes.\n")
48
50
  m = MuninMetric.new(:munin_plugin_path => path)
49
51
  assert_equal m.base_metadata["group"], "system"
@@ -51,13 +53,48 @@ module Neutrino
51
53
  assert_equal m.base_metadata["name"], "Load average"
52
54
  end
53
55
 
56
+ def test_can_handle_memory_output
57
+ path = "/some_plugin"
58
+ output = "swap_cache.value 0\nswap.value 0\n"
59
+ Open3.stubs(:popen3).with("#{path} config").returns("")
60
+ Open3.stubs(:popen3).with("#{path}").returns(output)
61
+ m = MuninMetric.new(:munin_plugin_path => path)
62
+ end
63
+
64
+ def test_can_handle_multiple_values
65
+ path = "/some_plugin"
66
+ output = "swap_cache.value 33\nswap.value 44\n"
67
+ Open3.stubs(:popen3).with("#{path} config").returns("")
68
+ Open3.stubs(:popen3).with("#{path}").returns(output)
69
+ m = MuninMetric.new(:munin_plugin_path => path)
70
+ assert_equal m.values["swap_cache"], 33
71
+ assert_equal m.values["swap"], 44
72
+ end
73
+
74
+ def test_can_handle_no_values
75
+ path = "/some_plugin"
76
+ output = "swap_cache.value\nswap.value 44\n"
77
+ Open3.stubs(:popen3).with("#{path} config").returns("")
78
+ Open3.stubs(:popen3).with("#{path}").returns(output)
79
+ m = MuninMetric.new(:munin_plugin_path => path)
80
+ assert_equal m.values["swap_cache"], nil
81
+ assert m.values.keys.include? "swap_cache"
82
+ end
83
+
84
+ def test_instanciation_configures_and_queries
85
+ path = "/some_plugin"
86
+ Open3.stubs(:popen3).with("#{path}")
87
+ Open3.expects(:popen3).with("#{path} config")
88
+ MuninMetric.new(:munin_plugin_path => path)
89
+ end
90
+
54
91
  def test_query
55
92
  path = "/some_plugin"
56
93
  Open3.expects(:popen3).with("#{path} config").returns("")
57
94
  Open3.expects(:popen3).with(path).returns("load.value 123\n")
58
95
  m = MuninMetric.new(:munin_plugin_path => path)
59
- m.query
60
- assert_equal m.value, "123"
96
+ assert m.values.keys.include? "load"
97
+ assert_equal m.values["load"], 123
61
98
  end
62
99
  end
63
100
  end
@@ -1,4 +1,4 @@
1
- require "neutrino/client"
1
+ require "lib/neutrino/client"
2
2
  require "test/unit"
3
3
  require 'mocha'
4
4
  require 'fakeweb'
@@ -12,6 +12,7 @@ module Neutrino
12
12
  ShellMetric.stubs(:execute).returns(3.14159)
13
13
 
14
14
  FakeWeb.allow_net_connect = false
15
+ FakeWeb.register_uri(:post, %r|neutrino2\.heroku\.com/|, :body => "{ok:1}")
15
16
  end
16
17
 
17
18
  def test_reporter_should_call_record_one_per_metric
@@ -20,17 +21,11 @@ module Neutrino
20
21
  Reporter.report
21
22
  end
22
23
 
23
- def test_reporter_swallows_errors_and_logs_warnings
24
- Open3.stubs(:popen3).returns('')
25
- metrics = Reporter.get_metrics
26
- Log.expects(:warn).times(metrics.length)
27
- Reporter.report
28
- end
29
-
30
24
  def test_reporter_adds_munin_plugins
25
+ dummy_metric = Metric.new(:name => "a", :hostname => 'asdf', :values => {:a => 1})
31
26
  Dir.expects(:glob).with("/somedir/*").returns(["/path1", "/path2"])
32
- MuninMetric.expects(:new).with(:munin_plugin_path => "/path1").returns(Metric.new)
33
- MuninMetric.expects(:new).with(:munin_plugin_path => "/path2").returns(Metric.new)
27
+ MuninMetric.expects(:new).with(:munin_plugin_path => "/path1").returns(dummy_metric)
28
+ MuninMetric.expects(:new).with(:munin_plugin_path => "/path2").returns(dummy_metric)
34
29
  Config.munin_plugin_globs "/somedir/*"
35
30
  Reporter.report
36
31
  end
@@ -1,4 +1,4 @@
1
- require "neutrino/client"
1
+ require "lib/neutrino/client"
2
2
  require "test/unit"
3
3
  require 'mocha'
4
4
 
@@ -9,22 +9,43 @@ module Neutrino
9
9
  Config.defaults!
10
10
  end
11
11
 
12
+ def test_initialization_calls_query
13
+ ShellMetric.expects(:execute).with("somecmd").returns(100)
14
+ m = ShellMetric.new(:commands => {:myval => "somecmd"})
15
+ end
16
+
12
17
  def test_execute_calculates_value
13
18
  cmd = "ps aux | wc -l"
14
- m = ShellMetric.new(:command => cmd)
15
19
  ShellMetric.expects(:execute).with(cmd)
16
- m.value
20
+ m = ShellMetric.new(:commands => {:myval => cmd})
17
21
  end
18
22
 
19
- def test_executes_command
23
+ def test_creates_values_hash
24
+ ShellMetric.stubs(:execute).with("somecmd").returns(100)
25
+ ShellMetric.stubs(:execute).with("othercmd").returns(150)
26
+ m = ShellMetric.new(:commands => {:myval => "somecmd", :bval => "othercmd"})
27
+ assert_equal m.values[:myval], 100
28
+ assert_equal m.values[:bval], 150
29
+ end
30
+
31
+ def test_reporter_logs_warnings_for_empty_output
32
+ cmd = "ps aux | wc -l"
33
+ Open3.stubs(:popen3).with(cmd).returns("")
34
+ Log.expects(:warn)
35
+ ShellMetric.execute(cmd)
36
+ end
37
+
38
+ def test_reporter_logs_debugs
20
39
  cmd = "ps aux | wc -l"
21
- Open3.expects(:popen3).with(cmd).returns(100)
40
+ Open3.stubs(:popen3).with(cmd).returns("100")
41
+ Log.expects(:debug)
22
42
  ShellMetric.execute(cmd)
23
43
  end
24
44
 
25
- def test_execute_raises_error_without_value
26
- Open3.stubs(:popen3).returns('')
27
- assert_raises(StandardError){ShellMetric.execute("some bogus command")}
45
+ def test_executes_command
46
+ cmd = "ps aux | wc -l"
47
+ Open3.expects(:popen3).with(cmd).returns("100")
48
+ ShellMetric.execute(cmd)
28
49
  end
29
50
  end
30
51
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: neutrino_client
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
4
+ hash: 21
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 3
10
- version: 0.0.3
9
+ - 5
10
+ version: 0.0.5
11
11
  platform: ruby
12
12
  authors:
13
13
  - Nick Stielau
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-02-14 00:00:00 -08:00
18
+ date: 2011-02-25 00:00:00 -08:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency