mirror of
https://github.com/munin-monitoring/contrib.git
synced 2025-07-21 18:41:03 +00:00
[plugins/mysql/mysql_disk_by_prefix] Add plugin for DB size by user
This commit is contained in:
parent
6fdf699575
commit
ee226a609e
1 changed files with 151 additions and 0 deletions
151
plugins/mysql/mysql_disk_by_prefix
Executable file
151
plugins/mysql/mysql_disk_by_prefix
Executable file
|
@ -0,0 +1,151 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- python -*-
|
||||
|
||||
"""
|
||||
=head1 INTRODUCTION
|
||||
|
||||
Plugin to monitor MySQL database disk usage per prefix. A prefix can be eg.
|
||||
'user' for the databases 'user_testdb' and 'user_db2', as can be seen in
|
||||
certain shared hosting setups.
|
||||
|
||||
=head1 APPLICABLE SYSTEMS
|
||||
|
||||
Local access to the database files is required (which are stored in
|
||||
/var/lib/mysql by default).
|
||||
|
||||
=head1 INSTALLATION
|
||||
|
||||
Place in /etc/munin/plugins/ (or link it there using ln -s)
|
||||
|
||||
=head1 CONFIGURATION
|
||||
|
||||
Add this to your /etc/munin/plugin-conf.d/munin-node:
|
||||
|
||||
=over 2
|
||||
|
||||
[mysql_disk_by_prefix]
|
||||
user mysql
|
||||
env.prefixes_with_underscores foo_bar d_ritchie # prefixes that include an underscore
|
||||
env.db_minsize 1024000 # minimum db size in order to report a specific prefix,
|
||||
# in bytes (defaults to 50M). "0" for none.
|
||||
env.mysql_db_dir /var/lib/mysql # default value
|
||||
|
||||
=back
|
||||
|
||||
=head1 HISTORY
|
||||
|
||||
2019-07-25: v 1.0 pcy <pcy.ulyssis.org>: created
|
||||
|
||||
=head1 USAGE
|
||||
|
||||
Parameters understood:
|
||||
|
||||
config (required)
|
||||
autoconf (optional - used by munin-config)
|
||||
|
||||
=head1 MAGIC MARKERS
|
||||
|
||||
#%# family=auto
|
||||
#%# capabilities=autoconf
|
||||
"""
|
||||
|
||||
|
||||
import os
|
||||
import re
|
||||
import subprocess as sp
|
||||
import sys
|
||||
|
||||
|
||||
def weakbool(x):
|
||||
return x.lower().strip() in {'true', 'yes', 'y', 1}
|
||||
|
||||
|
||||
LIMIT = os.getenv('db_minsize', str(50000 * 1024))
|
||||
try:
|
||||
LIMIT = int(LIMIT)
|
||||
except ValueError:
|
||||
LIMIT = 0
|
||||
|
||||
exceptions = os.getenv('prefix_with_underscores', '').split(' ')
|
||||
if exceptions == ['']:
|
||||
exceptions = []
|
||||
|
||||
mysqldir = os.getenv('mysql_db_dir', '/var/lib/mysql')
|
||||
|
||||
|
||||
def name_from_path(path):
|
||||
filename = os.path.basename(path)
|
||||
for name in exceptions:
|
||||
if filename.startswith(name):
|
||||
return name
|
||||
name = filename.split('_')[0]
|
||||
|
||||
def decode_byte(m):
|
||||
return bytes.fromhex(m.group(1)).decode('utf-8')
|
||||
|
||||
# Decode MySQL's encoding of non-ascii characters in the table names
|
||||
return re.sub('@00([0-9a-z]{2})', decode_byte, name)
|
||||
|
||||
|
||||
def calc_dir_size(directory):
|
||||
total = 0
|
||||
|
||||
for filename in os.listdir(directory):
|
||||
filedir = os.path.join(directory, filename)
|
||||
|
||||
if os.path.islink(filedir):
|
||||
continue
|
||||
if os.path.isfile(filedir):
|
||||
total += os.path.getsize(filedir)
|
||||
|
||||
return total
|
||||
|
||||
|
||||
def size_per_subdir(parentdir):
|
||||
for subdir in os.listdir(parentdir):
|
||||
dirpath = os.path.join(parentdir, subdir)
|
||||
|
||||
if os.path.islink(dirpath):
|
||||
continue
|
||||
if os.path.isdir(dirpath):
|
||||
yield calc_dir_size(dirpath), name_from_path(os.path.split(dirpath)[1])
|
||||
|
||||
|
||||
def sizes_by_name(limit=None):
|
||||
sizes = {}
|
||||
for size, name in size_per_subdir(mysqldir):
|
||||
sizes[name] = sizes.get(name, 0) + size
|
||||
for name, total_size in sizes.items():
|
||||
if limit <= 0 or limit <= total_size:
|
||||
yield name, total_size
|
||||
|
||||
|
||||
def fetch():
|
||||
for name, total_size in sorted(sizes_by_name(limit=LIMIT), key=lambda x: x[0]):
|
||||
print('{}.value {}'.format(name, total_size))
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) == 1:
|
||||
fetch()
|
||||
elif sys.argv[1] == 'config':
|
||||
print('graph_title MySQL disk usage by prefix')
|
||||
print('graph_vlabel bytes')
|
||||
print('graph_category db')
|
||||
|
||||
names = sorted(name for name, _ in sizes_by_name(limit=LIMIT))
|
||||
for name in names:
|
||||
print('{0}.label {0}'.format(name))
|
||||
print('{}.type GAUGE'.format(name))
|
||||
print('{}.draw AREASTACK'.format(name))
|
||||
elif sys.argv[1] == 'autoconf':
|
||||
print('yes' if os.path.isdir(mysqldir)
|
||||
else "no (can't find MySQL's data directory)")
|
||||
else:
|
||||
fetch()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
# flake8: noqa: E265
|
Loading…
Add table
Add a link
Reference in a new issue