- 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
This commit is contained in:
parent
bb7dd53ed0
commit
25eab12604
@ -15,6 +15,7 @@ RE_LEFTRIGHT = re.compile(r"^(?P<left>\S+)\s+(?P<right>\S+)$")
|
|||||||
|
|
||||||
## TODO: Catch keyboard interrupt properly and die when requested
|
## TODO: Catch keyboard interrupt properly and die when requested
|
||||||
|
|
||||||
|
|
||||||
class Munin():
|
class Munin():
|
||||||
"""Munin host object with querying getter functions."""
|
"""Munin host object with querying getter functions."""
|
||||||
def __init__(self, hostname, port=4949, args=None):
|
def __init__(self, hostname, port=4949, args=None):
|
||||||
@ -22,6 +23,9 @@ class Munin():
|
|||||||
self.port = port
|
self.port = port
|
||||||
self.args = args
|
self.args = args
|
||||||
self.displayname = self.hostname.split(".")[0]
|
self.displayname = self.hostname.split(".")[0]
|
||||||
|
self._sock = None
|
||||||
|
self._conn = None
|
||||||
|
self.hello_string = None
|
||||||
|
|
||||||
if self.args.displayname:
|
if self.args.displayname:
|
||||||
self.displayname = self.args.displayname
|
self.displayname = self.args.displayname
|
||||||
@ -39,15 +43,18 @@ class Munin():
|
|||||||
def connect(self):
|
def connect(self):
|
||||||
"""Initial connection to Munin host."""
|
"""Initial connection to Munin host."""
|
||||||
try:
|
try:
|
||||||
self._sock = socket.create_connection((self.hostname, self.port),
|
self._sock = socket.create_connection((self.hostname, self.port), 10)
|
||||||
10)
|
|
||||||
except socket.error:
|
except socket.error:
|
||||||
logging.exception("Unable to connect to Munin host %s, port: %s",
|
logging.exception("Unable to connect to Munin host %s, port: %s",
|
||||||
self.hostname, self.port)
|
self.hostname, self.port)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
try:
|
||||||
self._conn = self._sock.makefile()
|
self._conn = self._sock.makefile()
|
||||||
self.hello_string = self._readline()
|
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):
|
def close_connection(self):
|
||||||
"""Close connection to Munin host."""
|
"""Close connection to Munin host."""
|
||||||
@ -73,7 +80,7 @@ class Munin():
|
|||||||
def fetch(self, plugin):
|
def fetch(self, plugin):
|
||||||
"""Fetch plugin's data fields from Munin."""
|
"""Fetch plugin's data fields from Munin."""
|
||||||
self._sock.sendall("fetch %s\n" % plugin)
|
self._sock.sendall("fetch %s\n" % plugin)
|
||||||
response = { None: {} }
|
response = {None: {}}
|
||||||
multigraph = None
|
multigraph = None
|
||||||
multigraph_prefix = ""
|
multigraph_prefix = ""
|
||||||
for current_line in self._iterline():
|
for current_line in self._iterline():
|
||||||
@ -83,9 +90,12 @@ class Munin():
|
|||||||
response[multigraph] = {}
|
response[multigraph] = {}
|
||||||
continue
|
continue
|
||||||
# Some munin plugins have more than one space between key and value.
|
# Some munin plugins have more than one space between key and value.
|
||||||
|
try:
|
||||||
full_key_name, key_value = RE_LEFTRIGHT.search(current_line).group(1, 2)
|
full_key_name, key_value = RE_LEFTRIGHT.search(current_line).group(1, 2)
|
||||||
key_name = multigraph_prefix + full_key_name.split(".")[0]
|
key_name = multigraph_prefix + full_key_name.split(".")[0]
|
||||||
response[multigraph][key_name] = key_value
|
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
|
return response
|
||||||
|
|
||||||
@ -100,7 +110,7 @@ class Munin():
|
|||||||
def get_config(self, plugin):
|
def get_config(self, plugin):
|
||||||
"""Get config values for Munin plugin."""
|
"""Get config values for Munin plugin."""
|
||||||
self._sock.sendall("config %s\n" % plugin)
|
self._sock.sendall("config %s\n" % plugin)
|
||||||
response = { None: {} }
|
response = {None: {}}
|
||||||
multigraph = None
|
multigraph = None
|
||||||
|
|
||||||
for current_line in self._iterline():
|
for current_line in self._iterline():
|
||||||
@ -127,7 +137,6 @@ class Munin():
|
|||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
def process_host_stats(self):
|
def process_host_stats(self):
|
||||||
"""Process Munin node data, potentially sending to Carbon."""
|
"""Process Munin node data, potentially sending to Carbon."""
|
||||||
start_timestamp = time.time()
|
start_timestamp = time.time()
|
||||||
@ -147,16 +156,19 @@ class Munin():
|
|||||||
logging.debug("Plugin Data: %s", plugin_data)
|
logging.debug("Plugin Data: %s", plugin_data)
|
||||||
if self.args.carbon:
|
if self.args.carbon:
|
||||||
for multigraph in plugin_config:
|
for multigraph in plugin_config:
|
||||||
|
try:
|
||||||
self.send_to_carbon(epoch_timestamp,
|
self.send_to_carbon(epoch_timestamp,
|
||||||
current_plugin,
|
current_plugin,
|
||||||
plugin_config[multigraph],
|
plugin_config[multigraph],
|
||||||
plugin_data[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
|
end_timestamp = time.time() - start_timestamp
|
||||||
self.close_connection()
|
self.close_connection()
|
||||||
logging.info("Finished querying host %s (Execution Time: %.2f sec).",
|
logging.info("Finished querying host %s (Execution Time: %.2f sec).",
|
||||||
self.hostname, end_timestamp)
|
self.hostname, end_timestamp)
|
||||||
|
|
||||||
|
|
||||||
def send_to_carbon(self, timestamp, plugin_name, plugin_config, plugin_data):
|
def send_to_carbon(self, timestamp, plugin_name, plugin_config, plugin_data):
|
||||||
"""Send plugin data to Carbon over Pickle format."""
|
"""Send plugin data to Carbon over Pickle format."""
|
||||||
carbon_host, carbon_port = self.args.carbon.split(":")
|
carbon_host, carbon_port = self.args.carbon.split(":")
|
||||||
@ -169,11 +181,14 @@ class Munin():
|
|||||||
plugin_name, timestamp)
|
plugin_name, timestamp)
|
||||||
|
|
||||||
for data_key in plugin_data:
|
for data_key in plugin_data:
|
||||||
|
try:
|
||||||
plugin_category = plugin_config["graph_category"]
|
plugin_category = plugin_config["graph_category"]
|
||||||
metric = "%s%s.%s.%s.%s" % (prefix, self.displayname, plugin_category, plugin_name, data_key)
|
metric = "%s%s.%s.%s.%s" % (prefix, self.displayname, plugin_category, plugin_name, data_key)
|
||||||
value = plugin_data[data_key]
|
value = plugin_data[data_key]
|
||||||
logging.debug("Creating metric %s, value: %s", metric, value)
|
logging.debug("Creating metric %s, value: %s", metric, value)
|
||||||
data_list.append((metric, (timestamp, 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:
|
if self.args.noop:
|
||||||
logging.info("NOOP: Not sending data to Carbon")
|
logging.info("NOOP: Not sending data to Carbon")
|
||||||
@ -184,11 +199,17 @@ class Munin():
|
|||||||
payload = pickle.dumps(data_list)
|
payload = pickle.dumps(data_list)
|
||||||
header = struct.pack("!L", len(payload))
|
header = struct.pack("!L", len(payload))
|
||||||
message = header + payload
|
message = header + payload
|
||||||
|
try:
|
||||||
carbon_sock = socket.create_connection((carbon_host, carbon_port), 10)
|
carbon_sock = socket.create_connection((carbon_host, carbon_port), 10)
|
||||||
carbon_sock.sendall(message)
|
carbon_sock.sendall(message)
|
||||||
carbon_sock.close()
|
carbon_sock.close()
|
||||||
logging.info("Finished sending plugin %s data to Carbon for host %s.",
|
logging.info("Finished sending plugin %s data to Carbon for host %s.",
|
||||||
plugin_name, self.hostname)
|
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():
|
def parse_args():
|
||||||
"""Parse command line arguments."""
|
"""Parse command line arguments."""
|
||||||
@ -202,11 +223,13 @@ def parse_args():
|
|||||||
help="Munin host to query for stats. Default: %(default)s")
|
help="Munin host to query for stats. Default: %(default)s")
|
||||||
parser.add_argument("--displayname",
|
parser.add_argument("--displayname",
|
||||||
default=False,
|
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",
|
parser.add_argument("--interval",
|
||||||
type=int,
|
type=int,
|
||||||
default=60,
|
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",
|
parser.add_argument("--noop",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
help="Don't actually send Munin data to Carbon. Default: %(default)s")
|
help="Don't actually send Munin data to Carbon. Default: %(default)s")
|
||||||
@ -218,7 +241,7 @@ def parse_args():
|
|||||||
action="store",
|
action="store",
|
||||||
default="servers",
|
default="servers",
|
||||||
help="Prefix used on graphite target's name. Default: %(default)s")
|
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],
|
choices=[1, 2, 3],
|
||||||
default=2,
|
default=2,
|
||||||
type=int,
|
type=int,
|
||||||
@ -227,16 +250,17 @@ def parse_args():
|
|||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
return args
|
return args
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
args = parse_args()
|
args = parse_args()
|
||||||
if args.verbose == 1:
|
if args.verbose == 1:
|
||||||
LOGGING_LEVEL = logging.ERROR
|
logging_level = logging.ERROR
|
||||||
elif args.verbose == 3:
|
elif args.verbose == 3:
|
||||||
LOGGING_LEVEL = logging.DEBUG
|
logging_level = logging.DEBUG
|
||||||
else:
|
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 = Munin(hostname=args.host, args=args)
|
||||||
munin.go()
|
munin.go()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user