sensu-plugins-mysql-boutetnico 1.0.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.
@@ -0,0 +1,113 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # MySQL Select Count Check
4
+ #
5
+ # Checks the length of a result set from a MySQL query.
6
+ #
7
+ # Copyright 2017 Andrew Thal <athal7@me.com> to check-mysql-query-result-count.rb
8
+ # Modified by Mutsutoshi Yoshimoto <negachov@gmail.com> 2018 to select count(*) version
9
+ #
10
+ # Released under the same terms as Sensu (the MIT license); see LICENSE
11
+ # for details.
12
+
13
+ require 'sensu-plugin/check/cli'
14
+ require 'mysql'
15
+ require 'inifile'
16
+
17
+ class MysqlSelectCountCheck < Sensu::Plugin::Check::CLI
18
+ option :host,
19
+ short: '-h HOST',
20
+ long: '--host HOST',
21
+ description: 'MySQL Host to connect to'
22
+
23
+ option :port,
24
+ short: '-P PORT',
25
+ long: '--port PORT',
26
+ description: 'MySQL Port to connect to',
27
+ proc: proc(&:to_i),
28
+ default: 3306
29
+
30
+ option :username,
31
+ short: '-u USERNAME',
32
+ long: '--user USERNAME',
33
+ description: 'MySQL Username'
34
+
35
+ option :password,
36
+ short: '-p PASSWORD',
37
+ long: '--pass PASSWORD',
38
+ description: 'MySQL password'
39
+
40
+ option :database,
41
+ short: '-d DATABASE',
42
+ long: '--database DATABASE',
43
+ description: 'MySQL database',
44
+ required: true
45
+
46
+ option :ini,
47
+ short: '-i',
48
+ long: '--ini VALUE',
49
+ description: 'My.cnf ini file'
50
+
51
+ option :ini_section,
52
+ description: 'Section in my.cnf ini file',
53
+ long: '--ini-section VALUE',
54
+ default: 'client'
55
+
56
+ option :socket,
57
+ short: '-S SOCKET',
58
+ long: '--socket SOCKET',
59
+ description: 'MySQL Unix socket to connect to'
60
+
61
+ option :warn,
62
+ short: '-w COUNT',
63
+ long: '--warning COUNT',
64
+ description: 'Warning when query value exceeds threshold',
65
+ proc: proc(&:to_i),
66
+ required: true
67
+
68
+ option :crit,
69
+ short: '-c COUNT',
70
+ long: '--critical COUNT',
71
+ description: 'Critical when query value exceeds threshold',
72
+ proc: proc(&:to_i),
73
+ required: true
74
+
75
+ option :query,
76
+ short: '-q SELECT_COUNT_QUERY',
77
+ long: '--query SELECT_COUNT_QUERY',
78
+ description: 'Query to execute',
79
+ required: true
80
+
81
+ def run
82
+ if config[:ini]
83
+ ini = IniFile.load(config[:ini])
84
+ section = ini[config[:ini_section]]
85
+ db_user = section['user']
86
+ db_pass = section['password']
87
+ config[:host] = section['host']
88
+ config[:socket] = section['socket']
89
+ else
90
+ db_user = config[:username]
91
+ db_pass = config[:password]
92
+ end
93
+ raise 'Please specify hostname using -h or in mysql.cnf file' unless config[:host]
94
+
95
+ db = Mysql.real_connect(config[:host], db_user, db_pass, config[:database], config[:port], config[:socket])
96
+
97
+ count = db.query(config[:query]).fetch_row[0].to_i
98
+ if count >= config[:crit]
99
+ critical "Count is above the CRITICAL limit: #{count} count / #{config[:crit]} limit"
100
+ elsif count >= config[:warn]
101
+ warning "Count is above the WARNING limit: #{count} count / #{config[:warn]} limit"
102
+ else
103
+ ok "Count is below thresholds : #{count} count"
104
+ end
105
+ rescue Mysql::Error => e
106
+ errstr = "Error code: #{e.errno} Error message: #{e.error}"
107
+ critical "#{errstr} SQLSTATE: #{e.sqlstate}" if e.respond_to?('sqlstate')
108
+ rescue StandardError => e
109
+ critical "unhandled exception: #{e}"
110
+ ensure
111
+ db.close if db
112
+ end
113
+ end
@@ -0,0 +1,209 @@
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,
38
+ description: 'MySQL User, you really should use ini to hide credentials instead of using me',
39
+ short: '-u USER',
40
+ long: '--user USER',
41
+ default: 'mosim'
42
+
43
+ option :password,
44
+ description: 'MySQL Password, you really should use ini to hide credentials instead of using me',
45
+ short: '-p PASS',
46
+ long: '--password PASS',
47
+ default: 'mysqlPassWord'
48
+
49
+ option :ini,
50
+ description: 'My.cnf ini file',
51
+ short: '-i',
52
+ long: '--ini VALUE'
53
+
54
+ option :ini_section,
55
+ description: 'Section in my.cnf ini file',
56
+ long: '--ini-section VALUE',
57
+ default: 'client'
58
+
59
+ option :hostname,
60
+ description: 'Hostname to login to',
61
+ short: '-h HOST',
62
+ long: '--hostname HOST',
63
+ default: 'localhost'
64
+
65
+ option :database,
66
+ description: 'Database schema to connect to',
67
+ short: '-d DATABASE',
68
+ long: '--database DATABASE',
69
+ default: 'test'
70
+
71
+ option :port,
72
+ description: 'Port to connect to',
73
+ short: '-P PORT',
74
+ long: '--port PORT',
75
+ default: '3306'
76
+
77
+ option :socket,
78
+ description: 'Socket to use',
79
+ short: '-s SOCKET',
80
+ long: '--socket SOCKET',
81
+ default: '/var/run/mysqld/mysqld.sock'
82
+
83
+ option :binary,
84
+ description: 'Absolute path to mysql binary',
85
+ short: '-b BINARY',
86
+ long: '--binary BINARY',
87
+ default: 'mysql'
88
+
89
+ option :check,
90
+ description: 'type of check: (status|replication)',
91
+ short: '-C CHECK',
92
+ long: '--check CHECK',
93
+ default: 'status'
94
+
95
+ option :warn,
96
+ description: 'Warning threshold for replication lag',
97
+ short: '-w',
98
+ long: '--warning=VALUE',
99
+ default: 900
100
+
101
+ option :crit,
102
+ description: 'Critical threshold for replication lag',
103
+ short: '-c',
104
+ long: '--critical=VALUE',
105
+ default: 1800
106
+
107
+ option :debug,
108
+ description: 'Print debug info',
109
+ long: '--debug',
110
+ default: false
111
+
112
+ def credentials
113
+ if config[:ini]
114
+ ini = IniFile.load(config[:ini])
115
+ section = ini[config[:ini_section]]
116
+ db_user = section['user']
117
+ db_pass = section['password']
118
+ db_socket = if config[:socket]
119
+ config[:socket]
120
+ else
121
+ section['socket']
122
+ end
123
+ else
124
+ db_user = config[:user]
125
+ db_pass = config[:password]
126
+ db_socket = config[:socket]
127
+ end
128
+ [db_user, db_pass, db_socket]
129
+ end
130
+
131
+ # Status check
132
+ def status_check(db_user, db_pass, db_socket)
133
+ cmd = "#{config[:binary]} -u #{db_user} -h #{config[:hostname]} --port #{config[:port]} \
134
+ --socket #{db_socket} -p\"#{db_pass.strip}\" --batch --disable-column-names -e 'show schemas;'"
135
+ begin
136
+ stdout, _stderr, status = Open3.capture3(cmd)
137
+ if status.to_i == 0
138
+ ok "#{status} | #{stdout.split("\n")}"
139
+ else
140
+ critical "Error message: status: #{status}"
141
+ end
142
+ rescue StandardError => e
143
+ critical "Error message: status: #{status} | Exception: #{e}"
144
+ ensure
145
+ puts ''
146
+ end
147
+ end
148
+
149
+ def replication_check(db_user, db_pass, db_socket)
150
+ table = {}
151
+ begin
152
+ cmd = "#{config[:binary]} -u #{db_user} -h #{config[:hostname]} --port #{config[:port]} \
153
+ --socket #{db_socket} -p\"#{db_pass.strip}\" -e 'SHOW SLAVE STATUS\\G'"
154
+ stdout, _stderr, status = Open3.capture3(cmd)
155
+ if status.to_i != 0
156
+ critical "Error message: status: #{status}"
157
+ end
158
+ stdout.split("\n").each do |line|
159
+ key = line.split(':')[0]
160
+ value = line.split(':')[1]
161
+ table[key.strip.to_s] = value.to_s unless key.include? '***'
162
+ end
163
+ dict = []
164
+ table.keys.to_a.each do |k|
165
+ %w[Slave_IO_State Slave_IO_Running Slave_SQL_Running Last_IO_Error Last_SQL_Error Seconds_Behind_Master].each do |key|
166
+ dict.push(k.strip.to_s) if key.strip == k.strip
167
+ end
168
+ end
169
+ table.each do |attribute, value|
170
+ puts "#{attribute} : #{value}" if config[:debug]
171
+ warn "couldn't detect replication status :#{dict.size}" unless dict.size == 6
172
+ slave_running = %w[Slave_IO_Running Slave_SQL_Running].all? do |key|
173
+ table[key].to_s =~ /Yes/
174
+ end
175
+ output = 'Slave not running!'
176
+ output += ' STATES:'
177
+ output += " Slave_IO_Running=#{table['Slave_IO_Running']}"
178
+ output += ", Slave_SQL_Running=#{table['Slave_SQL_Running']}"
179
+ output += ", LAST ERROR: #{table['Last_SQL_Error']}"
180
+ critical output unless slave_running
181
+ replication_delay = table['Seconds_Behind_Master'].to_i
182
+ message = "replication delayed by #{replication_delay}"
183
+ if replication_delay > config[:warn].to_i && replication_delay <= config[:crit].to_i
184
+ warning message
185
+ elsif replication_delay >= config[:crit].to_i
186
+ critical message
187
+ else
188
+ ok "slave running: #{slave_running}, #{message}"
189
+ end
190
+ end
191
+ ok 'show slave status was nil. This server is not a slave.'
192
+ rescue StandardError => e
193
+ critical "Error message: status: #{status} | Exception: #{e}"
194
+ end
195
+ end
196
+
197
+ def run
198
+ db_user = credentials[0]
199
+ db_pass = credentials[1]
200
+ db_socket = credentials[2]
201
+ if config[:check] == 'status'
202
+ status_check(db_user, db_pass, db_socket)
203
+ end
204
+ if config[:check] == 'replication'
205
+ replication_check(db_user, db_pass, db_socket)
206
+ end
207
+ unknown 'No check type succeeded. Check your options'
208
+ end
209
+ end
@@ -0,0 +1,122 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # check-mysql-threads.rb
4
+ #
5
+ # DESCRIPTION:
6
+ # MySQL Threads Health plugin
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
12
+ #
13
+ # OUTPUT:
14
+ # plain text
15
+ #
16
+ # PLATFORMS:
17
+ # All
18
+ #
19
+ # DEPENDENCIES:
20
+ # gem: sensu-plugin
21
+ #
22
+ # USAGE:
23
+ # check-mysql-threads.rb -w [threshold] -c [threshold] -m [threshold] -l [threshold]
24
+ #
25
+ # NOTES:
26
+ #
27
+ # LICENSE:
28
+ # Author: Guillaume Lefranc <guillaume@mariadb.com>
29
+ # Released under the same terms as Sensu (the MIT license); see LICENSE
30
+ # for details.
31
+ #
32
+
33
+ require 'sensu-plugin/check/cli'
34
+ require 'mysql'
35
+ require 'inifile'
36
+
37
+ class CheckMySQLHealth < Sensu::Plugin::Check::CLI
38
+ option :user,
39
+ description: 'MySQL User',
40
+ short: '-u USER',
41
+ long: '--user USER',
42
+ default: 'root'
43
+
44
+ option :password,
45
+ description: 'MySQL Password',
46
+ short: '-p PASS',
47
+ long: '--password PASS'
48
+
49
+ option :ini,
50
+ description: 'My.cnf ini file',
51
+ short: '-i',
52
+ long: '--ini VALUE'
53
+
54
+ option :ini_section,
55
+ description: 'Section in my.cnf ini file',
56
+ long: '--ini-section VALUE',
57
+ default: 'client'
58
+
59
+ option :hostname,
60
+ description: 'Hostname to login to',
61
+ short: '-h HOST',
62
+ long: '--hostname HOST',
63
+ default: 'localhost'
64
+
65
+ option :port,
66
+ description: 'Port to connect to',
67
+ short: '-P PORT',
68
+ long: '--port PORT',
69
+ default: '3306'
70
+
71
+ option :socket,
72
+ description: 'Socket to use',
73
+ short: '-s SOCKET',
74
+ long: '--socket SOCKET'
75
+
76
+ option :maxwarn,
77
+ description: "Number of running threads upon which we'll issue a warning",
78
+ short: '-w NUMBER',
79
+ long: '--warnnum NUMBER',
80
+ default: 20
81
+
82
+ option :maxcrit,
83
+ description: "Number of running threads upon which we'll issue an alert",
84
+ short: '-c NUMBER',
85
+ long: '--critnum NUMBER',
86
+ default: 25
87
+
88
+ option :minwarn,
89
+ description: "Number of running threads under which we'll issue a warning",
90
+ short: '-m NUMBER',
91
+ long: '--warnlow NUMBER',
92
+ default: 1
93
+
94
+ option :mincrit,
95
+ description: "Number of running threads under which we'll issue an alert",
96
+ short: '-l NUMBER',
97
+ long: '--critlow NUMBER',
98
+ default: 0
99
+
100
+ def run
101
+ if config[:ini]
102
+ ini = IniFile.load(config[:ini])
103
+ section = ini[config[:ini_section]]
104
+ db_user = section['user']
105
+ db_pass = section['password']
106
+ else
107
+ db_user = config[:user]
108
+ db_pass = config[:password]
109
+ end
110
+ db = Mysql.real_connect(config[:hostname], db_user, db_pass, config[:database], config[:port].to_i, config[:socket])
111
+ run_thr = db.query("SHOW GLOBAL STATUS LIKE 'Threads_running'").fetch_hash.fetch('Value').to_i
112
+ critical "MySQL currently running threads: #{run_thr}" if run_thr >= config[:maxcrit].to_i
113
+ warning "MySQL currently running threads: #{run_thr}" if run_thr >= config[:maxwarn].to_i
114
+ critical "MySQL currently running threads: #{run_thr}" if run_thr <= config[:mincrit].to_i
115
+ warning "MySQL currently running threads: #{run_thr}" if run_thr <= config[:minwarn].to_i
116
+ ok "Currently running threads are under limit in MySQL: #{run_thr}"
117
+ rescue Mysql::Error => e
118
+ critical "MySQL check failed: #{e.error}"
119
+ ensure
120
+ db.close if db
121
+ end
122
+ end
@@ -0,0 +1,273 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Push mysql stats into graphite
4
+ # ===
5
+ #
6
+ # NOTE: This plugin will attempt to get replication stats but the user
7
+ # must have SUPER or REPLICATION CLIENT privileges to run 'SHOW SLAVE
8
+ # STATUS'. It will silently ignore and continue if 'SHOW SLAVE STATUS'
9
+ # fails for any reason. The key 'slaveLag' will not be present in the
10
+ # output.
11
+ #
12
+ # Copyright 2012 Pete Shima <me@peteshima.com>
13
+ # Additional hacks by Joe Miller - https://github.com/joemiller
14
+ # Updated by Oluwaseun Obajobi 2014 to accept ini argument
15
+ #
16
+ # Released under the same terms as Sensu (the MIT license); see LICENSE
17
+ # for details.
18
+ #
19
+ # USING INI ARGUMENT
20
+ # This was implemented to load mysql credentials without parsing the username/password.
21
+ # The ini file should be readable by the sensu user/group.
22
+ # Ref: http://eric.lubow.org/2009/ruby/parsing-ini-files-with-ruby/
23
+ #
24
+ # EXAMPLE
25
+ # mysql-alive.rb -h db01 --ini '/etc/sensu/my.cnf'
26
+ # mysql-alive.rb -h db01 --ini '/etc/sensu/my.cnf' --ini-section customsection
27
+ #
28
+ # MY.CNF INI FORMAT
29
+ # [client]
30
+ # user=sensu
31
+ # password="abcd1234"
32
+ #
33
+ # [customsection]
34
+ # user=user
35
+ # password="password"
36
+ #
37
+
38
+ require 'sensu-plugin/metric/cli'
39
+ require 'mysql'
40
+ require 'socket'
41
+ require 'inifile'
42
+
43
+ class MysqlGraphite < Sensu::Plugin::Metric::CLI::Graphite
44
+ option :host,
45
+ short: '-h HOST',
46
+ long: '--host HOST',
47
+ description: 'Mysql Host to connect to',
48
+ required: true
49
+
50
+ option :port,
51
+ short: '-P PORT',
52
+ long: '--port PORT',
53
+ description: 'Mysql Port to connect to',
54
+ proc: proc(&:to_i),
55
+ default: 3306
56
+
57
+ option :username,
58
+ short: '-u USERNAME',
59
+ long: '--user USERNAME',
60
+ description: 'Mysql Username'
61
+
62
+ option :password,
63
+ short: '-p PASSWORD',
64
+ long: '--pass PASSWORD',
65
+ description: 'Mysql password',
66
+ default: ''
67
+
68
+ option :ini,
69
+ short: '-i',
70
+ long: '--ini VALUE',
71
+ description: 'My.cnf ini file'
72
+
73
+ option :ini_section,
74
+ description: 'Section in my.cnf ini file',
75
+ long: '--ini-section VALUE',
76
+ default: 'client'
77
+
78
+ option :scheme,
79
+ description: 'Metric naming scheme, text to prepend to metric',
80
+ short: '-s SCHEME',
81
+ long: '--scheme SCHEME',
82
+ default: "#{Socket.gethostname}.mysql"
83
+
84
+ option :socket,
85
+ short: '-S SOCKET',
86
+ long: '--socket SOCKET'
87
+
88
+ option :verbose,
89
+ short: '-v',
90
+ long: '--verbose',
91
+ boolean: true
92
+
93
+ def metrics_hash
94
+ {
95
+ 'general' => {
96
+ 'Bytes_received' => 'rxBytes',
97
+ 'Bytes_sent' => 'txBytes',
98
+ 'Key_read_requests' => 'keyRead_requests',
99
+ 'Key_reads' => 'keyReads',
100
+ 'Key_write_requests' => 'keyWrite_requests',
101
+ 'Key_writes' => 'keyWrites',
102
+ 'Binlog_cache_use' => 'binlogCacheUse',
103
+ 'Binlog_cache_disk_use' => 'binlogCacheDiskUse',
104
+ 'Max_used_connections' => 'maxUsedConnections',
105
+ 'Aborted_clients' => 'abortedClients',
106
+ 'Aborted_connects' => 'abortedConnects',
107
+ 'Threads_connected' => 'threadsConnected',
108
+ 'Open_files' => 'openFiles',
109
+ 'Open_tables' => 'openTables',
110
+ 'Opened_tables' => 'openedTables',
111
+ 'Prepared_stmt_count' => 'preparedStmtCount',
112
+ 'Seconds_Behind_Master' => 'slaveLag',
113
+ 'Select_full_join' => 'fullJoins',
114
+ 'Select_full_range_join' => 'fullRangeJoins',
115
+ 'Select_range' => 'selectRange',
116
+ 'Select_range_check' => 'selectRange_check',
117
+ 'Select_scan' => 'selectScan',
118
+ 'Slow_queries' => 'slowQueries',
119
+ },
120
+ 'querycache' => {
121
+ 'Qcache_queries_in_cache' => 'queriesInCache',
122
+ 'Qcache_hits' => 'cacheHits',
123
+ 'Qcache_inserts' => 'inserts',
124
+ 'Qcache_not_cached' => 'notCached',
125
+ 'Qcache_lowmem_prunes' => 'lowMemPrunes',
126
+ },
127
+ 'commands' => {
128
+ 'Com_admin_commands' => 'admin_commands',
129
+ 'Com_begin' => 'begin',
130
+ 'Com_change_db' => 'change_db',
131
+ 'Com_commit' => 'commit',
132
+ 'Com_create_table' => 'create_table',
133
+ 'Com_drop_table' => 'drop_table',
134
+ 'Com_show_keys' => 'show_keys',
135
+ 'Com_delete' => 'delete',
136
+ 'Com_create_db' => 'create_db',
137
+ 'Com_grant' => 'grant',
138
+ 'Com_show_processlist' => 'show_processlist',
139
+ 'Com_flush' => 'flush',
140
+ 'Com_insert' => 'insert',
141
+ 'Com_purge' => 'purge',
142
+ 'Com_replace' => 'replace',
143
+ 'Com_rollback' => 'rollback',
144
+ 'Com_select' => 'select',
145
+ 'Com_set_option' => 'set_option',
146
+ 'Com_show_binlogs' => 'show_binlogs',
147
+ 'Com_show_databases' => 'show_databases',
148
+ 'Com_show_fields' => 'show_fields',
149
+ 'Com_show_status' => 'show_status',
150
+ 'Com_show_tables' => 'show_tables',
151
+ 'Com_show_variables' => 'show_variables',
152
+ 'Com_update' => 'update',
153
+ 'Com_drop_db' => 'drop_db',
154
+ 'Com_revoke' => 'revoke',
155
+ 'Com_drop_user' => 'drop_user',
156
+ 'Com_show_grants' => 'show_grants',
157
+ 'Com_lock_tables' => 'lock_tables',
158
+ 'Com_show_create_table' => 'show_create_table',
159
+ 'Com_unlock_tables' => 'unlock_tables',
160
+ 'Com_alter_table' => 'alter_table',
161
+ },
162
+ 'counters' => {
163
+ 'Handler_write' => 'handlerWrite',
164
+ 'Handler_update' => 'handlerUpdate',
165
+ 'Handler_delete' => 'handlerDelete',
166
+ 'Handler_read_first' => 'handlerRead_first',
167
+ 'Handler_read_key' => 'handlerRead_key',
168
+ 'Handler_read_next' => 'handlerRead_next',
169
+ 'Handler_read_prev' => 'handlerRead_prev',
170
+ 'Handler_read_rnd' => 'handlerRead_rnd',
171
+ 'Handler_read_rnd_next' => 'handlerRead_rnd_next',
172
+ 'Handler_commit' => 'handlerCommit',
173
+ 'Handler_rollback' => 'handlerRollback',
174
+ 'Handler_savepoint' => 'handlerSavepoint',
175
+ 'Handler_savepoint_rollback' => 'handlerSavepointRollback',
176
+ },
177
+ 'innodb' => {
178
+ 'Innodb_buffer_pool_pages_total' => 'bufferTotal_pages',
179
+ 'Innodb_buffer_pool_pages_free' => 'bufferFree_pages',
180
+ 'Innodb_buffer_pool_pages_dirty' => 'bufferDirty_pages',
181
+ 'Innodb_buffer_pool_pages_data' => 'bufferUsed_pages',
182
+ 'Innodb_page_size' => 'pageSize',
183
+ 'Innodb_pages_created' => 'pagesCreated',
184
+ 'Innodb_pages_read' => 'pagesRead',
185
+ 'Innodb_pages_written' => 'pagesWritten',
186
+ 'Innodb_row_lock_current_waits' => 'currentLockWaits',
187
+ 'Innodb_row_lock_waits' => 'lockWaitTimes',
188
+ 'Innodb_row_lock_time' => 'rowLockTime',
189
+ 'Innodb_data_reads' => 'fileReads',
190
+ 'Innodb_data_writes' => 'fileWrites',
191
+ 'Innodb_data_fsyncs' => 'fileFsyncs',
192
+ 'Innodb_log_writes' => 'logWrites',
193
+ 'Innodb_rows_updated' => 'rowsUpdated',
194
+ 'Innodb_rows_read' => 'rowsRead',
195
+ 'Innodb_rows_deleted' => 'rowsDeleted',
196
+ 'Innodb_rows_inserted' => 'rowsInserted',
197
+ },
198
+ 'configuration' => {
199
+ 'max_connections' => 'MaxConnections',
200
+ 'Max_prepared_stmt_count' => 'MaxPreparedStmtCount',
201
+ },
202
+ }
203
+ end
204
+
205
+ def run
206
+ # props to https://github.com/coredump/hoardd/blob/master/scripts-available/mysql.coffee
207
+
208
+ metrics = metrics_hash
209
+
210
+ # FIXME: break this up
211
+ config[:host].split(' ').each do |mysql_host| # rubocop:disable Metrics/BlockLength
212
+ mysql_shorthostname = mysql_host.split('.')[0]
213
+ if config[:ini]
214
+ ini = IniFile.load(config[:ini])
215
+ section = ini[config[:ini_section]]
216
+ db_user = section['user']
217
+ db_pass = section['password']
218
+ else
219
+ db_user = config[:username]
220
+ db_pass = config[:password]
221
+ end
222
+ begin
223
+ mysql = Mysql.new(mysql_host, db_user, db_pass, nil, config[:port], config[:socket])
224
+
225
+ results = mysql.query('SHOW GLOBAL STATUS')
226
+ rescue StandardError => e
227
+ puts e.message
228
+ end
229
+
230
+ results.each_hash do |row|
231
+ metrics.each do |category, var_mapping|
232
+ if var_mapping.key?(row['Variable_name'])
233
+ output "#{config[:scheme]}.#{mysql_shorthostname}.#{category}.#{var_mapping[row['Variable_name']]}", row['Value']
234
+ end
235
+ end
236
+ end
237
+
238
+ begin
239
+ slave_results = mysql.query('SHOW SLAVE STATUS')
240
+ # should return a single element array containing one hash
241
+ # #YELLOW
242
+ slave_results.fetch_hash.each_pair do |key, value|
243
+ if metrics['general'].include?(key)
244
+ # Replication lag being null is bad, very bad, so negativate it here
245
+ value = -1 if key == 'Seconds_Behind_Master' && value.nil?
246
+ output "#{config[:scheme]}.#{mysql_shorthostname}.general.#{metrics['general'][key]}", value
247
+ end
248
+ end
249
+ rescue StandardError => e
250
+ puts "Error querying slave status: #{e}" if config[:verbose]
251
+ end
252
+
253
+ begin
254
+ variables_results = mysql.query('SHOW GLOBAL VARIABLES')
255
+
256
+ category = 'configuration'
257
+ variables_results.each_hash do |row|
258
+ metrics[category].each do |metric, desc|
259
+ if metric.casecmp(row['Variable_name']).zero?
260
+ output "#{config[:scheme]}.#{mysql_shorthostname}.#{category}.#{desc}", row['Value']
261
+ end
262
+ end
263
+ end
264
+ rescue StandardError => e
265
+ puts e.message
266
+ end
267
+
268
+ mysql.close if mysql
269
+ end
270
+
271
+ ok
272
+ end
273
+ end