python/aqmp: Add logging utility helpers

Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-id: 20210915162955.333025-8-jsnow@redhat.com
Signed-off-by: John Snow <jsnow@redhat.com>
This commit is contained in:
John Snow 2021-09-15 12:29:35 -04:00
parent c58b42e095
commit c1408345af

View File

@ -4,10 +4,15 @@ Miscellaneous Utilities
This module provides asyncio utilities and compatibility wrappers for This module provides asyncio utilities and compatibility wrappers for
Python 3.6 to provide some features that otherwise become available in Python 3.6 to provide some features that otherwise become available in
Python 3.7+. Python 3.7+.
Various logging and debugging utilities are also provided, such as
`exception_summary()` and `pretty_traceback()`, used primarily for
adding information into the logging stream.
""" """
import asyncio import asyncio
import sys import sys
import traceback
from typing import ( from typing import (
Any, Any,
Coroutine, Coroutine,
@ -140,3 +145,54 @@ async def wait_closed(writer: asyncio.StreamWriter) -> None:
while sock.fileno() != -1: while sock.fileno() != -1:
await asyncio.sleep(0) await asyncio.sleep(0)
# ----------------------------
# Section: Logging & Debugging
# ----------------------------
def exception_summary(exc: BaseException) -> str:
"""
Return a summary string of an arbitrary exception.
It will be of the form "ExceptionType: Error Message", if the error
string is non-empty, and just "ExceptionType" otherwise.
"""
name = type(exc).__qualname__
smod = type(exc).__module__
if smod not in ("__main__", "builtins"):
name = smod + '.' + name
error = str(exc)
if error:
return f"{name}: {error}"
return name
def pretty_traceback(prefix: str = " | ") -> str:
"""
Formats the current traceback, indented to provide visual distinction.
This is useful for printing a traceback within a traceback for
debugging purposes when encapsulating errors to deliver them up the
stack; when those errors are printed, this helps provide a nice
visual grouping to quickly identify the parts of the error that
belong to the inner exception.
:param prefix: The prefix to append to each line of the traceback.
:return: A string, formatted something like the following::
| Traceback (most recent call last):
| File "foobar.py", line 42, in arbitrary_example
| foo.baz()
| ArbitraryError: [Errno 42] Something bad happened!
"""
output = "".join(traceback.format_exception(*sys.exc_info()))
exc_lines = []
for line in output.split('\n'):
exc_lines.append(prefix + line)
# The last line is always empty, omit it
return "\n".join(exc_lines[:-1])