Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions pkg/cmd/printer/printer.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"io"
"net/http"
"net/url"
"os"
"path/filepath"
"strconv"
"strings"
Expand Down Expand Up @@ -349,6 +350,10 @@ func (p tableEventPrinter) Epilogue(stats metrics.Stats) {
}

func (p tableEventPrinter) Close() {
// Sync flushes buffered data, ensuring events aren't lost on process exit
if f, ok := p.out.(*os.File); ok && f != nil {
Copy link

Copilot AI Oct 28, 2025

Choose a reason for hiding this comment

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

The nil check f != nil is redundant after a successful type assertion. If the type assertion succeeds, f cannot be nil. Consider simplifying to if f, ok := p.out.(*os.File); ok {.

Suggested change
if f, ok := p.out.(*os.File); ok && f != nil {
if f, ok := p.out.(*os.File); ok {

Copilot uses AI. Check for mistakes.
_ = f.Sync()
}
}

type templateEventPrinter struct {
Expand Down Expand Up @@ -389,6 +394,10 @@ func (p templateEventPrinter) Print(event trace.Event) {
func (p templateEventPrinter) Epilogue(stats metrics.Stats) {}

func (p templateEventPrinter) Close() {
// Sync flushes buffered data, ensuring events aren't lost on process exit
if f, ok := p.out.(*os.File); ok && f != nil {
Copy link

Copilot AI Oct 28, 2025

Choose a reason for hiding this comment

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

The nil check f != nil is redundant after a successful type assertion. If the type assertion succeeds, f cannot be nil. Consider simplifying to if f, ok := p.out.(*os.File); ok {.

Suggested change
if f, ok := p.out.(*os.File); ok && f != nil {
if f, ok := p.out.(*os.File); ok {

Copilot uses AI. Check for mistakes.
_ = f.Sync()
}
}

type jsonEventPrinter struct {
Expand All @@ -410,6 +419,10 @@ func (p jsonEventPrinter) Print(event trace.Event) {
func (p jsonEventPrinter) Epilogue(stats metrics.Stats) {}

func (p jsonEventPrinter) Close() {
// Sync flushes buffered data, ensuring events aren't lost on process exit
if f, ok := p.out.(*os.File); ok && f != nil {
Copy link

Copilot AI Oct 28, 2025

Choose a reason for hiding this comment

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

The nil check f != nil is redundant after a successful type assertion. If the type assertion succeeds, f cannot be nil. Consider simplifying to if f, ok := p.out.(*os.File); ok {.

Suggested change
if f, ok := p.out.(*os.File); ok && f != nil {
if f, ok := p.out.(*os.File); ok {

Copilot uses AI. Check for mistakes.
_ = f.Sync()
}
}

// ignoreEventPrinter ignores events
Expand Down
118 changes: 118 additions & 0 deletions pkg/cmd/printer/printer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,121 @@ func TestTemplateEventPrinterSprigFunctions(t *testing.T) {
// Should contain timestamp
assert.Contains(t, output, `1234567890`, "timestamp should be included")
}

// TestPrinterCloseFlusheData tests that Close() calls Sync() to flush buffered data to disk
Copy link

Copilot AI Oct 28, 2025

Choose a reason for hiding this comment

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

Corrected spelling of 'FlushesData' in function name (typo in comment: 'FlusheData').

Suggested change
// TestPrinterCloseFlusheData tests that Close() calls Sync() to flush buffered data to disk
// TestPrinterCloseFlushesData tests that Close() calls Sync() to flush buffered data to disk

Copilot uses AI. Check for mistakes.
func TestPrinterCloseFlushesData(t *testing.T) {
t.Parallel()

testCases := []struct {
name string
printerKind string
}{
{
name: "json printer",
printerKind: "json",
},
{
name: "table printer",
printerKind: "table",
},
}

for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()

// Create a temporary file
tempDir := t.TempDir()
outputPath := filepath.Join(tempDir, "test_output.txt")

// Create the output file
file, err := flags.CreateOutputFile(outputPath)
require.NoError(t, err)
defer file.Close() // We close it since we created it

// Create printer config
cfg := config.PrinterConfig{
Kind: tc.printerKind,
OutFile: file,
}

// Create and initialize the printer
p, err := printer.New(cfg)
require.NoError(t, err)

// Create a sample event
sampleEvent := trace.Event{
ProcessName: "test_process",
EventID: 1,
EventName: "test_event",
Timestamp: 1234567890,
Args: []trace.Argument{
{ArgMeta: trace.ArgMeta{Name: "arg1", Type: "string"}, Value: "value1"},
},
}

// Print an event
p.Preamble()
p.Print(sampleEvent)
p.Close() // This should flush the buffer via Sync()

// Read the file content (file is still open, but Sync() should have flushed data to disk)
content, err := os.ReadFile(outputPath)
require.NoError(t, err, "Should be able to read flushed data while file is still open")

// Verify data was written and flushed
assert.NotEmpty(t, content, "File should contain data after Sync()")
assert.Contains(t, string(content), "test_process", "File should contain event data")
})
}
}

// TestTemplateEventPrinterCloseFlushesData tests that template printer Close() calls Sync() to flush data
func TestTemplateEventPrinterCloseFlushesData(t *testing.T) {
t.Parallel()

// Create a temporary template file
templateContent := `{"event": "{{ .EventName }}", "process": "{{ .ProcessName }}"}`
tempDir := t.TempDir()
templatePath := filepath.Join(tempDir, "test.tmpl")
outputPath := filepath.Join(tempDir, "test_output.txt")

err := os.WriteFile(templatePath, []byte(templateContent), 0644)
require.NoError(t, err)

// Create the output file
file, err := flags.CreateOutputFile(outputPath)
require.NoError(t, err)
defer file.Close() // We close it since we created it

// Create printer config
cfg := config.PrinterConfig{
Kind: "gotemplate=" + templatePath,
OutFile: file,
}

// Create and initialize the printer
p, err := printer.New(cfg)
require.NoError(t, err)

// Create a sample event
sampleEvent := trace.Event{
ProcessName: "test_process",
EventName: "test_event",
}

// Print an event
p.Preamble()
p.Print(sampleEvent)
p.Close() // This should flush the buffer via Sync()

// Read the file content (file is still open, but Sync() should have flushed data to disk)
content, err := os.ReadFile(outputPath)
require.NoError(t, err, "Should be able to read flushed data while file is still open")

// Verify data was written and flushed
assert.NotEmpty(t, content, "File should contain data after Sync()")
assert.Contains(t, string(content), "test_process", "File should contain event data")
assert.Contains(t, string(content), "test_event", "File should contain event name")
}