copy log level parsing from tendemint
API change due to me not wanting `flags` package to depend on tendermint's config package. Refs https://github.com/tendermint/tendermint/issues/504
This commit is contained in:
parent
306795ae1d
commit
5032b224bc
|
@ -0,0 +1,86 @@
|
||||||
|
package flags
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"github.com/tendermint/tmlibs/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultLogLevelKey = "*"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ParseLogLevel parses complex log level - comma-separated
|
||||||
|
// list of module:level pairs with an optional *:level pair (* means
|
||||||
|
// all other modules).
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
// ParseLogLevel("consensus:debug,mempool:debug,*:error", log.NewTMLogger(os.Stdout), "info")
|
||||||
|
func ParseLogLevel(lvl string, logger log.Logger, defaultLogLevelValue string) (log.Logger, error) {
|
||||||
|
if lvl == "" {
|
||||||
|
return nil, errors.New("Empty log level")
|
||||||
|
}
|
||||||
|
|
||||||
|
l := lvl
|
||||||
|
|
||||||
|
// prefix simple one word levels (e.g. "info") with "*"
|
||||||
|
if !strings.Contains(l, ":") {
|
||||||
|
l = defaultLogLevelKey + ":" + l
|
||||||
|
}
|
||||||
|
|
||||||
|
options := make([]log.Option, 0)
|
||||||
|
|
||||||
|
isDefaultLogLevelSet := false
|
||||||
|
var option log.Option
|
||||||
|
var err error
|
||||||
|
|
||||||
|
list := strings.Split(l, ",")
|
||||||
|
for _, item := range list {
|
||||||
|
moduleAndLevel := strings.Split(item, ":")
|
||||||
|
|
||||||
|
if len(moduleAndLevel) != 2 {
|
||||||
|
return nil, fmt.Errorf("Expected list in a form of \"module:level\" pairs, given pair %s, list %s", item, list)
|
||||||
|
}
|
||||||
|
|
||||||
|
module := moduleAndLevel[0]
|
||||||
|
level := moduleAndLevel[1]
|
||||||
|
|
||||||
|
if module == defaultLogLevelKey {
|
||||||
|
option, err = log.AllowLevel(level)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, fmt.Sprintf("Failed to parse default log level (pair %s, list %s)", item, l))
|
||||||
|
}
|
||||||
|
options = append(options, option)
|
||||||
|
isDefaultLogLevelSet = true
|
||||||
|
} else {
|
||||||
|
switch level {
|
||||||
|
case "debug":
|
||||||
|
option = log.AllowDebugWith("module", module)
|
||||||
|
case "info":
|
||||||
|
option = log.AllowInfoWith("module", module)
|
||||||
|
case "error":
|
||||||
|
option = log.AllowErrorWith("module", module)
|
||||||
|
case "none":
|
||||||
|
option = log.AllowNoneWith("module", module)
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("Expected either \"info\", \"debug\", \"error\" or \"none\" log level, given %s (pair %s, list %s)", level, item, list)
|
||||||
|
}
|
||||||
|
options = append(options, option)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if "*" is not provided, set default global level
|
||||||
|
if !isDefaultLogLevelSet {
|
||||||
|
option, err = log.AllowLevel(defaultLogLevelValue)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
options = append(options, option)
|
||||||
|
}
|
||||||
|
|
||||||
|
return log.NewFilter(logger, options...), nil
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
package flags_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
tmflags "github.com/tendermint/tmlibs/cli/flags"
|
||||||
|
"github.com/tendermint/tmlibs/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultLogLevelValue = "info"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestParseLogLevel(t *testing.T) {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
jsonLogger := log.NewTMJSONLogger(&buf)
|
||||||
|
|
||||||
|
correctLogLevels := []struct {
|
||||||
|
lvl string
|
||||||
|
expectedLogLines []string
|
||||||
|
}{
|
||||||
|
{"mempool:error", []string{``, ``, `{"_msg":"Mesmero","level":"error","module":"mempool"}`}},
|
||||||
|
{"mempool:error,*:debug", []string{``, ``, `{"_msg":"Mesmero","level":"error","module":"mempool"}`}},
|
||||||
|
{"*:debug,wire:none", []string{
|
||||||
|
`{"_msg":"Kingpin","level":"debug","module":"mempool"}`,
|
||||||
|
`{"_msg":"Kitty Pryde","level":"info","module":"mempool"}`,
|
||||||
|
`{"_msg":"Mesmero","level":"error","module":"mempool"}`}},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range correctLogLevels {
|
||||||
|
logger, err := tmflags.ParseLogLevel(c.lvl, jsonLogger, defaultLogLevelValue)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
logger = logger.With("module", "mempool")
|
||||||
|
|
||||||
|
buf.Reset()
|
||||||
|
|
||||||
|
logger.Debug("Kingpin")
|
||||||
|
if have := strings.TrimSpace(buf.String()); c.expectedLogLines[0] != have {
|
||||||
|
t.Errorf("\nwant '%s'\nhave '%s'\nlevel '%s'", c.expectedLogLines[0], have, c.lvl)
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.Reset()
|
||||||
|
|
||||||
|
logger.Info("Kitty Pryde")
|
||||||
|
if have := strings.TrimSpace(buf.String()); c.expectedLogLines[1] != have {
|
||||||
|
t.Errorf("\nwant '%s'\nhave '%s'\nlevel '%s'", c.expectedLogLines[1], have, c.lvl)
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.Reset()
|
||||||
|
|
||||||
|
logger.Error("Mesmero")
|
||||||
|
if have := strings.TrimSpace(buf.String()); c.expectedLogLines[2] != have {
|
||||||
|
t.Errorf("\nwant '%s'\nhave '%s'\nlevel '%s'", c.expectedLogLines[2], have, c.lvl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
incorrectLogLevel := []string{"some", "mempool:some", "*:some,mempool:error"}
|
||||||
|
for _, lvl := range incorrectLogLevel {
|
||||||
|
if _, err := tmflags.ParseLogLevel(lvl, jsonLogger, defaultLogLevelValue); err == nil {
|
||||||
|
t.Fatalf("Expected %s to produce error", lvl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue