diff --git a/.gitignore b/.gitignore index ada68ff..10eca27 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ *.so *.dylib bin/* +logs/* Dockerfile.cross # Test binary, built with `go test -c` diff --git a/internal/logger/logger.go b/internal/logger/logger.go new file mode 100644 index 0000000..61b60cd --- /dev/null +++ b/internal/logger/logger.go @@ -0,0 +1,53 @@ +package logger + +import ( + "fmt" + "log" + "os" + "path/filepath" + "time" +) + +// Global logger +// since we are running a TUI, we dont want to write to stdout, +// so we will write to stderr + a log file +var errorLogger *log.Logger + +func init() { + initLog() +} + +// initLog creates a new log file with a timestamped name each run. +func initLog() (*os.File, error) { + logDir := "logs" + err := os.MkdirAll(logDir, 0755) + if err != nil { + return nil, fmt.Errorf("failed to create log directory: %w", err) + } else { + fmt.Printf("Log directory '%s' created or already exists\n", logDir) + } + + timestamp := time.Now().Format("2006-01-02_15-04-05") + filename := filepath.Join(logDir, fmt.Sprintf("signalhound_%s.log", timestamp)) + + file, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) + if err != nil { + return nil, fmt.Errorf("failed to open log file: %w", err) + } else { + fmt.Printf("Log file %s created\n", filename) + } + + // Create a logger that writes to both file and stderr + errorLogger = log.New(file, "ERROR: ", log.Ldate|log.Ltime|log.Lshortfile) + return file, nil +} + +// HandleError logs errors bot to stderr and also a log file +func HandleError(err error) { + if err != nil { + // Print to stderr + fmt.Fprintf(os.Stderr, "Error: %v\n", err) + // Log to file + errorLogger.Println(err) + } +} diff --git a/internal/tui/panel.go b/internal/tui/panel.go index 4b62271..102a6be 100644 --- a/internal/tui/panel.go +++ b/internal/tui/panel.go @@ -11,6 +11,7 @@ import ( "github.com/gdamore/tcell/v2" "github.com/knabben/signalhound/api/v1alpha1" "github.com/knabben/signalhound/internal/github" + "github.com/knabben/signalhound/internal/logger" "github.com/rivo/tview" "golang.org/x/text/cases" "golang.org/x/text/language" @@ -78,7 +79,7 @@ func RenderVisual(tabs []*v1alpha1.DashboardTab, githubToken string) error { githubPanel.SetWrap(true) // Final position bottom panel for information - var positionText = "[yellow]Select a content Windows and press [blue]Ctrl-Space [yellow]to COPY or press [blue]Ctrl-C [yellow]to exit" + var positionText = "[yellow]Select a content window and press [blue]Ctrl-Space [yellow]to COPY or press [blue]Ctrl-C [yellow]to exit" position.SetDynamicColors(true).SetTextAlign(tview.AlignCenter).SetText(positionText) // Create the grid layout @@ -137,6 +138,7 @@ func updateSlackPanel(tab *v1alpha1.DashboardTab, currentTest *v1alpha1.TestResu position.SetText("[blue]COPIED [yellow]SLACK [blue]TO THE CLIPBOARD!") if err := CopyToClipboard(slackPanel.GetText()); err != nil { position.SetText(fmt.Sprintf("[red]error: %v", err.Error())) + logger.HandleError(err) return event } setPanelFocusStyle(slackPanel.Box) @@ -184,6 +186,7 @@ func updateGitHubPanel(tab *v1alpha1.DashboardTab, currentTest *v1alpha1.TestRes template, err := renderTemplate(issue, templateFile) if err != nil { position.SetText(fmt.Sprintf("[red]error: %v", err.Error())) + logger.HandleError(err) return } issueTemplate := template.String() @@ -197,6 +200,7 @@ func updateGitHubPanel(tab *v1alpha1.DashboardTab, currentTest *v1alpha1.TestRes position.SetText("[blue]COPIED [yellow]ISSUE [blue]TO THE CLIPBOARD!") if err := CopyToClipboard(githubPanel.GetText()); err != nil { position.SetText(fmt.Sprintf("[red]error: %v", err.Error())) + logger.HandleError(err) return event } setPanelFocusStyle(githubPanel.Box) @@ -212,6 +216,7 @@ func updateGitHubPanel(tab *v1alpha1.DashboardTab, currentTest *v1alpha1.TestRes gh := github.NewGithub(context.Background(), token) if err := gh.CreateDraftIssue(issueTitle, issueTemplate); err != nil { position.SetText(fmt.Sprintf("[red]error: %v", err.Error())) + logger.HandleError(err) return event } position.SetText("[blue]Created [yellow]DRAFT ISSUE [blue] on GitHub Project!") @@ -280,7 +285,9 @@ func CopyToClipboard(text string) error { } default: - return fmt.Errorf("unsupported operating system: %s", runtime.GOOS) + err := fmt.Errorf("unsupported operating system: %s", runtime.GOOS) + logger.HandleError(err) + return err } return cmd.Run()