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  }