Skip to content

Conversation

@gyutaeb
Copy link

@gyutaeb gyutaeb commented Jan 14, 2026

Summary

  • Add output file rotation support for long-running trace sessions
  • Introduce --output-file-max-size, --output-file-max-files, and --output-file-compress flags

Motivation

When analyzing issues that require long-running packet tracing (e.g., intermittent connectivity problems, rare race conditions), the output file can grow indefinitely and exhaust disk space. This PR adds file rotation support to safely capture traces over extended periods.

New Flags

Flag Description Default
--output-file-max-size Max size per file before rotation (e.g., 100M, 1G) disabled
--output-file-max-files Max number of rotated files to keep 5
--output-file-compress Compress rotated files with gzip false

Example

pwru --output-file trace.log \
     --output-file-max-size 100M \
     --output-file-max-files 10 \
     --output-file-compress \
     'host 10.0.0.1'

@gyutaeb gyutaeb requested a review from a team as a code owner January 14, 2026 09:19
@gyutaeb gyutaeb requested review from brb and removed request for a team January 14, 2026 09:19
@gyutaeb gyutaeb force-pushed the feature/output-file-rotation branch from f0b4b4a to 4bfbc42 Compare January 16, 2026 01:24
@gyutaeb
Copy link
Author

gyutaeb commented Jan 16, 2026

@brb
I've split the changes into three patches to facilitate review and added implementation details. Thanks :)

@brb
Copy link
Member

brb commented Jan 16, 2026

Thanks, I will take a look in a bit!

@brb
Copy link
Member

brb commented Jan 16, 2026

Have you considered using https://github.com/natefinch/lumberjack/tree/v3 or similar for traces rotation?

@brb
Copy link
Member

brb commented Jan 22, 2026

@gyutaeb Please let me know if you plan to work on using the lumberjack pkg?

@gyutaeb
Copy link
Author

gyutaeb commented Jan 22, 2026

@gyutaeb Please let me know if you plan to work on using the lumberjack pkg?

@brb Sorry for the late reply. I originally implemented that rotation logic manually to have fine-grained control. However, after testing it with lumberjack as you suggested, I agree that it is much cleaner. I'm running final tests now and will push the updates ASAP!

@brb
Copy link
Member

brb commented Jan 22, 2026

Perfect, thank you! Just one side note, maybe you could add some benchmarking tests to avoid any hidden costs by that pkg (we have some already in BenchmarkOutputPrint)?

@gyutaeb
Copy link
Author

gyutaeb commented Jan 22, 2026

@brb
Got it! I'll add the benchmarking tests as well. Also, I think a few more feature would be useful for TCP tracing. I plan to implement these ideas incrementally and submit follow-up PRs.

@gyutaeb gyutaeb closed this Jan 27, 2026
@gyutaeb gyutaeb force-pushed the feature/output-file-rotation branch from 4bfbc42 to a8eef08 Compare January 27, 2026 09:25
@gyutaeb gyutaeb reopened this Jan 27, 2026
for i := 0; i < b.N; i++ {
output.Print(event)
}
func BenchmarkOutputPrint(b *testing.B) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❯ go test --bench=. ./internal/pwru/
goos: linux
goarch: arm64
pkg: github.com/cilium/pwru/internal/pwru
BenchmarkOutputPrint/DevNull-8         	  723668	      1519 ns/op
BenchmarkOutputPrint/RegularFile-8     	  656631	      1804 ns/op
BenchmarkOutputPrint/Lumberjack-8      	  613897	      1833 ns/op

@gyutaeb
Copy link
Author

gyutaeb commented Jan 27, 2026

@brb Thanks for the review. I've switched to using lumberjack and added benchmark tests.

Add automatic log file rotation when using --output-file flag.
Files rotate at 100MB by default with configurable options:

- --output-file-max-size: max size in MB before rotation (default 100)
- --output-file-max-backups: max rotated files to keep (0 = no limit)
- --output-file-max-age: max days to keep rotated files (0 = no limit)
- --output-file-compress: compress rotated files with gzip

Signed-off-by: Gyutae Bae <[email protected]>
@gyutaeb gyutaeb force-pushed the feature/output-file-rotation branch from b8212b5 to fb49a97 Compare January 27, 2026 09:33
Comment on lines +103 to +121
rightPadding := width - len(s) - leftPadding
return fmt.Sprintf("%s%s%s", strings.Repeat(" ", leftPadding), s, strings.Repeat(" ", rightPadding))
}

func NewOutput(flags *Flags, printSkbMap, printShinfoMap, printStackMap, printBpfmapMap *ebpf.Map, addr2Name Addr2Name, skbMds, xdpMds []*SkbMetadata, kprobeMulti bool, btfSpec *btf.Spec) (*output, error) {
writer := os.Stdout
var writer io.Writer = os.Stdout
var closer io.Closer

if flags.OutputFile != "" {
file, err := os.Create(flags.OutputFile)
if err != nil {
return nil, err
lj := &lumberjack.Logger{
Filename: flags.OutputFile,
MaxSize: flags.OutputFileMaxSize,
MaxAge: flags.OutputFileMaxAge,
MaxBackups: flags.OutputFileMaxBackups,
Compress: flags.OutputFileCompress,
LocalTime: true,
}
writer = file
writer = lj
closer = lj
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I decided to drop support for file creation via os.Create, as it would introduce unnecessarily complexity to the code. I also believe we should standardize on lumberjack as the default moving forward.

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.

2 participants