def _add_last_error_info(self, exc_info=None): ex = exc_info[1] if show_exc_info(ex): # if we are showing internal task - we don't know how to "minimize" stack. # everything is databand.* ... isolate = not self.task.task_definition.full_task_family.startswith( "databand.") traceback_str = self.settings.log.format_exception_as_str( exc_info=exc_info, isolate=isolate) self.banner.column( colored("TRACEBACK", color="red", attrs=["bold"]), traceback_str, raw_name=True, ) self.banner.column( colored("ERROR MESSAGE", color="red", attrs=["bold"]), str(ex), raw_name=True, ) self.banner.column( colored("HELP", attrs=["bold"]), get_help_msg(ex), raw_name=True, skip_if_empty=True, ) self.banner.column( colored("CAUSED BY", color="red", attrs=["bold"]), nested_exceptions_str(ex, limit=3), raw_name=True, skip_if_empty=True, )
def get_callable_spec(self): if not self._callable_spec: try: self._callable_spec = build_callable_spec( class_or_func=self.original_class_or_func ) except Exception as ex: logger.error( "Failed to create task %s: %s\n%s\n", self.original_class_or_func.__name__, str(ex), user_side_code(context=5), exc_info=show_exc_info(ex), ) raise return self._callable_spec
def decorated(item): try: func_spec = build_task_decorator_spec( item=item, decorator_kwargs=decorator_kwargs, default_result=task_default_result, ) # we can't create class dynamically because of python2/3 # __name__ is not overridable task_cls = TaskMetaclass( str(item.__name__), (task_type, ), dict( _conf__decorator_spec=func_spec, _callable_item=None, __doc__=item.__doc__, __module__=item.__module__, defaults=task_defaults, ), ) except Exception as ex: logger.error( "Failed to create task %s: %s\n%s\n", item.__name__, str(ex), user_side_code(context=5), exc_info=show_exc_info(ex), ) raise if func_spec.is_class: callable_item = six.add_metaclass(_DecoratedUserClassMeta)(item) else: callable_item = DbndFuncProxy(task_cls=task_cls) task_cls._callable_item = callable_item callable_item.func = item callable_item.task_cls = task_cls callable_item.task = task_cls callable_item.t = task_cls return task_cls._callable_item
def decorated(class_or_func): try: func_spec = build_task_decorator_spec( class_or_func=class_or_func, decorator_kwargs=decorator_kwargs, default_result=task_default_result, ) except Exception as ex: logger.error( "Failed to create task %s: %s\n%s\n", class_or_func.__name__, str(ex), user_side_code(context=5), exc_info=show_exc_info(ex), ) raise fp = TaskClsBuilder(func_spec, task_type, task_defaults) if func_spec.is_class: wrapper = six.add_metaclass(_DecoratedUserClassMeta)(class_or_func) fp._callable_item = wrapper else: @functools.wraps(class_or_func) def wrapper(*args, **kwargs): if in_tracking_mode(): with fp.tracking_context(args, kwargs) as track_result_callback: return track_result_callback(fp.func(*args, **kwargs)) return _call_handler( fp.get_task_cls(), call_user_code=fp.func, call_args=args, call_kwargs=kwargs, ) wrapper.dbnd_run = fp.dbnd_run wrapper.__is_dbnd_task__ = True wrapper.func = class_or_func # we're using CallableLazyObjectProxy to have lazy evaluation for creating task_cls # this is only orchestration scenarios task_cls = CallableLazyObjectProxy(fp.get_task_cls) wrapper.task_cls = task_cls wrapper.task = task_cls wrapper.t = task_cls # we need lazy task_definition here, for example for dbnd_task_as_bash_operator wrapper.task_definition = CallableLazyObjectProxy( fp.get_task_definition) # we need to manually register the task here, since in regular flow # this happens in TaskMetaclass, but it's not invoked here due to lazy # evaluation using CallableLazyObjectProxy tp = TaskPassport.from_func_spec(func_spec, decorator_kwargs) # TODO: we can use CallableLazyObjectProxy object (task_cls) instead of task_cls_factory r = get_task_registry() r.register_task_cls_factory( task_cls_factory=fp.get_task_cls, full_task_family=tp.full_task_family, task_family=tp.task_family, ) return wrapper
def get_databand_error_message(ex, args=None, sys_exit=True): args = args or sys.argv please_report = False print_source = True if isinstance(ex, DatabandRunError): # we already printed all information! return ( "There is an error! Your run has failed!", DatabandExitCodes.execution_failed, ) if isinstance(ex, DatabandRuntimeError): exit_code = DatabandExitCodes.execution_failed elif isinstance(ex, DatabandConfigError): exit_code = DatabandExitCodes.configuration_error elif isinstance(ex, DatabandSystemError): exit_code = DatabandExitCodes.error please_report = True elif isinstance(ex, DatabandError): exit_code = DatabandExitCodes.error elif ex.__class__.__name__ == "NoCredentialsError": # aws exit_code = DatabandExitCodes.configuration_error ex = friendly_error.config.no_credentials() print_source = False else: please_report = True exit_code = DatabandExitCodes.unknown_error msg = str(ex) extra_msg_lines = [] nested_exceptions = nested_exceptions_str(ex) if nested_exceptions: extra_msg_lines.append("Caused by: \n%s\n" % indent(nested_exceptions, "\t")) help_msg = get_help_msg(ex) if help_msg: extra_msg_lines.append(" Help: \n%s\n" % indent(help_msg, "\t")) user_frame_info_str = get_user_frame_info_str(ex) if user_frame_info_str and print_source: extra_msg_lines.append("Source: \n%s\n" % indent(user_frame_info_str, "\t")) # if we crashed before finishing bootstrap we probably want to see the full trace, and we could have failed during config init so the verbose flag does nothing if (show_exc_info(ex) or config.getboolean("databand", "verbose") or not bootstrap._dbnd_bootstrap): error_info = sys.exc_info() extra_msg_lines.append(format_exception_as_str(error_info)) msg = truncate_msg(msg, ERROR_MESSAGE_HEAD_SIZE, ERROR_MESSAGE_TAIL_SIZE) if please_report: extra_msg_lines.append( " Please report it to [email protected] or appropriate slack channel!" ) msg = ("There is an error! Your run has failed with {exc_type}\n" "{sep}\n" " Command line: {command_line}\n" " Failure:\n{msg}\n\n" "{extra_msg}\n" "{sep}\n" "".format( sep=console_utils.error_separator(), command_line=subprocess.list2cmdline(args or []), sep_small=console_utils.error_separator_small(), msg=console_utils.bold(indent(msg, "\t")), exc_type=ex.__class__.__name__, extra_msg="\n ".join(extra_msg_lines), )) return msg, exit_code