Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions os/glog/glog_logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"os"
"runtime"
"strings"
"sync"
"time"

"github.com/fatih/color"
Expand All @@ -36,6 +37,7 @@ import (
type Logger struct {
parent *Logger // Parent logger, if it is not empty, it means the logger is used in chaining function.
config Config // Logger configuration.
mu sync.RWMutex
}

const (
Expand Down Expand Up @@ -76,6 +78,8 @@ func NewWithWriter(writer io.Writer) *Logger {
// Clone returns a new logger, which a `shallow copy` of the current logger.
// Note that the attribute `config` of the cloned one is the shallow copy of current one.
func (l *Logger) Clone() *Logger {
l.mu.RLock()
defer l.mu.RUnlock()
return &Logger{
config: l.config,
parent: l,
Expand All @@ -95,6 +99,8 @@ func (l *Logger) getFilePath(now time.Time) string {

// print prints `s` to defined writer, logging file or passed `std`.
func (l *Logger) print(ctx context.Context, level int, stack string, values ...any) {
l.mu.RLock()
defer l.mu.RUnlock()
// Lazy initialize for rotation feature.
// It uses atomic reading operation to enhance the performance checking.
// It here uses CAP for performance and concurrent safety.
Expand Down Expand Up @@ -222,6 +228,8 @@ func (l *Logger) print(ctx context.Context, level int, stack string, values ...a

// doFinalPrint outputs the logging content according configuration.
func (l *Logger) doFinalPrint(ctx context.Context, input *HandlerInput) *bytes.Buffer {
l.mu.RLock()
defer l.mu.RUnlock()
var buffer *bytes.Buffer
// Allow output to stdout?
if l.config.StdoutPrint {
Expand Down Expand Up @@ -369,10 +377,12 @@ func (l *Logger) printErr(ctx context.Context, level int, values ...any) {
if l == nil {
return
}
l.mu.RLock()
var stack string
if l.config.StStatus == 1 {
stack = l.GetStack()
}
l.mu.RUnlock()
// In matter of sequence, do not use stderr here, but use the same stdout.
l.print(ctx, level, stack, values...)
}
Expand All @@ -395,6 +405,8 @@ func (l *Logger) PrintStack(ctx context.Context, skip ...int) {
// GetStack returns the caller stack content,
// the optional parameter `skip` specify the skipped stack offset from the end point.
func (l *Logger) GetStack(skip ...int) string {
l.mu.RLock()
defer l.mu.RUnlock()
stackSkip := l.config.StSkip
if len(skip) > 0 {
stackSkip += skip[0]
Expand Down
2 changes: 2 additions & 0 deletions os/glog/glog_logger_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,5 +146,7 @@ func (l *Logger) checkLevel(level int) bool {
if l == nil {
return false
}
l.mu.RLock()
defer l.mu.RUnlock()
return l.config.Level&level > 0
}
55 changes: 54 additions & 1 deletion os/glog/glog_logger_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"context"
"io"
"strings"
"sync"

Check failure on line 13 in os/glog/glog_logger_config.go

View workflow job for this annotation

GitHub Actions / golang-ci-lint (stable)

"sync" imported and not used
"time"

"github.com/gogf/gf/v2/container/gtype"
Expand Down Expand Up @@ -83,11 +84,15 @@

// GetConfig returns the configuration of current Logger.
func (l *Logger) GetConfig() Config {
l.mu.RLock()
defer l.mu.RUnlock()
return l.config
}

// SetConfig set configurations for the logger.
func (l *Logger) SetConfig(config Config) error {
l.mu.Lock()
defer l.mu.Unlock()
l.config = config
// Necessary validation.
if config.Path != "" {
Expand All @@ -102,6 +107,8 @@

// SetConfigWithMap set configurations with map for the logger.
func (l *Logger) SetConfigWithMap(m map[string]any) error {
l.mu.Lock()
defer l.mu.Unlock()
if len(m) == 0 {
return gerror.NewCode(gcode.CodeInvalidParameter, "configuration cannot be empty")
}
Expand Down Expand Up @@ -134,6 +141,8 @@
// SetDebug enables/disables the debug level for logger.
// The debug level is enabled in default.
func (l *Logger) SetDebug(debug bool) {
l.mu.Lock()
defer l.mu.Unlock()
if debug {
l.config.Level = l.config.Level | LEVEL_DEBU
} else {
Expand All @@ -143,6 +152,8 @@

// SetAsync enables/disables async logging output feature.
func (l *Logger) SetAsync(enabled bool) {
l.mu.Lock()
defer l.mu.Unlock()
if enabled {
l.config.Flags = l.config.Flags | F_ASYNC
} else {
Expand All @@ -152,16 +163,22 @@

// SetFlags sets extra flags for logging output features.
func (l *Logger) SetFlags(flags int) {
l.mu.Lock()
defer l.mu.Unlock()
l.config.Flags = flags
}

// GetFlags returns the flags of logger.
func (l *Logger) GetFlags() int {
l.mu.RLock()
defer l.mu.RUnlock()
return l.config.Flags
}

// SetStack enables/disables the stack feature in failure logging outputs.
func (l *Logger) SetStack(enabled bool) {
l.mu.Lock()
defer l.mu.Unlock()
if enabled {
l.config.StStatus = 1
} else {
Expand All @@ -171,11 +188,15 @@

// SetStackSkip sets the stack offset from the end point.
func (l *Logger) SetStackSkip(skip int) {
l.mu.Lock()
defer l.mu.Unlock()
l.config.StSkip = skip
}

// SetStackFilter sets the stack filter from the end point.
func (l *Logger) SetStackFilter(filter string) {
l.mu.Lock()
defer l.mu.Unlock()
l.config.StFilter = filter
}

Expand All @@ -184,12 +205,16 @@
//
// Note that multiple calls of this function will overwrite the previous set context keys.
func (l *Logger) SetCtxKeys(keys ...any) {
l.mu.Lock()
defer l.mu.Unlock()
l.config.CtxKeys = keys
}

// AppendCtxKeys appends extra keys to logger.
// It ignores the key if it is already appended to the logger previously.
func (l *Logger) AppendCtxKeys(keys ...any) {
l.mu.Lock()
defer l.mu.Unlock()
var isExist bool
for _, key := range keys {
isExist = false
Expand All @@ -207,6 +232,8 @@

// GetCtxKeys retrieves and returns the context keys for logging.
func (l *Logger) GetCtxKeys() []any {
l.mu.RLock()
defer l.mu.RUnlock()
return l.config.CtxKeys
}

Expand All @@ -215,12 +242,16 @@
// Developer can use customized logging `writer` to redirect logging output to another service,
// eg: kafka, mysql, mongodb, etc.
func (l *Logger) SetWriter(writer io.Writer) {
l.mu.Lock()
defer l.mu.Unlock()
l.config.Writer = writer
}

// GetWriter returns the customized writer object, which implements the io.Writer interface.
// It returns nil if no writer previously set.
func (l *Logger) GetWriter() io.Writer {
l.mu.RLock()
defer l.mu.RUnlock()
return l.config.Writer
}

Expand All @@ -234,60 +265,82 @@
return gerror.Wrapf(err, `Mkdir "%s" failed in PWD "%s"`, path, gfile.Pwd())
}
}
l.mu.Lock()
defer l.mu.Unlock()
l.config.Path = strings.TrimRight(path, gfile.Separator)
return nil
}

// GetPath returns the logging directory path for file logging.
// It returns empty string if no directory path set.
func (l *Logger) GetPath() string {
l.mu.RLock()
defer l.mu.RUnlock()
return l.config.Path
}

// SetFile sets the file name `pattern` for file logging.
// Datetime pattern can be used in `pattern`, eg: access-{Ymd}.log.
// The default file name pattern is: Y-m-d.log, eg: 2018-01-01.log
func (l *Logger) SetFile(pattern string) {
l.mu.Lock()
defer l.mu.Unlock()
l.config.File = pattern
}

// SetTimeFormat sets the time format for the logging time.
func (l *Logger) SetTimeFormat(timeFormat string) {
l.mu.Lock()
defer l.mu.Unlock()
l.config.TimeFormat = timeFormat
}

// SetStdoutPrint sets whether output the logging contents to stdout, which is true in default.
func (l *Logger) SetStdoutPrint(enabled bool) {
l.mu.Lock()
defer l.mu.Unlock()
l.config.StdoutPrint = enabled
}

// SetHeaderPrint sets whether output header of the logging contents, which is true in default.
func (l *Logger) SetHeaderPrint(enabled bool) {
l.mu.Lock()
defer l.mu.Unlock()
l.config.HeaderPrint = enabled
}

// SetLevelPrint sets whether output level string of the logging contents, which is true in default.
func (l *Logger) SetLevelPrint(enabled bool) {
l.mu.Lock()
defer l.mu.Unlock()
l.config.LevelPrint = enabled
}

// SetPrefix sets prefix string for every logging content.
// Prefix is part of header, which means if header output is shut, no prefix will be output.
func (l *Logger) SetPrefix(prefix string) {
l.mu.Lock()
defer l.mu.Unlock()
l.config.Prefix = prefix
}

// SetHandlers sets the logging handlers for current logger.
func (l *Logger) SetHandlers(handlers ...Handler) {
l.mu.Lock()
defer l.mu.Unlock()
l.config.Handlers = handlers
}

// SetWriterColorEnable enables file/writer logging with color.
func (l *Logger) SetWriterColorEnable(enabled bool) {
l.mu.Lock()
defer l.mu.Unlock()
l.config.WriterColorEnable = enabled
}

// SetStdoutColorDisabled disables stdout logging with color.
func (l *Logger) SetStdoutColorDisabled(disabled bool) {
l.mu.Lock()
defer l.mu.Unlock()
l.config.StdoutColorDisabled = disabled
}
}
17 changes: 16 additions & 1 deletion os/glog/glog_logger_level.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import (
"strings"
"sync"

Check failure on line 11 in os/glog/glog_logger_level.go

View workflow job for this annotation

GitHub Actions / golang-ci-lint (stable)

"sync" imported and not used (typecheck)

"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
Expand Down Expand Up @@ -66,16 +67,22 @@
// Note that levels ` LEVEL_CRIT | LEVEL_PANI | LEVEL_FATA ` cannot be removed for logging content,
// which are automatically added to levels.
func (l *Logger) SetLevel(level int) {
l.mu.Lock()
defer l.mu.Unlock()
l.config.Level = level | LEVEL_CRIT | LEVEL_PANI | LEVEL_FATA
}

// GetLevel returns the logging level value.
func (l *Logger) GetLevel() int {
l.mu.RLock()
defer l.mu.RUnlock()
return l.config.Level
}

// SetLevelStr sets the logging level by level string.
func (l *Logger) SetLevelStr(levelStr string) error {
l.mu.Lock()
defer l.mu.Unlock()
if level, ok := levelStringMap[strings.ToUpper(levelStr)]; ok {
l.config.Level = level
} else {
Expand All @@ -86,26 +93,34 @@

// SetLevelPrefix sets the prefix string for specified level.
func (l *Logger) SetLevelPrefix(level int, prefix string) {
l.mu.Lock()
defer l.mu.Unlock()
l.config.LevelPrefixes[level] = prefix
}

// SetLevelPrefixes sets the level to prefix string mapping for the logger.
func (l *Logger) SetLevelPrefixes(prefixes map[int]string) {
l.mu.Lock()
defer l.mu.Unlock()
for k, v := range prefixes {
l.config.LevelPrefixes[k] = v
}
}

// GetLevelPrefix returns the prefix string for specified level.
func (l *Logger) GetLevelPrefix(level int) string {
l.mu.RLock()
defer l.mu.RUnlock()
return l.config.LevelPrefixes[level]
}

// getLevelPrefixWithBrackets returns the prefix string with brackets for specified level.
func (l *Logger) getLevelPrefixWithBrackets(level int) string {
l.mu.RLock()
defer l.mu.RUnlock()
levelStr := ""
if s, ok := l.config.LevelPrefixes[level]; ok {
levelStr = "[" + s + "]"
}
return levelStr
}
}
Loading