Skip to content

Commit

Permalink
When saving a traceback, shorten very large locals (#3468)
Browse files Browse the repository at this point in the history
* When saving a traceback, shorten very large locals

A traceback in `log.txt` can be very large, especially when saving
locals like a huge set of result or junit XML. Adding a level of
traceback verbosity, `locals`, which will log locals, but shorten the
very long ones. `full` will keep showing everything on terminal.

Co-authored-by: Petr Šplíchal <psplicha@redhat.com>
  • Loading branch information
happz and psss authored Jan 28, 2025
1 parent 384bb56 commit cb2c31e
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 9 deletions.
21 changes: 17 additions & 4 deletions docs/overview.rst
Original file line number Diff line number Diff line change
Expand Up @@ -407,10 +407,23 @@ TMT_FORCE_COLOR

TMT_SHOW_TRACEBACK
By default, when tmt reports an error, the corresponding
traceback is not printed out. When ``TMT_SHOW_TRACEBACK`` is
set to any string except ``0``, traceback would be printed out.
When set to ``full``, traceback would list also local variables
in each stack frame.
traceback is not printed out. By setting this variable, the
traceback and details would be shown:

TMT_SHOW_TRACEBACK=0 (or unset)
Render only exception and its causes.

TMT_SHOW_TRACEBACK=1
Render also call stack for exception and each of its causes.

TMT_SHOW_TRACEBACK=2
Render also call stack for exception and each of its causes,
plus all local variables in each frame, trimmed to first 1024
characters of their values.

TMT_SHOW_TRACEBACK=full
Render everything that can be show: all causes, their call
stacks, all frames and all locals in their completeness.

TMT_OUTPUT_WIDTH
By default, the output width of commands like ``tmt * show`` is constrained
Expand Down
27 changes: 22 additions & 5 deletions tmt/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ def configure_constant(default: int, envvar: str) -> int:
log = fmf.utils.Logging('tmt').logger


#: How many leading characters to display in tracebacks with
#: ``TMT_SHOW_TRACEBACK=2``.
TRACEBACK_LOCALS_TRIM = 1024

# Default workdir root and max
WORKDIR_ROOT = Path('/var/tmp/tmt') # noqa: S108 insecure usage of temporary dir
WORKDIR_MAX = 1000
Expand Down Expand Up @@ -2394,7 +2398,12 @@ class TracebackVerbosity(enum.Enum):
DEFAULT = '0'
#: Render also call stack for exception and each of its causes.
VERBOSE = '1'
#: Render also call stack and local variables for exception and each of its causes.
#: Render also call stack for exception and each of its causes,
#: plus all local variables in each frame, trimmed to first 1024
#: characters of their values.
LOCALS = '2'
#: Render everything that can be shown: all causes, their call
#: stacks, all frames and all locals in their completeness.
FULL = 'full'

@classmethod
Expand Down Expand Up @@ -2549,11 +2558,19 @@ def render_exception_stack(
yield f'File {Y(frame.filename)}, line {Y(str(frame.lineno))}, in {Y(frame.name)}'
yield f' {B(frame.line)}'

if traceback_verbosity is TracebackVerbosity.FULL and frame.locals:
if frame.locals:
yield ''

for k, v in frame.locals.items():
yield f' {B(k)} = {Y(v)}'
if traceback_verbosity is TracebackVerbosity.LOCALS:
for k, v in frame.locals.items():
v_formatted = (v[:TRACEBACK_LOCALS_TRIM] + '...') \
if len(v) > TRACEBACK_LOCALS_TRIM else v

yield f' {B(k)} = {Y(v_formatted)}'

elif traceback_verbosity is TracebackVerbosity.FULL:
for k, v in frame.locals.items():
yield f' {B(k)} = {Y(v)}'

yield ''

Expand Down Expand Up @@ -2652,7 +2669,7 @@ def _render_exception(traceback_verbosity: TracebackVerbosity) -> Iterator[str]:
GeneralError(f"Cannot log error into logfile '{path}'.", causes=[exc]),
include_logfiles=False)

for line in _render_exception(traceback_verbosity=TracebackVerbosity.FULL):
for line in _render_exception(traceback_verbosity=TracebackVerbosity.LOCALS):
for stream in logfile_streams:
logger.print(line, file=stream)

Expand Down

0 comments on commit cb2c31e

Please sign in to comment.