mirror of
https://github.com/munin-monitoring/contrib.git
synced 2025-07-21 18:41:03 +00:00
disk/zram: new plugin to monitor zram devices
This commit is contained in:
parent
210c5dbe8f
commit
e23f2af4b0
1 changed files with 180 additions and 0 deletions
180
plugins/disk/zram
Executable file
180
plugins/disk/zram
Executable file
|
@ -0,0 +1,180 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
"""Munin plugin to monitor zram devices.
|
||||
|
||||
=head1 NAME
|
||||
|
||||
zram - monitor zram devices
|
||||
|
||||
=head1 APPLICABLE SYSTEMS
|
||||
|
||||
Linux systems with zram devices.
|
||||
|
||||
=head1 CONFIGURATION
|
||||
|
||||
No configuration is required for this plugin.
|
||||
|
||||
Optionally you may specify specific warning and critical levels:
|
||||
|
||||
[zram]
|
||||
env.df_dev_zram0_warning 98
|
||||
env.df_dev_zram0_critical 99
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Kim B. Heino <b@bbbs.net>
|
||||
|
||||
=head1 LICENSE
|
||||
|
||||
GPLv2
|
||||
|
||||
=head1 MAGIC MARKERS
|
||||
|
||||
#%# family=auto
|
||||
#%# capabilities=autoconf
|
||||
|
||||
=cut
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import unicodedata
|
||||
|
||||
|
||||
def safename(name):
|
||||
"""Return safe variable name."""
|
||||
# Convert ä->a as isalpha('ä') is true
|
||||
value = unicodedata.normalize('NFKD', name)
|
||||
value = value.encode('ASCII', 'ignore').decode('utf-8')
|
||||
|
||||
# Remove non-alphanumeric chars
|
||||
return ''.join(char.lower() if char.isalnum() else '_' for char in value)
|
||||
|
||||
|
||||
def run_binary(arg):
|
||||
"""Run binary and return output."""
|
||||
try:
|
||||
return subprocess.run(arg, stdout=subprocess.PIPE, check=False,
|
||||
encoding='utf-8', errors='ignore').stdout
|
||||
except FileNotFoundError:
|
||||
return ''
|
||||
|
||||
|
||||
def parse_unit(value):
|
||||
"""Parse "1.60G" to bytes."""
|
||||
unit = value[-1]
|
||||
number = float(value[:-1])
|
||||
if unit == 'T':
|
||||
return number * 1024 * 1024 * 1024 * 1024
|
||||
if unit == 'G':
|
||||
return number * 1024 * 1024 * 1024
|
||||
if unit == 'M':
|
||||
return number * 1024 * 1024
|
||||
if unit == 'K':
|
||||
return number * 1024
|
||||
return number
|
||||
|
||||
|
||||
def warning_critical(graph, name, warning=None, critical=None):
|
||||
"""Print warning/critical config entries."""
|
||||
warning = os.environ.get(f'{graph}{name}_warning', warning)
|
||||
critical = os.environ.get(f'{graph}{name}_critical', critical)
|
||||
if warning and warning != ':':
|
||||
print(f'{name}.warning {warning}')
|
||||
if critical and critical != ':':
|
||||
print(f'{name}.critical {critical}')
|
||||
|
||||
|
||||
def find_zram():
|
||||
"""Return list of found zram devices."""
|
||||
zram = []
|
||||
for line in sorted(run_binary(['zramctl']).splitlines()):
|
||||
if not line.startswith('/dev/'):
|
||||
continue
|
||||
items = line.split()
|
||||
if len(items) == 7: # Not mounted, use device name
|
||||
mount = items[0]
|
||||
else:
|
||||
mount = items[7]
|
||||
if mount == '[SWAP]':
|
||||
mount = 'Swap'
|
||||
zram.append((safename(items[0]), # 0, device
|
||||
parse_unit(items[2]), # 1, disksize
|
||||
parse_unit(items[3]), # 2, data
|
||||
parse_unit(items[5]), # 3, total
|
||||
mount)) # 4, mountpoint
|
||||
return zram
|
||||
|
||||
|
||||
def config(zram):
|
||||
"""Print plugin config."""
|
||||
# Similar to df plugin
|
||||
print('multigraph zram_df')
|
||||
print('graph_title zram usage in percent')
|
||||
print('graph_info zram device usage in percent.')
|
||||
print('graph_category disk')
|
||||
print('graph_vlabel %')
|
||||
print('graph_args --lower-limit 0 --upper-limit 100')
|
||||
print('graph_scale no')
|
||||
for item in zram:
|
||||
print(f'{item[0]}.label {item[4]}')
|
||||
warning_critical('df', item[0], 92, 98)
|
||||
|
||||
# Compression ratio:
|
||||
# 100 = compresses to few bytes only
|
||||
# 0 = stays same (or increases, this happens if metadata grows)
|
||||
print('multigraph zram_compression')
|
||||
print('graph_title zram compression ratio')
|
||||
print('graph_info zram data compression ratio.')
|
||||
print('graph_category disk')
|
||||
print('graph_vlabel %')
|
||||
print('graph_args --lower-limit 0 --upper-limit 100')
|
||||
for item in zram:
|
||||
print(f'{item[0]}.label {item[4]}')
|
||||
warning_critical('compression', item[0])
|
||||
|
||||
# Real memory usage
|
||||
print('multigraph zram_memory')
|
||||
print('graph_title zram memory usage')
|
||||
print('graph_info zram device compressed memory usage.')
|
||||
print('graph_category disk')
|
||||
print('graph_vlabel bytes')
|
||||
print('graph_args --base 1024 --lower-limit 0')
|
||||
first = True
|
||||
for item in zram:
|
||||
print(f'{item[0]}.label {item[4]}')
|
||||
warning_critical('memory', item[0])
|
||||
print(f'{item[0]}.draw {"STACK" if first else "AREA"}')
|
||||
first = False
|
||||
|
||||
if os.environ.get('MUNIN_CAP_DIRTYCONFIG') == '1':
|
||||
fetch(zram)
|
||||
|
||||
|
||||
def fetch(zram):
|
||||
"""Print values."""
|
||||
print('multigraph zram_df')
|
||||
for item in zram:
|
||||
print(f'{item[0]}.value {item[2] / item[1]:.3f}')
|
||||
|
||||
print('multigraph zram_compression')
|
||||
for item in zram:
|
||||
if item[3] >= item[2]: # Empty or size increases
|
||||
print(f'{item[0]}.value 0')
|
||||
else:
|
||||
print(f'{item[0]}.value {100 - 100 * (item[3] / item[2])}')
|
||||
|
||||
print('multigraph zram_memory')
|
||||
for item in zram:
|
||||
print(f'{item[0]}.value {item[3]}')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) > 1 and sys.argv[1] == 'autoconf':
|
||||
print('yes' if find_zram() else 'no (no zram devices found)')
|
||||
elif len(sys.argv) > 1 and sys.argv[1] == 'config':
|
||||
config(find_zram())
|
||||
else:
|
||||
fetch(find_zram())
|
Loading…
Add table
Add a link
Reference in a new issue