formatter.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. package logger
  2. import (
  3. "bytes"
  4. "fmt"
  5. "regexp"
  6. "slices"
  7. "strings"
  8. "time"
  9. "unicode/utf8"
  10. logrus "github.com/sirupsen/logrus"
  11. )
  12. var logQuotingRe = regexp.MustCompile(`^[a-zA-Z0-9\-._/@^+]+$`)
  13. func logKeyPriority(k string) int {
  14. switch k {
  15. case "request_id":
  16. return 3
  17. case "method":
  18. return 2
  19. case "status":
  20. return 1
  21. case "error":
  22. return -1
  23. case "source":
  24. return -2
  25. case "stack":
  26. return -3
  27. default:
  28. return 0
  29. }
  30. }
  31. func sortKeys(keys []string) {
  32. slices.SortFunc(keys, func(key1, key2 string) int {
  33. if d := logKeyPriority(key2) - logKeyPriority(key1); d != 0 {
  34. return d
  35. }
  36. return strings.Compare(key1, key2)
  37. })
  38. }
  39. type prettyFormatter struct {
  40. levelFormat string
  41. }
  42. func newPrettyFormatter() *prettyFormatter {
  43. f := new(prettyFormatter)
  44. levelLenMax := 0
  45. for _, level := range logrus.AllLevels {
  46. levelLen := utf8.RuneCount([]byte(level.String()))
  47. if levelLen > levelLenMax {
  48. levelLenMax = levelLen
  49. }
  50. }
  51. f.levelFormat = fmt.Sprintf("%%-%ds", levelLenMax)
  52. return f
  53. }
  54. func (f *prettyFormatter) Format(entry *logrus.Entry) ([]byte, error) {
  55. var keys []string
  56. if len(entry.Data) > 0 {
  57. keys = make([]string, 0, len(entry.Data))
  58. for k := range entry.Data {
  59. if k != "stack" {
  60. keys = append(keys, k)
  61. }
  62. }
  63. sortKeys(keys)
  64. }
  65. levelColor := 36
  66. switch entry.Level {
  67. case logrus.DebugLevel, logrus.TraceLevel:
  68. levelColor = 37
  69. case logrus.WarnLevel:
  70. levelColor = 33
  71. case logrus.ErrorLevel, logrus.FatalLevel, logrus.PanicLevel:
  72. levelColor = 31
  73. }
  74. levelText := fmt.Sprintf(f.levelFormat, strings.ToUpper(entry.Level.String()))
  75. msg := strings.TrimSuffix(entry.Message, "\n")
  76. var b *bytes.Buffer
  77. if entry.Buffer != nil {
  78. b = entry.Buffer
  79. } else {
  80. b = new(bytes.Buffer)
  81. }
  82. fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m [%s] %s ", levelColor, levelText, entry.Time.Format(time.RFC3339), msg)
  83. for _, k := range keys {
  84. v := entry.Data[k]
  85. fmt.Fprintf(b, " \x1b[1m%s\x1b[0m=", k)
  86. f.appendValue(b, v)
  87. }
  88. b.WriteByte('\n')
  89. if stack, ok := entry.Data["stack"]; ok {
  90. fmt.Fprintln(b, stack)
  91. }
  92. return b.Bytes(), nil
  93. }
  94. func (f *prettyFormatter) appendValue(b *bytes.Buffer, value interface{}) {
  95. strValue, ok := value.(string)
  96. if !ok {
  97. strValue = fmt.Sprint(value)
  98. }
  99. if logQuotingRe.MatchString(strValue) {
  100. b.WriteString(strValue)
  101. } else {
  102. fmt.Fprintf(b, "%q", strValue)
  103. }
  104. }
  105. type structuredFormatter struct{}
  106. func (f *structuredFormatter) Format(entry *logrus.Entry) ([]byte, error) {
  107. var keys []string
  108. if len(entry.Data) > 0 {
  109. keys = make([]string, 0, len(entry.Data))
  110. for k := range entry.Data {
  111. keys = append(keys, k)
  112. }
  113. sortKeys(keys)
  114. }
  115. msg := strings.TrimSuffix(entry.Message, "\n")
  116. var b *bytes.Buffer
  117. if entry.Buffer != nil {
  118. b = entry.Buffer
  119. } else {
  120. b = new(bytes.Buffer)
  121. }
  122. f.appendKeyValue(b, "time", entry.Time.Format(time.RFC3339))
  123. f.appendKeyValue(b, "level", entry.Level.String())
  124. f.appendKeyValue(b, "message", msg)
  125. for _, k := range keys {
  126. f.appendKeyValue(b, k, entry.Data[k])
  127. }
  128. b.WriteByte('\n')
  129. return b.Bytes(), nil
  130. }
  131. func (f *structuredFormatter) appendKeyValue(b *bytes.Buffer, key string, value interface{}) {
  132. if b.Len() != 0 {
  133. b.WriteByte(' ')
  134. }
  135. strValue, ok := value.(string)
  136. if !ok {
  137. strValue = fmt.Sprint(value)
  138. }
  139. fmt.Fprintf(b, "%s=%q", key, strValue)
  140. }