sensu-plugins-mysql-checks 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b5fd0d7edc5bb266573a286dde1620c2ce3c3b81
4
+ data.tar.gz: 22b3303c6b3e2794f2c033a6f92a458d4174c080
5
+ SHA512:
6
+ metadata.gz: 6f7829206dd1bd32c4451a7b7d72ee0ccd3841b966936aabba345f70ccd2c9ae89d1fe93b37e2da0dc172c490c926224dba2a20fa661a5da3dc1b7749c0d7609
7
+ data.tar.gz: 3452e50d14dc9d7bb9968172b432b92702a90a8dd3414c2ef297c2991e9c966e95545e0218b28847ec4c30e837941f3caf49ca08df5112bcb13d20be002b9873
data/CHANGELOG.md ADDED
@@ -0,0 +1,10 @@
1
+ # Change Log
2
+ This project adheres to [Semantic Versioning](http://semver.org/).
3
+
4
+ This CHANGELOG follows the format listed at [Keep A Changelog](http://keepachangelog.com/)
5
+
6
+ ## Unreleased
7
+
8
+ ## [0.0.1] - 2016-01-18
9
+ ### Added
10
+ - Initial release
data/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ Copyright (c) 2015 Matteo Cerutti
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+
data/README.md ADDED
@@ -0,0 +1,45 @@
1
+ # Sensu plugin for monitoring MySQL
2
+
3
+ A sensu plugin to monitor MySQL, including slave replication.
4
+
5
+ The plugin generates multiple OK/WARN/CRIT/UNKNOWN events via the sensu client socket (https://sensuapp.org/docs/latest/clients#client-socket-input).
6
+
7
+ What is currently supported:
8
+
9
+ * Active connections check
10
+ * Max used connections check
11
+ * Slave IO/SQL threads running checks
12
+ * Slave replication lag check
13
+ * Uptime check
14
+ * Operational check (up/down)
15
+
16
+ ## Usage
17
+
18
+ The plugin accepts the following command line options:
19
+
20
+ ```
21
+ -c, --config <PATH> Optional configuration file (default: ./mysql.json)
22
+ --crit-conn <PERCENTAGE> Critical if PERCENTAGE exceeds the current number of open connections in relation to max connections (default: 90)
23
+ --crit-slave-lag <SECONDS> Critical if SECONDS exceeds the current slave replication lag (default: 120)
24
+ --dryrun Do not send events to sensu client socket
25
+ --handlers <HANDLER> Comma separated list of handlers
26
+ -H, --host <HOST> MySQL host (default: localhost)
27
+ --password <PASSWORD> MySQL password
28
+ -p, --port <PORT> MySQL port (default: 3306)
29
+ --uptime <UPTIME> Uptime in seconds
30
+ -u, --user <USER> MySQL user
31
+ --warn-conn <PERCENTAGE> Warn if PERCENTAGE exceeds the current number of open connections in relation to max connections (default: 80)
32
+ --warn-slave-lag <SECONDS> Warn if SECONDS exceeds the current slave replication lag (default: 60)
33
+ ```
34
+
35
+ For security reasons, it's recommended you placed the MySQL credentials in the JSON configuration file as follows:
36
+
37
+ ```
38
+ {
39
+ "username": "sensu",
40
+ "password": "secret"
41
+ }
42
+ ```
43
+
44
+ ## Author
45
+ Matteo Cerutti - <matteo.cerutti@hotmail.co.uk>
@@ -0,0 +1,224 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # check-mysql.rb
4
+ #
5
+ # Author: Matteo Cerutti <matteo.cerutti@hotmail.co.uk>
6
+ #
7
+
8
+ require 'sensu-plugin/check/cli'
9
+ require 'mysql2'
10
+ require 'json'
11
+
12
+ class CheckMySQL < Sensu::Plugin::Check::CLI
13
+ option :host,
14
+ :description => "MySQL host (default: localhost)",
15
+ :short => "-H <HOST>",
16
+ :long => "--host <HOST>",
17
+ :default => "localhost"
18
+
19
+ option :port,
20
+ :description => "MySQL port (default: 3306)",
21
+ :short => "-p <PORT>",
22
+ :long => "--port <PORT>",
23
+ :proc => proc(&:to_i),
24
+ :default => 3306
25
+
26
+ option :username,
27
+ :description => "MySQL user",
28
+ :short => "-u <USER>",
29
+ :long => "--user <USER>",
30
+ :default => nil
31
+
32
+ option :password,
33
+ :description => "MySQL password",
34
+ :long => "--password <PASSWORD>",
35
+ :default => nil
36
+
37
+ option :config_file,
38
+ :description => "Optional configuration file (default: #{File.dirname(__FILE__)}/mysql.json)",
39
+ :short => "-c <PATH>",
40
+ :long => "--config <PATH>",
41
+ :default => File.dirname(__FILE__) + "/mysql.json"
42
+
43
+ option :uptime,
44
+ :description => "Uptime in seconds",
45
+ :long => "--uptime <UPTIME>",
46
+ :proc => proc(&:to_i),
47
+ :default => 300
48
+
49
+ option :warn_conn,
50
+ :description => "Warn if PERCENTAGE exceeds the current number of open connections in relation to max connections (default: 80)",
51
+ :long => "--warn-conn <PERCENTAGE>",
52
+ :proc => proc(&:to_i),
53
+ :default => 80
54
+
55
+ option :crit_conn,
56
+ :description => "Critical if PERCENTAGE exceeds the current number of open connections in relation to max connections (default: 90)",
57
+ :long => "--crit-conn <PERCENTAGE>",
58
+ :proc => proc(&:to_i),
59
+ :default => 90
60
+
61
+ option :warn_slave_lag,
62
+ :description => "Warn if SECONDS exceeds the current slave replication lag (default: 60)",
63
+ :long => "--warn-slave-lag <SECONDS>",
64
+ :proc => proc(&:to_i),
65
+ :default => 60
66
+
67
+ option :crit_slave_lag,
68
+ :description => "Critical if SECONDS exceeds the current slave replication lag (default: 120)",
69
+ :long => "--crit-slave-lag <SECONDS>",
70
+ :proc => proc(&:to_i),
71
+ :default => 120
72
+
73
+ option :handlers,
74
+ :description => "Comma separated list of handlers",
75
+ :long => "--handlers <HANDLER>",
76
+ :proc => proc { |s| s.split(',') },
77
+ :default => []
78
+
79
+ option :dryrun,
80
+ :description => "Do not send events to sensu client socket",
81
+ :long => "--dryrun",
82
+ :boolean => true,
83
+ :default => false
84
+
85
+ def initialize()
86
+ super
87
+
88
+ if File.exists?(config[:config_file])
89
+ config.merge!(JSON.parse(File.read(config[:config_file]), :symbolize_names => true))
90
+ end
91
+
92
+ raise "MySQL user is required" if config[:username].nil?
93
+ raise "MySQL password is required" if config[:password].nil?
94
+
95
+ begin
96
+ @client = Mysql2::Client.new(:host => config[:host], :port => config[:port], :username => config[:username], :password => config[:password])
97
+ rescue
98
+ critical("MySQL server is down (#{$!})")
99
+ end
100
+ end
101
+
102
+ def send_client_socket(data)
103
+ if config[:dryrun]
104
+ puts data.inspect
105
+ else
106
+ sock = UDPSocket.new
107
+ sock.send(data + "\n", 0, "127.0.0.1", 3030)
108
+ end
109
+ end
110
+
111
+ def send_ok(check_name, msg)
112
+ event = {"name" => check_name, "status" => 0, "output" => "#{self.class.name} OK: #{msg}", "handlers" => config[:handlers]}
113
+ send_client_socket(event.to_json)
114
+ end
115
+
116
+ def send_warning(check_name, msg)
117
+ event = {"name" => check_name, "status" => 1, "output" => "#{self.class.name} WARNING: #{msg}", "handlers" => config[:handlers]}
118
+ send_client_socket(event.to_json)
119
+ end
120
+
121
+ def send_critical(check_name, msg)
122
+ event = {"name" => check_name, "status" => 2, "output" => "#{self.class.name} CRITICAL: #{msg}", "handlers" => config[:handlers]}
123
+ send_client_socket(event.to_json)
124
+ end
125
+
126
+ def send_unknown(check_name, msg)
127
+ event = {"name" => check_name, "status" => 3, "output" => "#{self.class.name} UNKNOWN: #{msg}", "handlers" => config[:handlers]}
128
+ send_client_socket(event.to_json)
129
+ end
130
+
131
+ def get_uptime()
132
+ res = @client.query("SHOW GLOBAL STATUS LIKE 'Uptime'")
133
+ res.first['Value'].to_i
134
+ end
135
+
136
+ def get_threads_connected()
137
+ res = @client.query("SHOW GLOBAL STATUS LIKE 'Threads_connected'")
138
+ res.first['Value'].to_i
139
+ end
140
+
141
+ def get_max_connections_setting()
142
+ res = @client.query("SHOW VARIABLES LIKE 'max_connections'")
143
+ res.first['Value'].to_i
144
+ end
145
+
146
+ def get_max_used_connections()
147
+ res = @client.query("SHOW GLOBAL STATUS LIKE 'Max_used_connections'")
148
+ res.first['Value'].to_i
149
+ end
150
+
151
+ def get_slave_status()
152
+ res = @client.query("SHOW SLAVE STATUS")
153
+ res.first
154
+ end
155
+
156
+ def run
157
+ check_name = "mysql-active_connections"
158
+ threads_connected = get_threads_connected()
159
+ max_connections = get_max_connections_setting()
160
+ if threads_connected >= config[:crit_conn] * max_connections / 100
161
+ send_critical(check_name, "Too many active connections - Current: #{threads_connected} (>= #{config[:crit_conn] * max_connections / 100})")
162
+ elsif threads_connected >= config[:warn_conn] * max_connections / 100
163
+ send_warning(check_name, "High number of active connections - Current: #{threads_connected} (>= #{config[:warn_conn] * max_connections / 100})")
164
+ else
165
+ send_ok(check_name, "#{threads_connected} active connections (< #{config[:warn_conn] * max_connections / 100})")
166
+ end
167
+
168
+ check_name = "mysql-max_used_connections"
169
+ max_used = get_max_used_connections()
170
+ if max_used >= config[:crit_conn] * max_connections / 100
171
+ send_warning(check_name, "MySQL server max used connections reached #{max_used} (>= #{config[:crit_conn] * max_connections / 100})")
172
+ else
173
+ send_ok(check_name, "MySQL server max used connections is #{max_used} (< #{config[:crit_conn] * max_connections / 100})")
174
+ end
175
+
176
+ # is replication enabled?
177
+ slave = get_slave_status()
178
+ if slave.has_key?('Slave_IO_Running')
179
+ check_name = "mysql-slave-io_thread"
180
+ if slave['Slave_IO_Running'].downcase != 'yes'
181
+ send_critical(check_name, "MySQL slave IO thread not running (Errno: #{slave['Last_IO_Errno']}, Error: #{slave['Last_IO_Error']})")
182
+ else
183
+ send_ok(check_name, "MySQL slave IO thread is running")
184
+ end
185
+ end
186
+
187
+ if slave.has_key?('Slave_SQL_Running')
188
+ check_name = "mysql-slave-sql_thread"
189
+ if slave['Slave_SQL_Running'].downcase != 'yes'
190
+ send_critical(check_name, "MySQL slave SQL thread not running (Errno: #{slave['Last_SQL_Errno']}, Error: #{slave['Last_SQL_Error']})")
191
+ else
192
+ send_ok(check_name, "MySQL slave SQL thread is running")
193
+ end
194
+ end
195
+
196
+ if slave.has_key?('Last_Errno')
197
+ check_name = "mysql-slave-last_errno"
198
+ if slave['Last_Errno'] != 0
199
+ send_critical(check_name, "MySQL slave replication has failed with #{slave['Last_errno']} error (#{slave['Last_Error']})")
200
+ else
201
+ send_ok(check_name, "MySQL slave replication has no errors")
202
+ end
203
+ end
204
+
205
+ if slave.has_key?('Seconds_Behind_Master')
206
+ check_name = "mysql-slave-lag"
207
+ msg = "MySQL slave replication is #{slave['Seconds_Behind_Master']}s behind master"
208
+ if slave['Seconds_Behind_Master'] >= config[:crit_slave_lag]
209
+ send_critical(check_name, "#{msg} (>= #{config[:crit_slave_lag]}s)")
210
+ elsif slave['Seconds_Behind_Master'] >= config[:warn_slave_lag]
211
+ send_warning(check_name, "#{msg} (>= #{config[:warn_slave_lag]}s)")
212
+ else
213
+ send_ok(check_name, "MySQL slave replication is in sync")
214
+ end
215
+ end
216
+
217
+ uptime = get_uptime()
218
+ if uptime <= config[:uptime]
219
+ warning("MySQL server restarted #{uptime}s ago")
220
+ end
221
+
222
+ ok("MySQL server is running")
223
+ end
224
+ end
@@ -0,0 +1,9 @@
1
+ module SensuPluginsMySQLChecks
2
+ module Version
3
+ MAJOR = 0
4
+ MINOR = 0
5
+ PATCH = 1
6
+
7
+ VER_STRING = [MAJOR, MINOR, PATCH].compact.join('.')
8
+ end
9
+ end
@@ -0,0 +1 @@
1
+ require 'sensu-plugins-mysql-checks/version'
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sensu-plugins-mysql-checks
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Matteo Cerutti
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-01-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: sensu-plugin
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 1.2.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 1.2.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: mysql2
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 0.4.2
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 0.4.2
41
+ description: This plugin provides facilities for monitoring MySQL
42
+ email: "<matteo.cerutti@hotmail.co.uk>"
43
+ executables:
44
+ - check-mysql.rb
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - CHANGELOG.md
49
+ - LICENSE
50
+ - README.md
51
+ - bin/check-mysql.rb
52
+ - lib/sensu-plugins-mysql-checks.rb
53
+ - lib/sensu-plugins-mysql-checks/version.rb
54
+ homepage: https://github.com/m4ce/sensu-plugins-mysql-checks
55
+ licenses:
56
+ - MIT
57
+ metadata:
58
+ maintainer: "@m4ce"
59
+ development_status: active
60
+ production_status: stable
61
+ release_draft: 'false'
62
+ release_prerelease: 'false'
63
+ post_install_message: You can use the embedded Ruby by setting EMBEDDED_RUBY=true
64
+ in /etc/default/sensu
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: 1.9.3
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ requirements: []
79
+ rubyforge_project:
80
+ rubygems_version: 2.4.5.1
81
+ signing_key:
82
+ specification_version: 4
83
+ summary: Sensu plugins for monitoring MySQL
84
+ test_files: []