event.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. package log
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "log"
  6. "os"
  7. "sort"
  8. "strings"
  9. "time"
  10. )
  11. const (
  12. tagField = "tag"
  13. errorField = "error"
  14. )
  15. // Event represents a single log event
  16. type Event struct {
  17. Timestamp int64 `json:"time"`
  18. Level Level `json:"level"`
  19. Message string `json:"message"`
  20. fields Context
  21. }
  22. // newEvent creates a new log event
  23. func newEvent() *Event {
  24. return &Event{
  25. Timestamp: time.Now().UnixMilli(),
  26. fields: make(Context),
  27. }
  28. }
  29. // Fatal logs the event as FATAL, and exits the program with exit code 1
  30. func (e *Event) Fatal(message string, v ...any) {
  31. e.Field("exit_code", 1).Log(FatalLevel, message, v...)
  32. fmt.Fprintf(os.Stderr, fmt.Sprintf(message+"\n", v...)) // Always output error to stderr
  33. os.Exit(1)
  34. }
  35. // Error logs the event with log level error
  36. func (e *Event) Error(message string, v ...any) {
  37. e.Log(ErrorLevel, message, v...)
  38. }
  39. // Warn logs the event with log level warn
  40. func (e *Event) Warn(message string, v ...any) {
  41. e.Log(WarnLevel, message, v...)
  42. }
  43. // Info logs the event with log level info
  44. func (e *Event) Info(message string, v ...any) {
  45. e.Log(InfoLevel, message, v...)
  46. }
  47. // Debug logs the event with log level debug
  48. func (e *Event) Debug(message string, v ...any) {
  49. e.Log(DebugLevel, message, v...)
  50. }
  51. // Trace logs the event with log level trace
  52. func (e *Event) Trace(message string, v ...any) {
  53. e.Log(TraceLevel, message, v...)
  54. }
  55. // Tag adds a "tag" field to the log event
  56. func (e *Event) Tag(tag string) *Event {
  57. e.fields[tagField] = tag
  58. return e
  59. }
  60. // Time sets the time field
  61. func (e *Event) Time(time time.Time) *Event {
  62. e.Timestamp = time.UnixMilli()
  63. return e
  64. }
  65. // Err adds an "error" field to the log event
  66. func (e *Event) Err(err error) *Event {
  67. e.fields[errorField] = err.Error()
  68. return e
  69. }
  70. // Field adds a custom field and value to the log event
  71. func (e *Event) Field(key string, value any) *Event {
  72. e.fields[key] = value
  73. return e
  74. }
  75. // Fields adds a map of fields to the log event
  76. func (e *Event) Fields(fields Context) *Event {
  77. for k, v := range fields {
  78. e.fields[k] = v
  79. }
  80. return e
  81. }
  82. // With adds the fields of the given Contexter structs to the log event by calling their With method
  83. func (e *Event) With(contexts ...Contexter) *Event {
  84. for _, c := range contexts {
  85. e.Fields(c.Context())
  86. }
  87. return e
  88. }
  89. // Log logs a message with the given log level
  90. func (e *Event) Log(l Level, message string, v ...any) {
  91. e.Message = fmt.Sprintf(message, v...)
  92. e.Level = l
  93. if e.shouldPrint() {
  94. if CurrentFormat() == JSONFormat {
  95. log.Println(e.JSON())
  96. } else {
  97. log.Println(e.String())
  98. }
  99. }
  100. }
  101. // Loggable returns true if the given log level is lower or equal to the current log level
  102. func (e *Event) Loggable(l Level) bool {
  103. return e.globalLevelWithOverride() <= l
  104. }
  105. // IsTrace returns true if the current log level is TraceLevel
  106. func (e *Event) IsTrace() bool {
  107. return e.Loggable(TraceLevel)
  108. }
  109. // IsDebug returns true if the current log level is DebugLevel or below
  110. func (e *Event) IsDebug() bool {
  111. return e.Loggable(DebugLevel)
  112. }
  113. // JSON returns the event as a JSON representation
  114. func (e *Event) JSON() string {
  115. b, _ := json.Marshal(e)
  116. s := string(b)
  117. if len(e.fields) > 0 {
  118. b, _ := json.Marshal(e.fields)
  119. s = fmt.Sprintf("{%s,%s}", s[1:len(s)-1], string(b[1:len(b)-1]))
  120. }
  121. return s
  122. }
  123. // String returns the event as a string
  124. func (e *Event) String() string {
  125. if len(e.fields) == 0 {
  126. return fmt.Sprintf("%s %s", e.Level.String(), e.Message)
  127. }
  128. fields := make([]string, 0)
  129. for k, v := range e.fields {
  130. fields = append(fields, fmt.Sprintf("%s=%v", k, v))
  131. }
  132. sort.Strings(fields)
  133. return fmt.Sprintf("%s %s (%s)", e.Level.String(), e.Message, strings.Join(fields, ", "))
  134. }
  135. func (e *Event) shouldPrint() bool {
  136. return e.globalLevelWithOverride() <= e.Level
  137. }
  138. func (e *Event) globalLevelWithOverride() Level {
  139. mu.Lock()
  140. l, ov := level, overrides
  141. mu.Unlock()
  142. for field, override := range ov {
  143. value, exists := e.fields[field]
  144. if exists && value == override.value {
  145. return override.level
  146. }
  147. }
  148. return l
  149. }