Description
PrintTraceSummary in internal/telemetry/events.go currently takes 9 positional parameters (after #870 merged the sessionID param). This makes calls hard to read and error-prone as the signature grows. Additionally, all existing tests for this function are smoke tests that only verify "no panic" — they cannot assert the actual printed output because stdout.Writer() captures os.Stdout at init time and there is no swap/redirect mechanism for tests.
This issue covers two related improvements:
1. Refactor the function signature
Current signature (after #870):
func PrintTraceSummary(filesReviewed, commentsGenerated int64,
inputTokens, outputTokens, totalTokens int64,
cacheReadTokens, cacheWriteTokens int64,
duration time.Duration, sessionID string)
Option A (preferred): Introduce a TraceSummary struct and accept it as a single parameter:
type TraceSummary struct {
FilesReviewed int64
CommentsGenerated int64
InputTokens int64
OutputTokens int64
TotalTokens int64
CacheReadTokens int64
CacheWriteTokens int64
Duration time.Duration
SessionID string
}
func PrintTraceSummary(s TraceSummary) { ... }
Option B: Extract session printing into a separate PrintSessionID(id string) helper and keep the remaining 8-param signature (less ideal long-term but simpler diff).
2. Add a stdout.Swap test helper for output assertions
The internal/stdout package currently exposes Writer() and Quiet(). A new Swap(w io.Writer) func() (or a test-only CaptureOutput(t *testing.T) *bytes.Buffer) would allow tests to redirect output and assert content:
// Swap replaces the stdout writer and returns a restore function.
func Swap(replacement io.Writer) func() {
mu.Lock()
old := w
w = replacement
mu.Unlock()
return func() {
mu.Lock()
w = old
mu.Unlock()
}
}
Then tests can assert actual output:
func TestPrintTraceSummary_WithSessionID(t *testing.T) {
var buf bytes.Buffer
defer stdout.Swap(&buf)()
PrintTraceSummary(TraceSummary{..., SessionID: "abc-123"})
assert.Contains(t, buf.String(), "[ocr] Session: abc-123")
}
Scope
- File(s):
internal/telemetry/events.go, internal/telemetry/events_test.go, internal/stdout/stdout.go
- Function/area:
PrintTraceSummary, stdout package
- Call site:
cmd/opencodereview/shared.go (update to use struct)
Acceptance Criteria
Context
Follow-up from #870 (which closed #866). The PR author flagged both items as out-of-scope improvements. See the PR description "Design notes" section for rationale.
Description
PrintTraceSummaryininternal/telemetry/events.gocurrently takes 9 positional parameters (after #870 merged thesessionIDparam). This makes calls hard to read and error-prone as the signature grows. Additionally, all existing tests for this function are smoke tests that only verify "no panic" — they cannot assert the actual printed output becausestdout.Writer()capturesos.Stdoutat init time and there is no swap/redirect mechanism for tests.This issue covers two related improvements:
1. Refactor the function signature
Current signature (after #870):
Option A (preferred): Introduce a
TraceSummarystruct and accept it as a single parameter:Option B: Extract session printing into a separate
PrintSessionID(id string)helper and keep the remaining 8-param signature (less ideal long-term but simpler diff).2. Add a
stdout.Swaptest helper for output assertionsThe
internal/stdoutpackage currently exposesWriter()andQuiet(). A newSwap(w io.Writer) func()(or a test-onlyCaptureOutput(t *testing.T) *bytes.Buffer) would allow tests to redirect output and assert content:Then tests can assert actual output:
Scope
internal/telemetry/events.go,internal/telemetry/events_test.go,internal/stdout/stdout.goPrintTraceSummary,stdoutpackagecmd/opencodereview/shared.go(update to use struct)Acceptance Criteria
PrintTraceSummaryaccepts a struct (or the session line is extracted to a helper)internal/stdoutexposes aSwap(or test-capture) mechanismPrintTraceSummarytests assert actual output strings, not just "no panic"make test)make check)make coverage)Context
Follow-up from #870 (which closed #866). The PR author flagged both items as out-of-scope improvements. See the PR description "Design notes" section for rationale.