Skip to content

fix(log): send Debug and Trace output to stderr (#851)#860

Open
gustcol wants to merge 2 commits intopeak:masterfrom
gustcol:fix/issue-851-debug-trace-logs-to-stderr
Open

fix(log): send Debug and Trace output to stderr (#851)#860
gustcol wants to merge 2 commits intopeak:masterfrom
gustcol:fix/issue-851-debug-trace-logs-to-stderr

Conversation

@gustcol
Copy link
Copy Markdown

@gustcol gustcol commented Apr 12, 2026

Context

Fixes #851

Root cause

Trace() and Debug() both called global.printf(..., os.Stdout).
When a user ran s5cmd --log debug cat s3://... and piped the output
into another program, diagnostic messages were interleaved with the
object payload, corrupting the stream.

Fix

Changed Trace and Debug to write to os.Stderr. Info continues
to write to os.Stdout (it carries functional output). Only Error
already used os.Stderr; this brings Debug and Trace in line with the
same convention.

Files changed: log/log.go

Tests

  • Added TestDebugWritesToStderr — asserts Debug output appears on stderr and nothing on stdout.
  • Added TestTraceWritesToStderr — same for Trace.
  • Added TestInfoWritesToStdout — regression guard confirming Info still goes to stdout.

Manual verification

# Before: debug lines appear in stdout and break the pipe
s5cmd --log debug cat s3://bucket/object | wc -c   # inflated count

# After: only object bytes on stdout; debug lines on stderr
s5cmd --log debug cat s3://bucket/object 2>/dev/null | wc -c   # correct

gustcol added 2 commits April 12, 2026 15:28
Fixes peak#851

Debug and Trace calls both used os.Stdout as the write target. When
users piped 's5cmd --log debug cat s3://...' into another tool (e.g.
xmlstarlet), the diagnostic messages were interleaved with the object
payload and corrupted the stream.

Only Error already used os.Stderr. This commit applies the same
convention to Debug and Trace: diagnostics go to stderr, data goes
to stdout.

Reproducer:
  s5cmd --log debug cat s3://bucket/object.xml | xmlstarlet sel ...

After this change:
  Debug/trace lines appear on stderr; stdout carries only object content.
Companion to the log fix: e2e tests that used --log debug were asserting
DEBUG lines in result.Stdout(). Now that Debug and Trace write to stderr,
move those expectations to result.Stderr() and assert stdout is empty
(or contains only the non-debug lines for mixed-output tests).
@gustcol gustcol marked this pull request as ready for review April 12, 2026 15:35
@gustcol gustcol requested a review from a team as a code owner April 12, 2026 15:35
@gustcol gustcol requested review from ilkinulas and sonmezonur and removed request for a team April 12, 2026 15:35
@gustcol
Copy link
Copy Markdown
Author

gustcol commented Apr 12, 2026

Test results

Unit tests (go test -race ./...): PASS (after adding e2e assertion fixes)

Changes included in this branch beyond the original fix:

  • e2e/cp_test.go: 4 test functions updated — moved DEBUG assertions from result.Stdout() to result.Stderr(), asserted stdout empty
  • e2e/pipe_test.go: 1 test function updated — same pattern
  • e2e/sync_test.go: 6 test functions updated — for mixed-output tests (DEBUG + cp lines), split: DEBUG lines to result.Stderr(), cp lines remain in result.Stdout()

Wasabi smoke test:

$ ./s5cmd --log debug cp -n /tmp/smoke.txt s3://bucket/smoke.txt 2>/tmp/stderr >/tmp/stdout
$ cat /tmp/stdout     # empty
$ cat /tmp/stderr
DEBUG "cp /tmp/smoke.txt s3://bucket/smoke.txt": object already exists

Confirmed: DEBUG lines go to stderr; stdout stays clean.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Logs get into stdout. Messing up commands that pipe from cat.

1 participant