From 25eab1260491f7a4f1b9b85fa7f9d5798db1d196 Mon Sep 17 00:00:00 2001 From: Zdenek Pizl Date: Tue, 4 Feb 2014 20:07:15 +0100 Subject: [PATCH] - PEP8 cleaning - add try/catch exception for most frequent cases - catch key_value errors - catch socket error for carbon connection - catch for multiple exception in multigraph - catch exception for hello string read --- m2g-poller.py | 88 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 56 insertions(+), 32 deletions(-) diff --git a/m2g-poller.py b/m2g-poller.py index cd1ffd3..e22938a 100755 --- a/m2g-poller.py +++ b/m2g-poller.py @@ -15,6 +15,7 @@ RE_LEFTRIGHT = re.compile(r"^(?P\S+)\s+(?P\S+)$") ## TODO: Catch keyboard interrupt properly and die when requested + class Munin(): """Munin host object with querying getter functions.""" def __init__(self, hostname, port=4949, args=None): @@ -22,6 +23,9 @@ class Munin(): self.port = port self.args = args self.displayname = self.hostname.split(".")[0] + self._sock = None + self._conn = None + self.hello_string = None if self.args.displayname: self.displayname = self.args.displayname @@ -39,15 +43,18 @@ class Munin(): def connect(self): """Initial connection to Munin host.""" try: - self._sock = socket.create_connection((self.hostname, self.port), - 10) + self._sock = socket.create_connection((self.hostname, self.port), 10) except socket.error: logging.exception("Unable to connect to Munin host %s, port: %s", self.hostname, self.port) sys.exit(1) - self._conn = self._sock.makefile() - self.hello_string = self._readline() + try: + self._conn = self._sock.makefile() + self.hello_string = self._readline() + except socket.error: + logging.exception("Unable to communicate to Munin host %s, port: %s", + self.hostname, self.port) def close_connection(self): """Close connection to Munin host.""" @@ -73,7 +80,7 @@ class Munin(): def fetch(self, plugin): """Fetch plugin's data fields from Munin.""" self._sock.sendall("fetch %s\n" % plugin) - response = { None: {} } + response = {None: {}} multigraph = None multigraph_prefix = "" for current_line in self._iterline(): @@ -83,9 +90,12 @@ class Munin(): response[multigraph] = {} continue # Some munin plugins have more than one space between key and value. - full_key_name, key_value = RE_LEFTRIGHT.search(current_line).group(1, 2) - key_name = multigraph_prefix + full_key_name.split(".")[0] - response[multigraph][key_name] = key_value + try: + full_key_name, key_value = RE_LEFTRIGHT.search(current_line).group(1, 2) + key_name = multigraph_prefix + full_key_name.split(".")[0] + response[multigraph][key_name] = key_value + except (KeyError, AttributeError): + logging.info("plugin multi_graph %s returns invalid data for host %s\n ", multigraph, self.hostname) return response @@ -100,7 +110,7 @@ class Munin(): def get_config(self, plugin): """Get config values for Munin plugin.""" self._sock.sendall("config %s\n" % plugin) - response = { None: {} } + response = {None: {}} multigraph = None for current_line in self._iterline(): @@ -127,7 +137,6 @@ class Munin(): return response - def process_host_stats(self): """Process Munin node data, potentially sending to Carbon.""" start_timestamp = time.time() @@ -147,16 +156,19 @@ class Munin(): logging.debug("Plugin Data: %s", plugin_data) if self.args.carbon: for multigraph in plugin_config: - self.send_to_carbon(epoch_timestamp, - current_plugin, - plugin_config[multigraph], - plugin_data[multigraph]) + try: + self.send_to_carbon(epoch_timestamp, + current_plugin, + plugin_config[multigraph], + plugin_data[multigraph]) + except KeyError: + logging.info("plugin returns invalid data:\n plugin_config: %r host %s.", + plugin_config, self.hostname) end_timestamp = time.time() - start_timestamp self.close_connection() logging.info("Finished querying host %s (Execution Time: %.2f sec).", self.hostname, end_timestamp) - def send_to_carbon(self, timestamp, plugin_name, plugin_config, plugin_data): """Send plugin data to Carbon over Pickle format.""" carbon_host, carbon_port = self.args.carbon.split(":") @@ -169,11 +181,14 @@ class Munin(): plugin_name, timestamp) for data_key in plugin_data: - plugin_category = plugin_config["graph_category"] - metric = "%s%s.%s.%s.%s" % (prefix, self.displayname, plugin_category, plugin_name, data_key) - value = plugin_data[data_key] - logging.debug("Creating metric %s, value: %s", metric, value) - data_list.append((metric, (timestamp, value))) + try: + plugin_category = plugin_config["graph_category"] + metric = "%s%s.%s.%s.%s" % (prefix, self.displayname, plugin_category, plugin_name, data_key) + value = plugin_data[data_key] + logging.debug("Creating metric %s, value: %s", metric, value) + data_list.append((metric, (timestamp, value))) + except KeyError: + logging.info("plugin returns invalid data:\n plugin_config: %r host %s.", plugin_config, self.hostname) if self.args.noop: logging.info("NOOP: Not sending data to Carbon") @@ -184,11 +199,17 @@ class Munin(): payload = pickle.dumps(data_list) header = struct.pack("!L", len(payload)) message = header + payload - carbon_sock = socket.create_connection((carbon_host, carbon_port), 10) - carbon_sock.sendall(message) - carbon_sock.close() - logging.info("Finished sending plugin %s data to Carbon for host %s.", - plugin_name, self.hostname) + try: + carbon_sock = socket.create_connection((carbon_host, carbon_port), 10) + carbon_sock.sendall(message) + carbon_sock.close() + logging.info("Finished sending plugin %s data to Carbon for host %s.", + plugin_name, self.hostname) + except socket.error: + logging.exception("Unable to connect to Carbon on host %s, port: %s", + carbon_host, carbon_port) + sys.exit(1) + def parse_args(): """Parse command line arguments.""" @@ -202,11 +223,13 @@ def parse_args(): help="Munin host to query for stats. Default: %(default)s") parser.add_argument("--displayname", default=False, - help="If defined, use this as the name to store metrics in Graphite instead of the Munin hostname.") + help="If defined, use this as the name to store metrics in Graphite instead of the Munin" + " hostname.") parser.add_argument("--interval", type=int, default=60, - help="Interval (seconds) between polling Munin host for statistics. If set to 0, exit after polling once. Default: %(default)s") + help="Interval (seconds) between polling Munin host for statistics. If set to 0, exit after " + "polling once. Default: %(default)s") parser.add_argument("--noop", action="store_true", help="Don't actually send Munin data to Carbon. Default: %(default)s") @@ -218,7 +241,7 @@ def parse_args(): action="store", default="servers", help="Prefix used on graphite target's name. Default: %(default)s") - parser.add_argument("--verbose","-v", + parser.add_argument("--verbose", "-v", choices=[1, 2, 3], default=2, type=int, @@ -227,16 +250,17 @@ def parse_args(): args = parser.parse_args() return args + def main(): args = parse_args() if args.verbose == 1: - LOGGING_LEVEL = logging.ERROR + logging_level = logging.ERROR elif args.verbose == 3: - LOGGING_LEVEL = logging.DEBUG + logging_level = logging.DEBUG else: - LOGGING_LEVEL = logging.INFO + logging_level = logging.INFO - logging.basicConfig(format=LOGGING_FORMAT, level=LOGGING_LEVEL) + logging.basicConfig(format=LOGGING_FORMAT, level=logging_level) munin = Munin(hostname=args.host, args=args) munin.go()