riemann-tools 1.0.0 → 1.1.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.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +11 -0
  3. data/.github/workflows/ci.yml +13 -0
  4. data/.github/workflows/codeql-analysis.yml +72 -0
  5. data/.rubocop.yml +32 -0
  6. data/CHANGELOG.md +31 -2
  7. data/README.markdown +8 -24
  8. data/Rakefile +4 -2
  9. data/SECURITY.md +42 -0
  10. data/bin/riemann-apache-status +92 -78
  11. data/bin/riemann-bench +54 -49
  12. data/bin/riemann-cloudant +44 -40
  13. data/bin/riemann-consul +82 -76
  14. data/bin/riemann-dir-files-count +53 -47
  15. data/bin/riemann-dir-space +53 -47
  16. data/bin/riemann-diskstats +78 -75
  17. data/bin/riemann-fd +68 -48
  18. data/bin/riemann-freeswitch +108 -103
  19. data/bin/riemann-haproxy +46 -40
  20. data/bin/riemann-health +4 -343
  21. data/bin/riemann-kvminstance +18 -13
  22. data/bin/riemann-memcached +35 -29
  23. data/bin/riemann-net +4 -104
  24. data/bin/riemann-nginx-status +74 -67
  25. data/bin/riemann-ntp +4 -33
  26. data/bin/riemann-portcheck +40 -31
  27. data/bin/riemann-proc +96 -90
  28. data/bin/riemann-varnish +51 -45
  29. data/bin/riemann-zookeeper +38 -34
  30. data/lib/riemann/tools/health.rb +347 -0
  31. data/lib/riemann/tools/net.rb +104 -0
  32. data/lib/riemann/tools/ntp.rb +41 -0
  33. data/lib/riemann/tools/version.rb +1 -1
  34. data/lib/riemann/tools.rb +37 -40
  35. data/riemann-tools.gemspec +4 -1
  36. data/tools/riemann-aws/{Rakefile.rb → Rakefile} +2 -0
  37. data/tools/riemann-aws/bin/riemann-aws-billing +72 -66
  38. data/tools/riemann-aws/bin/riemann-aws-rds-status +55 -41
  39. data/tools/riemann-aws/bin/riemann-aws-sqs-status +37 -31
  40. data/tools/riemann-aws/bin/riemann-aws-status +63 -51
  41. data/tools/riemann-aws/bin/riemann-elb-metrics +149 -148
  42. data/tools/riemann-aws/bin/riemann-s3-list +70 -65
  43. data/tools/riemann-aws/bin/riemann-s3-status +85 -82
  44. data/tools/riemann-chronos/{Rakefile.rb → Rakefile} +2 -0
  45. data/tools/riemann-chronos/bin/riemann-chronos +136 -119
  46. data/tools/riemann-docker/{Rakefile.rb → Rakefile} +2 -0
  47. data/tools/riemann-docker/bin/riemann-docker +163 -174
  48. data/tools/riemann-elasticsearch/{Rakefile.rb → Rakefile} +2 -0
  49. data/tools/riemann-elasticsearch/bin/riemann-elasticsearch +155 -147
  50. data/tools/riemann-marathon/{Rakefile.rb → Rakefile} +2 -0
  51. data/tools/riemann-marathon/bin/riemann-marathon +138 -122
  52. data/tools/riemann-mesos/{Rakefile.rb → Rakefile} +2 -0
  53. data/tools/riemann-mesos/bin/riemann-mesos +125 -110
  54. data/tools/riemann-munin/{Rakefile.rb → Rakefile} +2 -0
  55. data/tools/riemann-munin/bin/riemann-munin +28 -22
  56. data/tools/riemann-rabbitmq/{Rakefile.rb → Rakefile} +2 -0
  57. data/tools/riemann-rabbitmq/bin/riemann-rabbitmq +226 -222
  58. data/tools/riemann-riak/{Rakefile.rb → Rakefile} +2 -0
  59. data/tools/riemann-riak/bin/riemann-riak +281 -289
  60. data/tools/riemann-riak/riak_status/riak_status.rb +39 -39
  61. metadata +65 -16
data/bin/riemann-cloudant CHANGED
@@ -1,59 +1,63 @@
1
1
  #!/usr/bin/env ruby
2
- Process.setproctitle($0)
2
+ # frozen_string_literal: true
3
3
 
4
- # Gathers load balancer statistics from Cloudant.com (shared cluster) and submits them to Riemann.
4
+ Process.setproctitle($PROGRAM_NAME)
5
5
 
6
- require File.expand_path('../../lib/riemann/tools', __FILE__)
6
+ # Gathers load balancer statistics from Cloudant.com (shared cluster) and submits them to Riemann.
7
7
 
8
- class Riemann::Tools::Cloudant
9
- include Riemann::Tools
10
- require 'net/http'
11
- require 'json'
8
+ require File.expand_path('../lib/riemann/tools', __dir__)
12
9
 
13
- opt :cloudant_username, "Cloudant username", :type => :string, :required => true
14
- opt :cloudant_password, "Cloudant pasword", :type => :string, :required => true
10
+ module Riemann
11
+ module Tools
12
+ class Cloudant
13
+ include Riemann::Tools
14
+ require 'net/http'
15
+ require 'json'
15
16
 
16
- def tick
17
- json = JSON.parse(get_json().body)
18
- json.each do |node|
19
- return if node['svname'] == 'BACKEND' # this is just a sum of all nodes.
17
+ opt :cloudant_username, 'Cloudant username', type: :string, required: true
18
+ opt :cloudant_password, 'Cloudant pasword', type: :string, required: true
20
19
 
21
- ns = "cloudant #{node['pxname']}"
22
- cluster_name = node['tracked'].split('.')[0] # ie: meritage.cloudant.com
20
+ def tick
21
+ json.each do |node|
22
+ break if node['svname'] == 'BACKEND' # this is just a sum of all nodes.
23
23
 
24
- # report health of each node.
25
- report(
26
- :service => ns,
27
- :state => (node['status'] == 'UP' ? 'ok' : 'critical'),
28
- :tags => ['cloudant', cluster_name]
29
- )
24
+ ns = "cloudant #{node['pxname']}"
25
+ cluster_name = node['tracked'].split('.')[0] # ie: meritage.cloudant.com
30
26
 
31
- # report property->metric of each node.
32
- node.each do |property, metric|
33
- unless ['pxname', 'svname', 'status', 'tracked'].include?(property)
27
+ # report health of each node.
34
28
  report(
35
- :host => node['tracked'],
36
- :service => "#{ns} #{property}",
37
- :metric => metric.to_f,
38
- :state => (node['status'] == 'UP' ? 'ok' : 'critical'),
39
- :tags => ['cloudant', cluster_name]
29
+ service: ns,
30
+ state: (node['status'] == 'UP' ? 'ok' : 'critical'),
31
+ tags: ['cloudant', cluster_name],
40
32
  )
33
+
34
+ # report property->metric of each node.
35
+ node.each do |property, metric|
36
+ next if %w[pxname svname status tracked].include?(property)
37
+
38
+ report(
39
+ host: node['tracked'],
40
+ service: "#{ns} #{property}",
41
+ metric: metric.to_f,
42
+ state: (node['status'] == 'UP' ? 'ok' : 'critical'),
43
+ tags: ['cloudant', cluster_name],
44
+ )
45
+ end
41
46
  end
42
47
  end
43
48
 
49
+ def json
50
+ http = Net::HTTP.new('cloudant.com', 443)
51
+ http.use_ssl = true
52
+ http.start do |h|
53
+ get = Net::HTTP::Get.new('/api/load_balancer')
54
+ get.basic_auth opts[:cloudant_username], opts[:cloudant_password]
55
+ h.request get
56
+ end
57
+ JSON.parse(http.boby)
58
+ end
44
59
  end
45
60
  end
46
-
47
- def get_json
48
- http = Net::HTTP.new('cloudant.com', 443)
49
- http.use_ssl = true
50
- http.start do |h|
51
- get = Net::HTTP::Get.new('/api/load_balancer')
52
- get.basic_auth opts[:cloudant_username], opts[:cloudant_password]
53
- h.request get
54
- end
55
- end
56
-
57
61
  end
58
62
 
59
63
  Riemann::Tools::Cloudant.run
data/bin/riemann-consul CHANGED
@@ -1,106 +1,112 @@
1
1
  #!/usr/bin/env ruby
2
- Process.setproctitle($0)
2
+ # frozen_string_literal: true
3
+
4
+ Process.setproctitle($PROGRAM_NAME)
3
5
 
4
6
  # Reports service and node status to riemann
5
7
 
6
- require File.expand_path('../../lib/riemann/tools', __FILE__)
8
+ require File.expand_path('../lib/riemann/tools', __dir__)
7
9
  require 'socket'
8
10
  require 'net/http'
9
11
  require 'uri'
10
12
  require 'json'
11
13
 
12
- class Riemann::Tools::ConsulHealth
13
- include Riemann::Tools
14
-
15
- opt :consul_host, "Consul API Host (default to localhost)", :default => "localhost"
16
- opt :consul_port, "Consul API Host (default to 8500)", :default => "8500"
17
- opt :prefix, "prefix to use for all service names when reporting", :default => "consul "
18
- opt :minimum_services_per_node, "minimum services per node (default: 0)", :default => 0
19
-
20
- def initialize
21
-
22
- @hostname = opts[:consul_host]
23
- @prefix = opts[:prefix]
24
- @minimum_services_per_node = opts[:minimum_services_per_node]
25
- @underlying_ip = IPSocket.getaddress(@hostname)
26
- @consul_leader_url = URI.parse("http://" + opts[:consul_host] + ":" + opts[:consul_port] + "/v1/status/leader")
27
- @consul_services_url = URI.parse("http://" + opts[:consul_host] + ":" + opts[:consul_port] + "/v1/catalog/services")
28
- @consul_nodes_url = URI.parse("http://" + opts[:consul_host] + ":" + opts[:consul_port] + "/v1/catalog/nodes")
29
- @consul_health_url_prefix = "http://" + opts[:consul_host] + ":" + opts[:consul_port] + "/v1/health/service/"
30
-
31
- @last_services_read = Hash.new
32
-
33
- end
14
+ module Riemann
15
+ module Tools
16
+ class ConsulHealth
17
+ include Riemann::Tools
18
+
19
+ opt :consul_host, 'Consul API Host (default to localhost)', default: 'localhost'
20
+ opt :consul_port, 'Consul API Host (default to 8500)', default: '8500'
21
+ opt :prefix, 'prefix to use for all service names when reporting', default: 'consul '
22
+ opt :minimum_services_per_node, 'minimum services per node (default: 0)', default: 0
23
+
24
+ def initialize
25
+ @hostname = opts[:consul_host]
26
+ @prefix = opts[:prefix]
27
+ @minimum_services_per_node = opts[:minimum_services_per_node]
28
+ @underlying_ip = IPSocket.getaddress(@hostname)
29
+ @consul_leader_url = URI.parse("http://#{opts[:consul_host]}:#{opts[:consul_port]}/v1/status/leader")
30
+ @consul_services_url = URI.parse("http://#{opts[:consul_host]}:#{opts[:consul_port]}/v1/catalog/services")
31
+ @consul_nodes_url = URI.parse("http://#{opts[:consul_host]}:#{opts[:consul_port]}/v1/catalog/nodes")
32
+ @consul_health_url_prefix = "http://#{opts[:consul_host]}:#{opts[:consul_port]}/v1/health/service/"
33
+
34
+ @last_services_read = {}
35
+ end
34
36
 
35
- def alert(hostname, service, state, metric, description)
37
+ def alert(hostname, service, state, metric, description)
38
+ opts = {
39
+ host: hostname,
40
+ service: service.to_s,
41
+ state: state.to_s,
42
+ metric: metric,
43
+ description: description,
44
+ }
36
45
 
37
- opts = { :host => hostname,
38
- :service => service.to_s,
39
- :state => state.to_s,
40
- :metric => metric,
41
- :description => description }
46
+ report(opts)
47
+ end
42
48
 
43
- report(opts)
44
- end
49
+ def get(url)
50
+ Net::HTTP.get_response(url).body
51
+ end
45
52
 
46
- def get(url)
47
- Net::HTTP.get_response(url).body
48
- end
53
+ def tick
54
+ leader = JSON.parse(get(@consul_leader_url))
55
+ leader_hostname = URI.parse("http://#{leader}").hostname
49
56
 
50
- def tick
57
+ return unless leader_hostname == @underlying_ip
51
58
 
52
- leader = JSON.parse(get(@consul_leader_url))
53
- leader_hostname = URI.parse("http://" + leader).hostname
59
+ nodes = JSON.parse(get(@consul_nodes_url))
60
+ services = JSON.parse(get(@consul_services_url))
61
+ services_by_nodes = {}
54
62
 
55
- if (leader_hostname == @underlying_ip)
56
- nodes = JSON.parse(get(@consul_nodes_url))
57
- services = JSON.parse(get(@consul_services_url))
58
- services_by_nodes = Hash.new
63
+ nodes.each do |node|
64
+ node_name = node['Node']
65
+ services_by_nodes[node_name] = 0
66
+ end
59
67
 
60
- for node in nodes
61
- node_name = node["Node"]
62
- services_by_nodes[node_name] = 0
63
- end
68
+ # For every service
69
+ services.each do |service|
70
+ service_name = service[0]
71
+ health_url = URI.parse(@consul_health_url_prefix + service_name)
72
+ health_nodes = JSON.parse(get(health_url))
64
73
 
74
+ total_count = 0
75
+ ok_count = 0
65
76
 
66
- # For every service
67
- for service in services
68
- service_name = service[0]
69
- health_url = URI.parse(@consul_health_url_prefix + service_name)
70
- health_nodes = JSON.parse(get(health_url))
77
+ health_nodes.each do |node|
78
+ hostname = node['Node']['Node']
79
+ ok = node['Checks'].all? { |check| check['Status'] == 'passing' }
80
+ alert(hostname, "#{@prefix}#{service_name}", ok ? :ok : :critical, ok ? 1 : 0, JSON.generate(node))
81
+ total_count += 1
82
+ ok_count += ok ? 1 : 0
71
83
 
72
- totalCount = 0
73
- okCount = 0
84
+ last_services_by_nodes = services_by_nodes[hostname].to_i
85
+ services_by_nodes[hostname] = last_services_by_nodes + 1
86
+ end
74
87
 
75
- for node in health_nodes
76
- hostname = node["Node"]["Node"]
77
- ok = node["Checks"].all? {|check| check["Status"] == "passing"}
78
- alert(hostname, "#{@prefix}#{service_name}", ok ? :ok : :critical, ok ? 1 : 0, JSON.generate(node))
79
- totalCount += 1
80
- okCount += ok ? 1 : 0
88
+ unless @last_services_read[service_name].nil?
89
+ last_ok = @last_services_read[service_name]
90
+ if last_ok != ok_count
91
+ alert(
92
+ 'total', "#{@prefix}#{service_name}-count", ok_count >= last_ok ? :ok : :critical, ok_count,
93
+ "Number of passing #{service_name} is: #{ok_count}/#{total_count}, Last time it was: #{last_ok}",
94
+ )
95
+ end
96
+ end
81
97
 
82
- last_services_by_nodes = services_by_nodes[hostname].to_i
83
- services_by_nodes[hostname] = last_services_by_nodes + 1
98
+ @last_services_read[service_name] = ok_count
84
99
  end
85
100
 
86
- if (@last_services_read[service_name] != nil)
87
- lastOk = @last_services_read[service_name]
88
- if (lastOk != okCount)
89
- alert("total", "#{@prefix}#{service_name}-count", okCount >= lastOk ? :ok : :critical, okCount, "Number of passing #{service_name} is: #{okCount}/#{totalCount}, Last time it was: #{lastOk}")
90
- end
101
+ # For every node
102
+ services_by_nodes.each do |node, count|
103
+ alert(
104
+ node, "#{@prefix}total-services", count >= @minimum_services_per_node ? :ok : :critical, count,
105
+ "#{count} services in the specified node",
106
+ )
91
107
  end
92
-
93
- @last_services_read[service_name] = okCount
94
-
95
- end
96
-
97
- # For every node
98
- for node,count in services_by_nodes
99
- alert(node, "#{@prefix}total-services", (count >= @minimum_services_per_node) ? :ok : :critical, count, "#{count} services in the specified node")
100
108
  end
101
-
102
109
  end
103
-
104
110
  end
105
111
  end
106
112
 
@@ -1,54 +1,60 @@
1
1
  #!/usr/bin/env ruby
2
- Process.setproctitle($0)
2
+ # frozen_string_literal: true
3
3
 
4
- # Gets the number of files present on a directory and submits it to riemann
5
-
6
- require File.expand_path('../../lib/riemann/tools', __FILE__)
7
-
8
- class Riemann::Tools::DirFilesCount
9
- include Riemann::Tools
4
+ Process.setproctitle($PROGRAM_NAME)
10
5
 
11
- opt :directory, "", :default => '/var/log'
12
- opt :service_prefix, "The first part of the service name, before the directory path", :default => "dir-files-count"
13
- opt :warning, "Dir files number warning threshold", :type => Integer
14
- opt :critical, "Dir files number critical threshold", :type => Integer
15
- opt :alert_on_missing, "Send a critical metric if the directory is missing?", :default => true
16
-
17
- def initialize
18
- @dir = opts.fetch(:directory)
19
- @service_prefix = opts.fetch(:service_prefix)
20
- @warning = opts.fetch(:warning, nil)
21
- @critical = opts.fetch(:critical, nil)
22
- @alert_on_missing = opts.fetch(:alert_on_missing)
23
- end
24
-
25
- def tick
26
- if Dir.exists?(@dir)
27
- metric = Dir.entries(@dir).size - 2
28
- report(
29
- :service => "#{@service_prefix} #{@dir}",
30
- :metric => metric,
31
- :state => state(metric),
32
- :tags => ['dir_files_count']
33
- )
34
- elsif @alert_on_missing
35
- report(
36
- :service => "#{@service_prefix} #{@dir} missing",
37
- :description => "#{@service_prefix} #{@dir} does not exist",
38
- :metric => metric,
39
- :state => 'critical',
40
- :tags => ['dir_files_count']
41
- )
42
- end
43
- end
6
+ # Gets the number of files present on a directory and submits it to riemann
44
7
 
45
- def state(metric)
46
- if @critical && metric > @critical
47
- 'critical'
48
- elsif @warning && metric > @warning
49
- 'warning'
50
- else
51
- 'ok'
8
+ require File.expand_path('../lib/riemann/tools', __dir__)
9
+
10
+ module Riemann
11
+ module Tools
12
+ class DirFilesCount
13
+ include Riemann::Tools
14
+
15
+ opt :directory, '', default: '/var/log'
16
+ opt :service_prefix, 'The first part of the service name, before the directory path', default: 'dir-files-count'
17
+ opt :warning, 'Dir files number warning threshold', type: Integer
18
+ opt :critical, 'Dir files number critical threshold', type: Integer
19
+ opt :alert_on_missing, 'Send a critical metric if the directory is missing?', default: true
20
+
21
+ def initialize
22
+ @dir = opts.fetch(:directory)
23
+ @service_prefix = opts.fetch(:service_prefix)
24
+ @warning = opts.fetch(:warning, nil)
25
+ @critical = opts.fetch(:critical, nil)
26
+ @alert_on_missing = opts.fetch(:alert_on_missing)
27
+ end
28
+
29
+ def tick
30
+ if Dir.exist?(@dir)
31
+ metric = Dir.entries(@dir).size - 2
32
+ report(
33
+ service: "#{@service_prefix} #{@dir}",
34
+ metric: metric,
35
+ state: state(metric),
36
+ tags: ['dir_files_count'],
37
+ )
38
+ elsif @alert_on_missing
39
+ report(
40
+ service: "#{@service_prefix} #{@dir} missing",
41
+ description: "#{@service_prefix} #{@dir} does not exist",
42
+ metric: metric,
43
+ state: 'critical',
44
+ tags: ['dir_files_count'],
45
+ )
46
+ end
47
+ end
48
+
49
+ def state(metric)
50
+ if @critical && metric > @critical
51
+ 'critical'
52
+ elsif @warning && metric > @warning
53
+ 'warning'
54
+ else
55
+ 'ok'
56
+ end
57
+ end
52
58
  end
53
59
  end
54
60
  end
@@ -1,54 +1,60 @@
1
1
  #!/usr/bin/env ruby
2
- Process.setproctitle($0)
2
+ # frozen_string_literal: true
3
3
 
4
- # Gathers the space used by a directory and submits it to riemann
5
-
6
- require File.expand_path('../../lib/riemann/tools', __FILE__)
7
-
8
- class Riemann::Tools::DirSpace
9
- include Riemann::Tools
4
+ Process.setproctitle($PROGRAM_NAME)
10
5
 
11
- opt :directory, "", :default => '/var/log'
12
- opt :service_prefix, "The first part of the service name, before the directory path", :default => "dir-space"
13
- opt :warning, "Dir space warning threshold (in bytes)", :type => Integer
14
- opt :critical, "Dir space critical threshold (in bytes)", :type => Integer
15
- opt :alert_on_missing, "Send a critical metric if the directory is missing?", :default => true
16
-
17
- def initialize
18
- @dir = opts.fetch(:directory)
19
- @service_prefix = opts.fetch(:service_prefix)
20
- @warning = opts.fetch(:warning, nil)
21
- @critical = opts.fetch(:critical, nil)
22
- @alert_on_missing = opts.fetch(:alert_on_missing)
23
- end
24
-
25
- def tick
26
- if Dir.exists?(@dir)
27
- metric = `du '#{@dir}'`.lines.to_a.last.split("\t")[0].to_i
28
- report(
29
- :service => "#{@service_prefix} #{@dir}",
30
- :metric => metric,
31
- :state => state(metric),
32
- :tags => ['dir_space']
33
- )
34
- elsif @alert_on_missing
35
- report(
36
- :service => "#{@service_prefix} #{@dir} missing",
37
- :description => "#{@service_prefix} #{@dir} does not exist",
38
- :metric => metric,
39
- :state => 'critical',
40
- :tags => ['dir_space']
41
- )
42
- end
43
- end
6
+ # Gathers the space used by a directory and submits it to riemann
44
7
 
45
- def state(metric)
46
- if @critical && metric > @critical
47
- 'critical'
48
- elsif @warning && metric > @warning
49
- 'warning'
50
- else
51
- 'ok'
8
+ require File.expand_path('../lib/riemann/tools', __dir__)
9
+
10
+ module Riemann
11
+ module Tools
12
+ class DirSpace
13
+ include Riemann::Tools
14
+
15
+ opt :directory, '', default: '/var/log'
16
+ opt :service_prefix, 'The first part of the service name, before the directory path', default: 'dir-space'
17
+ opt :warning, 'Dir space warning threshold (in bytes)', type: Integer
18
+ opt :critical, 'Dir space critical threshold (in bytes)', type: Integer
19
+ opt :alert_on_missing, 'Send a critical metric if the directory is missing?', default: true
20
+
21
+ def initialize
22
+ @dir = opts.fetch(:directory)
23
+ @service_prefix = opts.fetch(:service_prefix)
24
+ @warning = opts.fetch(:warning, nil)
25
+ @critical = opts.fetch(:critical, nil)
26
+ @alert_on_missing = opts.fetch(:alert_on_missing)
27
+ end
28
+
29
+ def tick
30
+ if Dir.exist?(@dir)
31
+ metric = `du '#{@dir}'`.lines.to_a.last.split("\t")[0].to_i
32
+ report(
33
+ service: "#{@service_prefix} #{@dir}",
34
+ metric: metric,
35
+ state: state(metric),
36
+ tags: ['dir_space'],
37
+ )
38
+ elsif @alert_on_missing
39
+ report(
40
+ service: "#{@service_prefix} #{@dir} missing",
41
+ description: "#{@service_prefix} #{@dir} does not exist",
42
+ metric: metric,
43
+ state: 'critical',
44
+ tags: ['dir_space'],
45
+ )
46
+ end
47
+ end
48
+
49
+ def state(metric)
50
+ if @critical && metric > @critical
51
+ 'critical'
52
+ elsif @warning && metric > @warning
53
+ 'warning'
54
+ else
55
+ 'ok'
56
+ end
57
+ end
52
58
  end
53
59
  end
54
60
  end