logfmt_logger.go 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. package log
  2. import (
  3. "bytes"
  4. "io"
  5. "sync"
  6. "github.com/go-logfmt/logfmt"
  7. )
  8. type logfmtEncoder struct {
  9. *logfmt.Encoder
  10. buf bytes.Buffer
  11. }
  12. func (l *logfmtEncoder) Reset() {
  13. l.Encoder.Reset()
  14. l.buf.Reset()
  15. }
  16. var logfmtEncoderPool = sync.Pool{
  17. New: func() interface{} {
  18. var enc logfmtEncoder
  19. enc.Encoder = logfmt.NewEncoder(&enc.buf)
  20. return &enc
  21. },
  22. }
  23. type logfmtLogger struct {
  24. w io.Writer
  25. }
  26. // NewLogfmtLogger returns a logger that encodes keyvals to the Writer in
  27. // logfmt format. Each log event produces no more than one call to w.Write.
  28. // The passed Writer must be safe for concurrent use by multiple goroutines if
  29. // the returned Logger will be used concurrently.
  30. func NewLogfmtLogger(w io.Writer) Logger {
  31. return &logfmtLogger{w}
  32. }
  33. func (l logfmtLogger) Log(keyvals ...interface{}) error {
  34. enc := logfmtEncoderPool.Get().(*logfmtEncoder)
  35. enc.Reset()
  36. defer logfmtEncoderPool.Put(enc)
  37. if err := enc.EncodeKeyvals(keyvals...); err != nil {
  38. return err
  39. }
  40. // Add newline to the end of the buffer
  41. if err := enc.EndRecord(); err != nil {
  42. return err
  43. }
  44. // The Logger interface requires implementations to be safe for concurrent
  45. // use by multiple goroutines. For this implementation that means making
  46. // only one call to l.w.Write() for each call to Log.
  47. if _, err := l.w.Write(enc.buf.Bytes()); err != nil {
  48. return err
  49. }
  50. return nil
  51. }