mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-16 06:22:59 +00:00
scrub repetitive gen.py, coroutine.py frames from coroutine tracebacks
when logging exceptions
This commit is contained in:
@@ -26,7 +26,7 @@ import tornado.httpserver
|
|||||||
import tornado.options
|
import tornado.options
|
||||||
from tornado.httpclient import HTTPError
|
from tornado.httpclient import HTTPError
|
||||||
from tornado.ioloop import IOLoop, PeriodicCallback
|
from tornado.ioloop import IOLoop, PeriodicCallback
|
||||||
from tornado.log import LogFormatter, app_log, access_log, gen_log
|
from tornado.log import app_log, access_log, gen_log
|
||||||
from tornado import gen, web
|
from tornado import gen, web
|
||||||
|
|
||||||
import IPython
|
import IPython
|
||||||
@@ -47,6 +47,7 @@ from .handlers.static import CacheControlStaticFilesHandler
|
|||||||
|
|
||||||
from . import orm
|
from . import orm
|
||||||
from ._data import DATA_FILES_PATH
|
from ._data import DATA_FILES_PATH
|
||||||
|
from .log import CoroutineLogFormatter
|
||||||
from .traitlets import URLPrefix
|
from .traitlets import URLPrefix
|
||||||
from .utils import (
|
from .utils import (
|
||||||
url_path_join,
|
url_path_join,
|
||||||
@@ -350,7 +351,7 @@ class JupyterHub(Application):
|
|||||||
|
|
||||||
handlers = List()
|
handlers = List()
|
||||||
|
|
||||||
_log_formatter_cls = LogFormatter
|
_log_formatter_cls = CoroutineLogFormatter
|
||||||
http_server = None
|
http_server = None
|
||||||
proxy_process = None
|
proxy_process = None
|
||||||
io_loop = None
|
io_loop = None
|
||||||
|
40
jupyterhub/log.py
Normal file
40
jupyterhub/log.py
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
"""logging utilities"""
|
||||||
|
# Copyright (c) Jupyter Development Team.
|
||||||
|
# Distributed under the terms of the Modified BSD License.
|
||||||
|
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
from tornado.log import LogFormatter
|
||||||
|
|
||||||
|
def coroutine_traceback(typ, value, tb):
|
||||||
|
"""Scrub coroutine frames from a traceback
|
||||||
|
|
||||||
|
Coroutine tracebacks have a bunch of identical uninformative frames at each yield point.
|
||||||
|
This removes those extra frames, so tracebacks should be easier to read.
|
||||||
|
This might be a horrible idea.
|
||||||
|
|
||||||
|
Returns a list of strings (like traceback.format_tb)
|
||||||
|
"""
|
||||||
|
all_frames = traceback.extract_tb(tb)
|
||||||
|
useful_frames = []
|
||||||
|
for frame in all_frames:
|
||||||
|
if frame[0] == '<string>' and frame[2] == 'raise_exc_info':
|
||||||
|
continue
|
||||||
|
# start out conservative with filename + function matching
|
||||||
|
# maybe just filename matching would be sufficient
|
||||||
|
elif frame[0].endswith('tornado/gen.py') and frame[2] in {'run', 'wrapper'}:
|
||||||
|
continue
|
||||||
|
elif frame[0].endswith('tornado/concurrent.py') and frame[2] == 'result':
|
||||||
|
continue
|
||||||
|
useful_frames.append(frame)
|
||||||
|
tb_list = ['Traceback (most recent call last):\n']
|
||||||
|
tb_list.extend(traceback.format_list(useful_frames))
|
||||||
|
tb_list.extend(traceback.format_exception_only(typ, value))
|
||||||
|
return tb_list
|
||||||
|
|
||||||
|
|
||||||
|
class CoroutineLogFormatter(LogFormatter):
|
||||||
|
"""Log formatter that scrubs coroutine frames"""
|
||||||
|
def formatException(self, exc_info):
|
||||||
|
return ''.join(coroutine_traceback(*exc_info))
|
||||||
|
|
Reference in New Issue
Block a user