riemann-tools 0.2.13 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +5 -5
  2. data/.docker/Dockerfile +7 -0
  3. data/.docker/publish.sh +35 -0
  4. data/.github/dependabot.yml +11 -0
  5. data/.github/workflows/ci.yml +42 -0
  6. data/.github/workflows/codeql-analysis.yml +72 -0
  7. data/.gitignore +6 -0
  8. data/.rspec +2 -0
  9. data/.rubocop.yml +32 -0
  10. data/.travis.yml +31 -0
  11. data/CHANGELOG.md +422 -0
  12. data/Gemfile +6 -0
  13. data/ISSUE_TEMPLATE.md +15 -0
  14. data/README.markdown +14 -15
  15. data/Rakefile +23 -0
  16. data/SECURITY.md +42 -0
  17. data/bin/riemann-apache-status +92 -77
  18. data/bin/riemann-bench +54 -48
  19. data/bin/riemann-cloudant +44 -39
  20. data/bin/riemann-consul +82 -75
  21. data/bin/riemann-dir-files-count +53 -46
  22. data/bin/riemann-dir-space +53 -46
  23. data/bin/riemann-diskstats +78 -74
  24. data/bin/riemann-fd +68 -47
  25. data/bin/riemann-freeswitch +108 -102
  26. data/bin/riemann-haproxy +46 -39
  27. data/bin/riemann-health +4 -335
  28. data/bin/riemann-kvminstance +18 -12
  29. data/bin/riemann-memcached +35 -28
  30. data/bin/riemann-net +4 -103
  31. data/bin/riemann-nginx-status +74 -66
  32. data/bin/riemann-ntp +4 -32
  33. data/bin/riemann-portcheck +40 -30
  34. data/bin/riemann-proc +96 -89
  35. data/bin/riemann-varnish +51 -44
  36. data/bin/riemann-zookeeper +38 -33
  37. data/lib/riemann/tools/health.rb +347 -0
  38. data/lib/riemann/tools/net.rb +104 -0
  39. data/lib/riemann/tools/ntp.rb +41 -0
  40. data/lib/riemann/tools/utils.rb +17 -0
  41. data/lib/riemann/tools/version.rb +7 -0
  42. data/lib/riemann/tools.rb +40 -33
  43. data/riemann-tools.gemspec +42 -0
  44. data/tools/riemann-aws/LICENSE +21 -0
  45. data/tools/riemann-aws/README.md +54 -0
  46. data/tools/riemann-aws/Rakefile +37 -0
  47. data/tools/riemann-aws/bin/riemann-aws-billing +93 -0
  48. data/tools/riemann-aws/bin/riemann-aws-rds-status +68 -0
  49. data/tools/riemann-aws/bin/riemann-aws-sqs-status +50 -0
  50. data/tools/riemann-aws/bin/riemann-aws-status +83 -0
  51. data/tools/riemann-aws/bin/riemann-elb-metrics +168 -0
  52. data/tools/riemann-aws/bin/riemann-s3-list +87 -0
  53. data/tools/riemann-aws/bin/riemann-s3-status +102 -0
  54. data/tools/riemann-chronos/LICENSE +21 -0
  55. data/tools/riemann-chronos/README.md +10 -0
  56. data/tools/riemann-chronos/Rakefile +37 -0
  57. data/tools/riemann-chronos/bin/riemann-chronos +161 -0
  58. data/tools/riemann-docker/LICENSE +21 -0
  59. data/tools/riemann-docker/README.md +10 -0
  60. data/tools/riemann-docker/Rakefile +36 -0
  61. data/tools/riemann-docker/bin/riemann-docker +206 -0
  62. data/tools/riemann-elasticsearch/LICENSE +21 -0
  63. data/tools/riemann-elasticsearch/README.md +10 -0
  64. data/tools/riemann-elasticsearch/Rakefile +37 -0
  65. data/tools/riemann-elasticsearch/bin/riemann-elasticsearch +174 -0
  66. data/tools/riemann-marathon/LICENSE +21 -0
  67. data/tools/riemann-marathon/README.md +10 -0
  68. data/tools/riemann-marathon/Rakefile +37 -0
  69. data/tools/riemann-marathon/bin/riemann-marathon +163 -0
  70. data/tools/riemann-mesos/LICENSE +21 -0
  71. data/tools/riemann-mesos/README.md +10 -0
  72. data/tools/riemann-mesos/Rakefile +37 -0
  73. data/tools/riemann-mesos/bin/riemann-mesos +146 -0
  74. data/tools/riemann-munin/LICENSE +21 -0
  75. data/tools/riemann-munin/README.md +10 -0
  76. data/tools/riemann-munin/Rakefile +36 -0
  77. data/tools/riemann-munin/bin/riemann-munin +43 -0
  78. data/tools/riemann-rabbitmq/LICENSE +21 -0
  79. data/tools/riemann-rabbitmq/README.md +10 -0
  80. data/tools/riemann-rabbitmq/Rakefile +37 -0
  81. data/tools/riemann-rabbitmq/bin/riemann-rabbitmq +273 -0
  82. data/tools/riemann-riak/LICENSE +21 -0
  83. data/tools/riemann-riak/README.md +10 -0
  84. data/tools/riemann-riak/Rakefile +36 -0
  85. data/tools/riemann-riak/bin/riemann-riak +323 -0
  86. data/tools/riemann-riak/bin/riemann-riak-keys +13 -0
  87. data/tools/riemann-riak/bin/riemann-riak-ring +9 -0
  88. data/tools/riemann-riak/riak_status/key_count.erl +13 -0
  89. data/tools/riemann-riak/riak_status/riak_status.rb +152 -0
  90. data/tools/riemann-riak/riak_status/ringready.erl +9 -0
  91. metadata +195 -34
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2011 Kyle Kingsbury
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,10 @@
1
+ # Riemann Mesos
2
+
3
+ Gathers Mesos metrics and sends them to Riemann.
4
+
5
+ # Getting started
6
+
7
+ ```
8
+ gem install riemann-mesos
9
+ riemann-mesos --help
10
+ ```
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubygems'
4
+ require 'rubygems/package_task'
5
+ require 'rdoc/task'
6
+ require 'find'
7
+
8
+ # Don't include resource forks in tarballs on Mac OS X.
9
+ ENV['COPY_EXTENDED_ATTRIBUTES_DISABLE'] = 'true'
10
+ ENV['COPYFILE_DISABLE'] = 'true'
11
+
12
+ # Gemspec
13
+ gemspec = Gem::Specification.new do |s|
14
+ s.rubyforge_project = 'riemann-mesos'
15
+
16
+ s.name = 'riemann-mesos'
17
+ s.version = '0.1.2'
18
+ s.author = 'Giulio Eulisse'
19
+ s.email = 'giulio.eulisse@cern.ch'
20
+ s.homepage = 'https://github.com/riemann/riemann-tools'
21
+ s.platform = Gem::Platform::RUBY
22
+ s.summary = 'Submits mesos stats to riemann.'
23
+ s.license = 'MIT'
24
+
25
+ s.add_dependency 'riemann-tools', '>= 0.2.13'
26
+ s.add_dependency 'faraday', '>= 0.8.5'
27
+ s.add_dependency 'json'
28
+
29
+ s.files = FileList['bin/*', 'LICENSE', 'README.md'].to_a
30
+ s.executables |= Dir.entries('bin/')
31
+ s.has_rdoc = false
32
+
33
+ s.required_ruby_version = '>= 1.8.7'
34
+ end
35
+
36
+ Gem::PackageTask.new gemspec do |p|
37
+ end
@@ -0,0 +1,146 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ Process.setproctitle($PROGRAM_NAME)
5
+
6
+ require 'riemann/tools'
7
+
8
+ module Riemann
9
+ module Tools
10
+ class Mesos
11
+ include Riemann::Tools
12
+
13
+ require 'faraday'
14
+ require 'json'
15
+ require 'uri'
16
+
17
+ opt :read_timeout, 'Faraday read timeout', type: :int, default: 2
18
+ opt :open_timeout, 'Faraday open timeout', type: :int, default: 1
19
+ opt :path_prefix,
20
+ 'Mesos path prefix for proxied installations e.g. "mesos" for target http://localhost/mesos/metrics/snapshot', default: '/'
21
+ opt :mesos_host, 'Mesos host', default: 'localhost'
22
+ opt :mesos_port, 'Mesos port', type: :int, default: 5050
23
+
24
+ # Handles HTTP connections and GET requests safely
25
+ def safe_get(uri)
26
+ # Handle connection timeouts
27
+ response = nil
28
+ begin
29
+ connection = Faraday.new(uri)
30
+ response = connection.get do |req|
31
+ req.options[:timeout] = options[:read_timeout]
32
+ req.options[:open_timeout] = options[:open_timeout]
33
+ end
34
+ rescue StandardError => e
35
+ report(
36
+ host: uri.host,
37
+ service: 'mesos health',
38
+ state: 'critical',
39
+ description: "HTTP connection error: #{e.class} - #{e.message}",
40
+ )
41
+ end
42
+ response
43
+ end
44
+
45
+ def health_url
46
+ path_prefix = options[:path_prefix]
47
+ path_prefix[0] = '' if path_prefix[0] == '/'
48
+ path_prefix[path_prefix.length - 1] = '' if path_prefix[path_prefix.length - 1] == '/'
49
+ "http://#{options[:mesos_host]}:#{options[:mesos_port]}#{path_prefix.length.positive? ? '/' : ''}#{path_prefix}/metrics/snapshot"
50
+ end
51
+
52
+ def slaves_url
53
+ path_prefix = options[:path_prefix]
54
+ path_prefix[0] = '' if path_prefix[0] == '/'
55
+ path_prefix[path_prefix.length - 1] = '' if path_prefix[path_prefix.length - 1] == '/'
56
+ "http://#{options[:mesos_host]}:#{options[:mesos_port]}#{path_prefix.length.positive? ? '/' : ''}#{path_prefix}/master/slaves"
57
+ end
58
+
59
+ def tick
60
+ tick_slaves
61
+ uri = URI(health_url)
62
+ response = safe_get(uri)
63
+
64
+ return if response.nil?
65
+
66
+ if response.status != 200
67
+ report(
68
+ host: uri.host,
69
+ service: 'mesos health',
70
+ state: 'critical',
71
+ description: "HTTP connection error: #{response.status} - #{response.body}",
72
+ )
73
+ else
74
+ # Assuming that a 200 will give json
75
+ json = JSON.parse(response.body)
76
+ state = 'ok'
77
+
78
+ report(
79
+ host: uri.host,
80
+ service: 'mesos health',
81
+ state: state,
82
+ )
83
+
84
+ json.each_pair do |k, v|
85
+ report(
86
+ host: uri.host,
87
+ service: "mesos #{k}",
88
+ metric: v,
89
+ )
90
+ end
91
+ end
92
+ end
93
+
94
+ def tick_slaves
95
+ uri = URI(slaves_url)
96
+ response = safe_get(uri)
97
+
98
+ return if response.nil?
99
+
100
+ if response.status != 200
101
+ report(
102
+ host: uri.host,
103
+ service: 'mesos health',
104
+ state: 'critical',
105
+ description: "HTTP connection error: #{response.status} - #{response.body}",
106
+ )
107
+ else
108
+ # Assuming that a 200 will give json
109
+ json = JSON.parse(response.body)
110
+ state = 'ok'
111
+
112
+ report(
113
+ host: uri.host,
114
+ service: 'mesos health',
115
+ state: state,
116
+ )
117
+
118
+ json['slaves'].each do |slave|
119
+ next unless slave.respond_to? 'each_pair'
120
+
121
+ slave.each_pair do |k, v|
122
+ if v.respond_to? 'each_pair'
123
+ v.each_pair do |k1, v1|
124
+ next unless v1.is_a? Numeric
125
+
126
+ report(
127
+ host: slave['hostname'],
128
+ service: "mesos slave/#{k}/#{k1}",
129
+ metric: v1,
130
+ )
131
+ end
132
+ elsif v.is_a? Numeric
133
+ report(
134
+ host: slave['hostname'],
135
+ service: "mesos slave/#{k}",
136
+ metric: v,
137
+ )
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
145
+ end
146
+ Riemann::Tools::Mesos.run
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2011 Kyle Kingsbury
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,10 @@
1
+ # Riemann Munin
2
+
3
+ Gathers munin statistics and submits them to Riemann.
4
+
5
+ # Getting started
6
+
7
+ ```
8
+ gem install riemann-munin
9
+ riemann-munin --help
10
+ ```
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubygems'
4
+ require 'rubygems/package_task'
5
+ require 'rdoc/task'
6
+ require 'find'
7
+
8
+ # Don't include resource forks in tarballs on Mac OS X.
9
+ ENV['COPY_EXTENDED_ATTRIBUTES_DISABLE'] = 'true'
10
+ ENV['COPYFILE_DISABLE'] = 'true'
11
+
12
+ # Gemspec
13
+ gemspec = Gem::Specification.new do |s|
14
+ s.rubyforge_project = 'riemann-munin'
15
+
16
+ s.name = 'riemann-munin'
17
+ s.version = '0.1.2'
18
+ s.author = 'Kyle Kingsbury'
19
+ s.email = 'aphyr@aphyr.com'
20
+ s.homepage = 'https://github.com/riemann/riemann-tools'
21
+ s.platform = Gem::Platform::RUBY
22
+ s.summary = 'Submits munin stats to riemann.'
23
+ s.license = 'MIT'
24
+
25
+ s.add_dependency 'riemann-tools', '>= 0.2.13'
26
+ s.add_dependency 'munin-ruby', '>= 0.2.1'
27
+
28
+ s.files = FileList['bin/*', 'LICENSE', 'README.md'].to_a
29
+ s.executables |= Dir.entries('bin/')
30
+ s.has_rdoc = false
31
+
32
+ s.required_ruby_version = '>= 1.8.7'
33
+ end
34
+
35
+ Gem::PackageTask.new gemspec do |p|
36
+ end
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ Process.setproctitle($PROGRAM_NAME)
5
+
6
+ # Gathers munin statistics and submits them to Riemann.
7
+
8
+ require 'riemann/tools'
9
+
10
+ module Riemann
11
+ module Tools
12
+ class Munin
13
+ include Riemann::Tools
14
+ require 'munin-ruby'
15
+
16
+ def initialize
17
+ @munin = ::Munin::Node.new
18
+ end
19
+
20
+ def tick
21
+ services = opts[:services] || @munin.list
22
+ services.each do |service_name|
23
+ @munin.fetch(service_name).each do |service, parts|
24
+ parts.each do |part, metric|
25
+ report(
26
+ service: "#{service} #{part}",
27
+ metric: metric.to_f,
28
+ state: 'ok',
29
+ tags: ['munin'],
30
+ )
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ opt :munin_host, 'Munin hostname', default: 'localhost'
37
+ opt :munin_port, 'Munin port', default: 4949
38
+ opt :services, 'Munin services to translate (if not specified, all services are relayed)', type: :strings
39
+ end
40
+ end
41
+ end
42
+
43
+ Riemann::Tools::Munin.run
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2011 Kyle Kingsbury
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,10 @@
1
+ # Riemann RabbitMQ
2
+
3
+ Gathers RabbitMQ metrics and sends them to Riemann.
4
+
5
+ # Getting started
6
+
7
+ ```
8
+ gem install riemann-rabbitmq
9
+ riemann-rabbitmq --help
10
+ ```
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubygems'
4
+ require 'rubygems/package_task'
5
+ require 'rdoc/task'
6
+ require 'find'
7
+
8
+ # Don't include resource forks in tarballs on Mac OS X.
9
+ ENV['COPY_EXTENDED_ATTRIBUTES_DISABLE'] = 'true'
10
+ ENV['COPYFILE_DISABLE'] = 'true'
11
+
12
+ # Gemspec
13
+ gemspec = Gem::Specification.new do |s|
14
+ s.rubyforge_project = 'riemann-rabbitmq'
15
+
16
+ s.name = 'riemann-rabbitmq'
17
+ s.version = '0.1.3'
18
+ s.author = 'Gavin Sandie'
19
+ s.email = 'beach@vicecity.co.uk'
20
+ s.homepage = 'https://github.com/riemann/riemann-tools'
21
+ s.platform = Gem::Platform::RUBY
22
+ s.summary = 'Submits RabbitMQ stats to riemann.'
23
+ s.license = 'MIT'
24
+
25
+ s.add_dependency 'riemann-tools', '>= 0.2.13'
26
+ s.add_dependency 'faraday', '>= 0.8.5'
27
+ s.add_dependency 'json'
28
+
29
+ s.files = FileList['bin/*', 'LICENSE', 'README.md'].to_a
30
+ s.executables |= Dir.entries('bin/')
31
+ s.has_rdoc = false
32
+
33
+ s.required_ruby_version = '>= 1.8.7'
34
+ end
35
+
36
+ Gem::PackageTask.new gemspec do |p|
37
+ end
@@ -0,0 +1,273 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ Process.setproctitle($PROGRAM_NAME)
5
+
6
+ require 'riemann/tools'
7
+
8
+ module Riemann
9
+ module Tools
10
+ class Rabbitmq
11
+ include Riemann::Tools
12
+
13
+ require 'faraday'
14
+ require 'json'
15
+ require 'uri'
16
+
17
+ opt :read_timeout, 'Faraday read timeout', type: :int, default: 2
18
+ opt :open_timeout, 'Faraday open timeout', type: :int, default: 1
19
+
20
+ opt :monitor_user, 'RabbitMQ monitoring user', type: :string
21
+ opt :monitor_pass, 'RabbitMQ monitoring user password', type: :string
22
+ opt :monitor_port, 'RabbitMQ monitoring port', type: :int, default: 15_672
23
+ opt :monitor_host, 'RabbitMQ monitoring host', type: :string, default: 'localhost'
24
+ opt :monitor_use_tls, 'RabbitMQ use tls', type: :bool, default: false
25
+
26
+ opt :max_queue_size, 'max number of items in a queue that is acceptable', type: :int, default: 1_000_000
27
+ opt :ignore_max_size_queues, "A regular expression to match queues that shouldn't be size-checked", type: :string
28
+
29
+ opt :node, 'Specify a node to monitor', type: :strings
30
+
31
+ def base_url
32
+ protocol = 'http'
33
+ protocol = 'https' if options[:monitor_use_tls] && (options[:monitor_use_tls] == true)
34
+ "#{protocol}://#{options[:monitor_user]}:#{options[:monitor_pass]}@#{options[:monitor_host]}:#{options[:monitor_port]}/api"
35
+ end
36
+
37
+ def overview_url
38
+ "#{base_url}/overview"
39
+ end
40
+
41
+ def node_url(node)
42
+ "#{base_url}/nodes/#{node}"
43
+ end
44
+
45
+ def queues_url
46
+ "#{base_url}/queues"
47
+ end
48
+
49
+ def event_host
50
+ options[:event_host] || :monitor_host
51
+ end
52
+
53
+ def safe_get(uri, event_host)
54
+ # Handle connection timeouts
55
+ response = nil
56
+ begin
57
+ connection = Faraday.new(uri)
58
+ response = connection.get do |req|
59
+ req.options[:timeout] = options[:read_timeout]
60
+ req.options[:open_timeout] = options[:open_timeout]
61
+ end
62
+ report(
63
+ host: event_host,
64
+ service: 'rabbitmq monitoring',
65
+ state: 'ok',
66
+ description: 'Monitoring operational',
67
+ )
68
+ rescue StandardError => e
69
+ report(
70
+ host: event_host,
71
+ service: 'rabbitmq monitoring',
72
+ state: 'critical',
73
+ description: "HTTP connection error: #{e.class} - #{e.message}",
74
+ )
75
+ end
76
+ response
77
+ end
78
+
79
+ def check_queues
80
+ response = safe_get(queues_url, event_host)
81
+ max_size_check_filter = (Regexp.new(options[:ignore_max_size_queues]) if options[:ignore_max_size_queues])
82
+
83
+ return if response.nil?
84
+
85
+ if response.status != 200
86
+ report(
87
+ host: event_host,
88
+ service: 'rabbitmq.queue',
89
+ state: 'critical',
90
+ description: "HTTP connection error to /api/queues: #{response.status} - #{response.body}",
91
+ )
92
+ else
93
+ report(
94
+ host: event_host,
95
+ service: 'rabbitmq.queue',
96
+ state: 'ok',
97
+ description: 'HTTP connection ok',
98
+ )
99
+
100
+ json = JSON.parse(response.body)
101
+
102
+ json.each do |queue|
103
+ svc = "rabbitmq.queue.#{queue['vhost']}.#{queue['name']}"
104
+ errs = []
105
+
106
+ errs << 'Queue has jobs but no consumers' if !queue['messages_ready'].nil? && (queue['messages_ready']).positive? && (queue['consumers']).zero?
107
+
108
+ errs << "Queue has #{queue['messages_ready']} jobs" if (max_size_check_filter.nil? || queue['name'] !~ (max_size_check_filter)) && !queue['messages_ready'].nil? && (queue['messages_ready'] > options[:max_queue_size])
109
+
110
+ if errs.empty?
111
+ report(
112
+ host: event_host,
113
+ service: svc,
114
+ state: 'ok',
115
+ description: 'Queue is looking good',
116
+ )
117
+ else
118
+ report(
119
+ host: event_host,
120
+ service: svc,
121
+ state: 'critical',
122
+ description: errs.join('; '),
123
+ )
124
+ end
125
+
126
+ stats = (queue['message_stats'] || {}).merge(
127
+ 'messages' => queue['messages'],
128
+ 'messages_details' => queue['messages_details'],
129
+ 'messages_ready' => queue['messages_ready'],
130
+ 'messages_ready_details' => queue['messages_ready_details'],
131
+ 'messages_unacknowledged' => queue['messages_unacknowledged'],
132
+ 'messages_unacknowledged_details' => queue['messages_unacknowledged_details'],
133
+ 'consumers' => queue['consumers'],
134
+ 'memory' => queue['memory'],
135
+ )
136
+
137
+ stats.each_pair do |k, v|
138
+ service = "#{svc}.#{k}"
139
+ metric = if k =~ (/details$/) && !v.nil?
140
+ v['rate']
141
+ else
142
+ v
143
+ end
144
+
145
+ # TODO: Set state via thresholds which can be configured
146
+
147
+ report(
148
+ host: event_host,
149
+ service: service,
150
+ metric: metric,
151
+ description: 'RabbitMQ monitor',
152
+ )
153
+ end
154
+ end
155
+ end
156
+ end
157
+
158
+ def check_overview
159
+ uri = URI(overview_url)
160
+ response = safe_get(uri, event_host)
161
+
162
+ return if response.nil?
163
+
164
+ json = JSON.parse(response.body)
165
+
166
+ if response.status != 200
167
+ report(
168
+ host: event_host,
169
+ service: 'rabbitmq',
170
+ state: 'critical',
171
+ description: "HTTP connection error: #{response.status} - #{response.body}",
172
+ )
173
+ else
174
+ report(
175
+ host: event_host,
176
+ service: 'rabbitmq monitoring',
177
+ state: 'ok',
178
+ description: 'HTTP connection ok',
179
+ )
180
+
181
+ %w[message_stats queue_totals object_totals].each do |stat|
182
+ # NOTE: / BUG ?
183
+ # Brand new servers can have blank message stats. Is this ok?
184
+ # I can't decide.
185
+ next if json[stat].empty?
186
+
187
+ json[stat].each_pair do |k, v|
188
+ service = "rabbitmq.#{stat}.#{k}"
189
+ metric = if k =~ /details$/
190
+ v['rate']
191
+ else
192
+ v
193
+ end
194
+
195
+ # TODO: Set state via thresholds which can be configured
196
+
197
+ report(
198
+ host: event_host,
199
+ service: service,
200
+ metric: metric,
201
+ description: 'RabbitMQ monitor',
202
+ )
203
+ end
204
+ end
205
+ end
206
+ end
207
+
208
+ def check_node
209
+ opts[:node].each do |n|
210
+ uri = URI(node_url(n))
211
+ response = safe_get(uri, event_host)
212
+
213
+ break if response.nil?
214
+
215
+ if response.status != 200
216
+ if response.status == 404
217
+ report(
218
+ host: event_host,
219
+ service: "rabbitmq.node.#{n}",
220
+ state: 'critical',
221
+ description: 'Node was not found in the cluster',
222
+ )
223
+ else
224
+ report(
225
+ host: event_host,
226
+ service: "rabbitmq.node.#{n}",
227
+ state: 'critical',
228
+ description: "HTTP error: #{response.status} - #{response.body}",
229
+ )
230
+ end
231
+ break
232
+ end
233
+
234
+ json = JSON.parse(response.body)
235
+
236
+ if json['mem_alarm']
237
+ report(
238
+ host: event_host,
239
+ service: "rabbitmq.node.#{n}",
240
+ state: 'critical',
241
+ description: 'Memory alarm has triggered; job submission throttled',
242
+ )
243
+ break
244
+ end
245
+
246
+ if json['disk_free_alarm']
247
+ report(
248
+ host: event_host,
249
+ service: "rabbitmq.node.#{n}",
250
+ state: 'critical',
251
+ description: 'Disk free alarm has triggered; job submission throttled',
252
+ )
253
+ break
254
+ end
255
+
256
+ report(
257
+ host: event_host,
258
+ service: "rabbitmq.node.#{n}",
259
+ state: 'ok',
260
+ description: 'Node looks OK to me',
261
+ )
262
+ end
263
+ end
264
+
265
+ def tick
266
+ check_overview
267
+ check_node if opts[:node]
268
+ check_queues
269
+ end
270
+ end
271
+ end
272
+ end
273
+ Riemann::Tools::Rabbitmq.run