logging.go 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. package tea
  2. import (
  3. "fmt"
  4. "io"
  5. "log"
  6. "os"
  7. "unicode"
  8. )
  9. // LogToFile sets up default logging to log to a file. This is helpful as we
  10. // can't print to the terminal since our TUI is occupying it. If the file
  11. // doesn't exist it will be created.
  12. //
  13. // Don't forget to close the file when you're done with it.
  14. //
  15. // f, err := LogToFile("debug.log", "debug")
  16. // if err != nil {
  17. // fmt.Println("fatal:", err)
  18. // os.Exit(1)
  19. // }
  20. // defer f.Close()
  21. func LogToFile(path string, prefix string) (*os.File, error) {
  22. return LogToFileWith(path, prefix, log.Default())
  23. }
  24. // LogOptionsSetter is an interface implemented by stdlib's log and charm's log
  25. // libraries.
  26. type LogOptionsSetter interface {
  27. SetOutput(io.Writer)
  28. SetPrefix(string)
  29. }
  30. // LogToFileWith does allows to call LogToFile with a custom LogOptionsSetter.
  31. func LogToFileWith(path string, prefix string, log LogOptionsSetter) (*os.File, error) {
  32. f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0o600) //nolint:gomnd
  33. if err != nil {
  34. return nil, fmt.Errorf("error opening file for logging: %w", err)
  35. }
  36. log.SetOutput(f)
  37. // Add a space after the prefix if a prefix is being specified and it
  38. // doesn't already have a trailing space.
  39. if len(prefix) > 0 {
  40. finalChar := prefix[len(prefix)-1]
  41. if !unicode.IsSpace(rune(finalChar)) {
  42. prefix += " "
  43. }
  44. }
  45. log.SetPrefix(prefix)
  46. return f, nil
  47. }