glog_logger_config.go 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
  2. //
  3. // This Source Code Form is subject to the terms of the MIT License.
  4. // If a copy of the MIT was not distributed with this file,
  5. // You can obtain one at https://github.com/gogf/gf.
  6. package glog
  7. import (
  8. "github.com/gogf/gf/errors/gcode"
  9. "github.com/gogf/gf/os/gctx"
  10. "io"
  11. "strings"
  12. "time"
  13. "github.com/gogf/gf/errors/gerror"
  14. "github.com/gogf/gf/internal/intlog"
  15. "github.com/gogf/gf/os/gfile"
  16. "github.com/gogf/gf/util/gconv"
  17. "github.com/gogf/gf/util/gutil"
  18. )
  19. // Config is the configuration object for logger.
  20. type Config struct {
  21. Handlers []Handler `json:"-"` // Logger handlers which implement feature similar as middleware.
  22. Writer io.Writer `json:"-"` // Customized io.Writer.
  23. Flags int `json:"flags"` // Extra flags for logging output features.
  24. Path string `json:"path"` // Logging directory path.
  25. File string `json:"file"` // Format pattern for logging file.
  26. Level int `json:"level"` // Output level.
  27. Prefix string `json:"prefix"` // Prefix string for every logging content.
  28. StSkip int `json:"stSkip"` // Skipping count for stack.
  29. StStatus int `json:"stStatus"` // Stack status(1: enabled - default; 0: disabled)
  30. StFilter string `json:"stFilter"` // Stack string filter.
  31. CtxKeys []interface{} `json:"ctxKeys"` // Context keys for logging, which is used for value retrieving from context.
  32. HeaderPrint bool `json:"header"` // Print header or not(true in default).
  33. StdoutPrint bool `json:"stdout"` // Output to stdout or not(true in default).
  34. LevelPrefixes map[int]string `json:"levelPrefixes"` // Logging level to its prefix string mapping.
  35. RotateSize int64 `json:"rotateSize"` // Rotate the logging file if its size > 0 in bytes.
  36. RotateExpire time.Duration `json:"rotateExpire"` // Rotate the logging file if its mtime exceeds this duration.
  37. RotateBackupLimit int `json:"rotateBackupLimit"` // Max backup for rotated files, default is 0, means no backups.
  38. RotateBackupExpire time.Duration `json:"rotateBackupExpire"` // Max expire for rotated files, which is 0 in default, means no expiration.
  39. RotateBackupCompress int `json:"rotateBackupCompress"` // Compress level for rotated files using gzip algorithm. It's 0 in default, means no compression.
  40. RotateCheckInterval time.Duration `json:"rotateCheckInterval"` // Asynchronously checks the backups and expiration at intervals. It's 1 hour in default.
  41. WriterColorEnable bool `json:"writerColorEnable"` // Logging level prefix with color to writer or not (false in default).
  42. }
  43. // DefaultConfig returns the default configuration for logger.
  44. func DefaultConfig() Config {
  45. c := Config{
  46. File: defaultFileFormat,
  47. Flags: F_TIME_STD,
  48. Level: LEVEL_ALL,
  49. CtxKeys: []interface{}{gctx.CtxKey},
  50. StStatus: 1,
  51. HeaderPrint: true,
  52. StdoutPrint: true,
  53. LevelPrefixes: make(map[int]string, len(defaultLevelPrefixes)),
  54. RotateCheckInterval: time.Hour,
  55. }
  56. for k, v := range defaultLevelPrefixes {
  57. c.LevelPrefixes[k] = v
  58. }
  59. if !defaultDebug {
  60. c.Level = c.Level & ^LEVEL_DEBU
  61. }
  62. return c
  63. }
  64. // SetConfig set configurations for the logger.
  65. func (l *Logger) SetConfig(config Config) error {
  66. l.config = config
  67. // Necessary validation.
  68. if config.Path != "" {
  69. if err := l.SetPath(config.Path); err != nil {
  70. intlog.Error(l.ctx, err)
  71. return err
  72. }
  73. }
  74. intlog.Printf(l.ctx, "SetConfig: %+v", l.config)
  75. return nil
  76. }
  77. // SetConfigWithMap set configurations with map for the logger.
  78. func (l *Logger) SetConfigWithMap(m map[string]interface{}) error {
  79. if m == nil || len(m) == 0 {
  80. return gerror.NewCode(gcode.CodeInvalidParameter, "configuration cannot be empty")
  81. }
  82. // The m now is a shallow copy of m.
  83. // A little tricky, isn't it?
  84. m = gutil.MapCopy(m)
  85. // Change string configuration to int value for level.
  86. levelKey, levelValue := gutil.MapPossibleItemByKey(m, "Level")
  87. if levelValue != nil {
  88. if level, ok := levelStringMap[strings.ToUpper(gconv.String(levelValue))]; ok {
  89. m[levelKey] = level
  90. } else {
  91. return gerror.NewCodef(gcode.CodeInvalidParameter, `invalid level string: %v`, levelValue)
  92. }
  93. }
  94. // Change string configuration to int value for file rotation size.
  95. rotateSizeKey, rotateSizeValue := gutil.MapPossibleItemByKey(m, "RotateSize")
  96. if rotateSizeValue != nil {
  97. m[rotateSizeKey] = gfile.StrToSize(gconv.String(rotateSizeValue))
  98. if m[rotateSizeKey] == -1 {
  99. return gerror.NewCodef(gcode.CodeInvalidConfiguration, `invalid rotate size: %v`, rotateSizeValue)
  100. }
  101. }
  102. if err := gconv.Struct(m, &l.config); err != nil {
  103. return err
  104. }
  105. return l.SetConfig(l.config)
  106. }
  107. // SetDebug enables/disables the debug level for logger.
  108. // The debug level is enabled in default.
  109. func (l *Logger) SetDebug(debug bool) {
  110. if debug {
  111. l.config.Level = l.config.Level | LEVEL_DEBU
  112. } else {
  113. l.config.Level = l.config.Level & ^LEVEL_DEBU
  114. }
  115. }
  116. // SetAsync enables/disables async logging output feature.
  117. func (l *Logger) SetAsync(enabled bool) {
  118. if enabled {
  119. l.config.Flags = l.config.Flags | F_ASYNC
  120. } else {
  121. l.config.Flags = l.config.Flags & ^F_ASYNC
  122. }
  123. }
  124. // SetFlags sets extra flags for logging output features.
  125. func (l *Logger) SetFlags(flags int) {
  126. l.config.Flags = flags
  127. }
  128. // GetFlags returns the flags of logger.
  129. func (l *Logger) GetFlags() int {
  130. return l.config.Flags
  131. }
  132. // SetStack enables/disables the stack feature in failure logging outputs.
  133. func (l *Logger) SetStack(enabled bool) {
  134. if enabled {
  135. l.config.StStatus = 1
  136. } else {
  137. l.config.StStatus = 0
  138. }
  139. }
  140. // SetStackSkip sets the stack offset from the end point.
  141. func (l *Logger) SetStackSkip(skip int) {
  142. l.config.StSkip = skip
  143. }
  144. // SetStackFilter sets the stack filter from the end point.
  145. func (l *Logger) SetStackFilter(filter string) {
  146. l.config.StFilter = filter
  147. }
  148. // SetCtxKeys sets the context keys for logger. The keys is used for retrieving values
  149. // from context and printing them to logging content.
  150. //
  151. // Note that multiple calls of this function will overwrite the previous set context keys.
  152. func (l *Logger) SetCtxKeys(keys ...interface{}) {
  153. l.config.CtxKeys = keys
  154. l.config.CtxKeys = append(l.config.CtxKeys, gctx.CtxKey)
  155. }
  156. // AppendCtxKeys appends extra keys to logger.
  157. // It ignores the key if it is already appended to the logger previously.
  158. func (l *Logger) AppendCtxKeys(keys ...interface{}) {
  159. var isExist bool
  160. for _, key := range keys {
  161. isExist = false
  162. for _, ctxKey := range l.config.CtxKeys {
  163. if ctxKey == key {
  164. isExist = true
  165. break
  166. }
  167. }
  168. if !isExist {
  169. l.config.CtxKeys = append(l.config.CtxKeys, key)
  170. }
  171. }
  172. }
  173. // GetCtxKeys retrieves and returns the context keys for logging.
  174. func (l *Logger) GetCtxKeys() []interface{} {
  175. return l.config.CtxKeys
  176. }
  177. // SetWriter sets the customized logging `writer` for logging.
  178. // The `writer` object should implements the io.Writer interface.
  179. // Developer can use customized logging `writer` to redirect logging output to another service,
  180. // eg: kafka, mysql, mongodb, etc.
  181. func (l *Logger) SetWriter(writer io.Writer) {
  182. l.config.Writer = writer
  183. }
  184. // GetWriter returns the customized writer object, which implements the io.Writer interface.
  185. // It returns nil if no writer previously set.
  186. func (l *Logger) GetWriter() io.Writer {
  187. return l.config.Writer
  188. }
  189. // SetPath sets the directory path for file logging.
  190. func (l *Logger) SetPath(path string) error {
  191. if path == "" {
  192. return gerror.NewCode(gcode.CodeInvalidParameter, "logging path is empty")
  193. }
  194. if !gfile.Exists(path) {
  195. if err := gfile.Mkdir(path); err != nil {
  196. return gerror.WrapCodef(gcode.CodeOperationFailed, err, `Mkdir "%s" failed in PWD "%s"`, path, gfile.Pwd())
  197. }
  198. }
  199. l.config.Path = strings.TrimRight(path, gfile.Separator)
  200. return nil
  201. }
  202. // GetPath returns the logging directory path for file logging.
  203. // It returns empty string if no directory path set.
  204. func (l *Logger) GetPath() string {
  205. return l.config.Path
  206. }
  207. // SetFile sets the file name `pattern` for file logging.
  208. // Datetime pattern can be used in `pattern`, eg: access-{Ymd}.log.
  209. // The default file name pattern is: Y-m-d.log, eg: 2018-01-01.log
  210. func (l *Logger) SetFile(pattern string) {
  211. l.config.File = pattern
  212. }
  213. // SetStdoutPrint sets whether output the logging contents to stdout, which is true in default.
  214. func (l *Logger) SetStdoutPrint(enabled bool) {
  215. l.config.StdoutPrint = enabled
  216. }
  217. // SetHeaderPrint sets whether output header of the logging contents, which is true in default.
  218. func (l *Logger) SetHeaderPrint(enabled bool) {
  219. l.config.HeaderPrint = enabled
  220. }
  221. // SetPrefix sets prefix string for every logging content.
  222. // Prefix is part of header, which means if header output is shut, no prefix will be output.
  223. func (l *Logger) SetPrefix(prefix string) {
  224. l.config.Prefix = prefix
  225. }
  226. // SetHandlers sets the logging handlers for current logger.
  227. func (l *Logger) SetHandlers(handlers ...Handler) {
  228. l.config.Handlers = handlers
  229. }
  230. //SetWriterColorEnable sets the file logging with color
  231. func (l *Logger) SetWriterColorEnable(enabled bool) {
  232. l.config.WriterColorEnable = enabled
  233. }