level.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. package golog
  2. import (
  3. "fmt"
  4. "strconv"
  5. "strings"
  6. "github.com/kataras/pio"
  7. )
  8. // Level is a number which defines the log level.
  9. type Level uint32
  10. // MarshalJSON implements the json marshaler for Level.
  11. func (l Level) MarshalJSON() ([]byte, error) {
  12. if level, ok := Levels[l]; ok {
  13. return []byte(strconv.Quote(level.Name)), nil
  14. }
  15. return nil, fmt.Errorf("unknown level %v", l)
  16. }
  17. // String implements the fmt.Stringer interface for level.
  18. // Returns the level's name.
  19. func (l Level) String() string {
  20. if level, ok := Levels[l]; ok {
  21. return level.Name
  22. }
  23. return ""
  24. }
  25. // The available built'n log levels, users can add or modify a level via `Levels` field.
  26. const (
  27. // DisableLevel will disable the printer.
  28. DisableLevel Level = iota
  29. // FatalLevel will `os.Exit(1)` no matter the level of the logger.
  30. // If the logger's level is fatal, error, warn, info or debug
  31. // then it will print the log message too.
  32. FatalLevel
  33. // ErrorLevel will print only errors.
  34. ErrorLevel
  35. // WarnLevel will print errors and warnings.
  36. WarnLevel
  37. // InfoLevel will print errors, warnings and infos.
  38. InfoLevel
  39. // DebugLevel will print on any level, fatals, errors, warnings, infos and debug logs.
  40. DebugLevel
  41. )
  42. // Levels contains the levels and their
  43. // mapped (pointer of, in order to be able to be modified) metadata, callers
  44. // are allowed to modify this package-level global variable
  45. // without any loses.
  46. var Levels = map[Level]*LevelMetadata{
  47. DisableLevel: {
  48. Name: "disable",
  49. AlternativeNames: []string{"disabled"},
  50. Title: "",
  51. },
  52. FatalLevel: {
  53. Name: "fatal",
  54. Title: "[FTAL]",
  55. ColorCode: pio.Red,
  56. Style: []pio.RichOption{pio.Background},
  57. },
  58. ErrorLevel: {
  59. Name: "error",
  60. Title: "[ERRO]",
  61. ColorCode: pio.Red,
  62. },
  63. WarnLevel: {
  64. Name: "warn",
  65. AlternativeNames: []string{"warning"},
  66. Title: "[WARN]",
  67. ColorCode: pio.Magenta,
  68. },
  69. InfoLevel: {
  70. Name: "info",
  71. Title: "[INFO]",
  72. ColorCode: pio.Cyan,
  73. },
  74. DebugLevel: {
  75. Name: "debug",
  76. Title: "[DBUG]",
  77. ColorCode: pio.Yellow,
  78. },
  79. }
  80. // ParseLevel returns a `golog.Level` from a string level.
  81. // Note that all existing log levels (name, prefix and color) can be customized
  82. // and new one can be added by the package-level `golog.Levels` map variable.
  83. func ParseLevel(levelName string) Level {
  84. levelName = strings.ToLower(levelName)
  85. for level, meta := range Levels {
  86. if strings.ToLower(meta.Name) == levelName {
  87. return level
  88. }
  89. for _, altName := range meta.AlternativeNames {
  90. if strings.ToLower(altName) == levelName {
  91. return level
  92. }
  93. }
  94. }
  95. return DisableLevel
  96. }
  97. // LevelMetadata describes the information
  98. // behind a log Level, each level has its own unique metadata.
  99. type LevelMetadata struct {
  100. // The Name of the Level
  101. // that named (lowercased) will be used
  102. // to convert a string level on `SetLevel`
  103. // to the correct Level type.
  104. Name string
  105. // AlternativeNames are the names that can be referred to this specific log level.
  106. // i.e Name = "warn"
  107. // AlternativeNames = []string{"warning"}, it's an optional field,
  108. // therefore we keep Name as a simple string and created this new field.
  109. AlternativeNames []string
  110. // Tha Title is the prefix of the log level.
  111. // See `ColorCode` and `Style` too.
  112. // Both `ColorCode` and `Style` should be respected across writers.
  113. Title string
  114. // ColorCode a color for the `Title`.
  115. ColorCode int
  116. // Style one or more rich options for the `Title`.
  117. Style []pio.RichOption
  118. }
  119. // Text returns the text that should be
  120. // prepended to the log message when a specific
  121. // log level is being written.
  122. func (m *LevelMetadata) Text(enableColor bool) string {
  123. if enableColor {
  124. return pio.Rich(m.Title, m.ColorCode, m.Style...)
  125. }
  126. return m.Title
  127. }
  128. // SetText can modify the prefix that will be prepended
  129. // to the output message log when `Error/Errorf` functions are being used.
  130. func (m *LevelMetadata) SetText(title string, colorCode int, style ...pio.RichOption) {
  131. m.Title = title
  132. m.ColorCode = colorCode
  133. m.Style = style
  134. }
  135. var (
  136. // ErrorText can modify the prefix that will be prepended
  137. // to the output message log when `Error/Errorf` functions are being used.
  138. //
  139. // If "newColorfulText" is empty then it will update the text color version using
  140. // the default values by using the new raw text.
  141. //
  142. // Defaults to "[ERRO]" and pio.Red("[ERRO]").
  143. //
  144. // Deprecated Use `Levels[ErrorLevel].SetText(string, string)` instead.
  145. ErrorText = Levels[ErrorLevel].SetText
  146. // WarnText can modify the prefix that will be prepended
  147. // to the output message log when `Warn/Warnf` functions are being used.
  148. //
  149. // If "newColorfulText" is empty then it will update the text color version using
  150. // the default values by using the new raw text.
  151. //
  152. // Defaults to "[WARN]" and pio.Purple("[WARN]").
  153. //
  154. // Deprecated Use `Levels[WarnLevel].SetText(string, string)` instead.
  155. WarnText = Levels[WarnLevel].SetText
  156. // InfoText can modify the prefix that will be prepended
  157. // to the output message log when `Info/Infof` functions are being used.
  158. //
  159. // If "newColorfulText" is empty then it will update the text color version using
  160. // the default values by using the new raw text.
  161. //
  162. // Defaults to "[INFO]" and pio.LightGreen("[INFO]").
  163. //
  164. // Deprecated Use `Levels[InfoLevel].SetText(string, string)` instead.
  165. InfoText = Levels[InfoLevel].SetText
  166. // DebugText can modify the prefix that will be prepended
  167. // to the output message log when `Info/Infof` functions are being used.
  168. //
  169. // If "newColorfulText" is empty then it will update the text color version using
  170. // the default values by using the new raw text.
  171. //
  172. // Defaults to "[DBUG]" and pio.Yellow("[DBUG]").
  173. //
  174. // Deprecated Use `Levels[DebugLevel].SetText(string, string)` instead.
  175. DebugText = Levels[DebugLevel].SetText
  176. // GetTextForLevel is the function which
  177. // has the "final" responsibility to generate the text (colorful or not)
  178. // that is prepended to the leveled log message
  179. // when `Error/Errorf, Warn/Warnf, Info/Infof or Debug/Debugf`
  180. // functions are being called.
  181. //
  182. // It can be used to override the default behavior, at the start-up state.
  183. GetTextForLevel = func(level Level, enableColor bool) string {
  184. if meta, ok := Levels[level]; ok {
  185. return meta.Text(enableColor)
  186. }
  187. return ""
  188. }
  189. // GetNameForLevel is the function which
  190. // has the "final" responsibility to generagte the name of the level
  191. // that is prepended to the leveled log message
  192. GetNameForLevel = func(level Level) string {
  193. if meta, ok := Levels[level]; ok {
  194. return meta.Name
  195. }
  196. return ""
  197. }
  198. )