From 03ba91e8a49704262d08b12947ea93d5741c1e06 Mon Sep 17 00:00:00 2001 From: ying-jeanne <74549700+ying-jeanne@users.noreply.github.com> Date: Mon, 11 Apr 2022 18:50:29 +0200 Subject: [PATCH] add feature toggle with new format (#47336) * add feature toggle with new format * fix some comments :heart: * Update pkg/infra/log/term/terminal_logger.go Co-authored-by: Emil Tullstedt Co-authored-by: Emil Tullstedt --- pkg/infra/log/level/level.go | 8 ++++ pkg/infra/log/log.go | 63 +++++++++++++++++++++++++-- pkg/infra/log/term/terminal_logger.go | 21 ++++++--- 3 files changed, 83 insertions(+), 9 deletions(-) diff --git a/pkg/infra/log/level/level.go b/pkg/infra/log/level/level.go index cc3ef214491..5b1308d5a17 100644 --- a/pkg/infra/log/level/level.go +++ b/pkg/infra/log/level/level.go @@ -196,6 +196,14 @@ var ( debugValue = &levelValue{level: levelDebug, name: "dbug"} ) +func SetLevelKeyAndValuesToGokitLog() { + key = "level" + errorValue = &levelValue{level: levelError, name: "error"} + warnValue = &levelValue{level: levelWarn, name: "warn"} + infoValue = &levelValue{level: levelInfo, name: "info"} + debugValue = &levelValue{level: levelDebug, name: "debug"} +} + type level byte const ( diff --git a/pkg/infra/log/log.go b/pkg/infra/log/log.go index 21c11705e6a..ea3b824388d 100644 --- a/pkg/infra/log/log.go +++ b/pkg/infra/log/log.go @@ -11,6 +11,7 @@ import ( "os" "path/filepath" "sort" + "strconv" "strings" "sync" "time" @@ -30,6 +31,7 @@ var ( loggersToReload []ReloadableHandler root *logManager now = time.Now + logTimeFormat = "2006-01-02T15:04:05.99-0700" ) const ( @@ -53,9 +55,10 @@ func init() { // logManager manage loggers type logManager struct { *ConcreteLogger - loggersByName map[string]*ConcreteLogger - logFilters []logWithFilters - mutex sync.RWMutex + loggersByName map[string]*ConcreteLogger + logFilters []logWithFilters + mutex sync.RWMutex + gokitLogActivated bool } func newManager(logger gokitlog.Logger) *logManager { @@ -69,6 +72,12 @@ func (lm *logManager) initialize(loggers []logWithFilters) { lm.mutex.Lock() defer lm.mutex.Unlock() + if lm.gokitLogActivated { + level.SetLevelKeyAndValuesToGokitLog() + term.SetTimeFormatGokitLog() + logTimeFormat = time.RFC3339Nano + } + defaultLoggers := make([]gokitlog.Logger, len(loggers)) for index, logger := range loggers { defaultLoggers[index] = level.NewFilter(logger.val, logger.maxLevel) @@ -181,7 +190,7 @@ func (cl *ConcreteLogger) Info(msg string, args ...interface{}) { } func (cl *ConcreteLogger) log(msg string, logLevel level.Value, args ...interface{}) error { - logger := gokitlog.With(&cl.SwapLogger, "t", gokitlog.TimestampFormat(now, "2006-01-02T15:04:05.99-0700")) + logger := gokitlog.With(&cl.SwapLogger, "t", gokitlog.TimestampFormat(now, logTimeFormat)) args = append([]interface{}{level.Key(), logLevel, "msg", msg}, args...) return logger.Log(args...) @@ -436,9 +445,55 @@ func ReadLoggingConfig(modes []string, logsPath string, cfg *ini.File) error { configLoggers = append(configLoggers, handler) } + var err error + root.gokitLogActivated, err = isNewLoggerActivated(cfg) + if err != nil { + return err + } if len(configLoggers) > 0 { root.initialize(configLoggers) } return nil } + +// This would be removed eventually, no need to make a fancy design. +// For the sake of important cycle I just copied the function +func isNewLoggerActivated(cfg *ini.File) (bool, error) { + section := cfg.Section("feature_toggles") + toggles, err := readFeatureTogglesFromInitFile(section) + if err != nil { + return false, err + } + return toggles["newlog"], nil +} + +func readFeatureTogglesFromInitFile(featureTogglesSection *ini.Section) (map[string]bool, error) { + featureToggles := make(map[string]bool, 10) + + // parse the comma separated list in `enable`. + featuresTogglesStr := valueAsString(featureTogglesSection, "enable", "") + for _, feature := range util.SplitString(featuresTogglesStr) { + featureToggles[feature] = true + } + + // read all other settings under [feature_toggles]. If a toggle is + // present in both the value in `enable` is overridden. + for _, v := range featureTogglesSection.Keys() { + if v.Name() == "enable" { + continue + } + + b, err := strconv.ParseBool(v.Value()) + if err != nil { + return featureToggles, err + } + + featureToggles[v.Name()] = b + } + return featureToggles, nil +} + +func valueAsString(section *ini.Section, keyName string, defaultValue string) string { + return section.Key(keyName).MustString(defaultValue) +} diff --git a/pkg/infra/log/term/terminal_logger.go b/pkg/infra/log/term/terminal_logger.go index 860ef27c7b6..d98644a87dc 100644 --- a/pkg/infra/log/term/terminal_logger.go +++ b/pkg/infra/log/term/terminal_logger.go @@ -14,14 +14,22 @@ import ( "github.com/grafana/grafana/pkg/infra/log/level" ) -const ( +var ( timeFormat = "2006-01-02T15:04:05-0700" termTimeFormat = "01-02|15:04:05" - floatFormat = 'f' - termMsgJust = 40 - errorKey = "LOG15_ERROR" ) +const ( + floatFormat = 'f' + termMsgJust = 40 + errorKey = "LOG15_ERROR" +) + +func SetTimeFormatGokitLog() { + timeFormat = "2006-01-02T15:04:05.000-0700" + termTimeFormat = "01-02|15:04:05.000" +} + type terminalLogger struct { w io.Writer } @@ -45,7 +53,10 @@ func (l terminalLogger) Log(keyvals ...interface{}) error { r := getRecord(keyvals) b := &bytes.Buffer{} - lvl := strings.ToUpper(r.level.String()) + + // To make the log output more readable, we make all log levels 5 characters long + lvl := fmt.Sprintf("%-5s", strings.ToUpper(r.level.String())) + if r.color > 0 { fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s] %s ", r.color, lvl, r.time.Format(termTimeFormat), r.msg) // lgtm[go/log-injection] } else {