Skip to content

Commit b94198c

Browse files
author
Jan Kunzmann
committed
Allow to collect multiple instances per host
(as inspired by https://github.com/powdahound/redis-collectd-plugin/blob/master/redis_info.py)
1 parent 09385e4 commit b94198c

File tree

2 files changed

+79
-41
lines changed

2 files changed

+79
-41
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,14 @@ You should then configure the MySQL plugin:
3232
Port 3306 (default: 3306)
3333
User "root" (default: root)
3434
Password "xxxx" (default: empty)
35+
Instance "" (default: empty instance identifier)
3536
HeartbeatTable "percona.heartbeat" (if using pt-heartbeat to track slave lag)
3637
Verbose false (default: false)
3738
</Module>
3839
</Plugin>
3940

41+
Repeat the "Module" section for multiple instances
42+
4043
## Metrics
4144

4245
### MySQL Status

mysql.py

Lines changed: 76 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
# all of the legacy compatibility, and favors metrics from SHOW GLOBAL STATUS
77
# as opposed to SHOW ENGINE INNODB STATUS where possible.
88
#
9-
# Configuration:
9+
# Configuration (repeat Module section for multiple instances):
1010
# Import mysql
1111
# <Module mysql>
1212
# Host localhost
@@ -29,16 +29,13 @@
2929
import collectd
3030
import re
3131
import MySQLdb
32+
import copy
3233

33-
MYSQL_CONFIG = {
34-
'Host': 'localhost',
35-
'Port': 3306,
36-
'User': 'root',
37-
'Password': '',
38-
'HeartbeatTable': '',
39-
'Verbose': False,
40-
'Instance': '',
41-
}
34+
35+
# Verbose logging on/off. Override in config by specifying 'Verbose'.
36+
VERBOSE_LOGGING = False
37+
38+
CONFIGS = []
4239

4340
MYSQL_STATUS_VARS = {
4441
'Aborted_clients': 'counter',
@@ -303,12 +300,12 @@
303300
},
304301
}
305302

306-
def get_mysql_conn():
303+
def get_mysql_conn(conf):
307304
return MySQLdb.connect(
308-
host=MYSQL_CONFIG['Host'],
309-
port=MYSQL_CONFIG['Port'],
310-
user=MYSQL_CONFIG['User'],
311-
passwd=MYSQL_CONFIG['Password']
305+
host=conf['host'],
306+
port=conf['port'],
307+
user=conf['user'],
308+
passwd=conf['password']
312309
)
313310

314311
def mysql_query(conn, query):
@@ -350,7 +347,7 @@ def fetch_mysql_master_stats(conn):
350347

351348
return stats
352349

353-
def fetch_mysql_slave_stats(conn):
350+
def fetch_mysql_slave_stats(conf, conn):
354351
result = mysql_query(conn, 'SHOW SLAVE STATUS')
355352
slave_row = result.fetchone()
356353
if slave_row is None:
@@ -362,12 +359,12 @@ def fetch_mysql_slave_stats(conn):
362359
'slave_lag': slave_row['Seconds_Behind_Master'] if slave_row['Seconds_Behind_Master'] != None else 0,
363360
}
364361

365-
if MYSQL_CONFIG['HeartbeatTable']:
362+
if conf['heartbeattable']:
366363
query = """
367364
SELECT MAX(UNIX_TIMESTAMP() - UNIX_TIMESTAMP(ts)) AS delay
368365
FROM %s
369366
WHERE server_id = %s
370-
""" % (MYSQL_CONFIG['HeartbeatTable'], slave_row['Master_Server_Id'])
367+
""" % (conf['heartbeattable'], slave_row['Master_Server_Id'])
371368
result = mysql_query(conn, query)
372369
row = result.fetchone()
373370
if 'delay' in row and row['delay'] != None:
@@ -471,11 +468,10 @@ def fetch_innodb_stats(conn):
471468
return stats
472469

473470
def log_verbose(msg):
474-
if MYSQL_CONFIG['Verbose'] == False:
475-
return
476-
collectd.info('mysql plugin: %s' % msg)
471+
if VERBOSE_LOGGING:
472+
collectd.info('mysql plugin: %s' % msg)
477473

478-
def dispatch_value(prefix, key, value, type, type_instance=None):
474+
def dispatch_value(instance, prefix, key, value, type, type_instance=None):
479475
if not type_instance:
480476
type_instance = key
481477

@@ -484,26 +480,61 @@ def dispatch_value(prefix, key, value, type, type_instance=None):
484480
return
485481
value = int(value) # safety check
486482

487-
val = collectd.Values(plugin='mysql', plugin_instance=prefix)
488-
val.plugin = 'mysql.%s' % MYSQL_CONFIG['Instance']
489-
val.plugin_instance = prefix
483+
if instance is None:
484+
plugin = 'mysql'
485+
else:
486+
plugin = 'mysql.%s' % instance
487+
val = collectd.Values(plugin=plugin, plugin_instance=prefix)
490488
val.type = type
491489
val.type_instance = type_instance
492490
val.values = [value]
493491
val.dispatch()
494492

495493
def configure_callback(conf):
496-
global MYSQL_CONFIG
494+
instance = None
495+
host = 'localhost'
496+
port = 3306
497+
user = 'root'
498+
password = ''
499+
heartbeattable = ''
500+
verbose = False
501+
497502
for node in conf.children:
498-
if node.key in MYSQL_CONFIG:
499-
MYSQL_CONFIG[node.key] = node.values[0]
503+
key = node.key.lower()
504+
val = node.values[0]
505+
if key == 'instance':
506+
instance = val
507+
elif key == 'host':
508+
host = val
509+
elif key == 'port':
510+
port = int(val)
511+
elif key == 'user':
512+
user = val
513+
elif key == 'password':
514+
password = val
515+
elif key == 'heartbeattable':
516+
heartbeattable = val
517+
elif key == 'verbose':
518+
global VERBOSE_LOGGING
519+
VERBOSE_LOGGING = bool(val) or VERBOSE_LOGGING
520+
else:
521+
collectd.warning('mysql plugin: Unknown config key: %s.' % key)
500522

501-
MYSQL_CONFIG['Port'] = int(MYSQL_CONFIG['Port'])
502-
MYSQL_CONFIG['Verbose'] = bool(MYSQL_CONFIG['Verbose'])
523+
log_verbose('Configured with host=%s, port=%s, instance name=%s, user=%s' % ( host, port, instance, user))
503524

504-
def read_callback():
525+
mysql_config = {
526+
'instance': instance,
527+
'host': host,
528+
'port': port,
529+
'user': user,
530+
'password': password,
531+
'heartbeattable': heartbeattable
532+
}
533+
CONFIGS.append(mysql_config)
534+
535+
def get_metrics(conf):
505536
global MYSQL_STATUS_VARS
506-
conn = get_mysql_conn()
537+
conn = get_mysql_conn(conf)
507538

508539
mysql_status = fetch_mysql_status(conn)
509540
for key in mysql_status:
@@ -519,33 +550,37 @@ def read_callback():
519550
else:
520551
continue
521552

522-
dispatch_value('status', key, mysql_status[key], ds_type)
553+
dispatch_value(conf['instance'], 'status', key, mysql_status[key], ds_type)
523554

524555
mysql_variables = fetch_mysql_variables(conn)
525556
for key in mysql_variables:
526-
dispatch_value('variables', key, mysql_variables[key], 'gauge')
557+
dispatch_value(conf['instance'], 'variables', key, mysql_variables[key], 'gauge')
527558

528559
mysql_master_status = fetch_mysql_master_stats(conn)
529560
for key in mysql_master_status:
530-
dispatch_value('master', key, mysql_master_status[key], 'gauge')
561+
dispatch_value(conf['instance'], 'master', key, mysql_master_status[key], 'gauge')
531562

532563
mysql_states = fetch_mysql_process_states(conn)
533564
for key in mysql_states:
534-
dispatch_value('state', key, mysql_states[key], 'gauge')
565+
dispatch_value(conf['instance'], 'state', key, mysql_states[key], 'gauge')
535566

536-
slave_status = fetch_mysql_slave_stats(conn)
567+
slave_status = fetch_mysql_slave_stats(conf, conn)
537568
for key in slave_status:
538-
dispatch_value('slave', key, slave_status[key], 'gauge')
569+
dispatch_value(conf['instance'], 'slave', key, slave_status[key], 'gauge')
539570

540571
response_times = fetch_mysql_response_times(conn)
541572
for key in response_times:
542-
dispatch_value('response_time_total', str(key), response_times[key]['total'], 'counter')
543-
dispatch_value('response_time_count', str(key), response_times[key]['count'], 'counter')
573+
dispatch_value(conf['instance'], 'response_time_total', str(key), response_times[key]['total'], 'counter')
574+
dispatch_value(conf['instance'], 'response_time_count', str(key), response_times[key]['count'], 'counter')
544575

545576
innodb_status = fetch_innodb_stats(conn)
546577
for key in MYSQL_INNODB_STATUS_VARS:
547578
if key not in innodb_status: continue
548-
dispatch_value('innodb', key, innodb_status[key], MYSQL_INNODB_STATUS_VARS[key])
579+
dispatch_value(conf['instance'], 'innodb', key, innodb_status[key], MYSQL_INNODB_STATUS_VARS[key])
580+
581+
def read_callback():
582+
for conf in CONFIGS:
583+
get_metrics(conf)
549584

550585
collectd.register_read(read_callback)
551586
collectd.register_config(configure_callback)

0 commit comments

Comments
 (0)