per module log levels (Refs #493)

This commit is contained in:
Anton Kaliaev
2017-05-15 19:33:45 +02:00
parent e041b2eee6
commit 05a8204508
7 changed files with 164 additions and 13 deletions

View File

@ -0,0 +1,85 @@
package flags
import (
"fmt"
"strings"
"github.com/pkg/errors"
cfg "github.com/tendermint/tendermint/config"
"github.com/tendermint/tmlibs/log"
)
const (
defaultLogLevelKey = "*"
)
// IsLogLevelSimple returns true if log level is a single word ("info", ...).
func IsLogLevelSimple(l string) bool {
return !strings.Contains(l, ":")
}
// ParseComplexLogLevel parses complex log level - comma-separated
// list of module:level pairs with an optional *:level pair (* means
// all other modules).
//
// Example:
// ParseComplexLogLevel("consensus:debug,mempool:debug,*:error", log.NewTMLogger(os.Stdout))
func ParseComplexLogLevel(l string, logger log.Logger) (log.Logger, error) {
if l == "" {
return nil, errors.New("Empty log level")
}
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(cfg.DefaultBaseConfig().LogLevel)
if err != nil {
return nil, err
}
options = append(options, option)
}
return log.NewFilter(logger, options...), nil
}

View File

@ -0,0 +1,42 @@
package flags_test
import (
"testing"
tmflags "github.com/tendermint/tendermint/cmd/tendermint/commands/flags"
"github.com/tendermint/tmlibs/log"
)
func TestIsLogLevelSimple(t *testing.T) {
simpleFlags := []string{"info", "debug", "some"}
for _, f := range simpleFlags {
if !tmflags.IsLogLevelSimple(f) {
t.Fatalf("%s is a simple flag", f)
}
}
complexFlags := []string{"mempool:error", "mempool:error,*:debug"}
for _, f := range complexFlags {
if tmflags.IsLogLevelSimple(f) {
t.Fatalf("%s is a complex flag", f)
}
}
}
func TestParseComplexLogLevel(t *testing.T) {
logger := log.TestingLogger()
correctLogLevels := []string{"mempool:error", "mempool:error,*:debug", "*:debug,wire:none"}
for _, lvl := range correctLogLevels {
if _, err := tmflags.ParseComplexLogLevel(lvl, logger); err != nil {
t.Fatal(err)
}
}
incorrectLogLevel := []string{"some", "mempool:some", "*:some,mempool:error"}
for _, lvl := range incorrectLogLevel {
if _, err := tmflags.ParseComplexLogLevel(lvl, logger); err == nil {
t.Fatalf("Expected %s to produce error", lvl)
}
}
}

View File

@ -1,11 +1,13 @@
package commands
import (
"fmt"
"os"
"github.com/spf13/cobra"
"github.com/spf13/viper"
tmflags "github.com/tendermint/tendermint/cmd/tendermint/commands/flags"
cfg "github.com/tendermint/tendermint/config"
"github.com/tendermint/tmlibs/log"
)
@ -26,9 +28,21 @@ var RootCmd = &cobra.Command{
err := viper.Unmarshal(config)
config.SetRoot(config.RootDir)
cfg.EnsureRoot(config.RootDir)
logger, err = log.NewFilterByLevel(logger, config.LogLevel)
if err != nil {
return err
if tmflags.IsLogLevelSimple(config.LogLevel) {
var option log.Option
switch config.LogLevel {
case "info":
option = log.AllowInfo()
case "debug":
option = log.AllowDebug()
case "error":
option = log.AllowError()
case "none":
option = log.AllowNone()
default:
return fmt.Errorf("Expected log level to be either \"info\", \"debug\", \"error\" or \"none\", given %s", config.LogLevel)
}
logger = log.NewFilter(logger, option)
}
return err
},

View File

@ -7,6 +7,7 @@ import (
"github.com/spf13/cobra"
tmflags "github.com/tendermint/tendermint/cmd/tendermint/commands/flags"
"github.com/tendermint/tendermint/node"
"github.com/tendermint/tendermint/types"
cmn "github.com/tendermint/tmlibs/common"
@ -79,6 +80,14 @@ func runNode(cmd *cobra.Command, args []string) error {
}
}
if !tmflags.IsLogLevelSimple(config.LogLevel) {
var err error
logger, err = tmflags.ParseComplexLogLevel(config.LogLevel, logger)
if err != nil {
return err
}
}
// Create & start node
n := node.NewNodeDefault(config, logger.With("module", "node"))
if _, err := n.Start(); err != nil {