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