sensu-plugins-mysql 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -1
- data/README.md +3 -0
- data/bin/check-mysql-disk.rb +14 -1
- data/bin/check-mysql-replication-status.rb +22 -3
- data/bin/check-mysql-status.rb +143 -0
- data/bin/check-mysql-threads.rb +19 -1
- data/bin/metrics-mysql-graphite.rb +2 -0
- data/bin/metrics-mysql-processes.rb +132 -0
- data/bin/metrics-mysql-raw.rb +382 -0
- data/lib/sensu-plugins-mysql/version.rb +1 -1
- metadata +9 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3f33a1ae073b52dccd89fdf73543c66b45e48432
|
4
|
+
data.tar.gz: e5a88da4ae4bcf3d1d13238effdbbc38d3f50001
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0a1a0c0c2b9749c73bfd86b909f7d7d7738ec784185241a7612d9c0dccf5f87bbc29665208ad77cc113dd9e2ff4c441360ecf0cf78481cf38d6b3b57ddc81974
|
7
|
+
data.tar.gz: b012237ad2fd4945605821722a1a8944fb80b08ed5219e52995c7d2f0353f341b6b7e7d99ce828f4c1be10ef3b6f8b1b6ba4f8c6d0c76185fcbedd256e5729a6
|
data/CHANGELOG.md
CHANGED
@@ -5,6 +5,17 @@ This CHANGELOG follows the format listed at [Keep A Changelog](http://keepachang
|
|
5
5
|
|
6
6
|
## [Unreleased]
|
7
7
|
|
8
|
+
## [1.1.0] - 2017-01-15
|
9
|
+
### Added
|
10
|
+
- Added minimum thresholds to the check-mysql-threads.rb script
|
11
|
+
- Added metrics plugin with mysql gem requirement
|
12
|
+
- Added metrics plugin metrics-mysql-processes from `SHOW PROCESSLIST`
|
13
|
+
- Added fallback plugin check-mysql-status.rb with no mysql gem requirement - status and replication
|
14
|
+
- Added multi source replication parameter on check-mysql-replication-status.rb
|
15
|
+
|
16
|
+
### Fixed
|
17
|
+
- metrics-mysql-graphite.rb: Properly close mysql connection
|
18
|
+
|
8
19
|
## [1.0.0] - 2016-08-15
|
9
20
|
### Added
|
10
21
|
- added check-mysql-threads.rb script
|
@@ -40,7 +51,8 @@ This CHANGELOG follows the format listed at [Keep A Changelog](http://keepachang
|
|
40
51
|
### Added
|
41
52
|
- initial release
|
42
53
|
|
43
|
-
[Unreleased]: https://github.com/sensu-plugins/sensu-plugins-mysql/compare/1.
|
54
|
+
[Unreleased]: https://github.com/sensu-plugins/sensu-plugins-mysql/compare/1.1.0...HEAD
|
55
|
+
[1.1.0]: https://github.com/sensu-plugins/sensu-plugins-mysql/compare/1.0.0...1.1.0
|
44
56
|
[1.0.0]: https://github.com/sensu-plugins/sensu-plugins-mysql/compare/0.0.4...1.0.0
|
45
57
|
[0.0.4]: https://github.com/sensu-plugins/sensu-plugins-mysql/compare/0.0.3...0.0.4
|
46
58
|
[0.0.3]: https://github.com/sensu-plugins/sensu-plugins-mysql/compare/0.0.2...0.0.3
|
data/README.md
CHANGED
@@ -11,11 +11,14 @@
|
|
11
11
|
## Files
|
12
12
|
* bin/check-cloudwatch-mysql-sensu.rb
|
13
13
|
* bin/check-mysql-alive.rb
|
14
|
+
* bin/check-mysql-status.rb
|
14
15
|
* bin/check-mysql-connections.rb
|
15
16
|
* bin/check-mysql-disk.rb
|
16
17
|
* bin/check-mysql-innodb-lock.rb
|
17
18
|
* bin/check-mysql-threads.rb
|
18
19
|
* bin/metrics-mysql-graphite.rb
|
20
|
+
* bin/metrics-mysql-processes.rb
|
21
|
+
* bin/metrics-mysql-raw.rb
|
19
22
|
* bin/metrics-mysql.rb
|
20
23
|
* bin/mysql-metrics.sql
|
21
24
|
|
data/bin/check-mysql-disk.rb
CHANGED
@@ -52,6 +52,19 @@ class CheckMysqlDisk < Sensu::Plugin::Check::CLI
|
|
52
52
|
description: 'Critical threshold',
|
53
53
|
default: '95'
|
54
54
|
|
55
|
+
option :port,
|
56
|
+
description: 'Port to connect to',
|
57
|
+
short: '-P PORT',
|
58
|
+
long: '--port PORT',
|
59
|
+
proc: proc(&:to_i),
|
60
|
+
default: '3306'
|
61
|
+
|
62
|
+
option :socket,
|
63
|
+
description: 'Socket to use',
|
64
|
+
short: '-s SOCKET',
|
65
|
+
long: '--socket SOCKET',
|
66
|
+
default: nil
|
67
|
+
|
55
68
|
def run
|
56
69
|
if config[:ini]
|
57
70
|
ini = IniFile.load(config[:ini])
|
@@ -73,7 +86,7 @@ class CheckMysqlDisk < Sensu::Plugin::Check::CLI
|
|
73
86
|
|
74
87
|
begin
|
75
88
|
total_size = 0.0
|
76
|
-
db = Mysql.
|
89
|
+
db = Mysql.real_connect(config[:host], db_user, db_pass, nil, config[:port], config[:socket])
|
77
90
|
|
78
91
|
results = db.query <<-EOSQL
|
79
92
|
SELECT table_schema,
|
@@ -5,6 +5,7 @@
|
|
5
5
|
#
|
6
6
|
# Copyright 2011 Sonian, Inc <chefs@sonian.net>
|
7
7
|
# Updated by Oluwaseun Obajobi 2014 to accept ini argument
|
8
|
+
# Updated by Nicola Strappazzon 2016 to implement Multi Source Replication
|
8
9
|
#
|
9
10
|
# Released under the same terms as Sensu (the MIT license); see LICENSE
|
10
11
|
# for details.
|
@@ -56,6 +57,11 @@ class CheckMysqlReplicationStatus < Sensu::Plugin::Check::CLI
|
|
56
57
|
long: '--password=VALUE',
|
57
58
|
description: 'Database password'
|
58
59
|
|
60
|
+
option :master_connection,
|
61
|
+
short: '-m',
|
62
|
+
long: '--master-connection=VALUE',
|
63
|
+
description: 'Replication master connection name'
|
64
|
+
|
59
65
|
option :ini,
|
60
66
|
short: '-i',
|
61
67
|
long: '--ini VALUE',
|
@@ -88,6 +94,7 @@ class CheckMysqlReplicationStatus < Sensu::Plugin::Check::CLI
|
|
88
94
|
db_pass = config[:pass]
|
89
95
|
end
|
90
96
|
db_host = config[:host]
|
97
|
+
db_conn = config[:master_connection]
|
91
98
|
|
92
99
|
if [db_host, db_user, db_pass].any?(&:nil?)
|
93
100
|
unknown 'Must specify host, user, password'
|
@@ -95,7 +102,12 @@ class CheckMysqlReplicationStatus < Sensu::Plugin::Check::CLI
|
|
95
102
|
|
96
103
|
begin
|
97
104
|
db = Mysql.new(db_host, db_user, db_pass, nil, config[:port], config[:socket])
|
98
|
-
|
105
|
+
|
106
|
+
results = if db_conn.nil?
|
107
|
+
db.query 'SHOW SLAVE STATUS'
|
108
|
+
else
|
109
|
+
db.query "SHOW SLAVE '#{db_conn}' STATUS"
|
110
|
+
end
|
99
111
|
|
100
112
|
unless results.nil?
|
101
113
|
results.each_hash do |row|
|
@@ -108,7 +120,12 @@ class CheckMysqlReplicationStatus < Sensu::Plugin::Check::CLI
|
|
108
120
|
row[key] =~ /Yes/
|
109
121
|
end
|
110
122
|
|
111
|
-
output =
|
123
|
+
output = if db_conn.nil?
|
124
|
+
'Slave not running!'
|
125
|
+
else
|
126
|
+
"Slave on master connection #{db_conn} not running!"
|
127
|
+
end
|
128
|
+
|
112
129
|
output += ' STATES:'
|
113
130
|
output += " Slave_IO_Running=#{row['Slave_IO_Running']}"
|
114
131
|
output += ", Slave_SQL_Running=#{row['Slave_SQL_Running']}"
|
@@ -125,8 +142,10 @@ class CheckMysqlReplicationStatus < Sensu::Plugin::Check::CLI
|
|
125
142
|
warning message
|
126
143
|
elsif replication_delay >= config[:crit]
|
127
144
|
critical message
|
128
|
-
|
145
|
+
elsif db_conn.nil?
|
129
146
|
ok "slave running: #{slave_running}, #{message}"
|
147
|
+
else
|
148
|
+
ok "master connection: #{db_conn}, slave running: #{slave_running}, #{message}"
|
130
149
|
end
|
131
150
|
end
|
132
151
|
ok 'show slave status was nil. This server is not a slave.'
|
@@ -0,0 +1,143 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# MySQL Status Plugin
|
4
|
+
# ===
|
5
|
+
#
|
6
|
+
# This plugin attempts to login to mysql with provided credentials.
|
7
|
+
# NO DEPENDENCIES (no mysql-devel and thus no implicit mysql-server restart)
|
8
|
+
# It checks whether MySQL is UP --check status
|
9
|
+
# It checks replication delay --check replication
|
10
|
+
# Author: Magic Online - www.magic.fr
|
11
|
+
# Date: September 2016
|
12
|
+
#
|
13
|
+
# Author: Magic Online - www.magic.fr - September 2016
|
14
|
+
# Released under the same terms as Sensu (the MIT license); see LICENSE
|
15
|
+
# for details.
|
16
|
+
#
|
17
|
+
# USING INI ARGUMENT
|
18
|
+
# The ini file should be readable by the sensu user/group.
|
19
|
+
#
|
20
|
+
# EXAMPLE
|
21
|
+
# check-mysql-status.rb -h localhost --ini '/etc/sensu/my.cnf' --check status
|
22
|
+
# check-mysql-status.rb -h localhost --ini '/etc/sensu/my.cnf' --check replication
|
23
|
+
#
|
24
|
+
# MY.CNF INI FORMAT
|
25
|
+
# [client]
|
26
|
+
# user=sensu
|
27
|
+
# password="abcd1234"
|
28
|
+
# socket="/var/lib/mysql/mysql.sock"
|
29
|
+
#
|
30
|
+
|
31
|
+
require 'sensu-plugin/check/cli'
|
32
|
+
require 'inifile'
|
33
|
+
require 'open3'
|
34
|
+
|
35
|
+
# Check MySQL Status
|
36
|
+
class CheckMySQLStatus < Sensu::Plugin::Check::CLI
|
37
|
+
option :user, description: 'MySQL User', short: '-u USER', long: '--user USER', default: 'mosim'
|
38
|
+
option :password, description: 'MySQL Password', short: '-p PASS', long: '--password PASS', default: 'mysqlPassWord'
|
39
|
+
option :ini, description: 'My.cnf ini file', short: '-i', long: '--ini VALUE'
|
40
|
+
option :hostname, description: 'Hostname to login to', short: '-h HOST', long: '--hostname HOST', default: 'localhost'
|
41
|
+
option :database, description: 'Database schema to connect to', short: '-d DATABASE', long: '--database DATABASE', default: 'test'
|
42
|
+
option :port, description: 'Port to connect to', short: '-P PORT', long: '--port PORT', default: '3306'
|
43
|
+
option :socket, description: 'Socket to use', short: '-s SOCKET', long: '--socket SOCKET', default: '/var/run/mysqld/mysqld.sock'
|
44
|
+
option :binary, description: 'Absolute path to mysql binary', short: '-b BINARY', long: '--binary BINARY', default: 'mysql'
|
45
|
+
option :check, description: 'type of check: status | replication', short: '-c CHECK', long: '--check CHECK', default: 'status'
|
46
|
+
option :warn, short: '-w', long: '--warning=VALUE', description: 'Warning threshold for replication lag', default: 900
|
47
|
+
option :crit, short: '-c', long: '--critical=VALUE', description: 'Critical threshold for replication lag', default: 1800
|
48
|
+
option :debug, description: 'Print debug info', long: '--debug', default: false
|
49
|
+
|
50
|
+
def credentials
|
51
|
+
if config[:ini]
|
52
|
+
ini = IniFile.load(config[:ini])
|
53
|
+
section = ini['client']
|
54
|
+
db_user = section['user']
|
55
|
+
db_pass = section['password']
|
56
|
+
db_socket = section['socket']
|
57
|
+
else
|
58
|
+
db_user = config[:user]
|
59
|
+
db_pass = config[:password]
|
60
|
+
db_socket = config[:socket]
|
61
|
+
end
|
62
|
+
[db_user, db_pass, db_socket]
|
63
|
+
end
|
64
|
+
|
65
|
+
# Status check
|
66
|
+
def status_check(db_user, db_pass, db_socket)
|
67
|
+
cmd = "#{config[:binary]} -u #{db_user} -h #{config[:hostname]} --port #{config[:port]} \
|
68
|
+
--socket #{db_socket} -p\"#{db_pass.strip}\" --batch --disable-column-names -e 'show schemas;'"
|
69
|
+
begin
|
70
|
+
stdout, _stderr, status = Open3.capture3(cmd)
|
71
|
+
if status.to_i == 0
|
72
|
+
ok "#{status} | #{stdout.split("\n")}"
|
73
|
+
else
|
74
|
+
critical "Error message: status: #{status}"
|
75
|
+
end
|
76
|
+
rescue => e
|
77
|
+
critical "Error message: status: #{status} | Exception: #{e}"
|
78
|
+
ensure
|
79
|
+
puts ''
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def replication_check(db_user, db_pass, db_socket)
|
84
|
+
table = {}
|
85
|
+
begin
|
86
|
+
cmd = "#{config[:binary]} -u #{db_user} -h #{config[:hostname]} --port #{config[:port]} \
|
87
|
+
--socket #{db_socket} -p\"#{db_pass.strip}\" -e 'SHOW SLAVE STATUS\\G'"
|
88
|
+
stdout, _stderr, status = Open3.capture3(cmd)
|
89
|
+
if status.to_i != 0
|
90
|
+
critical "Error message: status: #{status}"
|
91
|
+
end
|
92
|
+
stdout.split("\n").each do |line|
|
93
|
+
key = line.split(':')[0]
|
94
|
+
value = line.split(':')[1]
|
95
|
+
table[key.strip.to_s] = value.to_s unless key.include? '***'
|
96
|
+
end
|
97
|
+
dict = []
|
98
|
+
table.keys.to_a.each do |k|
|
99
|
+
%w(Slave_IO_State Slave_IO_Running Slave_SQL_Running Last_IO_Error Last_SQL_Error Seconds_Behind_Master).each do |key|
|
100
|
+
dict.push(k.strip.to_s) if key.strip == k.strip
|
101
|
+
end
|
102
|
+
end
|
103
|
+
table.each do |attribute, value|
|
104
|
+
puts "#{attribute} : #{value}" if config[:debug]
|
105
|
+
warn "couldn't detect replication status :#{dict.size}" unless dict.size == 6
|
106
|
+
slave_running = %w(Slave_IO_Running Slave_SQL_Running).all? do |key|
|
107
|
+
table[key].to_s =~ /Yes/
|
108
|
+
end
|
109
|
+
output = 'Slave not running!'
|
110
|
+
output += ' STATES:'
|
111
|
+
output += " Slave_IO_Running=#{table['Slave_IO_Running']}"
|
112
|
+
output += ", Slave_SQL_Running=#{table['Slave_SQL_Running']}"
|
113
|
+
output += ", LAST ERROR: #{table['Last_SQL_Error']}"
|
114
|
+
critical output unless slave_running
|
115
|
+
replication_delay = table['Seconds_Behind_Master'].to_i
|
116
|
+
message = "replication delayed by #{replication_delay}"
|
117
|
+
if replication_delay > config[:warn].to_i && replication_delay <= config[:crit].to_i
|
118
|
+
warning message
|
119
|
+
elsif replication_delay >= config[:crit].to_i
|
120
|
+
critical message
|
121
|
+
else
|
122
|
+
ok "slave running: #{slave_running}, #{message}"
|
123
|
+
end
|
124
|
+
end
|
125
|
+
ok 'show slave status was nil. This server is not a slave.'
|
126
|
+
rescue => e
|
127
|
+
critical "Error message: status: #{status} | Exception: #{e}"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def run
|
132
|
+
db_user = credentials[0]
|
133
|
+
db_pass = credentials[1]
|
134
|
+
db_socket = credentials[2]
|
135
|
+
if config[:check] == 'status'
|
136
|
+
status_check(db_user, db_pass, db_socket)
|
137
|
+
end
|
138
|
+
if config[:check] == 'replication'
|
139
|
+
replication_check(db_user, db_pass, db_socket)
|
140
|
+
end
|
141
|
+
unknown 'No check type succeeded. Check your options'
|
142
|
+
end
|
143
|
+
end
|
data/bin/check-mysql-threads.rb
CHANGED
@@ -5,6 +5,10 @@
|
|
5
5
|
# DESCRIPTION:
|
6
6
|
# MySQL Threads Health plugin
|
7
7
|
# This plugin evaluates the number of MySQL running threads and warns you according to specified limits
|
8
|
+
# -w for high threshold warning
|
9
|
+
# -c for high threshold critical
|
10
|
+
# -m for low threshold warning
|
11
|
+
# -l for low threshold critical
|
8
12
|
#
|
9
13
|
# OUTPUT:
|
10
14
|
# plain text
|
@@ -16,7 +20,7 @@
|
|
16
20
|
# gem: sensu-plugin
|
17
21
|
#
|
18
22
|
# USAGE:
|
19
|
-
# check-mysql-threads.rb -w [threshold] -c [threshold]
|
23
|
+
# check-mysql-threads.rb -w [threshold] -c [threshold] -m [threshold] -l [threshold]
|
20
24
|
#
|
21
25
|
# NOTES:
|
22
26
|
#
|
@@ -76,6 +80,18 @@ class CheckMySQLHealth < Sensu::Plugin::Check::CLI
|
|
76
80
|
long: '--critnum NUMBER',
|
77
81
|
default: 25
|
78
82
|
|
83
|
+
option :minwarn,
|
84
|
+
description: "Number of running threads under which we'll issue a warning",
|
85
|
+
short: '-m NUMBER',
|
86
|
+
long: '--warnlow NUMBER',
|
87
|
+
default: 1
|
88
|
+
|
89
|
+
option :mincrit,
|
90
|
+
description: "Number of running threads under which we'll issue an alert",
|
91
|
+
short: '-l NUMBER',
|
92
|
+
long: '--critlow NUMBER',
|
93
|
+
default: 0
|
94
|
+
|
79
95
|
def run
|
80
96
|
if config[:ini]
|
81
97
|
ini = IniFile.load(config[:ini])
|
@@ -90,6 +106,8 @@ class CheckMySQLHealth < Sensu::Plugin::Check::CLI
|
|
90
106
|
run_thr = db.query("SHOW GLOBAL STATUS LIKE 'Threads_running'").fetch_hash.fetch('Value').to_i
|
91
107
|
critical "MySQL currently running threads: #{run_thr}" if run_thr >= config[:maxcrit].to_i
|
92
108
|
warning "MySQL currently running threads: #{run_thr}" if run_thr >= config[:maxwarn].to_i
|
109
|
+
critical "MySQL currently running threads: #{run_thr}" if run_thr <= config[:mincrit].to_i
|
110
|
+
warning "MySQL currently running threads: #{run_thr}" if run_thr <= config[:minwarn].to_i
|
93
111
|
ok "Currently running threads are under limit in MySQL: #{run_thr}"
|
94
112
|
rescue Mysql::Error => e
|
95
113
|
critical "MySQL check failed: #{e.error}"
|
@@ -0,0 +1,132 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# metrics-mysql-processes
|
4
|
+
#
|
5
|
+
# DESCRIPTION:
|
6
|
+
# Gets metrics out of of MySQL's "SHOW PROCESSLIST" query.
|
7
|
+
#
|
8
|
+
# Output number of connections per-users, number of connections
|
9
|
+
# per-databases, number of the different commands running.
|
10
|
+
#
|
11
|
+
# OUTPUT:
|
12
|
+
# metric-data
|
13
|
+
#
|
14
|
+
# PLATFORMS:
|
15
|
+
# Linux, Windows, BSD, Solaris, etc
|
16
|
+
#
|
17
|
+
# DEPENDENCIES:
|
18
|
+
# gem: sensu-plugin
|
19
|
+
# gem: mysql
|
20
|
+
#
|
21
|
+
# USAGE:
|
22
|
+
# This was implemented to load mysql credentials without parsing the username/password.
|
23
|
+
# The ini file should be readable by the sensu user/group.
|
24
|
+
# Ref: http://eric.lubow.org/2009/ruby/parsing-ini-files-with-ruby/
|
25
|
+
#
|
26
|
+
# EXAMPLE
|
27
|
+
# mysql-alive.rb -h db01 --ini '/etc/sensu/my.cnf'
|
28
|
+
#
|
29
|
+
# MY.CNF INI FORMAT
|
30
|
+
# [client]
|
31
|
+
# user=sensu
|
32
|
+
# password="abcd1234"
|
33
|
+
#
|
34
|
+
# NOTES:
|
35
|
+
#
|
36
|
+
# LICENSE:
|
37
|
+
# Jonathan Ballet <jballet@edgelab.ch>
|
38
|
+
# Released under the same terms as Sensu (the MIT license); see LICENSE
|
39
|
+
# for details.
|
40
|
+
|
41
|
+
require 'sensu-plugin/metric/cli'
|
42
|
+
require 'mysql'
|
43
|
+
require 'socket'
|
44
|
+
require 'inifile'
|
45
|
+
|
46
|
+
class MetricsMySQLProcesses < Sensu::Plugin::Metric::CLI::Graphite
|
47
|
+
option :host,
|
48
|
+
short: '-h HOST',
|
49
|
+
long: '--host HOST',
|
50
|
+
description: 'MySQL Host to connect to',
|
51
|
+
required: true
|
52
|
+
|
53
|
+
option :port,
|
54
|
+
short: '-P PORT',
|
55
|
+
long: '--port PORT',
|
56
|
+
description: 'MySQL Port to connect to',
|
57
|
+
proc: proc(&:to_i),
|
58
|
+
default: 3306
|
59
|
+
|
60
|
+
option :username,
|
61
|
+
short: '-u USERNAME',
|
62
|
+
long: '--user USERNAME',
|
63
|
+
description: 'MySQL Username'
|
64
|
+
|
65
|
+
option :password,
|
66
|
+
short: '-p PASSWORD',
|
67
|
+
long: '--pass PASSWORD',
|
68
|
+
description: 'MySQL password',
|
69
|
+
default: ''
|
70
|
+
|
71
|
+
option :ini,
|
72
|
+
short: '-i',
|
73
|
+
long: '--ini VALUE',
|
74
|
+
description: 'My.cnf ini file'
|
75
|
+
|
76
|
+
option :scheme,
|
77
|
+
description: 'Metric naming scheme, text to prepend to metric',
|
78
|
+
short: '-s SCHEME',
|
79
|
+
long: '--scheme SCHEME',
|
80
|
+
default: "#{Socket.gethostname}.mysql"
|
81
|
+
|
82
|
+
option :socket,
|
83
|
+
short: '-S SOCKET',
|
84
|
+
long: '--socket SOCKET',
|
85
|
+
description: 'MySQL Unix socket to connect to'
|
86
|
+
|
87
|
+
def run
|
88
|
+
config[:host].split(' ').each do |mysql_host|
|
89
|
+
mysql_shorthostname = mysql_host.split('.')[0]
|
90
|
+
if config[:ini]
|
91
|
+
ini = IniFile.load(config[:ini])
|
92
|
+
section = ini['client']
|
93
|
+
db_user = section['user']
|
94
|
+
db_pass = section['password']
|
95
|
+
else
|
96
|
+
db_user = config[:username]
|
97
|
+
db_pass = config[:password]
|
98
|
+
end
|
99
|
+
begin
|
100
|
+
mysql = Mysql.new(mysql_host, db_user, db_pass, nil, config[:port], config[:socket])
|
101
|
+
|
102
|
+
results = mysql.query('SHOW PROCESSLIST')
|
103
|
+
rescue => e
|
104
|
+
unknown "Unable to query MySQL: #{e.message}"
|
105
|
+
end
|
106
|
+
|
107
|
+
metrics = {
|
108
|
+
'user' => {},
|
109
|
+
'database' => {},
|
110
|
+
'command' => {}
|
111
|
+
}
|
112
|
+
|
113
|
+
metrics.each_value { |value| value.default = 0 }
|
114
|
+
|
115
|
+
results.each_hash do |row|
|
116
|
+
metrics['user'][row['User']] += 1
|
117
|
+
if row['db'] # If no database has been selected by the process, it is set to nil.
|
118
|
+
metrics['database'][row['db']] += 1
|
119
|
+
end
|
120
|
+
metrics['command'][row['Command']] += 1
|
121
|
+
end
|
122
|
+
|
123
|
+
metrics.each do |key, value|
|
124
|
+
value.each do |instance, count|
|
125
|
+
output "#{config[:scheme]}.#{mysql_shorthostname}.#{key}.#{instance}", count
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
ok
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,382 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# MySQL metrics Plugin without mysql gem requirement
|
4
|
+
# ===
|
5
|
+
#
|
6
|
+
# This plugin attempts to login to mysql with provided credentials.
|
7
|
+
# and outputs metrics in graphite format
|
8
|
+
#
|
9
|
+
# Released under the same terms as Sensu (the MIT license); see LICENSE
|
10
|
+
# for details.
|
11
|
+
#
|
12
|
+
# USING INI ARGUMENT
|
13
|
+
# This was implemented to load mysql credentials without parsing
|
14
|
+
# the username/password.
|
15
|
+
# The ini file should be readable by the sensu user/group.
|
16
|
+
#
|
17
|
+
# EXAMPLE
|
18
|
+
# metrics-mysql-raw.rb -h localhost --ini '/etc/sensu/my.cnf'
|
19
|
+
#
|
20
|
+
# MY.CNF INI FORMAT
|
21
|
+
# [client]
|
22
|
+
# user=sensu
|
23
|
+
# password="abcd1234"
|
24
|
+
# socket="/var/lib/mysql/mysql.sock"
|
25
|
+
#
|
26
|
+
# LICENSE:
|
27
|
+
# Copyright 2012 Pete Shima <me@peteshima.com>
|
28
|
+
# Additional hacks by Joe Miller - https://github.com/joemiller
|
29
|
+
# Updated by Oluwaseun Obajobi 2014 to accept ini argument
|
30
|
+
# Forked by Magic Online 11.2016 to not depend on mysql gem
|
31
|
+
# - www.magic.fr <hanynowsky@gmail.com>
|
32
|
+
# MIT - Same as Sensu License
|
33
|
+
#
|
34
|
+
|
35
|
+
require 'sensu-plugin/metric/cli'
|
36
|
+
require 'open3'
|
37
|
+
require 'socket'
|
38
|
+
require 'inifile'
|
39
|
+
require 'timeout'
|
40
|
+
|
41
|
+
#
|
42
|
+
# Metrics Mysql Raw
|
43
|
+
#
|
44
|
+
class MetricsMySQLRaw < Sensu::Plugin::Metric::CLI::Graphite
|
45
|
+
option(
|
46
|
+
:user,
|
47
|
+
description: 'MySQL User',
|
48
|
+
short: '-u USER',
|
49
|
+
long: '--user USER',
|
50
|
+
default: 'mosim'
|
51
|
+
)
|
52
|
+
|
53
|
+
option(
|
54
|
+
:password,
|
55
|
+
description: 'MySQL Password',
|
56
|
+
short: '-p PASS',
|
57
|
+
long: '--password PASS',
|
58
|
+
default: 'mysqlPassWord'
|
59
|
+
)
|
60
|
+
option(
|
61
|
+
:ini,
|
62
|
+
description: 'My.cnf ini file',
|
63
|
+
short: '-i',
|
64
|
+
long: '--ini VALUE'
|
65
|
+
)
|
66
|
+
|
67
|
+
option(
|
68
|
+
:hostname,
|
69
|
+
description: 'Hostname to login to',
|
70
|
+
short: '-h HOST',
|
71
|
+
long: '--hostname HOST',
|
72
|
+
default: 'localhost'
|
73
|
+
)
|
74
|
+
|
75
|
+
option(
|
76
|
+
:database,
|
77
|
+
description: 'Database schema to connect to. NOT YET IMPlemented',
|
78
|
+
short: '-d DATABASE',
|
79
|
+
long: '--database DATABASE',
|
80
|
+
default: 'test'
|
81
|
+
)
|
82
|
+
|
83
|
+
option(
|
84
|
+
:timeout,
|
85
|
+
description: 'Timeout',
|
86
|
+
short: '-T TIMEOUT',
|
87
|
+
long: '--timeout TIMEOUT',
|
88
|
+
default: 10
|
89
|
+
)
|
90
|
+
|
91
|
+
option(
|
92
|
+
:port,
|
93
|
+
description: 'Port to connect to',
|
94
|
+
short: '-P PORT',
|
95
|
+
long: '--port PORT',
|
96
|
+
default: '3306'
|
97
|
+
)
|
98
|
+
|
99
|
+
option(
|
100
|
+
:socket,
|
101
|
+
description: 'Socket to use',
|
102
|
+
short: '-s SOCKET',
|
103
|
+
long: '--socket SOCKET',
|
104
|
+
default: '/var/run/mysqld/mysqld.sock'
|
105
|
+
)
|
106
|
+
|
107
|
+
option(
|
108
|
+
:binary,
|
109
|
+
description: 'Absolute path to mysql binary',
|
110
|
+
short: '-b BINARY',
|
111
|
+
long: '--binary BINARY',
|
112
|
+
default: 'mysql'
|
113
|
+
)
|
114
|
+
|
115
|
+
option(
|
116
|
+
:check,
|
117
|
+
description: 'type of check: metric',
|
118
|
+
short: '-c CHECK',
|
119
|
+
long: '--check CHECK',
|
120
|
+
default: 'metric'
|
121
|
+
)
|
122
|
+
|
123
|
+
option(
|
124
|
+
:scheme,
|
125
|
+
description: 'Metric naming scheme, text to prepend to metric',
|
126
|
+
short: '-s SCHEME',
|
127
|
+
long: '--scheme SCHEME',
|
128
|
+
default: "#{Socket.gethostname}.mysql"
|
129
|
+
)
|
130
|
+
|
131
|
+
option(
|
132
|
+
:verbose,
|
133
|
+
short: '-v',
|
134
|
+
long: '--verbose',
|
135
|
+
boolean: true
|
136
|
+
)
|
137
|
+
|
138
|
+
option(
|
139
|
+
:off,
|
140
|
+
description: 'Turn Metrics OFF',
|
141
|
+
long: '--off',
|
142
|
+
boolean: true,
|
143
|
+
default: false
|
144
|
+
)
|
145
|
+
|
146
|
+
# Metrics hash
|
147
|
+
def metrics_hash
|
148
|
+
metrics = {
|
149
|
+
'general' => {
|
150
|
+
'Bytes_received' => 'rxBytes',
|
151
|
+
'Bytes_sent' => 'txBytes',
|
152
|
+
'Key_read_requests' => 'keyRead_requests',
|
153
|
+
'Key_reads' => 'keyReads',
|
154
|
+
'Key_write_requests' => 'keyWrite_requests',
|
155
|
+
'Key_writes' => 'keyWrites',
|
156
|
+
'Binlog_cache_use' => 'binlogCacheUse',
|
157
|
+
'Binlog_cache_disk_use' => 'binlogCacheDiskUse',
|
158
|
+
'Max_used_connections' => 'maxUsedConnections',
|
159
|
+
'Aborted_clients' => 'abortedClients',
|
160
|
+
'Aborted_connects' => 'abortedConnects',
|
161
|
+
'Threads_connected' => 'threadsConnected',
|
162
|
+
'Open_files' => 'openFiles',
|
163
|
+
'Open_tables' => 'openTables',
|
164
|
+
'Opened_tables' => 'openedTables',
|
165
|
+
'Prepared_stmt_count' => 'preparedStmtCount',
|
166
|
+
'Seconds_Behind_Master' => 'slaveLag',
|
167
|
+
'Select_full_join' => 'fullJoins',
|
168
|
+
'Select_full_range_join' => 'fullRangeJoins',
|
169
|
+
'Select_range' => 'selectRange',
|
170
|
+
'Select_range_check' => 'selectRange_check',
|
171
|
+
'Select_scan' => 'selectScan',
|
172
|
+
'Slow_queries' => 'slowQueries'
|
173
|
+
},
|
174
|
+
'querycache' => {
|
175
|
+
'Qcache_queries_in_cache' => 'queriesInCache',
|
176
|
+
'Qcache_hits' => 'cacheHits',
|
177
|
+
'Qcache_inserts' => 'inserts',
|
178
|
+
'Qcache_not_cached' => 'notCached',
|
179
|
+
'Qcache_lowmem_prunes' => 'lowMemPrunes'
|
180
|
+
},
|
181
|
+
'commands' => {
|
182
|
+
'Com_admin_commands' => 'admin_commands',
|
183
|
+
'Com_begin' => 'begin',
|
184
|
+
'Com_change_db' => 'change_db',
|
185
|
+
'Com_commit' => 'commit',
|
186
|
+
'Com_create_table' => 'create_table',
|
187
|
+
'Com_drop_table' => 'drop_table',
|
188
|
+
'Com_show_keys' => 'show_keys',
|
189
|
+
'Com_delete' => 'delete',
|
190
|
+
'Com_create_db' => 'create_db',
|
191
|
+
'Com_grant' => 'grant',
|
192
|
+
'Com_show_processlist' => 'show_processlist',
|
193
|
+
'Com_flush' => 'flush',
|
194
|
+
'Com_insert' => 'insert',
|
195
|
+
'Com_purge' => 'purge',
|
196
|
+
'Com_replace' => 'replace',
|
197
|
+
'Com_rollback' => 'rollback',
|
198
|
+
'Com_select' => 'select',
|
199
|
+
'Com_set_option' => 'set_option',
|
200
|
+
'Com_show_binlogs' => 'show_binlogs',
|
201
|
+
'Com_show_databases' => 'show_databases',
|
202
|
+
'Com_show_fields' => 'show_fields',
|
203
|
+
'Com_show_status' => 'show_status',
|
204
|
+
'Com_show_tables' => 'show_tables',
|
205
|
+
'Com_show_variables' => 'show_variables',
|
206
|
+
'Com_update' => 'update',
|
207
|
+
'Com_drop_db' => 'drop_db',
|
208
|
+
'Com_revoke' => 'revoke',
|
209
|
+
'Com_drop_user' => 'drop_user',
|
210
|
+
'Com_show_grants' => 'show_grants',
|
211
|
+
'Com_lock_tables' => 'lock_tables',
|
212
|
+
'Com_show_create_table' => 'show_create_table',
|
213
|
+
'Com_unlock_tables' => 'unlock_tables',
|
214
|
+
'Com_alter_table' => 'alter_table'
|
215
|
+
},
|
216
|
+
'counters' => {
|
217
|
+
'Handler_write' => 'handlerWrite',
|
218
|
+
'Handler_update' => 'handlerUpdate',
|
219
|
+
'Handler_delete' => 'handlerDelete',
|
220
|
+
'Handler_read_first' => 'handlerRead_first',
|
221
|
+
'Handler_read_key' => 'handlerRead_key',
|
222
|
+
'Handler_read_next' => 'handlerRead_next',
|
223
|
+
'Handler_read_prev' => 'handlerRead_prev',
|
224
|
+
'Handler_read_rnd' => 'handlerRead_rnd',
|
225
|
+
'Handler_read_rnd_next' => 'handlerRead_rnd_next',
|
226
|
+
'Handler_commit' => 'handlerCommit',
|
227
|
+
'Handler_rollback' => 'handlerRollback',
|
228
|
+
'Handler_savepoint' => 'handlerSavepoint',
|
229
|
+
'Handler_savepoint_rollback' => 'handlerSavepointRollback'
|
230
|
+
},
|
231
|
+
'innodb' => {
|
232
|
+
'Innodb_buffer_pool_pages_total' => 'bufferTotal_pages',
|
233
|
+
'Innodb_buffer_pool_pages_free' => 'bufferFree_pages',
|
234
|
+
'Innodb_buffer_pool_pages_dirty' => 'bufferDirty_pages',
|
235
|
+
'Innodb_buffer_pool_pages_data' => 'bufferUsed_pages',
|
236
|
+
'Innodb_page_size' => 'pageSize',
|
237
|
+
'Innodb_pages_created' => 'pagesCreated',
|
238
|
+
'Innodb_pages_read' => 'pagesRead',
|
239
|
+
'Innodb_pages_written' => 'pagesWritten',
|
240
|
+
'Innodb_row_lock_current_waits' => 'currentLockWaits',
|
241
|
+
'Innodb_row_lock_waits' => 'lockWaitTimes',
|
242
|
+
'Innodb_row_lock_time' => 'rowLockTime',
|
243
|
+
'Innodb_data_reads' => 'fileReads',
|
244
|
+
'Innodb_data_writes' => 'fileWrites',
|
245
|
+
'Innodb_data_fsyncs' => 'fileFsyncs',
|
246
|
+
'Innodb_log_writes' => 'logWrites',
|
247
|
+
'Innodb_rows_updated' => 'rowsUpdated',
|
248
|
+
'Innodb_rows_read' => 'rowsRead',
|
249
|
+
'Innodb_rows_deleted' => 'rowsDeleted',
|
250
|
+
'Innodb_rows_inserted' => 'rowsInserted'
|
251
|
+
},
|
252
|
+
'configuration' => {
|
253
|
+
'Max_prepared_stmt_count' => 'MaxPreparedStmtCount'
|
254
|
+
}
|
255
|
+
}
|
256
|
+
metrics
|
257
|
+
end
|
258
|
+
|
259
|
+
# Credentials
|
260
|
+
def credentials
|
261
|
+
if config[:ini]
|
262
|
+
ini = IniFile.load(config[:ini])
|
263
|
+
section = ini['client']
|
264
|
+
db_user = section['user']
|
265
|
+
db_pass = section['password']
|
266
|
+
db_socket = section['socket']
|
267
|
+
else
|
268
|
+
db_user = config[:user]
|
269
|
+
db_pass = config[:password]
|
270
|
+
db_socket = config[:socket]
|
271
|
+
end
|
272
|
+
[db_user, db_pass, db_socket]
|
273
|
+
end
|
274
|
+
|
275
|
+
# Slave metrics
|
276
|
+
def slave_metrics(metrics)
|
277
|
+
# should return a single element array containing one hash
|
278
|
+
# #YELLOW
|
279
|
+
mysql_shorthostname = config[:hostname].tr('.', '_')
|
280
|
+
slave_results = Hash['a' => 100, 'b' => 200]
|
281
|
+
slave_results.first.each do |key, value|
|
282
|
+
if metrics['general'].include?(key)
|
283
|
+
# Replication lag being null is bad, very bad, so negativate it here
|
284
|
+
value = -1 if key == 'Seconds_Behind_Master' && value.nil?
|
285
|
+
output "#{config[:scheme]}.#{mysql_shorthostname}.general.#{metrics['general'][key]}", value
|
286
|
+
end
|
287
|
+
end
|
288
|
+
rescue => e
|
289
|
+
puts "Error querying slave status: #{e}" if config[:verbose]
|
290
|
+
end
|
291
|
+
|
292
|
+
# Configuration metrics
|
293
|
+
def configuration_metrics(metrics, db_user, db_pass, db_socket)
|
294
|
+
mysql_shorthostname = config[:hostname].tr('.', '_')
|
295
|
+
table = []
|
296
|
+
cmd = "#{config[:binary]} -u #{db_user} -h #{config[:hostname]} \
|
297
|
+
--port #{config[:port]} --socket #{db_socket} -p\"#{db_pass.chomp}\" --batch \
|
298
|
+
--disable-column-names -e 'SHOW GLOBAL VARIABLES;'"
|
299
|
+
stdout, _stderr, status = Open3.capture3(cmd)
|
300
|
+
puts status.to_s.split(' ')[3] if config[:verbose]
|
301
|
+
if status == 0
|
302
|
+
puts status.to_s if config[:verbose]
|
303
|
+
stdout.split("\n").each do |row|
|
304
|
+
line = row.tr("\t", ':')
|
305
|
+
key = line.split(':')[0]
|
306
|
+
value = line.split(':')[1]
|
307
|
+
table.push('Variable_name' => key, 'Value' => value)
|
308
|
+
end
|
309
|
+
else
|
310
|
+
critical "Error message: Global variables - status: #{status}"
|
311
|
+
end
|
312
|
+
variables_results = table
|
313
|
+
category = 'configuration'
|
314
|
+
variables_results.each do |row|
|
315
|
+
metrics[category].each do |metric, desc|
|
316
|
+
if metric.casecmp(row['Variable_name']) == 0
|
317
|
+
output "#{config[:scheme]}.#{mysql_shorthostname}.#{category}.#{desc}", row['Value']
|
318
|
+
end
|
319
|
+
end
|
320
|
+
end
|
321
|
+
rescue => e
|
322
|
+
puts e.message
|
323
|
+
end
|
324
|
+
|
325
|
+
# Fetch MySQL metrics
|
326
|
+
def fetcher(db_user, db_pass, db_socket)
|
327
|
+
metrics = metrics_hash
|
328
|
+
if config[:check] == 'metric'
|
329
|
+
mysql_shorthostname = config[:hostname].tr('.', '_')
|
330
|
+
begin
|
331
|
+
table = []
|
332
|
+
cmd = "#{config[:binary]} -u #{db_user} -h #{config[:hostname]} \
|
333
|
+
--port #{config[:port]} --socket #{db_socket} -p\"#{db_pass.chomp}\" --batch \
|
334
|
+
--disable-column-names -e 'SHOW GLOBAL STATUS;'"
|
335
|
+
stdout, _stderr, status = Open3.capture3(cmd)
|
336
|
+
puts status.to_s.split(' ')[3] if config[:verbose]
|
337
|
+
if status == 0
|
338
|
+
puts status.to_s if config[:verbose]
|
339
|
+
stdout.split("\n").each do |row|
|
340
|
+
line = row.tr("\t", ':')
|
341
|
+
key = line.split(':')[0]
|
342
|
+
value = line.split(':')[1]
|
343
|
+
table.push('Variable_name' => key, 'Value' => value)
|
344
|
+
end
|
345
|
+
else
|
346
|
+
critical "Error message: status: #{status}"
|
347
|
+
end
|
348
|
+
table.each do |row|
|
349
|
+
metrics.each do |category, var_mapping|
|
350
|
+
row_var_name = row['Variable_name'].to_s
|
351
|
+
var_mapping.keys.each do |vmkey|
|
352
|
+
if row_var_name.to_s == vmkey.to_s
|
353
|
+
prefix = "#{config[:scheme]}.#{mysql_shorthostname}.#{category}.#{vmkey[row_var_name]}"
|
354
|
+
output prefix, row['Value'] unless mysql_shorthostname.to_s.chomp.empty?
|
355
|
+
end
|
356
|
+
end
|
357
|
+
end
|
358
|
+
end
|
359
|
+
# Slave and configuration metrics here
|
360
|
+
slave_metrics(metrics)
|
361
|
+
configuration_metrics(metrics, db_user, db_pass, db_socket)
|
362
|
+
rescue => e
|
363
|
+
critical "Error message: status: #{status} | Exception: #{e.backtrace}"
|
364
|
+
ensure
|
365
|
+
ok ''
|
366
|
+
end
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
# Main Function
|
371
|
+
def run
|
372
|
+
ok 'Metrics deactivated by user using option --off' if config[:off] == true
|
373
|
+
begin
|
374
|
+
Timeout.timeout(config[:timeout]) do
|
375
|
+
fetcher(credentials[0], credentials[1], credentials[2])
|
376
|
+
end
|
377
|
+
rescue Timeout::Error => e
|
378
|
+
unknown "Timed out #{e.message}"
|
379
|
+
end
|
380
|
+
unknown 'Did not succeed to retrieve MySQL metrics. Check your options'
|
381
|
+
end
|
382
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sensu-plugins-mysql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sensu-Plugins and contributors
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-01-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: inifile
|
@@ -191,8 +191,11 @@ executables:
|
|
191
191
|
- check-mysql-disk.rb
|
192
192
|
- check-mysql-innodb-lock.rb
|
193
193
|
- check-mysql-replication-status.rb
|
194
|
+
- check-mysql-status.rb
|
194
195
|
- check-mysql-threads.rb
|
195
196
|
- metrics-mysql-graphite.rb
|
197
|
+
- metrics-mysql-processes.rb
|
198
|
+
- metrics-mysql-raw.rb
|
196
199
|
- metrics-mysql.rb
|
197
200
|
extensions: []
|
198
201
|
extra_rdoc_files: []
|
@@ -205,8 +208,11 @@ files:
|
|
205
208
|
- bin/check-mysql-disk.rb
|
206
209
|
- bin/check-mysql-innodb-lock.rb
|
207
210
|
- bin/check-mysql-replication-status.rb
|
211
|
+
- bin/check-mysql-status.rb
|
208
212
|
- bin/check-mysql-threads.rb
|
209
213
|
- bin/metrics-mysql-graphite.rb
|
214
|
+
- bin/metrics-mysql-processes.rb
|
215
|
+
- bin/metrics-mysql-raw.rb
|
210
216
|
- bin/metrics-mysql.rb
|
211
217
|
- bin/mysql-metrics.sql
|
212
218
|
- lib/sensu-plugins-mysql.rb
|
@@ -237,7 +243,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
237
243
|
version: '0'
|
238
244
|
requirements: []
|
239
245
|
rubyforge_project:
|
240
|
-
rubygems_version: 2.5
|
246
|
+
rubygems_version: 2.4.5
|
241
247
|
signing_key:
|
242
248
|
specification_version: 4
|
243
249
|
summary: Sensu plugins for MySql
|