logonce.go 1.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. // Package logonce implements an io.Writer facade that only performs distinct
  2. // writes. This can be used by log.Loggers as they're guaranteed to make a
  3. // single Write method call for each message. This is useful for loggers that
  4. // print useful information about unexpected conditions that aren't fatal in
  5. // code.
  6. package logonce
  7. import (
  8. "io"
  9. "log"
  10. "os"
  11. )
  12. // A default logger similar to the default logger in the log package.
  13. var Stderr *log.Logger
  14. func init() {
  15. // This should emulate the default logger in the log package where
  16. // possible. No time flag so that messages don't differ by time. Code
  17. // debug information is useful.
  18. Stderr = log.New(Writer(os.Stderr), "logonce: ", log.Lshortfile)
  19. }
  20. type writer struct {
  21. w io.Writer
  22. writes map[string]struct{}
  23. }
  24. func (w writer) Write(p []byte) (n int, err error) {
  25. s := string(p)
  26. if _, ok := w.writes[s]; ok {
  27. return
  28. }
  29. n, err = w.w.Write(p)
  30. if n != len(s) {
  31. s = string(p[:n])
  32. }
  33. w.writes[s] = struct{}{}
  34. return
  35. }
  36. func Writer(w io.Writer) io.Writer {
  37. return writer{
  38. w: w,
  39. writes: make(map[string]struct{}),
  40. }
  41. }