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  }