Skip to content

Commit 1b593b2

Browse files
Jan KunzmannLeonhardt Wille
authored andcommitted
Allow to collect multiple instances per host
(as inspired by https://github.com/powdahound/redis-collectd-plugin/blob/master/redis_info.py)
1 parent c7ae565 commit 1b593b2

File tree

2 files changed

+89
-44
lines changed

2 files changed

+89
-44
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: 86 additions & 44 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
@@ -37,16 +37,13 @@
3737
COLLECTD_ENABLED=False
3838
import re
3939
import MySQLdb
40+
import copy
4041

41-
MYSQL_CONFIG = {
42-
'Host': 'localhost',
43-
'Port': 3306,
44-
'User': 'root',
45-
'Password': '',
46-
'HeartbeatTable': '',
47-
'Verbose': False,
48-
'Instance': '',
49-
}
42+
43+
# Verbose logging on/off. Override in config by specifying 'Verbose'.
44+
VERBOSE_LOGGING = False
45+
46+
CONFIGS = []
5047

5148
MYSQL_STATUS_VARS = {
5249
'Aborted_clients': 'counter',
@@ -311,12 +308,12 @@
311308
},
312309
}
313310

314-
def get_mysql_conn():
311+
def get_mysql_conn(conf):
315312
return MySQLdb.connect(
316-
host=MYSQL_CONFIG['Host'],
317-
port=MYSQL_CONFIG['Port'],
318-
user=MYSQL_CONFIG['User'],
319-
passwd=MYSQL_CONFIG['Password']
313+
host=conf['host'],
314+
port=conf['port'],
315+
user=conf['user'],
316+
passwd=conf['password']
320317
)
321318

322319
def mysql_query(conn, query):
@@ -358,7 +355,7 @@ def fetch_mysql_master_stats(conn):
358355

359356
return stats
360357

361-
def fetch_mysql_slave_stats(conn):
358+
def fetch_mysql_slave_stats(conf, conn):
362359
result = mysql_query(conn, 'SHOW SLAVE STATUS')
363360
slave_row = result.fetchone()
364361
if slave_row is None:
@@ -370,12 +367,12 @@ def fetch_mysql_slave_stats(conn):
370367
'slave_lag': slave_row['Seconds_Behind_Master'] if slave_row['Seconds_Behind_Master'] != None else 0,
371368
}
372369

373-
if MYSQL_CONFIG['HeartbeatTable']:
370+
if conf['heartbeattable']:
374371
query = """
375372
SELECT MAX(UNIX_TIMESTAMP() - UNIX_TIMESTAMP(ts)) AS delay
376373
FROM %s
377374
WHERE server_id = %s
378-
""" % (MYSQL_CONFIG['HeartbeatTable'], slave_row['Master_Server_Id'])
375+
""" % (conf['heartbeattable'], slave_row['Master_Server_Id'])
379376
result = mysql_query(conn, query)
380377
row = result.fetchone()
381378
if 'delay' in row and row['delay'] != None:
@@ -482,14 +479,14 @@ def fetch_innodb_stats(conn):
482479
return stats
483480

484481
def log_verbose(msg):
485-
if not MYSQL_CONFIG['Verbose']:
482+
if not VERBOSE_LOGGING:
486483
return
487484
if COLLECTD_ENABLED:
488485
collectd.info('mysql plugin: %s' % msg)
489486
else:
490487
print('mysql plugin: %s' % msg)
491488

492-
def dispatch_value(prefix, key, value, type, type_instance=None):
489+
def dispatch_value(instance, prefix, key, value, type, type_instance=None):
493490
if not type_instance:
494491
type_instance = key
495492

@@ -500,8 +497,12 @@ def dispatch_value(prefix, key, value, type, type_instance=None):
500497
if not COLLECTD_ENABLED:
501498
return
502499

500+
if instance is None:
501+
plugin = 'mysql'
502+
else:
503+
plugin = 'mysql.%s' % instance
503504
value = int(value) # safety check
504-
val = collectd.Values(plugin='mysql', plugin_instance=prefix)
505+
val = collectd.Values(plugin=plugin, plugin_instance=prefix)
505506
val.plugin = 'mysql.%s' % MYSQL_CONFIG['Instance']
506507
val.plugin_instance = prefix
507508
val.type = type
@@ -510,17 +511,50 @@ def dispatch_value(prefix, key, value, type, type_instance=None):
510511
val.dispatch()
511512

512513
def configure_callback(conf):
513-
global MYSQL_CONFIG
514+
instance = None
515+
host = 'localhost'
516+
port = 3306
517+
user = 'root'
518+
password = ''
519+
heartbeattable = ''
520+
verbose = False
521+
514522
for node in conf.children:
515-
if node.key in MYSQL_CONFIG:
516-
MYSQL_CONFIG[node.key] = node.values[0]
523+
key = node.key.lower()
524+
val = node.values[0]
525+
if key == 'instance':
526+
instance = val
527+
elif key == 'host':
528+
host = val
529+
elif key == 'port':
530+
port = int(val)
531+
elif key == 'user':
532+
user = val
533+
elif key == 'password':
534+
password = val
535+
elif key == 'heartbeattable':
536+
heartbeattable = val
537+
elif key == 'verbose':
538+
global VERBOSE_LOGGING
539+
VERBOSE_LOGGING = bool(val) or VERBOSE_LOGGING
540+
else:
541+
collectd.warning('mysql plugin: Unknown config key: %s.' % key)
517542

518-
MYSQL_CONFIG['Port'] = int(MYSQL_CONFIG['Port'])
519-
MYSQL_CONFIG['Verbose'] = bool(MYSQL_CONFIG['Verbose'])
543+
log_verbose('Configured with host=%s, port=%s, instance name=%s, user=%s' % ( host, port, instance, user))
520544

521-
def read_callback():
545+
mysql_config = {
546+
'instance': instance,
547+
'host': host,
548+
'port': port,
549+
'user': user,
550+
'password': password,
551+
'heartbeattable': heartbeattable
552+
}
553+
CONFIGS.append(mysql_config)
554+
555+
def get_metrics(conf):
522556
global MYSQL_STATUS_VARS
523-
conn = get_mysql_conn()
557+
conn = get_mysql_conn(conf)
524558

525559
mysql_status = fetch_mysql_status(conn)
526560
for key in mysql_status:
@@ -536,48 +570,56 @@ def read_callback():
536570
else:
537571
continue
538572

539-
dispatch_value('status', key, mysql_status[key], ds_type)
573+
dispatch_value(conf['instance'], 'status', key, mysql_status[key], ds_type)
540574

541575
mysql_variables = fetch_mysql_variables(conn)
542576
for key in mysql_variables:
543-
dispatch_value('variables', key, mysql_variables[key], 'gauge')
577+
dispatch_value(conf['instance'], 'variables', key, mysql_variables[key], 'gauge')
544578

545579
mysql_master_status = fetch_mysql_master_stats(conn)
546580
for key in mysql_master_status:
547-
dispatch_value('master', key, mysql_master_status[key], 'gauge')
581+
dispatch_value(conf['instance'], 'master', key, mysql_master_status[key], 'gauge')
548582

549583
mysql_states = fetch_mysql_process_states(conn)
550584
for key in mysql_states:
551-
dispatch_value('state', key, mysql_states[key], 'gauge')
585+
dispatch_value(conf['instance'], 'state', key, mysql_states[key], 'gauge')
552586

553-
slave_status = fetch_mysql_slave_stats(conn)
587+
slave_status = fetch_mysql_slave_stats(conf, conn)
554588
for key in slave_status:
555-
dispatch_value('slave', key, slave_status[key], 'gauge')
589+
dispatch_value(conf['instance'], 'slave', key, slave_status[key], 'gauge')
556590

557591
response_times = fetch_mysql_response_times(conn)
558592
for key in response_times:
559-
dispatch_value('response_time_total', str(key), response_times[key]['total'], 'counter')
560-
dispatch_value('response_time_count', str(key), response_times[key]['count'], 'counter')
593+
dispatch_value(conf['instance'], 'response_time_total', str(key), response_times[key]['total'], 'counter')
594+
dispatch_value(conf['instance'], 'response_time_count', str(key), response_times[key]['count'], 'counter')
561595

562596
innodb_status = fetch_innodb_stats(conn)
563597
for key in MYSQL_INNODB_STATUS_VARS:
564598
if key not in innodb_status: continue
565-
dispatch_value('innodb', key, innodb_status[key], MYSQL_INNODB_STATUS_VARS[key])
599+
dispatch_value(conf['instance'], 'innodb', key, innodb_status[key], MYSQL_INNODB_STATUS_VARS[key])
600+
601+
def read_callback():
602+
for conf in CONFIGS:
603+
get_metrics(conf)
566604

567605
if COLLECTD_ENABLED:
568606
collectd.register_read(read_callback)
569607
collectd.register_config(configure_callback)
570608

571609
if __name__ == "__main__" and not COLLECTD_ENABLED:
572610
print "Running in test mode, invoke with"
573-
print sys.argv[0] + " Host Port User Password "
574-
MYSQL_CONFIG['Host'] = sys.argv[1]
575-
MYSQL_CONFIG['Port'] = int(sys.argv[2])
576-
MYSQL_CONFIG['User'] = sys.argv[3]
577-
MYSQL_CONFIG['Password'] = sys.argv[4]
578-
MYSQL_CONFIG['Verbose'] = True
611+
print sys.argv[0] + " Host Port User Password Instance"
612+
mysql_config = {}
613+
mysql_config['host'] = sys.argv[1]
614+
mysql_config['heartbeattable'] = ''
615+
mysql_config['instance'] = 'slave' if sys.argv.count < 6 else sys.argv[5]
616+
mysql_config['port'] = int(sys.argv[2])
617+
mysql_config['user'] = sys.argv[3]
618+
mysql_config['password'] = sys.argv[4]
619+
mysql_config['verbose'] = VERBOSE_LOGGING = True
579620
from pprint import pprint as pp
580-
pp(MYSQL_CONFIG)
621+
pp(mysql_config)
622+
CONFIGS.append(mysql_config)
581623
read_callback()
582624

583625

0 commit comments

Comments
 (0)