diff --git a/src/corelibs/debug_handling/debug_helpers.py b/src/corelibs/debug_handling/debug_helpers.py index 27c279d..a042812 100644 --- a/src/corelibs/debug_handling/debug_helpers.py +++ b/src/corelibs/debug_handling/debug_helpers.py @@ -4,7 +4,12 @@ Various debug helpers import traceback import os +import sys +from typing import Tuple, Type +from types import TracebackType +# _typeshed.OptExcInfo +OptExcInfo = Tuple[None, None, None] | Tuple[Type[BaseException], BaseException, TracebackType] def call_stack( start: int = 0, @@ -41,4 +46,30 @@ def call_stack( # print(f"* HERE: {dump_data(stack)}") return f"{separator}".join(f"{os.path.basename(f.filename)}:{f.name}:{f.lineno}" for f in __stack) + +def exception_stack( + exc_stack: OptExcInfo | None = None, + separator: str = ' -> ' +) -> str: + """ + Exception traceback, if no sys.exc_info is set, run internal + + Keyword Arguments: + exc_stack {OptExcInfo | None} -- _description_ (default: {None}) + separator {str} -- _description_ (default: {' -> '}) + + Returns: + str -- _description_ + """ + if exc_stack is not None: + _, _, exc_traceback = exc_stack + else: + exc_traceback = None + _, _, exc_traceback = sys.exc_info() + stack = traceback.extract_tb(exc_traceback) + if not separator: + separator = ' -> ' + # print(f"* HERE: {dump_data(stack)}") + return f"{separator}".join(f"{os.path.basename(f.filename)}:{f.name}:{f.lineno}" for f in stack) + # __END__ diff --git a/src/corelibs/logging_handling/log.py b/src/corelibs/logging_handling/log.py index 9a80db9..03af8b3 100644 --- a/src/corelibs/logging_handling/log.py +++ b/src/corelibs/logging_handling/log.py @@ -12,7 +12,7 @@ from pathlib import Path from typing import MutableMapping, TextIO, TypedDict, Any, TYPE_CHECKING, cast from corelibs.logging_handling.logging_level_handling.logging_level import LoggingLevel from corelibs.string_handling.text_colors import Colors -from corelibs.debug_handling.debug_helpers import call_stack +from corelibs.debug_handling.debug_helpers import call_stack, exception_stack if TYPE_CHECKING: from multiprocessing import Queue @@ -225,11 +225,12 @@ class LogParent: if extra is None: extra = {} extra['stack_trace'] = call_stack(skip_last=2) + extra['exception_trace'] = exception_stack() # write to console first with extra flag for filtering in file if log_error: self.logger.log( LoggingLevel.ERROR.value, - f"<=EXCEPTION> {msg} [{extra['stack_trace']}]", + f"<=EXCEPTION={extra['exception_trace']}> {msg} [{extra['stack_trace']}]", *args, extra=dict(extra) | {'console': True}, stacklevel=2 ) self.logger.log(LoggingLevel.EXCEPTION.value, msg, *args, exc_info=True, extra=extra, stacklevel=2) diff --git a/test-run/logging_handling/log.py b/test-run/logging_handling/log.py index 35433b9..e28a0de 100644 --- a/test-run/logging_handling/log.py +++ b/test-run/logging_handling/log.py @@ -3,9 +3,11 @@ Log logging_handling.log testing """ # import atexit +import sys from pathlib import Path # this is for testing only from corelibs.logging_handling.log import Log, Logger +from corelibs.debug_handling.debug_helpers import exception_stack, call_stack from corelibs.logging_handling.logging_level_handling.logging_level import LoggingLevel @@ -78,6 +80,8 @@ def main(): __test = 5 / 0 print(f"Divied: {__test}") except ZeroDivisionError as e: + print(f"** sys.exec_info(): {sys.exc_info()}") + print(f"** sys.exec_info(): [{exception_stack()}] | [{exception_stack(sys.exc_info())}] | [{call_stack()}]") log.logger.critical("Divison through zero: %s", e) log.exception("Divison through zero: %s", e) diff --git a/uv.lock b/uv.lock index 51ee24c..de0427d 100644 --- a/uv.lock +++ b/uv.lock @@ -44,7 +44,7 @@ wheels = [ [[package]] name = "corelibs" -version = "0.19.0" +version = "0.19.1" source = { editable = "." } dependencies = [ { name = "jmespath" },