diff --git a/lib/pbench/cli/server/repair.py b/lib/pbench/cli/server/repair.py index 4e35c94738..e5113f3920 100644 --- a/lib/pbench/cli/server/repair.py +++ b/lib/pbench/cli/server/repair.py @@ -61,7 +61,7 @@ def repair_audit(kwargs): didit = False for key, value in a.items(): if type(value) is str and len(value) > LIMIT: - a[key] = value[:LIMIT] + a[key] = f"[TRUNC({len(value)})]" + value[:LIMIT] detailer.message(f"{name} [{key}] truncated ({len(value)}) to {LIMIT}") didit = True if didit: @@ -112,34 +112,22 @@ def get_md5(file: Path) -> Optional[str]: isolator = controller / resource_id if isolator.is_dir(): tars = list(isolator.glob("*.tar.xz")) - if len(tars) == 1: - tar = tars[0] - if get_md5(tar) != resource_id: - detailer.error( - f"Isolated tarball {tar} MD5 doesn't match isolator {resource_id}" - ) - return None - verifier.status(f"Found {tars[0]} for ID {resource_id}", 2) - return tars[0] - else: + if len(tars) > 1: detailer.error( f"Isolator directory {isolator} contains multiple tarballs: {[str(t) for t in tars]}" ) - for tar in tars: - if get_md5(tar) == resource_id: - verifier.status( - f"Found {[str(t) for t in tars]} for ID {resource_id}", - 2, - ) - return tar - detailer.error( - f"Isolator directory {isolator} doesn't contain a tarball for {resource_id}" - ) - return None + for tar in tars: + if get_md5(tar) == resource_id: + verifier.status(f"Found {tar} for ID {resource_id}", 2) + return tar + detailer.error( + f"Isolator directory {isolator} doesn't contain a tarball for {resource_id}" + ) + return None else: for tar in controller.glob("**/*.tar.xz"): if get_md5(tar) == resource_id: - verifier.status(f"Found {str(tar)} for ID {resource_id}", 2) + verifier.status(f"Found {tar} for ID {resource_id}", 2) return tar return None diff --git a/lib/pbench/server/cache_manager.py b/lib/pbench/server/cache_manager.py index e3e096374a..691d7b9546 100644 --- a/lib/pbench/server/cache_manager.py +++ b/lib/pbench/server/cache_manager.py @@ -1029,20 +1029,32 @@ def subprocess_run( # tar failures can include a message for each file in the # archive, and can be quite large. Break stderr into lines, and # gather those lines only up to our configured size limit. + # + # The exception we raise and ultimately log will start by + # identifying the tarball, followed by the command and the + # return code. The appended stderr may provide additional + # useful context, but in general beyond the first line it'll + # be fairly meaningless. size = 0 message = [] lines = process.stderr.split("\n") + prefix = "" for line in lines: # Skip empty lines if not line: continue size += len(line) if size > MAX_ERROR: + prefix = "[TRUNC]" break message.append(line) - # If even the first line was too big, truncate it - msg = "\n".join(message) if message else lines[0][:MAX_ERROR] + # Prefix with [TRUNC] if we're not including the entire message + # and truncate the first line if it was too long by itself. + if message: + msg = prefix + ("\n".join(message)) + else: + msg = "[TRUNC]" + lines[0][:MAX_ERROR] raise exception( ctx, f"{cmd[0]} exited with status {process.returncode}: {msg!r}", diff --git a/lib/pbench/server/indexing_tarballs.py b/lib/pbench/server/indexing_tarballs.py index 85d3172b79..58b39e62d8 100644 --- a/lib/pbench/server/indexing_tarballs.py +++ b/lib/pbench/server/indexing_tarballs.py @@ -632,8 +632,10 @@ def sighup_handler(*args): # Re-raise a SIGTERM to avoid it being lumped in with general # exception handling below. raise - except Exception: - idxctx.logger.exception(error_code["GENERIC_ERROR"].message) + except Exception as e: + idxctx.logger.exception( + "{}: {!r}", error_code["GENERIC_ERROR"].message, str(e) + ) res = error_code["GENERIC_ERROR"] else: # No exceptions while processing tar balls, success. diff --git a/lib/pbench/test/unit/server/test_cache_manager.py b/lib/pbench/test/unit/server/test_cache_manager.py index d48dce84ab..118c6b863d 100644 --- a/lib/pbench/test/unit/server/test_cache_manager.py +++ b/lib/pbench/test/unit/server/test_cache_manager.py @@ -406,8 +406,8 @@ def mock_run(args, **_kwargs): "errmsg,expected", ( ("Error unpacking tarball\n", "Error unpacking tarball"), - ("This is a message we'll find too long", "This is a message we'll f"), - ("One line\nTwo line\nThree line\nFour line\n", "One line\nTwo line"), + ("This is a message we'll find too long", "[TRUNC]This is a message we'll f"), + ("One line\nTwo line\nThree line\nFour line\n", "[TRUNC]One line\nTwo line"), ), ) def test_tarball_subprocess_failure(self, monkeypatch, errmsg, expected):