#!/usr/bin/python3 """ =head1 NAME monit_parser - Monit status parser plugin for munin. =head1 APPLICABLE SYSTEMS Any system being able to query monit servers via http. Monit needs to be configured with the httpd port enabled, e.g.: set httpd port 2812 =head1 CONFIGURATION By default the monit instance at localhost is queried: [monit_parser] env.port 2812 env.host localhost =head1 AUTHOR Todd Troxell Lars Kruse =head1 MAGIC MARKERS family=auto capabilities=autoconf =cut """ import xml.dom.minidom import os import sys import urllib.request MONIT_XML_URL = ("http://{host}:{port}/_status?format=xml" .format(host=os.getenv("host", "localhost"), port=os.getenv("port", "2812"))) def sanitize(s): OK_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789" return "".join([char for char in s if char in OK_CHARS]) def get_monit_status_xml(): try: conn = urllib.request.urlopen(MONIT_XML_URL) except urllib.error.URLError as exc: conn = None if conn is None: raise RuntimeError("Failed to open monit status URL: {}".format(MONIT_XML_URL)) else: return xml.dom.minidom.parse(conn) def parse_processes(): dom = get_monit_status_xml() procs = {} for item in dom.getElementsByTagName("service"): if item.getAttribute("type") == "3": # daemon with memory usage and CPU name = item.getElementsByTagName("name")[0].childNodes[0].data memory_usage = item.getElementsByTagName("memory")[0].getElementsByTagName( "kilobytetotal")[0].childNodes[0].data cpu_usage = item.getElementsByTagName("cpu")[0].getElementsByTagName( "percenttotal")[0].childNodes[0].data procs[name] = {} procs[name]["total_memory"] = memory_usage procs[name]["total_cpu"] = cpu_usage return procs action = sys.argv[1] if (len(sys.argv) > 1) else None if action == 'autoconf': try: get_monit_status_xml() print("yes") except RuntimeError: print("no (failed to request monit status)") elif action == 'config': procs = parse_processes() print('graph_title Per process stats from Monit') print('graph_vlabel usage of memory [kB] or cpu [%]') print('graph_category monit') for process in procs: for stat in procs[process]: print("monit_%s_%s.label %s.%s" % (sanitize(process), stat, process, stat)) if stat == 'total_memory': # the allocated memory may never be zero print("monit_%s_%s.warning 1:" % (sanitize(process), stat)) else: for process, stats in parse_processes().items(): for stat_key, stat_value in stats.items(): print("monit_%s_%s.value %s" % (sanitize(process), stat_key, stat_value))