diff --git a/dvc/logger.py b/dvc/logger.py index 95362d19cc..e9b8f9c6af 100644 --- a/dvc/logger.py +++ b/dvc/logger.py @@ -62,7 +62,7 @@ def format(self, record): return record.msg if record.levelname == "ERROR" or record.levelname == "CRITICAL": - exception, stack_trace = self._parse_exc(record.exc_info) + exception, stack_trace = self._parse_exc(record) return ( "{color}{levelname}{nc}: {description}" "{stack_trace}\n" @@ -122,13 +122,15 @@ def _walk_exc(self, exc_info): return exc_list, tb_list - def _parse_exc(self, exc_info): - if not exc_info: + def _parse_exc(self, record): + tb_only = getattr(record, "tb_only", False) + + if not record.exc_info: return (None, "") - exc_list, tb_list = self._walk_exc(exc_info) + exc_list, tb_list = self._walk_exc(record.exc_info) - exception = ": ".join(exc_list) + exception = None if tb_only else ": ".join(exc_list) if self._current_level() == logging.DEBUG: stack_trace = ( diff --git a/dvc/main.py b/dvc/main.py index a2fa79d144..d162874218 100644 --- a/dvc/main.py +++ b/dvc/main.py @@ -60,7 +60,8 @@ def main(argv=None): except Exception as exc: # pylint: disable=broad-except if isinstance(exc, OSError) and exc.errno == errno.EMFILE: logger.exception( - "too many open files, please increase your `ulimit`" + "too many open files, please increase your `ulimit`", + extra={"tb_only": True}, ) else: logger.exception("unexpected error") diff --git a/tests/unit/test_logger.py b/tests/unit/test_logger.py index 201139f2eb..0847a5e451 100644 --- a/tests/unit/test_logger.py +++ b/tests/unit/test_logger.py @@ -102,6 +102,25 @@ def test_exception_under_verbose(self, caplog): assert expected == formatter.format(caplog.records[0]) + def test_tb_only(self, caplog): + with caplog.at_level(logging.DEBUG, logger="dvc"): + try: + raise Exception("description") + except Exception: + stack_trace = traceback.format_exc() + logger.exception("something", extra={"tb_only": True}) + + expected = ( + "{red}ERROR{nc}: something\n" + "{red}{line}{nc}\n" + "{stack_trace}" + "{red}{line}{nc}\n".format( + line="-" * 60, stack_trace=stack_trace, **colors + ) + ) + + assert expected == formatter.format(caplog.records[0]) + def test_nested_exceptions(self, caplog): with caplog.at_level(logging.DEBUG, logger="dvc"): try: