def error_callback(request_handler, exc_info): settings = request_handler.proj_settings server_name = settings['server_name'] + ':{}'.format(str(exc_info[1])) now = datetime.datetime.utcnow() out_lines = ['request_summary:{}\n'.format(request_handler._request_summary()), 'request:{}\n'.format(request_handler), "now:{}\n".format(utils.util_time_datetime_str(now)), "request_uri:{}\n".format(request_handler.request.uri), "request_body:{}\n".format(request_handler.request.body), "request_headers:{}\n".format(request_handler.request.headers), ] if exc_info: out_lines.append("errors:{}\n".format(exc_info[0])) out_lines.append(formatting.format_exc_info(*exc_info, truncate_vals=1000)) # for line in better_exceptions.format_exception(*exc_info): # out_lines.append(line) # generated_by_dict_unpack: request_handler logger = request_handler.logger if not logger.name.endswith(".error."): logger = logging.getLogger(logger.name + ".error.") logger.warning("error_callback:{}".format("send error msg")) # loop = ioloop.IOLoop.current() # func = http_email_send_from_settings(settings, server_name, ''.join(out_lines)) logger.error('error_callback' + ''.join(out_lines)) # service_manager: ServiceManager = request_handler.service_manager data = { 'server_name': server_name, 'content': ''.join(out_lines) } from {{cookiecutter.project_slug}}.tasks.tasks import task_web_send_web_error_email raw_str = escape.json_encode(data) task_web_send_web_error_email.apply_async([raw_str], queue='error')
def util_error_send_email(sender, task_id, exception, args, traceback, einfo, **kwargs): logger.info("[send_error_email]: {}, {}, {}".format(sender, task_id, exception)) server_name = settings['server_name'] lines = ['task_id:{}, args:{}, kwargs:{}\n'.format(task_id, args, kwargs)] exc_info = (type(exception), exception, traceback) lines.append(formatting.format_exc_info(*exc_info, truncate_vals=1000)) content = ''.join(lines) # remote_email_helper = RemoteEmail.create_from_settings(email_settings_d) subject = 'error_notify:{}:celery:{}'.format(server_name, str(exception)) logger.warning('send_error_email:{}'.format(content)) from {{cookiecutter.project_slug}}.tasks.error.task_error_callback import error_callback error_callback.apply_async([json.dumps({ 'server_name': subject, 'content': content })], queue='{{cookiecutter.project_slug}}_error')
def format(thing=None, **kwargs): """ Render the traceback of an exception or a frame's call stack Call this without arguments inside an `except` block to get a traceback for the currently handled exception: ``` try: something() except: logger.err(stackprinter.format(**kwargs)) ``` Explicitly pass an exception (or a triple as returned by `sys.exc_info()`) to handle that particular exception anywhere, also outside an except block. ``` try: something() except Exception as e: last_exc = e if last_exc: logger.err(stackprinter.format(last_exc, **kwargs)) ``` Pass a frame object to see the call stack leading up to that frame: ``` stack = stackprinter.format(sys._getframe(2), **kwargs)) ``` Pass a thread object to see its current call stack: ``` thread = threading.Thread(target=something) thread.start() # (...) stack = stackprinter.format(thread, **kwargs)) ``` Note: This displays variable values as they are _at the time of formatting_. In multi-threaded programs, variables can change while we're busy walking the stack & printing them. So, if nothing seems to make sense, consider that your exception and the traceback messages are from slightly different times. Sadly, there is no responsible way to freeze all other threads as soon as we want to inspect some thread's call stack (...or is there?) Params --- thing: (optional) exception, sys.exc_info() tuple, frame or thread What to format. Defaults to the currently handled exception or current stack frame. style: string 'plaintext' (default): Output just text 'darkbg', 'darkbg2', 'darkbg3', 'lightbg', 'lightbg2', 'lightbg3': Enable colors, for use in terminals that support 256 ansi colors or in jupyter notebooks (or even with `ansi2html`) source_lines: int or 'all' Select how much source code context will be shown. int 0: Don't include a source listing. int n > 0: Show n lines of code. (default: 5) string 'all': Show the whole scope of the frame. show_signature: bool (default True) Always include the function header in the source code listing. show_vals: str or None Select which variable values will be shown. 'line': Show only the variables on the highlighted line. 'like_source' (default): Show only those visible in the source listing 'all': Show every variable in the scope of the frame. None: Don't show any variable values. truncate_vals: int Maximum number of characters to be used for each variable value. Default: 500 suppressed_paths: list of regex patterns Set less verbose formatting for frames whose code lives in certain paths (e.g. library code). Files whose path matches any of the given regex patterns will be considered boring. The first call to boring code is rendered with fewer code lines (but with argument values still visible), while deeper calls within boring code get a single line and no variable values. Example: To hide numpy internals from the traceback, set `suppressed_paths=[r"lib/python.*/site-packages/numpy"]` reverse: bool List the innermost frame first. add_summary: True, False, 'auto' Append a compact list of involved files and source lines, similar to the built-in traceback message. 'auto' (default): do that if the main traceback is longer than 50 lines. """ if isinstance(thing, types.FrameType): return fmt.format_stack_from_frame(thing, **kwargs) elif isinstance(thing, Thread): return format_thread(thing, **kwargs) elif isinstance(thing, Exception): exc_info = (thing.__class__, thing, thing.__traceback__) return format(exc_info, **kwargs) elif _is_exc_info(thing): return fmt.format_exc_info(*thing, **kwargs) else: raise ValueError("Can't format %s. "\ "Expected an exception instance, sys.exc_info() tuple,"\ "a frame or a thread object." % repr(thing))