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