from functools import wraps import requests from flask import current_app def cronitor(task_name): def decorator(func): def ping_cronitor(command): if not current_app.config['CRONITOR_ENABLED']: return # it's useful to have a log that a periodic task has started in case it # get stuck without generating any other logs - we know it got this far current_app.logger.info(f'Pinging Cronitor for Celery task {task_name}') task_slug = current_app.config['CRONITOR_KEYS'].get(task_name) if not task_slug: current_app.logger.error( 'Cronitor enabled but task_name {} not found in environment'.format(task_name) ) return if command not in {'run', 'complete', 'fail'}: raise ValueError('command {} not a valid cronitor command'.format(command)) try: resp = requests.get( 'https://cronitor.link/{}/{}'.format(task_slug, command), # cronitor limits msg to 1000 characters params={ 'host': current_app.config['API_HOST_NAME'], } ) resp.raise_for_status() except requests.RequestException as e: current_app.logger.warning('Cronitor API failed for task {} due to {}'.format( task_name, repr(e) )) @wraps(func) def inner_decorator(*args, **kwargs): ping_cronitor('run') status = 'fail' try: ret = func(*args, **kwargs) status = 'complete' return ret finally: ping_cronitor(status) return inner_decorator return decorator