sensu-plugins-rabbitmq 0.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.
@@ -0,0 +1,128 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+ #
4
+ # Check RabbitMQ Messages
5
+ # ===
6
+ #
7
+ # DESCRIPTION:
8
+ # This plugin checks the total number of messages queued on the RabbitMQ server
9
+ #
10
+ # PLATFORMS:
11
+ # Linux, BSD, Solaris
12
+ #
13
+ # DEPENDENCIES:
14
+ # RabbitMQ rabbitmq_management plugin
15
+ # gem: sensu-plugin
16
+ # gem: carrot-top
17
+ #
18
+ # LICENSE:
19
+ # Copyright 2012 Evan Hazlett <ejhazlett@gmail.com>
20
+ # Copyright 2015 Tim Smith <tim@cozy.co> and Cozy Services Ltd.
21
+ #
22
+ # Released under the same terms as Sensu (the MIT license); see LICENSE
23
+ # for details.
24
+
25
+ require 'sensu-plugin/check/cli'
26
+ require 'socket'
27
+ require 'carrot-top'
28
+
29
+ # main plugin class
30
+ class CheckRabbitMQMessages < Sensu::Plugin::Check::CLI
31
+ option :host,
32
+ description: 'RabbitMQ management API host',
33
+ long: '--host HOST',
34
+ default: 'localhost'
35
+
36
+ option :port,
37
+ description: 'RabbitMQ management API port',
38
+ long: '--port PORT',
39
+ proc: proc(&:to_i),
40
+ default: 15_672
41
+
42
+ option :user,
43
+ description: 'RabbitMQ management API user',
44
+ long: '--user USER',
45
+ default: 'guest'
46
+
47
+ option :password,
48
+ description: 'RabbitMQ management API password',
49
+ long: '--password PASSWORD',
50
+ default: 'guest'
51
+
52
+ option :ssl,
53
+ description: 'Enable SSL for connection to the API',
54
+ long: '--ssl',
55
+ boolean: true,
56
+ default: false
57
+
58
+ option :warn,
59
+ short: '-w NUM_MESSAGES',
60
+ long: '--warn NUM_MESSAGES',
61
+ description: 'WARNING message count threshold',
62
+ default: 250
63
+
64
+ option :critical,
65
+ short: '-c NUM_MESSAGES',
66
+ long: '--critical NUM_MESSAGES',
67
+ description: 'CRITICAL message count threshold',
68
+ default: 500
69
+
70
+ option :queuelevel,
71
+ short: '-q',
72
+ long: '--queuelevel',
73
+ description: 'Monitors that no individual queue is above the thresholds specified'
74
+
75
+ option :excluded,
76
+ short: '-e queue_name',
77
+ long: '--excludedqueues queue_name',
78
+ description: 'Comma separated list of queues to exclude when using queue level monitoring',
79
+ proc: proc { |q| q.split(',') },
80
+ default: []
81
+
82
+ def generate_message(status_hash)
83
+ message = []
84
+ status_hash.each_pair do |k, v|
85
+ message << "#{k}: #{v}"
86
+ end
87
+ message.join(', ')
88
+ end
89
+
90
+ def acquire_rabbitmq_info
91
+ begin
92
+ rabbitmq_info = CarrotTop.new(
93
+ host: config[:host],
94
+ port: config[:port],
95
+ user: config[:user],
96
+ password: config[:password],
97
+ ssl: config[:ssl]
98
+ )
99
+ rescue
100
+ warning 'Could not connect to rabbitmq'
101
+ end
102
+ rabbitmq_info
103
+ end
104
+
105
+ def run
106
+ rabbitmq = acquire_rabbitmq_info
107
+
108
+ # monitor counts in each queue or monitor the total number of messages in the system
109
+ if config[:queuelevel]
110
+ warn_queues = {}
111
+ crit_queues = {}
112
+ rabbitmq.queues.each do |queue|
113
+ next if config[:excluded].include?(queue['name'])
114
+ (crit_queues["#{queue['name']}"] = queue['messages']; next) if queue['messages'] >= config[:critical].to_i # rubocop: disable Style/Semicolon
115
+ (warn_queues["#{queue['name']}"] = queue['messages']; next) if queue['messages'] >= config[:warn].to_i # rubocop: disable Style/Semicolon
116
+ end
117
+ message crit_queues.empty? ? generate_message(warn_queues) : generate_message(crit_queues)
118
+ critical unless crit_queues.empty?
119
+ warning unless warn_queues.empty?
120
+ else
121
+ total = rabbitmq.overview['queue_totals']['messages']
122
+ message "#{total}"
123
+ critical if total > config[:critical].to_i
124
+ warning if total > config[:warn].to_i
125
+ end
126
+ ok
127
+ end
128
+ end
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+ #
4
+ # RabbitMQ Network Partitions Check
5
+ # ===
6
+ #
7
+ # DESCRIPTION:
8
+ # This plugin checks if a RabbitMQ network partition has occured.
9
+ # https://www.rabbitmq.com/partitions.html
10
+ #
11
+ # PLATFORMS:
12
+ # Linux, BSD, Solaris
13
+ #
14
+ # DEPENDENCIES:
15
+ # RabbitMQ rabbitmq_management plugin
16
+ # gem: sensu-plugin
17
+ # gem: carrot-top
18
+ #
19
+ # LICENSE:
20
+ # Copyright 2015 Ed Robinson <ed@reevoo.com> and Reevoo LTD.
21
+ #
22
+ # Released under the same terms as Sensu (the MIT license); see LICENSE
23
+ # for details.
24
+
25
+ require 'sensu-plugin/check/cli'
26
+ require 'carrot-top'
27
+
28
+ # main plugin class
29
+ class CheckRabbitMQPartitions < Sensu::Plugin::Check::CLI
30
+ option :host,
31
+ description: 'RabbitMQ management API host',
32
+ short: '-w',
33
+ long: '--host HOST',
34
+ default: 'localhost'
35
+
36
+ option :port,
37
+ description: 'RabbitMQ management API port',
38
+ long: '--port PORT',
39
+ proc: proc(&:to_i),
40
+ default: 15_672
41
+
42
+ option :username,
43
+ description: 'RabbitMQ management API user',
44
+ short: '-u',
45
+ long: '--username USERNAME',
46
+ default: 'guest'
47
+
48
+ option :password,
49
+ description: 'RabbitMQ management API password',
50
+ short: '-p',
51
+ long: '--password PASSWORD',
52
+ default: 'guest'
53
+
54
+ option :ssl,
55
+ description: 'Enable SSL for connection to the API',
56
+ long: '--ssl',
57
+ boolean: true,
58
+ default: false
59
+
60
+ def run
61
+ critical 'network partition detected' if partition?
62
+ ok 'no network partition detected'
63
+ rescue Errno::ECONNREFUSED => e
64
+ critical e.message
65
+ rescue => e
66
+ unknown e.message
67
+ end
68
+
69
+ def partition?
70
+ rabbitmq_management.nodes.map { |node| node['partitions'] }.any?(&:any?)
71
+ end
72
+
73
+ def rabbitmq_management
74
+ CarrotTop.new(
75
+ host: config[:host],
76
+ port: config[:port],
77
+ user: config[:username],
78
+ password: config[:password],
79
+ ssl: config[:ssl]
80
+ )
81
+ end
82
+ end
@@ -0,0 +1,184 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+ #
4
+ # RabbitMQ check node health plugin
5
+ # ===
6
+ #
7
+ # DESCRIPTION:
8
+ # This plugin checks if RabbitMQ server node is in a running state.
9
+ #
10
+ # The plugin is based on the RabbitMQ cluster node health plugin by Tim Smith
11
+ #
12
+ # PLATFORMS:
13
+ # Linux, Windows, BSD, Solaris
14
+ #
15
+ # DEPENDENCIES:
16
+ # RabbitMQ rabbitmq_management plugin
17
+ # gem: sensu-plugin
18
+ # gem: rest-client
19
+ #
20
+ # LICENSE:
21
+ # Copyright 2012 Abhijith G <abhi@runa.com> and Runa Inc.
22
+ # Copyright 2014 Tim Smith <tim@cozy.co> and Cozy Services Ltd.
23
+ # Copyright 2015 Edward McLain <ed@edmclain.com> and Daxko, LLC.
24
+ #
25
+ # Released under the same terms as Sensu (the MIT license); see LICENSE
26
+ # for details.
27
+
28
+ require 'sensu-plugin/check/cli'
29
+ require 'json'
30
+ require 'rest_client'
31
+
32
+ # main plugin class
33
+ class CheckRabbitMQNodeHealth < Sensu::Plugin::Check::CLI
34
+ option :host,
35
+ description: 'RabbitMQ host',
36
+ short: '-w',
37
+ long: '--host HOST',
38
+ default: 'localhost'
39
+
40
+ option :username,
41
+ description: 'RabbitMQ username',
42
+ short: '-u',
43
+ long: '--username USERNAME',
44
+ default: 'guest'
45
+
46
+ option :password,
47
+ description: 'RabbitMQ password',
48
+ short: '-p',
49
+ long: '--password PASSWORD',
50
+ default: 'guest'
51
+
52
+ option :port,
53
+ description: 'RabbitMQ API port',
54
+ short: '-P',
55
+ long: '--port PORT',
56
+ default: '15672'
57
+
58
+ option :memwarn,
59
+ description: 'Warning % of mem usage vs high watermark',
60
+ short: '-m',
61
+ long: '--mwarn PERCENT',
62
+ proc: proc(&:to_f),
63
+ default: 80
64
+
65
+ option :memcrit,
66
+ description: 'Critical % of mem usage vs high watermark',
67
+ short: '-c',
68
+ long: '--mcrit PERCENT',
69
+ proc: proc(&:to_f),
70
+ default: 90
71
+
72
+ option :fdwarn,
73
+ description: 'Warning % of file descriptor usage vs high watermark',
74
+ short: '-m',
75
+ long: '--mwarn PERCENT',
76
+ proc: proc(&:to_f),
77
+ default: 80
78
+
79
+ option :fdcrit,
80
+ description: 'Critical % of file descriptor usage vs high watermark',
81
+ short: '-c',
82
+ long: '--mcrit PERCENT',
83
+ proc: proc(&:to_f),
84
+ default: 90
85
+
86
+ option :socketwarn,
87
+ description: 'Warning % of socket usage vs high watermark',
88
+ short: '-m',
89
+ long: '--mwarn PERCENT',
90
+ proc: proc(&:to_f),
91
+ default: 80
92
+
93
+ option :socketcrit,
94
+ description: 'Critical % of socket usage vs high watermark',
95
+ short: '-c',
96
+ long: '--mcrit PERCENT',
97
+ proc: proc(&:to_f),
98
+ default: 90
99
+
100
+ option :watchalarms,
101
+ description: 'Sound critical if one or more alarms are triggered',
102
+ short: '-a BOOLEAN',
103
+ long: '--alarms BOOLEAN',
104
+ default: 'true'
105
+
106
+ def run
107
+ res = node_healthy?
108
+
109
+ if res['status'] == 'ok'
110
+ ok res['message']
111
+ elsif res['status'] == 'warning'
112
+ warning res['message']
113
+ elsif res['status'] == 'critical'
114
+ critical res['message']
115
+ else
116
+ unknown res['message']
117
+ end
118
+ end
119
+
120
+ def node_healthy?
121
+ host = config[:host]
122
+ port = config[:port]
123
+ username = config[:username]
124
+ password = config[:password]
125
+
126
+ begin
127
+ resource = RestClient::Resource.new "http://#{host}:#{port}/api/nodes", username, password
128
+ # Parse our json data
129
+ nodeinfo = JSON.parse(resource.get)[0]
130
+
131
+ # Determine % memory consumed
132
+ pmem = format('%.2f', nodeinfo['mem_used'].fdiv(nodeinfo['mem_limit']) * 100)
133
+ # Determine % sockets consumed
134
+ psocket = format('%.2f', nodeinfo['sockets_used'].fdiv(nodeinfo['sockets_total']) * 100)
135
+ # Determine % file descriptors consumed
136
+ pfd = format('%.2f', nodeinfo['fd_used'].fdiv(nodeinfo['fd_total']) * 100)
137
+
138
+ # build status and message
139
+ status = 'ok'
140
+ message = 'Server is healthy'
141
+
142
+ # criticals
143
+ if pmem.to_f >= config[:memcrit]
144
+ message = "Memory usage is critical: #{pmem}%"
145
+ status = 'critical'
146
+ elsif psocket.to_f >= config[:socketcrit]
147
+ message = "Socket usage is critical: #{psocket}%"
148
+ status = 'critical'
149
+ elsif pfd.to_f >= config[:fdcrit]
150
+ message = "Socket usage is critical: #{pfd}%"
151
+ status = 'critical'
152
+ # warnings
153
+ elsif pmem.to_f >= config[:memwarn]
154
+ message = "Memory usage is at warning: #{pmem}%"
155
+ status = 'warning'
156
+ elsif psocket.to_f >= config[:socketwarn]
157
+ message = "Socket usage is at warning: #{psocket}%"
158
+ status = 'warning'
159
+ elsif pfd.to_f >= config[:fdwarn]
160
+ message = "Socket usage is at warning: #{pfd}%"
161
+ status = 'warning'
162
+ end
163
+
164
+ # If we are set to watch alarms then watch those and set status and messages accordingly
165
+ if config[:watchalarms] == 'true'
166
+ if nodeinfo['mem_alarm'] == true
167
+ status = 'critical'
168
+ message += ' Memory Alarm ON'
169
+ end
170
+
171
+ if nodeinfo['disk_free_alarm'] == true
172
+ status = 'critical'
173
+ message += ' Disk Alarm ON'
174
+ end
175
+ end
176
+
177
+ { 'status' => status, 'message' => message }
178
+ rescue Errno::ECONNREFUSED => e
179
+ { 'status' => 'critical', 'message' => e.message }
180
+ rescue => e
181
+ { 'status' => 'unknown', 'message' => e.message }
182
+ end
183
+ end
184
+ end
@@ -0,0 +1,129 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+ #
4
+ # RabbitMQ Queue Drain Time
5
+ # ===
6
+ #
7
+ # DESCRIPTION:
8
+ # This plugin checks the time it will take for each queue on the RabbitMQ
9
+ # server to drain based on the current message egress rate. For example
10
+ # if a queue has 1,000 messages in it, but egresses only 1 message a sec
11
+ # the alert would fire as this is greater than the default critical level of 360s
12
+ #
13
+ # The plugin is based on the RabbitMQ Queue Metrics plugin
14
+ #
15
+ # PLATFORMS:
16
+ # Linux, BSD, Solaris
17
+ #
18
+ # DEPENDENCIES:
19
+ # RabbitMQ rabbitmq_management plugin
20
+ # gem: sensu-plugin
21
+ # gem: carrot-top
22
+ #
23
+ # LICENSE:
24
+ # Copyright 2015 Tim Smith <tim@cozy.co> and Cozy Services Ltd.
25
+ #
26
+ # Released under the same terms as Sensu (the MIT license); see LICENSE
27
+ # for details.
28
+
29
+ require 'sensu-plugin/check/cli'
30
+ require 'socket'
31
+ require 'carrot-top'
32
+
33
+ # main plugin class
34
+ class CheckRabbitMQQueueDrainTime < Sensu::Plugin::Check::CLI
35
+ option :host,
36
+ description: 'RabbitMQ management API host',
37
+ long: '--host HOST',
38
+ default: 'localhost'
39
+
40
+ option :port,
41
+ description: 'RabbitMQ management API port',
42
+ long: '--port PORT',
43
+ proc: proc(&:to_i),
44
+ default: 15_672
45
+
46
+ option :user,
47
+ description: 'RabbitMQ management API user',
48
+ long: '--user USER',
49
+ default: 'guest'
50
+
51
+ option :password,
52
+ description: 'RabbitMQ management API password',
53
+ long: '--password PASSWORD',
54
+ default: 'guest'
55
+
56
+ option :filter,
57
+ description: 'Regular expression for filtering queues',
58
+ long: '--filter REGEX'
59
+
60
+ option :ssl,
61
+ description: 'Enable SSL for connection to the API',
62
+ long: '--ssl',
63
+ boolean: true,
64
+ default: false
65
+
66
+ option :warn,
67
+ short: '-w PROCESS_TIME_SECS',
68
+ long: '--warning PROCESS_TIME_SECS',
69
+ description: 'WARNING that messages will process at current rate',
70
+ default: 180
71
+
72
+ option :critical,
73
+ short: '-c PROCESS_TIME_SECS',
74
+ long: '--critical PROCESS_TIME_SECS',
75
+ description: 'CRITICAL time that messages will process at current rate',
76
+ default: 360
77
+
78
+ def acquire_rabbitmq_queues
79
+ begin
80
+ rabbitmq_info = CarrotTop.new(
81
+ host: config[:host],
82
+ port: config[:port],
83
+ user: config[:user],
84
+ password: config[:password],
85
+ ssl: config[:ssl]
86
+ )
87
+ rescue
88
+ warning 'could not get rabbitmq queue info'
89
+ end
90
+ rabbitmq_info.queues
91
+ end
92
+
93
+ def run
94
+ warn_queues = {}
95
+ crit_queues = {}
96
+ acquire_rabbitmq_queues.each do |queue|
97
+ if config[:filter]
98
+ next unless queue['name'].match(config[:filter])
99
+ end
100
+
101
+ # we don't care about empty queues and they'll have an infinite drain time so skip them
102
+ next if queue['messages'] == 0
103
+
104
+ # handle rate of zero which is an infinite time until empty
105
+ if queue['backing_queue_status']['avg_egress_rate'].to_f == 0
106
+ crit_queues[queue['name']] = 'Infinite (drain rate = 0)'
107
+ next
108
+ end
109
+
110
+ secs_till_empty = queue['messages'] / queue['backing_queue_status']['avg_egress_rate']
111
+
112
+ # place warn / crit counts into hashes to be parsed for the alert message
113
+ if secs_till_empty > config[:critical].to_i
114
+ crit_queues[queue['name']] = secs_till_empty
115
+ elsif secs_till_empty > config[:warn].to_i
116
+ warn_queues[queue['name']] = secs_till_empty
117
+ end
118
+ end
119
+
120
+ # decide if we need to alert and build the message
121
+ if !crit_queues.empty?
122
+ critical "Drain time: #{crit_queues.map { |q, c| "#{q} #{c} sec" }.join(', ')}"
123
+ elsif !warn_queues.empty?
124
+ warning "Drain time: #{warn_queues.map { |q, c| "#{q} #{c} sec" }.join(', ')}"
125
+ else
126
+ ok "All (#{acquire_rabbitmq_queues.count}) queues will be drained in under #{config[:warn].to_i} seconds"
127
+ end
128
+ end
129
+ end