Redesign logging and error handling#23
Conversation
|
🤖 Finished Review · ✅ Success · Started 4:02 PM UTC · Completed 4:15 PM UTC |
ReviewFindingsHigh
Medium
Low
Previous runReviewReason: stale-head The review agent reviewed commit Previous run (2)ReviewFindingsHigh
Medium
Low
Previous run (3)ReviewFindingsHigh
Medium
Low
Previous run (4)ReviewFindingsHigh
Medium
Low
Previous run (5)ReviewFindingsHigh
Medium
Low
Previous run (6)ReviewFindingsHigh
Medium
Low
Previous run (7)ReviewFindingsHigh
Medium
Previous run (8)ReviewFindingsHigh
Medium
Low
Previous run (9)ReviewFindingsHigh
Medium
Low
Previous run (10)ReviewReason: stale-head The review agent reviewed commit Previous run (11)ReviewFindingsHigh
Medium
Low
Labels: PR enhances error handling with typed errors and new exit codes. |
|
🤖 Finished Review · ✅ Success · Started 5:06 PM UTC · Completed 5:18 PM UTC |
|
/fs-review |
|
🤖 Finished Review · ❌ Failure · Started 5:21 PM UTC · Completed 5:33 PM UTC |
|
🤖 Finished Review · ✅ Success · Started 5:39 PM UTC · Completed 5:53 PM UTC |
|
🤖 Finished Review · ✅ Success · Started 8:31 AM UTC · Completed 8:42 AM UTC |
|
latest changes LGTM |
|
🤖 Finished Review · ✅ Success · Started 2:02 PM UTC · Completed 2:21 PM UTC |
|
🤖 Finished Review · ❌ Failure · Started 3:39 PM UTC · Completed 3:46 PM UTC |
|
🤖 Finished Review · ❌ Failure · Started 5:42 PM UTC · Completed 5:49 PM UTC |
perdasilva
left a comment
There was a problem hiding this comment.
Code review: 3 findings (1 bug, 1 convention, 1 cleanup). Details in inline comments.
| case errors.Is(err, errNoFBCOutput): | ||
| os.Exit(2) | ||
| default: | ||
| fmt.Fprintln(os.Stderr, "Error:", err) |
There was a problem hiding this comment.
Bug: double error output for generic errors (exit code 1)
For any error that isn't PackagesNotFoundError or errNoFBCOutput, run() logs it via slog.Error("fatal error", ...) (lines 120, 128, 138, 152) and then returns it here, where main() prints it again via fmt.Fprintln. Without -l, the user sees the same error twice in different formats on different streams (JSON on stdout, plain text on stderr).
Suggestion: either skip the slog.Error in run() for errors that will reach this default case, or remove fmt.Fprintln here and rely on slog alone. Alternatively, limit the fmt.Fprintln fallback to errors that occur before slog.SetDefault (line 101).
There was a problem hiding this comment.
Reworked logging:
- slog (structured JSON logs) now always goes to stdout: operational info like "fetched N products", "filtered packages", "wrote FBC data"
- -l flag now redirects validation/filtering reports (report.LogResults JSON lines) to a file: defaults to stderr when -l is not specified
This cleanly separates the two output channels: slog for operators watching the tool run, reports for downstream tooling or review.
For the error logging, we now always print them on stderr by main() via the fmt.Fprintln, keeping the error message brief.
slog.Errors are printed too in some cases, but in json format together with the other json logs on stdout. There all details are included.
|
🤖 Finished Review · ❌ Failure · Started 11:08 AM UTC · Completed 11:25 AM UTC |
Pre-v1 module, no external consumers. Intentional.
By design: the caller shouldn't silently ignore missing packages. The error forces explicit handling (strict: fail, permissive: warn). The old
Intentional. The previous model was backwards: operational logs (slog) belong on stdout, not in a file. The
By design: see above. Structured JSON logs on stdout is the standard pattern for CLI tools. Validation reports are a separate output channel.
Necessary to support differentiated exit codes (1/2/3).
Intentional. In default strict mode, missing packages are an error (the run fails). In permissive mode, they're a warning (the run continues with the found subset). Different severity = different log level. The permissive mode is more a debug feature to us the tool to still produce some data.
The flag name was intentionally kept as
Documented in README exit codes table. The distinction between "all filtered out" (2) and "requested packages not found" (3) enables better automation. |
|
/fs-review |
|
🤖 Finished Review · ❌ Failure · Started 7:38 PM UTC · Completed 7:57 PM UTC |
|
🤖 Finished Review · ✅ Success · Started 10:20 AM UTC · Completed 10:40 AM UTC |
|
🤖 Finished Review · ❌ Failure · Started 11:28 AM UTC · Completed 11:45 AM UTC |
|
🤖 Finished Review · ✅ Success · Started 12:05 PM UTC · Completed 12:20 PM UTC |
FilterByPackageNames now returns a typed PackagesNotFoundError instead of a plain []string, enabling callers to use errors.As for structured handling. In --strict mode the CLI aborts with exit code 3; otherwise it warns per missing package and continues with the found subset. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Francesco Giudici <fgiudici@redhat.com>
Move all error logging out of writeSplit, writeFile, and loadAndValidate into main() and run(). Functions now return errors without logging them, following the Go pattern of letting callers decide how to report. All error output uses slog (structured JSON) instead of the log package, which is removed as a dependency. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Francesco Giudici <fgiudici@redhat.com>
- Return actual blob count from writeFile/writeSplit instead of input product count - Return unexpected errors in permissive path instead of silently swallowing them - Document exit codes in README - Expand --permissive flag description to mention exit code 3 - Add packages-not-found row to VALIDATION_RULES.md filtering table Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Francesco Giudici <fgiudici@redhat.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Francesco Giudici <fgiudici@redhat.com>
slog operational logs now always go to stdout. The -l flag redirects validation/filtering reports (report.LogResults output) to a file instead of stderr. This cleanly separates the two output channels. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Francesco Giudici <fgiudici@redhat.com>
For fatal errors (exit code 1), main() already prints to stderr. The slog.Error calls in run() for these paths were redundant. Keep slog.Error only for exit-code-2/3 paths where main() is silent. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Francesco Giudici <fgiudici@redhat.com>
- Exit codes 2 and 3 now print a human-readable error to stderr
- Drop redundant slog.Error("no FBC data generated") from run()
- report.LogResults write failures propagate as errors instead of
slog-and-continue (prevents silently truncated reports)
- Propagate lf.Close() error on report log file via named return
- Wrap GenerateFBC error in writeFile for consistency with writeSplit
- Fix stale README.md -l flag description
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
the supported output formats are already included in the error returned by NewPackageWriter(): drop them from caller as they would be duplicated. Moreover, the exact error returned should belong to the NewPackageWriter() function. Signed-off-by: Francesco Giudici <fgiudici@redhat.com>
Make reviewer heppy. Signed-off-by: Francesco Giudici <fgiudici@redhat.com>
|
/fs-review |
|
🤖 Finished Review · ✅ Success · Started 12:23 PM UTC · Completed 12:37 PM UTC |
|
I think this PR ready. it took more than planned and too many back and forth rounds for the actual changes in it. |
Addressable insights have been tackled, inline comments have inline replies.
What is remaining are complaints about API changes, unauthorized changes (missing tracking issue?) and minor notes.
Summary
FilterByPackageNamesnow returns aPackagesNotFoundError(typed error) instead of[]string, enabling callers to useerrors.Asfor structured handling.--permissive, missing packages log a warning per name and processing continues with the found subset.Exit codes
--permissive)