"""Jobs Inputs/Outputs logger.""" from functools import wraps import re import sentry_sdk from video import config from video.constants import job_io_fields from video.constants import job_statuses from video.constants import services from video.models import ows_video def activity_task_logger( input_fields, is_first_handler=True, is_last_handler=True, job_type=None, output_fields_to_omit_from_pipeline_payload=[]): """Log Activity Tasks in ows-video. Args: input_fields (list): the input fields. output_fields (list): the output fields returned by the decorated function. is_first_handler (boolean): Indicates this is the first handler. is_last_handler (boolean): Indicates this is the last handler. job_type (string): Job type if different than handler name. output_fields_to_omit_from_pipeline_payload (list): Output fields to omit from pipeline payload. Returns: function (callable): The decorated function. """ def io_fields_logger(activity_task_handler): @wraps(activity_task_handler) def wrapper(inputs): job_id_field = '{}_job_id'.format( job_type or activity_task_handler.__name__) job_id = inputs[job_id_field] if config.ENVIRONMENT == config.ENVIRONMENT_TEST: from owsrequest.utils import mock_request mock_request.get( service=services.OWS_VIDEO, path='/job/{}'.format(job_id), ) mock_request.post( service=services.OWS_VIDEO, path='/job', ) job_fields_to_set_before_calling_activity_task_handler = {} job_fields_to_set_after_calling_activity_task_handler = {} outputs = {} try: filtered_inputs = { input_field: input_value for input_field, input_value in inputs.items() if input_field in input_fields} if is_first_handler: if filtered_inputs: job_fields_to_set_before_calling_activity_task_handler[ 'inputs'] = filtered_inputs job_fields_to_set_before_calling_activity_task_handler[ 'status'] = job_statuses.PROGRESSING ows_video.set_job_fields({ **job_fields_to_set_before_calling_activity_task_handler, # noqa 'id': job_id, }) # Execute the handler. outputs = activity_task_handler(filtered_inputs) or {} has_errors = any( re.match(r'\Aerror_.+\Z', k) for k, v in outputs.items()) if is_first_handler or is_last_handler or has_errors: job_fields_to_set_after_calling_activity_task_handler[ 'outputs'] = outputs if has_errors: job_fields_to_set_after_calling_activity_task_handler[ 'status'] = job_statuses.ERROR elif is_last_handler: job_fields_to_set_after_calling_activity_task_handler[ 'status'] = job_statuses.COMPLETE except Exception as e: sentry_sdk.capture_exception(e) outputs = {job_io_fields.ERROR_UNKNOWN: str(e)} job_fields_to_set_after_calling_activity_task_handler[ 'status'] = job_statuses.ERROR job_fields_to_set_after_calling_activity_task_handler[ 'outputs'] = outputs finally: if job_fields_to_set_after_calling_activity_task_handler: ows_video.set_job_fields({ **job_fields_to_set_after_calling_activity_task_handler, # noqa 'id': job_id, }) return { key: value for key, value in outputs.items() if key not in output_fields_to_omit_from_pipeline_payload} return wrapper return io_fields_logger