sensu-plugins-mysql-boutetnico 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,110 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # MySQL Select Count Metrics
4
+ #
5
+ # Creates a graphite-formatted metrics for the first values of a result set from MySQL queries
6
+ # defined as a JSON parameter.
7
+ #
8
+ # Copyright 2017 Andrew Thal <athal7@me.com>
9
+ # Copyright 2018 Tibor Nagy <nagyt@hu.inter.net>
10
+ #
11
+ # Released under the same terms as Sensu (the MIT license); see LICENSE
12
+ # for details.
13
+
14
+ require 'sensu-plugin/metric/cli'
15
+ require 'mysql'
16
+ require 'inifile'
17
+ require 'json'
18
+
19
+ class MysqlQueryCountMetric < Sensu::Plugin::Metric::CLI::Graphite
20
+ option :host,
21
+ short: '-h HOST',
22
+ long: '--host HOST',
23
+ description: 'MySQL Host to connect to',
24
+ required: true
25
+
26
+ option :port,
27
+ short: '-P PORT',
28
+ long: '--port PORT',
29
+ description: 'MySQL Port to connect to',
30
+ proc: proc(&:to_i),
31
+ default: 3306
32
+
33
+ option :username,
34
+ short: '-u USERNAME',
35
+ long: '--user USERNAME',
36
+ description: 'MySQL Username'
37
+
38
+ option :password,
39
+ short: '-p PASSWORD',
40
+ long: '--pass PASSWORD',
41
+ description: 'MySQL password'
42
+
43
+ option :database,
44
+ short: '-d DATABASE',
45
+ long: '--database DATABASE',
46
+ description: 'MySQL database',
47
+ default: ''
48
+
49
+ option :ini,
50
+ short: '-i',
51
+ long: '--ini VALUE',
52
+ description: 'My.cnf ini file'
53
+
54
+ option :ini_section,
55
+ description: 'Section in my.cnf ini file',
56
+ long: '--ini-section VALUE',
57
+ default: 'client'
58
+
59
+ option :socket,
60
+ short: '-S SOCKET',
61
+ long: '--socket SOCKET',
62
+ description: 'MySQL Unix socket to connect to'
63
+
64
+ option :name,
65
+ short: '-n NAME',
66
+ long: '--name NAME',
67
+ description: 'Metric name for a configured handler',
68
+ default: 'mysql.query_count'
69
+
70
+ option :query,
71
+ short: '-q SELECT_COUNT_QUERIES',
72
+ long: '--query SELECT_COUNT_QUERIES',
73
+ description: 'Queries to execute in JSON',
74
+ required: true
75
+
76
+ def run
77
+ if config[:ini]
78
+ ini = IniFile.load(config[:ini])
79
+ section = ini[config[:ini_section]]
80
+ db_user = section['user']
81
+ db_pass = section['password']
82
+ else
83
+ db_user = config[:username]
84
+ db_pass = config[:password]
85
+ end
86
+
87
+ begin
88
+ query_hash = ::JSON.parse config[:query]
89
+ rescue ::JSON::ParserError => e
90
+ critical "JSON.parse error: #{e}"
91
+ end
92
+
93
+ # traverse all SQL
94
+ query_hash.each do |key, sql|
95
+ raise "invalid query : #{sql}" unless sql =~ /^select\s+count\(\s*\*\s*\)/i
96
+
97
+ db = Mysql.real_connect(config[:host], db_user, db_pass, config[:database], config[:port], config[:socket])
98
+ count = db.query(sql).fetch_row[0].to_i
99
+
100
+ output "#{config[:name]}.#{key}", count
101
+ end
102
+
103
+ ok
104
+ rescue Mysql::Error => e
105
+ errstr = "Error code: #{e.errno} Error message: #{e.error}"
106
+ critical "#{errstr} SQLSTATE: #{e.sqlstate}" if e.respond_to?('sqlstate')
107
+ rescue StandardError => e
108
+ critical "unhandled exception: #{e}"
109
+ end
110
+ end
@@ -0,0 +1,149 @@
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
+ # mysql-alive.rb -h db01 --ini '/etc/sensu/my.cnf' --ini-section customsection
29
+ #
30
+ # MY.CNF INI FORMAT
31
+ # [client]
32
+ # user=sensu
33
+ # password="abcd1234"
34
+ #
35
+ # [customsection]
36
+ # user=user
37
+ # password="password"
38
+ #
39
+ # NOTES:
40
+ #
41
+ # LICENSE:
42
+ # Jonathan Ballet <jballet@edgelab.ch>
43
+ # Released under the same terms as Sensu (the MIT license); see LICENSE
44
+ # for details.
45
+
46
+ require 'sensu-plugin/metric/cli'
47
+ require 'mysql'
48
+ require 'socket'
49
+ require 'inifile'
50
+
51
+ class MetricsMySQLProcesses < Sensu::Plugin::Metric::CLI::Graphite
52
+ option :host,
53
+ short: '-h HOST',
54
+ long: '--host HOST',
55
+ description: 'MySQL Host to connect to',
56
+ required: true
57
+
58
+ option :port,
59
+ short: '-P PORT',
60
+ long: '--port PORT',
61
+ description: 'MySQL Port to connect to',
62
+ proc: proc(&:to_i),
63
+ default: 3306
64
+
65
+ option :username,
66
+ short: '-u USERNAME',
67
+ long: '--user USERNAME',
68
+ description: 'MySQL Username'
69
+
70
+ option :password,
71
+ short: '-p PASSWORD',
72
+ long: '--pass PASSWORD',
73
+ description: 'MySQL password',
74
+ default: ''
75
+
76
+ option :ini,
77
+ short: '-i',
78
+ long: '--ini VALUE',
79
+ description: 'My.cnf ini file'
80
+
81
+ option :ini_section,
82
+ description: 'Section in my.cnf ini file',
83
+ long: '--ini-section VALUE',
84
+ default: 'client'
85
+
86
+ option :scheme,
87
+ description: 'Metric naming scheme, text to prepend to metric',
88
+ short: '-s SCHEME',
89
+ long: '--scheme SCHEME',
90
+ default: "#{Socket.gethostname}.mysql"
91
+
92
+ option :socket,
93
+ short: '-S SOCKET',
94
+ long: '--socket SOCKET',
95
+ description: 'MySQL Unix socket to connect to'
96
+
97
+ def set_default_metrics
98
+ {
99
+ 'user' => {},
100
+ 'database' => {},
101
+ 'command' => {},
102
+ }.each_value { |value| value.default = 0 }
103
+ end
104
+
105
+ def db_connection_creds
106
+ if config[:ini]
107
+ ini = IniFile.load(config[:ini])
108
+ section = ini[config[:ini_section]]
109
+ db_user = section['user']
110
+ db_pass = section['password']
111
+ else
112
+ db_user = config[:username]
113
+ db_pass = config[:password]
114
+ end
115
+ [db_user, db_pass]
116
+ end
117
+
118
+ def run
119
+ config[:host].split(' ').each do |mysql_host|
120
+ mysql_shorthostname = mysql_host.split('.')[0]
121
+ db_user, db_pass = db_connection_creds
122
+ begin
123
+ mysql = Mysql.new(mysql_host, db_user, db_pass, nil, config[:port], config[:socket])
124
+
125
+ results = mysql.query('SHOW PROCESSLIST')
126
+ rescue StandardError => e
127
+ unknown "Unable to query MySQL: #{e.message}"
128
+ end
129
+
130
+ metrics = set_default_metrics
131
+
132
+ results.each_hash do |row|
133
+ metrics['user'][row['User']] += 1
134
+ if row['db'] # If no database has been selected by the process, it is set to nil.
135
+ metrics['database'][row['db']] += 1
136
+ end
137
+ metrics['command'][row['Command']] += 1
138
+ end
139
+
140
+ metrics.each do |key, value|
141
+ value.each do |instance, count|
142
+ output "#{config[:scheme]}.#{mysql_shorthostname}.#{key}.#{instance}", count
143
+ end
144
+ end
145
+ end
146
+
147
+ ok
148
+ end
149
+ end
@@ -0,0 +1,97 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # MySQL Query Result Count Metric
4
+ #
5
+ # Creates a graphite-formatted metric for the length of a result set from a MySQL query.
6
+ #
7
+ # Copyright 2017 Andrew Thal <athal7@me.com>
8
+ #
9
+ # Released under the same terms as Sensu (the MIT license); see LICENSE
10
+ # for details.
11
+
12
+ require 'sensu-plugin/metric/cli'
13
+ require 'mysql'
14
+ require 'inifile'
15
+
16
+ class MysqlQueryCountMetric < Sensu::Plugin::Metric::CLI::Graphite
17
+ option :host,
18
+ short: '-h HOST',
19
+ long: '--host HOST',
20
+ description: 'MySQL Host to connect to',
21
+ required: true
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
+ default: ''
40
+
41
+ option :database,
42
+ short: '-d DATABASE',
43
+ long: '--database DATABASE',
44
+ description: 'MySQL database',
45
+ default: ''
46
+
47
+ option :ini,
48
+ short: '-i',
49
+ long: '--ini VALUE',
50
+ description: 'My.cnf ini file'
51
+
52
+ option :ini_section,
53
+ description: 'Section in my.cnf ini file',
54
+ long: '--ini-section VALUE',
55
+ default: 'client'
56
+
57
+ option :socket,
58
+ short: '-S SOCKET',
59
+ long: '--socket SOCKET',
60
+ description: 'MySQL Unix socket to connect to'
61
+
62
+ option :name,
63
+ short: '-n NAME',
64
+ long: '--name NAME',
65
+ description: 'Metric name for a configured handler',
66
+ default: 'mysql.query_count'
67
+
68
+ option :query,
69
+ short: '-q QUERY',
70
+ long: '--query QUERY',
71
+ description: 'Query to execute',
72
+ required: true
73
+
74
+ def run
75
+ if config[:ini]
76
+ ini = IniFile.load(config[:ini])
77
+ section = ini[config[:ini_section]]
78
+ db_user = section['user']
79
+ db_pass = section['password']
80
+ else
81
+ db_user = config[:username]
82
+ db_pass = config[:password]
83
+ end
84
+ db = Mysql.real_connect(config[:host], db_user, db_pass, config[:database], config[:port].to_i, config[:socket])
85
+ length = db.query(config[:query]).count
86
+
87
+ output config[:name], length
88
+ ok
89
+ rescue Mysql::Error => e
90
+ errstr = "Error code: #{e.errno} Error message: #{e.error}"
91
+ critical "#{errstr} SQLSTATE: #{e.sqlstate}" if e.respond_to?('sqlstate')
92
+ rescue StandardError => e
93
+ critical e
94
+ ensure
95
+ db.close if db
96
+ end
97
+ end
@@ -0,0 +1,397 @@
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
+ # metrics-mysql-raw.rb -h localhost --ini '/etc/sensu/my.cnf' --ini-section customsection
20
+ #
21
+ # MY.CNF INI FORMAT
22
+ # [client]
23
+ # user=sensu
24
+ # password="abcd1234"
25
+ # socket="/var/lib/mysql/mysql.sock"
26
+ #
27
+ # [customsection]
28
+ # user=user
29
+ # password="password"
30
+ #
31
+ # LICENSE:
32
+ # Copyright 2012 Pete Shima <me@peteshima.com>
33
+ # Additional hacks by Joe Miller - https://github.com/joemiller
34
+ # Updated by Oluwaseun Obajobi 2014 to accept ini argument
35
+ # Forked by Magic Online 11.2016 to not depend on mysql gem
36
+ # - www.magic.fr <hanynowsky@gmail.com>
37
+ # MIT - Same as Sensu License
38
+ #
39
+
40
+ require 'sensu-plugin/metric/cli'
41
+ require 'open3'
42
+ require 'socket'
43
+ require 'inifile'
44
+ require 'timeout'
45
+
46
+ #
47
+ # Metrics Mysql Raw
48
+ #
49
+ class MetricsMySQLRaw < Sensu::Plugin::Metric::CLI::Graphite
50
+ option(
51
+ :user,
52
+ description: 'MySQL User',
53
+ short: '-u USER',
54
+ long: '--user USER',
55
+ default: 'mosim'
56
+ )
57
+
58
+ option(
59
+ :password,
60
+ description: 'MySQL Password',
61
+ short: '-p PASS',
62
+ long: '--password PASS',
63
+ default: 'mysqlPassWord'
64
+ )
65
+
66
+ option(
67
+ :ini,
68
+ description: 'My.cnf ini file',
69
+ short: '-i',
70
+ long: '--ini VALUE'
71
+ )
72
+
73
+ option(
74
+ :ini_section,
75
+ description: 'Section in my.cnf ini file',
76
+ long: '--ini-section VALUE',
77
+ default: 'client'
78
+ )
79
+
80
+ option(
81
+ :hostname,
82
+ description: 'Hostname to login to',
83
+ short: '-h HOST',
84
+ long: '--hostname HOST',
85
+ default: 'localhost'
86
+ )
87
+
88
+ option(
89
+ :database,
90
+ description: 'Database schema to connect to. NOT YET IMPlemented',
91
+ short: '-d DATABASE',
92
+ long: '--database DATABASE',
93
+ default: 'test'
94
+ )
95
+
96
+ option(
97
+ :timeout,
98
+ description: 'Timeout',
99
+ short: '-T TIMEOUT',
100
+ long: '--timeout TIMEOUT',
101
+ default: 10
102
+ )
103
+
104
+ option(
105
+ :port,
106
+ description: 'Port to connect to',
107
+ short: '-P PORT',
108
+ long: '--port PORT',
109
+ default: '3306'
110
+ )
111
+
112
+ option(
113
+ :socket,
114
+ description: 'Socket to use',
115
+ short: '-s SOCKET',
116
+ long: '--socket SOCKET',
117
+ default: '/var/run/mysqld/mysqld.sock'
118
+ )
119
+
120
+ option(
121
+ :binary,
122
+ description: 'Absolute path to mysql binary',
123
+ short: '-b BINARY',
124
+ long: '--binary BINARY',
125
+ default: 'mysql'
126
+ )
127
+
128
+ option(
129
+ :check,
130
+ description: 'type of check: metric',
131
+ short: '-c CHECK',
132
+ long: '--check CHECK',
133
+ default: 'metric'
134
+ )
135
+
136
+ option(
137
+ :scheme,
138
+ description: 'Metric naming scheme, text to prepend to metric',
139
+ short: '-s SCHEME',
140
+ long: '--scheme SCHEME',
141
+ default: "#{Socket.gethostname}.mysql"
142
+ )
143
+
144
+ option(
145
+ :verbose,
146
+ short: '-v',
147
+ long: '--verbose',
148
+ boolean: true
149
+ )
150
+
151
+ option(
152
+ :off,
153
+ description: 'Turn Metrics OFF',
154
+ long: '--off',
155
+ boolean: true,
156
+ default: false
157
+ )
158
+
159
+ # Metrics hash
160
+ def metrics_hash
161
+ metrics = {
162
+ 'general' => {
163
+ 'Bytes_received' => 'rxBytes',
164
+ 'Bytes_sent' => 'txBytes',
165
+ 'Key_read_requests' => 'keyRead_requests',
166
+ 'Key_reads' => 'keyReads',
167
+ 'Key_write_requests' => 'keyWrite_requests',
168
+ 'Key_writes' => 'keyWrites',
169
+ 'Binlog_cache_use' => 'binlogCacheUse',
170
+ 'Binlog_cache_disk_use' => 'binlogCacheDiskUse',
171
+ 'Max_used_connections' => 'maxUsedConnections',
172
+ 'Aborted_clients' => 'abortedClients',
173
+ 'Aborted_connects' => 'abortedConnects',
174
+ 'Threads_connected' => 'threadsConnected',
175
+ 'Open_files' => 'openFiles',
176
+ 'Open_tables' => 'openTables',
177
+ 'Opened_tables' => 'openedTables',
178
+ 'Prepared_stmt_count' => 'preparedStmtCount',
179
+ 'Seconds_Behind_Master' => 'slaveLag',
180
+ 'Select_full_join' => 'fullJoins',
181
+ 'Select_full_range_join' => 'fullRangeJoins',
182
+ 'Select_range' => 'selectRange',
183
+ 'Select_range_check' => 'selectRange_check',
184
+ 'Select_scan' => 'selectScan',
185
+ 'Slow_queries' => 'slowQueries',
186
+ },
187
+ 'querycache' => {
188
+ 'Qcache_queries_in_cache' => 'queriesInCache',
189
+ 'Qcache_hits' => 'cacheHits',
190
+ 'Qcache_inserts' => 'inserts',
191
+ 'Qcache_not_cached' => 'notCached',
192
+ 'Qcache_lowmem_prunes' => 'lowMemPrunes',
193
+ 'Qcache_free_memory' => 'freeMemory',
194
+ },
195
+ 'commands' => {
196
+ 'Com_admin_commands' => 'admin_commands',
197
+ 'Com_begin' => 'begin',
198
+ 'Com_change_db' => 'change_db',
199
+ 'Com_commit' => 'commit',
200
+ 'Com_create_table' => 'create_table',
201
+ 'Com_drop_table' => 'drop_table',
202
+ 'Com_show_keys' => 'show_keys',
203
+ 'Com_delete' => 'delete',
204
+ 'Com_create_db' => 'create_db',
205
+ 'Com_grant' => 'grant',
206
+ 'Com_show_processlist' => 'show_processlist',
207
+ 'Com_flush' => 'flush',
208
+ 'Com_insert' => 'insert',
209
+ 'Com_purge' => 'purge',
210
+ 'Com_replace' => 'replace',
211
+ 'Com_rollback' => 'rollback',
212
+ 'Com_select' => 'select',
213
+ 'Com_set_option' => 'set_option',
214
+ 'Com_show_binlogs' => 'show_binlogs',
215
+ 'Com_show_databases' => 'show_databases',
216
+ 'Com_show_fields' => 'show_fields',
217
+ 'Com_show_status' => 'show_status',
218
+ 'Com_show_tables' => 'show_tables',
219
+ 'Com_show_variables' => 'show_variables',
220
+ 'Com_update' => 'update',
221
+ 'Com_drop_db' => 'drop_db',
222
+ 'Com_revoke' => 'revoke',
223
+ 'Com_drop_user' => 'drop_user',
224
+ 'Com_show_grants' => 'show_grants',
225
+ 'Com_lock_tables' => 'lock_tables',
226
+ 'Com_show_create_table' => 'show_create_table',
227
+ 'Com_unlock_tables' => 'unlock_tables',
228
+ 'Com_alter_table' => 'alter_table',
229
+ },
230
+ 'counters' => {
231
+ 'Handler_write' => 'handlerWrite',
232
+ 'Handler_update' => 'handlerUpdate',
233
+ 'Handler_delete' => 'handlerDelete',
234
+ 'Handler_read_first' => 'handlerRead_first',
235
+ 'Handler_read_key' => 'handlerRead_key',
236
+ 'Handler_read_next' => 'handlerRead_next',
237
+ 'Handler_read_prev' => 'handlerRead_prev',
238
+ 'Handler_read_rnd' => 'handlerRead_rnd',
239
+ 'Handler_read_rnd_next' => 'handlerRead_rnd_next',
240
+ 'Handler_commit' => 'handlerCommit',
241
+ 'Handler_rollback' => 'handlerRollback',
242
+ 'Handler_savepoint' => 'handlerSavepoint',
243
+ 'Handler_savepoint_rollback' => 'handlerSavepointRollback',
244
+ },
245
+ 'innodb' => {
246
+ 'Innodb_buffer_pool_pages_total' => 'bufferTotal_pages',
247
+ 'Innodb_buffer_pool_pages_free' => 'bufferFree_pages',
248
+ 'Innodb_buffer_pool_pages_dirty' => 'bufferDirty_pages',
249
+ 'Innodb_buffer_pool_pages_data' => 'bufferUsed_pages',
250
+ 'Innodb_page_size' => 'pageSize',
251
+ 'Innodb_pages_created' => 'pagesCreated',
252
+ 'Innodb_pages_read' => 'pagesRead',
253
+ 'Innodb_pages_written' => 'pagesWritten',
254
+ 'Innodb_row_lock_current_waits' => 'currentLockWaits',
255
+ 'Innodb_row_lock_waits' => 'lockWaitTimes',
256
+ 'Innodb_row_lock_time' => 'rowLockTime',
257
+ 'Innodb_data_reads' => 'fileReads',
258
+ 'Innodb_data_writes' => 'fileWrites',
259
+ 'Innodb_data_fsyncs' => 'fileFsyncs',
260
+ 'Innodb_log_writes' => 'logWrites',
261
+ 'Innodb_rows_updated' => 'rowsUpdated',
262
+ 'Innodb_rows_read' => 'rowsRead',
263
+ 'Innodb_rows_deleted' => 'rowsDeleted',
264
+ 'Innodb_rows_inserted' => 'rowsInserted',
265
+ },
266
+ 'configuration' => {
267
+ 'Max_prepared_stmt_count' => 'MaxPreparedStmtCount',
268
+ },
269
+ }
270
+ metrics
271
+ end
272
+
273
+ # Credentials
274
+ def credentials
275
+ if config[:ini]
276
+ ini = IniFile.load(config[:ini])
277
+ section = ini[config[:ini_section]]
278
+ db_user = section['user']
279
+ db_pass = section['password']
280
+ db_socket = section['socket']
281
+ else
282
+ db_user = config[:user]
283
+ db_pass = config[:password]
284
+ db_socket = config[:socket]
285
+ end
286
+ [db_user, db_pass, db_socket]
287
+ end
288
+
289
+ # Slave metrics
290
+ def slave_metrics(metrics)
291
+ # should return a single element array containing one hash
292
+ # #YELLOW
293
+ mysql_shorthostname = config[:hostname].tr('.', '_')
294
+ slave_results = Hash['a' => 100, 'b' => 200]
295
+ slave_results.first.each do |key, value|
296
+ if metrics['general'].include?(key)
297
+ # Replication lag being null is bad, very bad, so negativate it here
298
+ value = -1 if key == 'Seconds_Behind_Master' && value.nil?
299
+ output "#{config[:scheme]}.#{mysql_shorthostname}.general.#{metrics['general'][key]}", value
300
+ end
301
+ end
302
+ rescue StandardError => e
303
+ puts "Error querying slave status: #{e}" if config[:verbose]
304
+ end
305
+
306
+ # Configuration metrics
307
+ def configuration_metrics(metrics, db_user, db_pass, db_socket)
308
+ mysql_shorthostname = config[:hostname].tr('.', '_')
309
+ table = []
310
+ cmd = "#{config[:binary]} -u #{db_user} -h #{config[:hostname]} \
311
+ --port #{config[:port]} --socket #{db_socket} -p\"#{db_pass.chomp}\" --batch \
312
+ --disable-column-names -e 'SHOW GLOBAL VARIABLES;'"
313
+ stdout, _stderr, status = Open3.capture3(cmd)
314
+ puts status.to_s.split(' ')[3] if config[:verbose]
315
+ if status == 0
316
+ puts status.to_s if config[:verbose]
317
+ stdout.split("\n").each do |row|
318
+ line = row.tr("\t", ':')
319
+ key = line.split(':')[0]
320
+ value = line.split(':')[1]
321
+ table.push('Variable_name' => key, 'Value' => value)
322
+ end
323
+ else
324
+ critical "Error message: Global variables - status: #{status}"
325
+ end
326
+ variables_results = table
327
+ category = 'configuration'
328
+ variables_results.each do |row|
329
+ metrics[category].each do |metric, desc|
330
+ if metric.casecmp(row['Variable_name']) == 0
331
+ output "#{config[:scheme]}.#{mysql_shorthostname}.#{category}.#{desc}", row['Value']
332
+ end
333
+ end
334
+ end
335
+ rescue StandardError => e
336
+ puts e.message
337
+ end
338
+
339
+ # Fetch MySQL metrics
340
+ def fetcher(db_user, db_pass, db_socket)
341
+ metrics = metrics_hash
342
+ # FIXME: this needs refactoring
343
+ if config[:check] == 'metric' # rubocop:disable Style/GuardClause
344
+ mysql_shorthostname = config[:hostname].tr('.', '_')
345
+ begin
346
+ table = []
347
+ cmd = "#{config[:binary]} -u #{db_user} -h #{config[:hostname]} \
348
+ --port #{config[:port]} --socket #{db_socket} -p\"#{db_pass.chomp}\" --batch \
349
+ --disable-column-names -e 'SHOW GLOBAL STATUS;'"
350
+ stdout, _stderr, status = Open3.capture3(cmd)
351
+ puts status.to_s.split(' ')[3] if config[:verbose]
352
+ if status == 0
353
+ puts status.to_s if config[:verbose]
354
+ stdout.split("\n").each do |row|
355
+ line = row.tr("\t", ':')
356
+ key = line.split(':')[0]
357
+ value = line.split(':')[1]
358
+ table.push('Variable_name' => key, 'Value' => value)
359
+ end
360
+ else
361
+ critical "Error message: status: #{status}"
362
+ end
363
+ table.each do |row|
364
+ metrics.each do |category, var_mapping|
365
+ row_var_name = row['Variable_name'].to_s
366
+ var_mapping.each_key do |vmkey|
367
+ if row_var_name.to_s == vmkey.to_s
368
+ prefix = "#{config[:scheme]}.#{mysql_shorthostname}.#{category}.#{vmkey[row_var_name]}"
369
+ output prefix, row['Value'] unless mysql_shorthostname.to_s.chomp.empty?
370
+ end
371
+ end
372
+ end
373
+ end
374
+ # Slave and configuration metrics here
375
+ slave_metrics(metrics)
376
+ configuration_metrics(metrics, db_user, db_pass, db_socket)
377
+ rescue StandardError => e
378
+ critical "Error message: status: #{status} | Exception: #{e.backtrace}"
379
+ ensure
380
+ ok ''
381
+ end
382
+ end
383
+ end
384
+
385
+ # Main Function
386
+ def run
387
+ ok 'Metrics deactivated by user using option --off' if config[:off] == true
388
+ begin
389
+ Timeout.timeout(config[:timeout]) do
390
+ fetcher(credentials[0], credentials[1], credentials[2])
391
+ end
392
+ rescue Timeout::Error => e
393
+ unknown "Timed out #{e.message}"
394
+ end
395
+ unknown 'Did not succeed to retrieve MySQL metrics. Check your options'
396
+ end
397
+ end