Skip to content

Commit 8ed9e33

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

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',
@@ -302,12 +299,12 @@
302299
},
303300
}
304301

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

313310
def mysql_query(conn, query):
@@ -349,7 +346,7 @@ def fetch_mysql_master_stats(conn):
349346

350347
return stats
351348

352-
def fetch_mysql_slave_stats(conn):
349+
def fetch_mysql_slave_stats(conf, conn):
353350
result = mysql_query(conn, 'SHOW SLAVE STATUS')
354351
slave_row = result.fetchone()
355352
if slave_row is None:
@@ -361,12 +358,12 @@ def fetch_mysql_slave_stats(conn):
361358
'slave_lag': slave_row['Seconds_Behind_Master'] if slave_row['Seconds_Behind_Master'] != None else 0,
362359
}
363360

364-
if MYSQL_CONFIG['HeartbeatTable']:
361+
if conf['heartbeattable']:
365362
query = """
366363
SELECT MAX(UNIX_TIMESTAMP() - UNIX_TIMESTAMP(ts)) AS delay
367364
FROM %s
368365
WHERE server_id = %s
369-
""" % (MYSQL_CONFIG['HeartbeatTable'], slave_row['Master_Server_Id'])
366+
""" % (conf['heartbeattable'], slave_row['Master_Server_Id'])
370367
result = mysql_query(conn, query)
371368
row = result.fetchone()
372369
if 'delay' in row and row['delay'] != None:
@@ -470,11 +467,10 @@ def fetch_innodb_stats(conn):
470467
return stats
471468

472469
def log_verbose(msg):
473-
if MYSQL_CONFIG['Verbose'] == False:
474-
return
475-
collectd.info('mysql plugin: %s' % msg)
470+
if VERBOSE_LOGGING:
471+
collectd.info('mysql plugin: %s' % msg)
476472

477-
def dispatch_value(prefix, key, value, type, type_instance=None):
473+
def dispatch_value(instance, prefix, key, value, type, type_instance=None):
478474
if not type_instance:
479475
type_instance = key
480476

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

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

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

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

503-
def read_callback():
524+
mysql_config = {
525+
'instance': instance,
526+
'host': host,
527+
'port': port,
528+
'user': user,
529+
'password': password,
530+
'heartbeattable': heartbeattable
531+
}
532+
CONFIGS.append(mysql_config)
533+
534+
def get_metrics(conf):
504535
global MYSQL_STATUS_VARS
505-
conn = get_mysql_conn()
536+
conn = get_mysql_conn(conf)
506537

507538
mysql_status = fetch_mysql_status(conn)
508539
for key in mysql_status:
@@ -518,33 +549,37 @@ def read_callback():
518549
else:
519550
continue
520551

521-
dispatch_value('status', key, mysql_status[key], ds_type)
552+
dispatch_value(conf['instance'], 'status', key, mysql_status[key], ds_type)
522553

523554
mysql_variables = fetch_mysql_variables(conn)
524555
for key in mysql_variables:
525-
dispatch_value('variables', key, mysql_variables[key], 'gauge')
556+
dispatch_value(conf['instance'], 'variables', key, mysql_variables[key], 'gauge')
526557

527558
mysql_master_status = fetch_mysql_master_stats(conn)
528559
for key in mysql_master_status:
529-
dispatch_value('master', key, mysql_master_status[key], 'gauge')
560+
dispatch_value(conf['instance'], 'master', key, mysql_master_status[key], 'gauge')
530561

531562
mysql_states = fetch_mysql_process_states(conn)
532563
for key in mysql_states:
533-
dispatch_value('state', key, mysql_states[key], 'gauge')
564+
dispatch_value(conf['instance'], 'state', key, mysql_states[key], 'gauge')
534565

535-
slave_status = fetch_mysql_slave_stats(conn)
566+
slave_status = fetch_mysql_slave_stats(conf, conn)
536567
for key in slave_status:
537-
dispatch_value('slave', key, slave_status[key], 'gauge')
568+
dispatch_value(conf['instance'], 'slave', key, slave_status[key], 'gauge')
538569

539570
response_times = fetch_mysql_response_times(conn)
540571
for key in response_times:
541-
dispatch_value('response_time_total', str(key), response_times[key]['total'], 'counter')
542-
dispatch_value('response_time_count', str(key), response_times[key]['count'], 'counter')
572+
dispatch_value(conf['instance'], 'response_time_total', str(key), response_times[key]['total'], 'counter')
573+
dispatch_value(conf['instance'], 'response_time_count', str(key), response_times[key]['count'], 'counter')
543574

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

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

0 commit comments

Comments
 (0)