|
"""A mixin for adding a debug log file.""" |
|
|
|
|
|
|
|
|
|
import contextlib |
|
import logging |
|
import os |
|
import sys |
|
import tempfile |
|
import traceback |
|
import warnings |
|
|
|
from traitlets import Unicode |
|
from traitlets.config import Configurable |
|
|
|
|
|
class DebugLogFileMixin(Configurable): |
|
debug_log_path = Unicode("", config=True, help="Path to use for the debug log file") |
|
|
|
@contextlib.contextmanager |
|
def debug_logging(self): |
|
log_path = self.debug_log_path |
|
if os.path.isdir(log_path): |
|
log_path = os.path.join(log_path, "jupyterlab-debug.log") |
|
if not log_path: |
|
handle, log_path = tempfile.mkstemp(prefix="jupyterlab-debug-", suffix=".log") |
|
os.close(handle) |
|
log = self.log |
|
|
|
|
|
for h in log.handlers: |
|
h.setLevel(self.log_level) |
|
log.setLevel("DEBUG") |
|
|
|
|
|
_debug_handler = logging.FileHandler(log_path, "w", "utf8", delay=True) |
|
_log_formatter = self._log_formatter_cls(fmt=self.log_format, datefmt=self.log_datefmt) |
|
_debug_handler.setFormatter(_log_formatter) |
|
_debug_handler.setLevel("DEBUG") |
|
|
|
log.addHandler(_debug_handler) |
|
|
|
try: |
|
yield |
|
except Exception as ex: |
|
_, _, exc_traceback = sys.exc_info() |
|
msg = traceback.format_exception(ex.__class__, ex, exc_traceback) |
|
for line in msg: |
|
self.log.debug(line) |
|
if isinstance(ex, SystemExit): |
|
warnings.warn(f"An error occurred. See the log file for details: {log_path!s}") |
|
raise |
|
warnings.warn("An error occurred.") |
|
warnings.warn(msg[-1].strip()) |
|
warnings.warn(f"See the log file for details: {log_path!s}") |
|
self.exit(1) |
|
else: |
|
log.removeHandler(_debug_handler) |
|
_debug_handler.flush() |
|
_debug_handler.close() |
|
try: |
|
os.remove(log_path) |
|
except FileNotFoundError: |
|
pass |
|
log.removeHandler(_debug_handler) |
|
|