formatter.go 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. package golog
  2. import (
  3. "encoding/json"
  4. "io"
  5. "sync"
  6. )
  7. // Formatter is responsible to print a log to the logger's writer.
  8. type Formatter interface {
  9. // The name of the formatter.
  10. String() string
  11. // Set any options and return a clone,
  12. // generic. See `Logger.SetFormat`.
  13. Options(opts ...interface{}) Formatter
  14. // Writes the "log" to "dest" logger.
  15. Format(dest io.Writer, log *Log) bool
  16. }
  17. // JSONFormatter is a Formatter type for JSON logs.
  18. type JSONFormatter struct {
  19. Indent string
  20. // Use one encoder per level, do not create new each time.
  21. // Even if the jser can set a different formatter for each level
  22. // on SetLevelFormat, the encoding's writers may be different
  23. // if that ^ is not called but SetLevelOutput did provide a different writer.
  24. encoders map[Level]*json.Encoder
  25. mu sync.RWMutex // encoders locker.
  26. encMu sync.Mutex // encode action locker.
  27. }
  28. // String returns the name of the Formatter.
  29. // In this case it returns "json".
  30. // It's used to map the formatter names with their implementations.
  31. func (f *JSONFormatter) String() string {
  32. return "json"
  33. }
  34. // Options sets the options for the JSON Formatter (currently only indent).
  35. func (f *JSONFormatter) Options(opts ...interface{}) Formatter {
  36. formatter := &JSONFormatter{
  37. Indent: " ",
  38. encoders: make(map[Level]*json.Encoder, len(Levels)),
  39. }
  40. for _, opt := range opts {
  41. if opt == nil {
  42. continue
  43. }
  44. if indent, ok := opt.(string); ok {
  45. formatter.Indent = indent
  46. break
  47. }
  48. }
  49. return formatter
  50. }
  51. // Format prints the logs in JSON format.
  52. //
  53. // Usage:
  54. // logger.SetFormat("json") or
  55. // logger.SetLevelFormat("info", "json")
  56. func (f *JSONFormatter) Format(dest io.Writer, log *Log) bool {
  57. f.mu.RLock()
  58. enc, ok := f.encoders[log.Level]
  59. f.mu.RUnlock()
  60. if !ok {
  61. enc = json.NewEncoder(dest)
  62. enc.SetIndent("", f.Indent)
  63. f.mu.Lock()
  64. f.encoders[log.Level] = enc
  65. f.mu.Unlock()
  66. }
  67. f.encMu.Lock()
  68. err := enc.Encode(log)
  69. f.encMu.Unlock()
  70. return err == nil
  71. }