import threading import time # Threaded repeating timer thing # From https://stackoverflow.com/a/40965385/16432246 # It shouldn't drift, but that's untested # Keep in mind you can't catch Exceptions for this, it just crashes the thread. # Some more scheduling stuff: https://www.redwood.com/article/python-job-scheduling/ class RepeatedTimer(object): ''' Run stuff repeatedly every x seconds Example usage (from SO and ported to Python 3): from time import sleep def hello(name): print(f'Hello {name}!') print()"starting...") rt = RepeatedTimer(1, hello, "World") # it auto-starts, no need of rt.start() try: sleep(5) # your long-running job goes here... except: rt.stop() # better in a try/catch block to make sure the program ends! ''' def __init__(self, interval, function, *args, **kwargs): ''' Run a functions with arguments every ''' self._timer = None self.interval = interval self.function = function self.args = args self.kwargs = kwargs self.is_running = False self.next_call = time.time() self.start() def _run(self): self.is_running = False self.start() self.function(*self.args, **self.kwargs) def start(self): if not self.is_running: self.next_call += self.interval self._timer = threading.Timer( self.next_call - time.time(), self._run) self._timer.start() self.is_running = True def stop(self): self._timer.cancel() self.is_running = False def create_instances(config, checkers, alerts, logging): ''' Creates instances of all the extensions according to config Parameters: config: the dictionary containing the config Returns: instances (dict): A dictionary containing instances of the extensions example: {'site': {'checker': instanceOfCheckerTemplate}} ''' instances = {} # global arguments default_checker = '' default_alerter = '' default_logger = '' for service in config.keys(): if service == 'global-args': default_checker = config['global-args'].get('default-checker', '') default_alerter = config['global-args'].get('default-alerts', '') default_logger = config['global-args'].get('default-logging', '') continue instances[service] = {} # create an instance of checker with the arguments for them, including the optional `default-checker` checker_args = config[service]['checker-args'] if config[service].get('checker', '') != '': checker = config[service]['checker'] else: checker = default_checker instances[service]['checker'] = checkers[checker](checker_args) # and for alerts alerter_args = config[service]['alerts-args'] if config[service].get('alerts', '') != '': alerter = config[service]['alerts'] else: alerter = default_alerter instances[service]['alerts'] = alerts[alerter](alerter_args) # and for logging logger_args = config[service]['logging-args'] if config[service].get('logging', '') != '': logger = config[service]['logging'] else: logger = default_logger instances[service]['logging'] = logging[logger](logger_args) return instances def run_check(service_name, checker, alerts, logging): ''' Does the logic and stuff for running the checker, calling alerts/logging, and so on ''' status = checker.get_status() return_codes = checker.get_return_codes() status_message = return_codes[status] logging.log(service_name, status, status_message) alerts.alert(service_name, status, status_message)