From 9c0cc58ab6407991e3f7e2191fc20ca39bd2a204 Mon Sep 17 00:00:00 2001 From: Yoav Date: Mon, 10 Feb 2014 13:27:43 +0000 Subject: [PATCH 1/3] updated logger message * the error is not specific to multi_plugin, and can happen with normal plugins * logging the line that caused this error and the plugin name --- m2g-poller.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/m2g-poller.py b/m2g-poller.py index 966b68c..ebc0e48 100755 --- a/m2g-poller.py +++ b/m2g-poller.py @@ -109,7 +109,8 @@ class Munin(): 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) + logging.info("plugin %s returned invalid data [%s] for host" + " %s\n", plugin, current_line, self.hostname) return response From aec4f100eeb8f2ea3c0c0c0c42f26b103dbec3c7 Mon Sep 17 00:00:00 2001 From: Yoav Date: Tue, 11 Feb 2014 11:07:27 +0000 Subject: [PATCH 2/3] better handling of intervals * reducing the actual processing time from the interval, so it runs in more accurate intervals independent of the processing time. * if processing time takes longer than the interval, we run it instantly --- m2g-poller.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/m2g-poller.py b/m2g-poller.py index ebc0e48..46a50ab 100755 --- a/m2g-poller.py +++ b/m2g-poller.py @@ -35,12 +35,14 @@ class Munin(): """Bootstrap method to start processing hosts's Munin stats.""" self.connect() self.update_hostname() - self.process_host_stats() + processing_time = self.process_host_stats() + interval = self.args.interval - while True and self.args.interval != 0: - time.sleep(self.args.interval) + while True and interval != 0: + sleep_time = max(interval - processing_time, 0) + time.sleep(sleep_time) self.connect() - self.process_host_stats() + processing_time = self.process_host_stats() def update_hostname(self): """Updating hostname from connection hello string.""" @@ -183,6 +185,7 @@ class Munin(): self.close_connection() logging.info("Finished querying host %s (Execution Time: %.2f sec).", self.hostname, end_timestamp) + return end_timestamp def send_to_carbon(self, timestamp, plugin_name, plugin_config, plugin_data): """Send plugin data to Carbon over Pickle format.""" From 3c57345a4e0d1ec552158de78c1421ca95b3451d Mon Sep 17 00:00:00 2001 From: Yoav Date: Tue, 11 Feb 2014 11:09:11 +0000 Subject: [PATCH 3/3] performance - reducing carbon footprint :) * Establishing one carbon connection for all plugins, instead of one connection for each. This rather drastically improves performance. From a few measurements this reduces processing time by over 50% * This can be even further enhanced, to keep one persistent carbon (/munin?) connection and only re-establish it if it drops (For Future) --- m2g-poller.py | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/m2g-poller.py b/m2g-poller.py index 46a50ab..d1b76aa 100755 --- a/m2g-poller.py +++ b/m2g-poller.py @@ -26,6 +26,7 @@ class Munin(): self.displayname = self.hostname.split(".")[0] self._sock = None self._conn = None + self._carbon_sock = None self.hello_string = None if self.args.displayname: @@ -72,10 +73,27 @@ class Munin(): logging.exception("Unable to communicate to Munin host %s, port: %s", self.hostname, self.port) + if self.args.carbon: + self.connect_carbon() + + def connect_carbon(self): + carbon_host, carbon_port = self.args.carbon.split(":") + try: + self._carbon_sock = socket.create_connection((carbon_host, carbon_port), 10) + except socket.error: + logging.exception("Unable to connect to Carbon on host %s, port: %s", + carbon_host, carbon_port) + sys.exit(1) + def close_connection(self): """Close connection to Munin host.""" self._sock.close() + def close_carbon_connection(self): + """Close connection to Carbon host.""" + if self._carbon_sock: + self._carbon_sock.close() + def _readline(self): """Read one line from Munin output, stripping leading/trailing chars.""" return self._conn.readline().strip() @@ -183,13 +201,13 @@ class Munin(): plugin_config, self.hostname) end_timestamp = time.time() - start_timestamp self.close_connection() + self.close_carbon_connection() logging.info("Finished querying host %s (Execution Time: %.2f sec).", self.hostname, end_timestamp) return 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(":") if self.args.noprefix: prefix = '' else: @@ -218,15 +236,11 @@ class Munin(): header = struct.pack("!L", len(payload)) message = header + payload try: - carbon_sock = socket.create_connection((carbon_host, carbon_port), 10) - carbon_sock.sendall(message) - carbon_sock.close() + self._carbon_sock.sendall(message) 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) + logging.exception("Unable to send data to Carbon") def parse_args():