2018-02-16 18:03:12 +00:00
|
|
|
import logging
|
2018-04-10 18:06:42 +00:00
|
|
|
import subprocess
|
2018-02-16 17:48:26 +00:00
|
|
|
import sys
|
2018-02-16 02:10:19 +00:00
|
|
|
from argparse import ArgumentParser
|
|
|
|
from datetime import datetime
|
2018-04-19 04:50:50 +00:00
|
|
|
from itertools import chain
|
2018-04-10 18:06:42 +00:00
|
|
|
from subprocess import CalledProcessError
|
|
|
|
from subprocess import check_output
|
2018-02-15 01:54:42 +00:00
|
|
|
from time import sleep
|
2018-02-14 23:37:15 +00:00
|
|
|
|
|
|
|
import yamlenv
|
2018-07-13 06:01:36 +00:00
|
|
|
from prometheus_client import Counter
|
|
|
|
from prometheus_client import Gauge
|
|
|
|
from prometheus_client import start_http_server
|
2018-02-14 23:37:15 +00:00
|
|
|
|
2018-02-16 18:03:12 +00:00
|
|
|
|
2018-07-13 06:01:36 +00:00
|
|
|
DEFAULT_METRICS_PORT = 8080
|
2018-04-10 18:06:42 +00:00
|
|
|
logging.basicConfig(
|
2019-06-03 18:44:39 +00:00
|
|
|
level=logging.ERROR,
|
2018-04-10 18:06:42 +00:00
|
|
|
format='%(asctime)s %(levelname)s %(name)s %(message)s'
|
|
|
|
)
|
2018-02-16 18:03:12 +00:00
|
|
|
logging.getLogger(__name__).addHandler(logging.NullHandler())
|
|
|
|
|
2018-02-14 23:37:15 +00:00
|
|
|
|
2018-02-16 02:10:19 +00:00
|
|
|
def read_yaml(path):
|
2018-02-14 23:37:15 +00:00
|
|
|
"""Loads config from a YAML file with env interpolation"""
|
|
|
|
with open(path, 'r') as yaml:
|
|
|
|
contents = yaml.read()
|
|
|
|
return yamlenv.load(contents)
|
|
|
|
|
|
|
|
|
2018-04-10 00:07:32 +00:00
|
|
|
def validate_monitor_settings(settings):
|
|
|
|
"""Validates that settings for a Monitor are valid
|
|
|
|
|
|
|
|
Note: Cannot yet validate the Alerts exist from within this class.
|
|
|
|
That will be done by Minitor later
|
|
|
|
"""
|
|
|
|
name = settings.get('name')
|
|
|
|
if not name:
|
|
|
|
raise InvalidMonitorException('Invalid name for monitor')
|
|
|
|
if not settings.get('command'):
|
|
|
|
raise InvalidMonitorException(
|
|
|
|
'Invalid command for monitor {}'.format(name)
|
|
|
|
)
|
|
|
|
|
|
|
|
type_assertions = (
|
|
|
|
('check_interval', int),
|
|
|
|
('alert_after', int),
|
|
|
|
('alert_every', int),
|
|
|
|
)
|
|
|
|
|
|
|
|
for key, val_type in type_assertions:
|
|
|
|
val = settings.get(key)
|
|
|
|
if not isinstance(val, val_type):
|
|
|
|
raise InvalidMonitorException(
|
|
|
|
'Invalid type on {}: {}. Expected {} and found {}'.format(
|
|
|
|
name, key, val_type.__name__, type(val).__name__
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
non_zero = (
|
|
|
|
'check_interval',
|
|
|
|
'alert_after',
|
|
|
|
)
|
|
|
|
|
|
|
|
for key in non_zero:
|
|
|
|
if settings.get(key) == 0:
|
|
|
|
raise InvalidMonitorException(
|
|
|
|
'Invalid value for {}: {}. Value cannot be 0'.format(
|
|
|
|
name, key
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2018-04-10 18:06:42 +00:00
|
|
|
def maybe_decode(bstr, encoding='utf-8'):
|
|
|
|
try:
|
|
|
|
return bstr.decode(encoding)
|
|
|
|
except TypeError:
|
|
|
|
return bstr
|
|
|
|
|
|
|
|
|
|
|
|
def call_output(*popenargs, **kwargs):
|
|
|
|
"""Similar to check_output, but instead returns output and exception"""
|
|
|
|
# So we can capture complete output, redirect sderr to stdout
|
|
|
|
kwargs.setdefault('stderr', subprocess.STDOUT)
|
|
|
|
output, ex = None, None
|
|
|
|
try:
|
|
|
|
output = check_output(*popenargs, **kwargs)
|
|
|
|
except CalledProcessError as e:
|
|
|
|
output, ex = e.output, e
|
|
|
|
|
|
|
|
output = output.rstrip(b'\n')
|
|
|
|
return output, ex
|
|
|
|
|
|
|
|
|
2018-02-16 02:10:19 +00:00
|
|
|
class InvalidAlertException(Exception):
|
|
|
|
pass
|
2018-02-14 23:37:15 +00:00
|
|
|
|
|
|
|
|
2018-02-16 02:10:19 +00:00
|
|
|
class InvalidMonitorException(Exception):
|
|
|
|
pass
|
2018-02-14 23:37:15 +00:00
|
|
|
|
|
|
|
|
2018-02-16 02:10:19 +00:00
|
|
|
class MinitorAlert(Exception):
|
2018-04-15 00:27:37 +00:00
|
|
|
def __init__(self, message, monitor):
|
|
|
|
super().__init__(message)
|
|
|
|
self.monitor = monitor
|
2018-02-16 02:10:19 +00:00
|
|
|
|
|
|
|
|
|
|
|
class Monitor(object):
|
|
|
|
"""Primary configuration item for Minitor"""
|
2018-04-09 19:08:42 +00:00
|
|
|
|
2019-06-03 18:44:39 +00:00
|
|
|
def __init__(self, config, counter=None, logger=None):
|
2018-02-16 02:10:19 +00:00
|
|
|
"""Accepts a dictionary of configuration items to override defaults"""
|
|
|
|
settings = {
|
2018-04-09 19:08:42 +00:00
|
|
|
'alerts': ['log'],
|
2018-02-16 02:10:19 +00:00
|
|
|
'check_interval': 30,
|
2018-02-18 04:45:37 +00:00
|
|
|
'alert_after': 4,
|
|
|
|
'alert_every': -1,
|
2018-02-16 02:10:19 +00:00
|
|
|
}
|
|
|
|
settings.update(config)
|
2018-04-10 00:07:32 +00:00
|
|
|
validate_monitor_settings(settings)
|
2018-02-16 02:10:19 +00:00
|
|
|
|
|
|
|
self.name = settings['name']
|
|
|
|
self.command = settings['command']
|
2018-04-15 00:27:37 +00:00
|
|
|
self.alert_down = settings.get('alert_down', [])
|
|
|
|
if not self.alert_down:
|
|
|
|
self.alert_down = settings.get('alerts', [])
|
|
|
|
self.alert_up = settings.get('alert_up', [])
|
2018-02-16 02:10:19 +00:00
|
|
|
self.check_interval = settings.get('check_interval')
|
|
|
|
self.alert_after = settings.get('alert_after')
|
|
|
|
self.alert_every = settings.get('alert_every')
|
|
|
|
|
2018-04-19 00:05:33 +00:00
|
|
|
self.alert_count = 0
|
2018-02-16 02:10:19 +00:00
|
|
|
self.last_check = None
|
2018-04-19 00:05:33 +00:00
|
|
|
self.last_output = None
|
2018-04-14 05:02:03 +00:00
|
|
|
self.last_success = None
|
2018-04-10 00:07:32 +00:00
|
|
|
self.total_failure_count = 0
|
2018-02-16 02:10:19 +00:00
|
|
|
|
2018-07-13 06:01:36 +00:00
|
|
|
self._counter = counter
|
2019-06-03 18:44:39 +00:00
|
|
|
if logger is None:
|
|
|
|
self._logger = logging.getLogger(
|
|
|
|
'{}({})'.format(self.__class__.__name__, self.name)
|
|
|
|
)
|
|
|
|
else:
|
|
|
|
self._logger = logger.getChild(
|
|
|
|
'{}({})'.format(self.__class__.__name__, self.name)
|
|
|
|
)
|
2018-04-10 18:06:42 +00:00
|
|
|
|
2018-07-13 06:01:36 +00:00
|
|
|
def _count_check(self, is_success=True, is_alert=False):
|
|
|
|
if self._counter is not None:
|
|
|
|
self._counter.labels(
|
|
|
|
monitor=self.name,
|
|
|
|
status=('success' if is_success else 'failure'),
|
|
|
|
is_alert=is_alert,
|
|
|
|
).inc()
|
|
|
|
|
2018-02-16 02:10:19 +00:00
|
|
|
def should_check(self):
|
|
|
|
"""Determines if this Monitor should run it's check command"""
|
|
|
|
if not self.last_check:
|
|
|
|
return True
|
2018-04-09 19:08:42 +00:00
|
|
|
since_last_check = (datetime.now() - self.last_check).total_seconds()
|
2018-02-16 02:10:19 +00:00
|
|
|
return since_last_check >= self.check_interval
|
|
|
|
|
|
|
|
def check(self):
|
|
|
|
"""Returns None if skipped, False if failed, and True if successful
|
|
|
|
|
|
|
|
Will raise an exception if should alert
|
|
|
|
"""
|
|
|
|
if not self.should_check():
|
|
|
|
return None
|
2018-04-10 18:06:42 +00:00
|
|
|
|
|
|
|
output, ex = call_output(
|
|
|
|
self.command,
|
|
|
|
shell=isinstance(self.command, str),
|
|
|
|
)
|
2018-04-19 00:05:33 +00:00
|
|
|
output = maybe_decode(output)
|
2018-07-13 06:01:36 +00:00
|
|
|
self._logger.debug(output)
|
2018-02-16 02:10:19 +00:00
|
|
|
self.last_check = datetime.now()
|
2018-04-19 00:05:33 +00:00
|
|
|
self.last_output = output
|
2018-04-10 18:06:42 +00:00
|
|
|
|
2018-07-13 06:01:36 +00:00
|
|
|
is_success = None
|
|
|
|
try:
|
|
|
|
if ex is None:
|
|
|
|
is_success = True
|
|
|
|
self.success()
|
|
|
|
else:
|
|
|
|
is_success = False
|
|
|
|
self.failure()
|
|
|
|
except MinitorAlert:
|
|
|
|
self._count_check(is_success=is_success, is_alert=True)
|
|
|
|
raise
|
|
|
|
|
|
|
|
self._count_check(is_success=is_success)
|
|
|
|
return is_success
|
2018-02-16 02:10:19 +00:00
|
|
|
|
|
|
|
def success(self):
|
|
|
|
"""Handles success tasks"""
|
2018-04-15 00:27:37 +00:00
|
|
|
back_up = None
|
|
|
|
if not self.is_up():
|
|
|
|
back_up = MinitorAlert(
|
|
|
|
'{} check is up again!'.format(self.name),
|
|
|
|
self,
|
|
|
|
)
|
2018-04-10 00:07:32 +00:00
|
|
|
self.total_failure_count = 0
|
2018-02-18 04:45:37 +00:00
|
|
|
self.alert_count = 0
|
2018-04-14 05:02:03 +00:00
|
|
|
self.last_success = datetime.now()
|
2018-04-15 00:27:37 +00:00
|
|
|
if back_up:
|
|
|
|
raise back_up
|
2018-02-16 02:10:19 +00:00
|
|
|
|
|
|
|
def failure(self):
|
|
|
|
"""Handles failure tasks and possibly raises MinitorAlert"""
|
2018-04-10 00:07:32 +00:00
|
|
|
self.total_failure_count += 1
|
|
|
|
# Ensure we've hit the minimum number of failures to alert
|
|
|
|
if self.total_failure_count < self.alert_after:
|
2018-02-18 04:45:37 +00:00
|
|
|
return
|
2018-04-10 00:07:32 +00:00
|
|
|
|
|
|
|
failure_count = (self.total_failure_count - self.alert_after)
|
|
|
|
if self.alert_every > 0:
|
|
|
|
# Otherwise, we should check against our alert_every
|
|
|
|
should_alert = (failure_count % self.alert_every) == 0
|
2019-06-03 19:15:38 +00:00
|
|
|
elif self.alert_every == 0:
|
|
|
|
# Only alert on the first failure
|
|
|
|
should_alert = failure_count == 1
|
2018-02-18 04:45:37 +00:00
|
|
|
else:
|
2018-04-10 00:07:32 +00:00
|
|
|
should_alert = (failure_count >= (2 ** self.alert_count) - 1)
|
|
|
|
|
|
|
|
if should_alert:
|
2018-02-18 04:45:37 +00:00
|
|
|
self.alert_count += 1
|
2018-04-15 00:27:37 +00:00
|
|
|
raise MinitorAlert(
|
|
|
|
'{} check has failed {} times'.format(
|
|
|
|
self.name, self.total_failure_count
|
|
|
|
),
|
|
|
|
self
|
|
|
|
)
|
|
|
|
|
|
|
|
def is_up(self):
|
|
|
|
"""Indicates if the monitor is already alerting failures"""
|
|
|
|
return self.alert_count == 0
|
2018-02-16 02:10:19 +00:00
|
|
|
|
|
|
|
|
|
|
|
class Alert(object):
|
2019-06-03 18:44:39 +00:00
|
|
|
def __init__(self, name, config, counter=None, logger=None):
|
2018-02-16 02:10:19 +00:00
|
|
|
"""An alert must be named and have a config dict"""
|
|
|
|
self.name = name
|
|
|
|
self.command = config.get('command')
|
|
|
|
if not self.command:
|
|
|
|
raise InvalidAlertException('Invalid alert {}'.format(self.name))
|
|
|
|
|
2018-07-13 06:01:36 +00:00
|
|
|
self._counter = counter
|
2019-06-03 18:44:39 +00:00
|
|
|
if logger is None:
|
|
|
|
self._logger = logging.getLogger(
|
|
|
|
'{}({})'.format(self.__class__.__name__, self.name)
|
|
|
|
)
|
|
|
|
else:
|
|
|
|
self._logger = logger.getChild(
|
|
|
|
'{}({})'.format(self.__class__.__name__, self.name)
|
|
|
|
)
|
2018-04-10 18:06:42 +00:00
|
|
|
|
2018-07-13 06:01:36 +00:00
|
|
|
def _count_alert(self, monitor):
|
|
|
|
"""Increments the alert counter"""
|
|
|
|
if self._counter is not None:
|
|
|
|
self._counter.labels(
|
|
|
|
alert=self.name,
|
|
|
|
monitor=monitor,
|
|
|
|
).inc()
|
|
|
|
|
2018-02-16 02:10:19 +00:00
|
|
|
def _formated_command(self, **kwargs):
|
|
|
|
"""Formats command array or string with kwargs from Monitor"""
|
|
|
|
if isinstance(self.command, str):
|
|
|
|
return self.command.format(**kwargs)
|
|
|
|
args = []
|
|
|
|
for arg in self.command:
|
|
|
|
args.append(arg.format(**kwargs))
|
|
|
|
return args
|
|
|
|
|
2018-04-14 05:02:03 +00:00
|
|
|
def _format_datetime(self, dt):
|
|
|
|
"""Formats a datetime for an alert"""
|
|
|
|
if dt is None:
|
|
|
|
return 'Never'
|
|
|
|
return dt.isoformat()
|
|
|
|
|
2018-04-15 00:27:37 +00:00
|
|
|
def alert(self, message, monitor):
|
2018-02-16 02:10:19 +00:00
|
|
|
"""Calls the alert command for the provided monitor"""
|
2018-07-13 06:01:36 +00:00
|
|
|
self._count_alert(monitor.name)
|
2018-04-10 18:06:42 +00:00
|
|
|
output, ex = call_output(
|
2018-04-11 04:58:01 +00:00
|
|
|
self._formated_command(
|
|
|
|
alert_count=monitor.alert_count,
|
2018-04-15 00:27:37 +00:00
|
|
|
alert_message=message,
|
2018-04-11 04:58:01 +00:00
|
|
|
failure_count=monitor.total_failure_count,
|
2018-04-19 00:05:33 +00:00
|
|
|
last_output=monitor.last_output,
|
2018-04-14 05:02:03 +00:00
|
|
|
last_success=self._format_datetime(monitor.last_success),
|
2018-04-19 00:05:33 +00:00
|
|
|
monitor_name=monitor.name,
|
2018-04-11 04:58:01 +00:00
|
|
|
),
|
2018-02-16 02:10:19 +00:00
|
|
|
shell=isinstance(self.command, str),
|
|
|
|
)
|
2018-07-13 06:01:36 +00:00
|
|
|
self._logger.error(maybe_decode(output))
|
2018-04-10 18:06:42 +00:00
|
|
|
if ex is not None:
|
|
|
|
raise ex
|
2018-02-16 02:10:19 +00:00
|
|
|
|
|
|
|
|
|
|
|
class Minitor(object):
|
|
|
|
monitors = None
|
|
|
|
alerts = None
|
|
|
|
state = None
|
|
|
|
check_interval = None
|
|
|
|
|
2018-02-16 18:03:12 +00:00
|
|
|
def __init__(self):
|
2018-07-13 06:01:36 +00:00
|
|
|
self._logger = logging.getLogger(self.__class__.__name__)
|
|
|
|
self._alert_counter = None
|
|
|
|
self._monitor_counter = None
|
|
|
|
self._monitor_status_gauge = None
|
2018-02-16 18:03:12 +00:00
|
|
|
|
2018-07-16 01:30:13 +00:00
|
|
|
def _parse_args(self, args=None):
|
2018-07-13 06:01:36 +00:00
|
|
|
"""Parses command line arguments and returns them"""
|
|
|
|
parser = ArgumentParser(description='Minimal monitoring')
|
|
|
|
parser.add_argument(
|
|
|
|
'--config', '-c',
|
|
|
|
dest='config_path',
|
|
|
|
default='config.yml',
|
|
|
|
help='Path to the config YAML file to use',
|
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
'--metrics', '-m',
|
|
|
|
dest='metrics',
|
|
|
|
action='store_true',
|
|
|
|
help='Start webserver with metrics',
|
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
'--metrics-port', '-p',
|
|
|
|
dest='metrics_port',
|
|
|
|
type=int,
|
|
|
|
default=DEFAULT_METRICS_PORT,
|
|
|
|
help='Port to use when serving metrics',
|
|
|
|
)
|
2019-06-03 18:44:39 +00:00
|
|
|
parser.add_argument(
|
|
|
|
'--verbose', '-v',
|
|
|
|
action='count',
|
|
|
|
help=('Adjust log verbosity by increasing arg count. Default log',
|
|
|
|
'level is ERROR. Level increases with each `v`'),
|
|
|
|
)
|
2018-07-16 01:30:13 +00:00
|
|
|
return parser.parse_args(args)
|
2018-07-13 06:01:36 +00:00
|
|
|
|
|
|
|
def _setup(self, config_path):
|
2018-02-16 02:10:19 +00:00
|
|
|
"""Load all setup from YAML file at provided path"""
|
|
|
|
config = read_yaml(config_path)
|
|
|
|
self.check_interval = config.get('check_interval', 30)
|
2018-07-13 06:01:36 +00:00
|
|
|
self.monitors = [
|
2019-06-03 18:44:39 +00:00
|
|
|
Monitor(
|
|
|
|
mon,
|
|
|
|
counter=self._monitor_counter,
|
|
|
|
logger=self._logger,
|
|
|
|
)
|
2018-07-13 06:01:36 +00:00
|
|
|
for mon in config.get('monitors', [])
|
|
|
|
]
|
2018-02-16 02:10:19 +00:00
|
|
|
# Add default alert for logging
|
|
|
|
self.alerts = {
|
|
|
|
'log': Alert(
|
|
|
|
'log',
|
2018-07-13 06:01:36 +00:00
|
|
|
{'command': ['echo', '{alert_message}!']},
|
|
|
|
counter=self._alert_counter,
|
2019-06-03 18:44:39 +00:00
|
|
|
logger=self._logger,
|
2018-02-16 02:10:19 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
self.alerts.update({
|
2019-06-03 18:44:39 +00:00
|
|
|
alert_name: Alert(
|
|
|
|
alert_name,
|
|
|
|
alert,
|
|
|
|
counter=self._alert_counter,
|
|
|
|
logger=self._logger,
|
|
|
|
)
|
2018-02-16 02:10:19 +00:00
|
|
|
for alert_name, alert in config.get('alerts', {}).items()
|
|
|
|
})
|
|
|
|
|
2018-07-13 06:01:36 +00:00
|
|
|
def _validate_monitors(self):
|
2018-02-16 02:10:19 +00:00
|
|
|
"""Validates monitors are valid against other config values"""
|
|
|
|
for monitor in self.monitors:
|
|
|
|
# Validate that the interval is valid
|
|
|
|
if monitor.check_interval < self.check_interval:
|
|
|
|
raise InvalidMonitorException(
|
|
|
|
'Monitor {} check interval is lower global value {}'.format(
|
|
|
|
monitor.name, self.check_interval
|
|
|
|
)
|
|
|
|
)
|
|
|
|
# Validate that the the alerts for the monitor exist
|
2018-04-19 04:50:50 +00:00
|
|
|
for alert in chain(monitor.alert_down, monitor.alert_up):
|
2018-02-16 02:10:19 +00:00
|
|
|
if alert not in self.alerts:
|
|
|
|
raise InvalidMonitorException(
|
|
|
|
'Monitor {} contains an unknown alert: {}'.format(
|
|
|
|
monitor.name, alert
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
2018-07-13 06:01:36 +00:00
|
|
|
def _init_metrics(self):
|
|
|
|
self._alert_counter = Counter(
|
|
|
|
'minitor_alert_total',
|
|
|
|
'Number of Minitor alerts',
|
|
|
|
['alert', 'monitor'],
|
|
|
|
)
|
|
|
|
self._monitor_counter = Counter(
|
|
|
|
'minitor_check_total',
|
|
|
|
'Number of Minitor checks',
|
|
|
|
['monitor', 'status', 'is_alert'],
|
|
|
|
)
|
|
|
|
self._monitor_status_gauge = Gauge(
|
|
|
|
'minitor_monitor_up_count',
|
|
|
|
'Currently responsive monitors',
|
|
|
|
['monitor'],
|
2018-02-16 02:10:19 +00:00
|
|
|
)
|
|
|
|
|
2018-07-13 06:01:36 +00:00
|
|
|
def _loop(self):
|
2018-02-16 02:10:19 +00:00
|
|
|
while True:
|
2018-07-16 01:30:13 +00:00
|
|
|
self._check()
|
|
|
|
sleep(self.check_interval)
|
2018-07-13 06:01:36 +00:00
|
|
|
|
2018-07-16 01:30:13 +00:00
|
|
|
def _check(self):
|
|
|
|
"""The main run loop"""
|
|
|
|
for monitor in self.monitors:
|
|
|
|
try:
|
|
|
|
result = monitor.check()
|
|
|
|
if result is not None:
|
|
|
|
self._logger.info(
|
|
|
|
'%s: %s',
|
|
|
|
monitor.name,
|
|
|
|
'SUCCESS' if result else 'FAILURE'
|
|
|
|
)
|
|
|
|
except MinitorAlert as minitor_alert:
|
|
|
|
self._logger.warning(minitor_alert)
|
|
|
|
self._handle_minitor_alert(minitor_alert)
|
2018-02-16 02:10:19 +00:00
|
|
|
|
2018-07-16 01:30:13 +00:00
|
|
|
# Track the status of the Monitor
|
|
|
|
if self._monitor_status_gauge:
|
|
|
|
self._monitor_status_gauge.labels(
|
|
|
|
monitor=monitor.name,
|
|
|
|
).set(int(monitor.is_up()))
|
2018-02-14 23:37:15 +00:00
|
|
|
|
2018-07-13 06:01:36 +00:00
|
|
|
def _handle_minitor_alert(self, minitor_alert):
|
|
|
|
"""Issues all alerts for a provided monitor"""
|
|
|
|
monitor = minitor_alert.monitor
|
|
|
|
alerts = monitor.alert_up if monitor.is_up() else monitor.alert_down
|
|
|
|
for alert in alerts:
|
|
|
|
self.alerts[alert].alert(str(minitor_alert), monitor)
|
|
|
|
|
2019-06-03 18:44:39 +00:00
|
|
|
def _set_log_level(self, verbose):
|
|
|
|
"""Sets the log level for the class using the provided verbose count"""
|
|
|
|
if verbose == 1:
|
|
|
|
self._logger.setLevel(logging.WARNING)
|
|
|
|
elif verbose == 2:
|
|
|
|
self._logger.setLevel(logging.INFO)
|
|
|
|
elif verbose >= 3:
|
|
|
|
self._logger.setLevel(logging.DEBUG)
|
|
|
|
|
2018-07-16 01:30:13 +00:00
|
|
|
def run(self, args=None):
|
2018-07-13 06:01:36 +00:00
|
|
|
"""Runs Minitor in a loop"""
|
2018-07-16 01:30:13 +00:00
|
|
|
args = self._parse_args(args)
|
2018-07-13 06:01:36 +00:00
|
|
|
|
2019-06-03 18:44:39 +00:00
|
|
|
if args.verbose:
|
|
|
|
self._set_log_level(args.verbose)
|
|
|
|
|
2018-07-13 06:01:36 +00:00
|
|
|
if args.metrics:
|
|
|
|
self._init_metrics()
|
|
|
|
start_http_server(args.metrics_port)
|
|
|
|
|
2018-10-29 18:58:14 +00:00
|
|
|
self._setup(args.config_path)
|
|
|
|
self._validate_monitors()
|
|
|
|
|
2018-07-13 06:01:36 +00:00
|
|
|
self._loop()
|
|
|
|
|
2018-02-16 17:48:26 +00:00
|
|
|
|
2018-07-16 01:30:13 +00:00
|
|
|
def main(args=None):
|
2018-02-16 17:48:26 +00:00
|
|
|
try:
|
2018-07-16 01:30:13 +00:00
|
|
|
Minitor().run(args)
|
2018-02-16 17:48:26 +00:00
|
|
|
except KeyboardInterrupt:
|
|
|
|
pass
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
2018-02-14 23:37:15 +00:00
|
|
|
if __name__ == '__main__':
|
2018-02-16 17:48:26 +00:00
|
|
|
sys.exit(main())
|