#!/usr/bin/env python3 import argparse import json import sys import numpy as np import requests from checker import nagios parser = argparse.ArgumentParser(description='') parser.add_argument('--metrics-endpoint', required=True, help='Target URL to scrape.') parser.add_argument('--domain', required=True, help='Our domain.') parser.add_argument('--prometheus', action='store_true', help='Use Promethus instead of scraping the status page.') parser.add_argument('--ignore', nargs='*', default=[], help='Ignore these hosts.') parser.add_argument('--timeout', type=float, default=90, help='Request timeout limit.') parser.add_argument('--warn', type=float, default=20, help='Manually set warn level.') parser.add_argument('--crit', type=float, default=30, help='Manually set critical level.') args = parser.parse_args() if args.prometheus: from checker.prometheus import parse_metrics r = requests.get(args.metrics_endpoint) if r.status_code != 200: sys.exit(nagios.UNKNOWN) metrics = {} for item in parse_metrics(r.text)['monbot_ping_receive_delay_seconds']['monbot_ping_receive_delay_seconds_sum']: if item.labels['receivingDomain'] not in metrics.keys(): metrics[item.labels['receivingDomain']] = {} metrics[item.labels['receivingDomain']][item.labels['sourceDomain']] = item.value pings = {'receiver': [], 'sender': [], } for receiving_domain, senders in metrics.items(): if receiving_domain == args.domain: for k, v in senders.items(): pings['receiver'].append(v) else: for k, v in senders.items(): if k == args.domain: pings['sender'].append(v) print(json.dumps(pings)) receiver_avg = np.round(np.average(pings['receiver']), 2) sender_avg = np.round(np.average(pings['sender']), 2) print('receiver latency is', receiver_avg) print('sender latency is', sender_avg) else: from bs4 import BeautifulSoup import re # Split the values since icinga will quote the args if len(args.ignore) == 1: args.ignore = args.ignore[0].strip(' ').split(' ') def get_sec(time_str): """Get seconds from time.""" h, m, s = time_str.split(':') return int(h) * 3600 + int(m) * 60 + int(s) def ms_to_s(s): min_m = re.match(r'^(\d+)m([\d.]+)s', s) if min_m: return get_sec(f'0:{min_m.group(1)}:{int(float(min_m.group(2)))}') elif s.endswith('ms'): return float('0.' + s.strip('ms')) elif s.endswith('s'): return float(s.strip('ms')) r = requests.get(args.metrics_endpoint) if r.status_code != 200: sys.exit(nagios.UNKNOWN) soup = BeautifulSoup(r.text, 'html.parser') tooltips = soup.find_all('span', {'class', 'tooltip'}) data = {} for item in tooltips: m = re.match(r'\s*Send: (.*?)\s*\s*Receive: (.*?)\s*<\/span>', str(item)) if m: domain = item.parent.parent.find('span', {'class': 'domain'}).text data[domain] = { 'send': ms_to_s(m.group(1)), 'receive': ms_to_s(m.group(2)), } exit_code = nagios.OK info_str = [] data_str = [] if len(data.keys()) == 0: print('UNKNOWN: failed to find any servers.') sys.exit(nagios.UNKNOWN) for domain, values in data.items(): if domain not in args.ignore: if values['send'] >= args.crit: info_str.append(f'CRITICAL: {domain} send is {values["send"]}s.') exit_code = nagios.CRITICAL elif values['send'] >= args.warn: info_str.append(f'WARN: {domain} send is {values["send"]}s.') if exit_code < nagios.WARNING: exit_code = nagios.WARNING # else: # print(f'OK: {domain} send is {values["send"]}s.') if values['receive'] >= args.crit: info_str.append(f'CRITICAL: {domain} receive is {values["receive"]}s.') exit_code = nagios.CRITICAL elif values['receive'] >= args.warn: info_str.append(f'WARN: {domain} receive is {values["receive"]}s.') if exit_code < nagios.WARNING: exit_code = nagios.WARNING # else: # print(f'OK: {domain} receive is {values["receive"]}s.') data_str.append( f"'{domain}-send'={values['send']}s;;; '{domain}-receive'={values['receive']}s;;;" ) if any(('CRITICAL' not in s and 'WARNING' not in s) for s in info_str) or len(info_str) == 0: print(f'OK: ping time is good.', end=' ') else: for x in info_str: print(x, end=('\n' if info_str.index(x) + 1 < len(info_str) else '')) print(f'|{" ".join(data_str)}') sys.exit(exit_code)