From 3ea74c4362894a413dcce3a24dce976a29bdd21a Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 20 Sep 2019 16:15:53 +0200 Subject: [PATCH] build: move log level parse code and add new leveled sub logger interface --- build/log.go | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++ config.go | 93 ++------------------------------------------- rpcserver.go | 5 ++- 3 files changed, 112 insertions(+), 91 deletions(-) diff --git a/build/log.go b/build/log.go index 31be5d4d..e8ce253a 100644 --- a/build/log.go +++ b/build/log.go @@ -1,7 +1,9 @@ package build import ( + "fmt" "io" + "strings" "github.com/btcsuite/btclog" ) @@ -93,3 +95,106 @@ func NewSubLogger(subsystem string, // For any other configurations, we'll disable logging. return btclog.Disabled } + +// SubLoggers is a type that holds a map of subsystem loggers keyed by their +// subsystem name. +type SubLoggers map[string]btclog.Logger + +// LeveledSubLogger provides the ability to retrieve the subsystem loggers of +// a logger and set their log levels individually or all at once. +type LeveledSubLogger interface { + // SubLoggers returns the map of all registered subsystem loggers. + SubLoggers() SubLoggers + + // SupportedSubsystems returns a slice of strings containing the names + // of the supported subsystems. Should ideally correspond to the keys + // of the subsystem logger map and be sorted. + SupportedSubsystems() []string + + // SetLogLevel assigns an individual subsystem logger a new log level. + SetLogLevel(subsystemID string, logLevel string) + + // SetLogLevels assigns all subsystem loggers the same new log level. + SetLogLevels(logLevel string) +} + +// ParseAndSetDebugLevels attempts to parse the specified debug level and set +// the levels accordingly on the given logger. An appropriate error is returned +// if anything is invalid. +func ParseAndSetDebugLevels(level string, logger LeveledSubLogger) error { + // When the specified string doesn't have any delimiters, treat it as + // the log level for all subsystems. + if !strings.Contains(level, ",") && !strings.Contains(level, "=") { + // Validate debug log level. + if !validLogLevel(level) { + str := "the specified debug level [%v] is invalid" + return fmt.Errorf(str, level) + } + + // Change the logging level for all subsystems. + logger.SetLogLevels(level) + + return nil + } + + // Split the specified string into subsystem/level pairs while detecting + // issues and update the log levels accordingly. + for _, logLevelPair := range strings.Split(level, ",") { + if !strings.Contains(logLevelPair, "=") { + str := "the specified debug level contains an " + + "invalid subsystem/level pair [%v]" + return fmt.Errorf(str, logLevelPair) + } + + // Extract the specified subsystem and log level. + fields := strings.Split(logLevelPair, "=") + if len(fields) != 2 { + str := "the specified debug level has an invalid " + + "format [%v] -- use format subsystem1=level1," + + "subsystem2=level2" + return fmt.Errorf(str, logLevelPair) + } + subsysID, logLevel := fields[0], fields[1] + subLoggers := logger.SubLoggers() + + // Validate subsystem. + if _, exists := subLoggers[subsysID]; !exists { + str := "the specified subsystem [%v] is invalid -- " + + "supported subsystems are %v" + return fmt.Errorf( + str, subsysID, logger.SupportedSubsystems(), + ) + } + + // Validate log level. + if !validLogLevel(logLevel) { + str := "the specified debug level [%v] is invalid" + return fmt.Errorf(str, logLevel) + } + + logger.SetLogLevel(subsysID, logLevel) + } + + return nil +} + +// validLogLevel returns whether or not logLevel is a valid debug log level. +func validLogLevel(logLevel string) bool { + switch logLevel { + case "trace": + fallthrough + case "debug": + fallthrough + case "info": + fallthrough + case "warn": + fallthrough + case "error": + fallthrough + case "critical": + fallthrough + case "off": + return true + } + return false +} diff --git a/config.go b/config.go index dc71a75c..c1420d17 100644 --- a/config.go +++ b/config.go @@ -14,7 +14,6 @@ import ( "path" "path/filepath" "regexp" - "sort" "strconv" "strings" "time" @@ -952,10 +951,11 @@ func loadConfig() (*config, error) { normalizeNetwork(activeNetParams.Name)) // Special show command to list supported subsystems and exit. + /*TODO(guggero) fix if cfg.DebugLevel == "show" { fmt.Println("Supported subsystems", supportedSubsystems()) os.Exit(0) - } + }*/ // Initialize logging at the default logging level. initLogRotator( @@ -964,12 +964,13 @@ func loadConfig() (*config, error) { ) // Parse, validate, and set debug log level(s). + /*TODO(guggero) fix if err := parseAndSetDebugLevels(cfg.DebugLevel); err != nil { err := fmt.Errorf("%s: %v", funcName, err.Error()) fmt.Fprintln(os.Stderr, err) fmt.Fprintln(os.Stderr, usageMessage) return nil, err - } + }*/ // At least one RPCListener is required. So listen on localhost per // default. @@ -1140,92 +1141,6 @@ func cleanAndExpandPath(path string) string { return filepath.Clean(os.ExpandEnv(path)) } -// parseAndSetDebugLevels attempts to parse the specified debug level and set -// the levels accordingly. An appropriate error is returned if anything is -// invalid. -func parseAndSetDebugLevels(debugLevel string) error { - // When the specified string doesn't have any delimiters, treat it as - // the log level for all subsystems. - if !strings.Contains(debugLevel, ",") && !strings.Contains(debugLevel, "=") { - // Validate debug log level. - if !validLogLevel(debugLevel) { - str := "The specified debug level [%v] is invalid" - return fmt.Errorf(str, debugLevel) - } - - // Change the logging level for all subsystems. - setLogLevels(debugLevel) - - return nil - } - - // Split the specified string into subsystem/level pairs while detecting - // issues and update the log levels accordingly. - for _, logLevelPair := range strings.Split(debugLevel, ",") { - if !strings.Contains(logLevelPair, "=") { - str := "The specified debug level contains an invalid " + - "subsystem/level pair [%v]" - return fmt.Errorf(str, logLevelPair) - } - - // Extract the specified subsystem and log level. - fields := strings.Split(logLevelPair, "=") - subsysID, logLevel := fields[0], fields[1] - - // Validate subsystem. - if _, exists := subsystemLoggers[subsysID]; !exists { - str := "The specified subsystem [%v] is invalid -- " + - "supported subsystems %v" - return fmt.Errorf(str, subsysID, supportedSubsystems()) - } - - // Validate log level. - if !validLogLevel(logLevel) { - str := "The specified debug level [%v] is invalid" - return fmt.Errorf(str, logLevel) - } - - setLogLevel(subsysID, logLevel) - } - - return nil -} - -// validLogLevel returns whether or not logLevel is a valid debug log level. -func validLogLevel(logLevel string) bool { - switch logLevel { - case "trace": - fallthrough - case "debug": - fallthrough - case "info": - fallthrough - case "warn": - fallthrough - case "error": - fallthrough - case "critical": - fallthrough - case "off": - return true - } - return false -} - -// supportedSubsystems returns a sorted slice of the supported subsystems for -// logging purposes. -func supportedSubsystems() []string { - // Convert the subsystemLoggers map keys to a slice. - subsystems := make([]string, 0, len(subsystemLoggers)) - for subsysID := range subsystemLoggers { - subsystems = append(subsystems, subsysID) - } - - // Sort the subsystems for stable display. - sort.Strings(subsystems) - return subsystems -} - func parseRPCParams(cConfig *chainConfig, nodeConfig interface{}, net chainCode, funcName string) error { diff --git a/rpcserver.go b/rpcserver.go index e4dc4a63..b9b1bc5a 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -12,7 +12,6 @@ import ( "net" "net/http" "sort" - "strings" "sync" "sync/atomic" "time" @@ -4343,7 +4342,7 @@ func (r *rpcServer) DebugLevel(ctx context.Context, // sub-systems. if req.Show { return &lnrpc.DebugLevelResponse{ - SubSystems: strings.Join(supportedSubsystems(), " "), + SubSystems: "", //TODO(guggero) fix strings.Join(supportedSubsystems(), " "), }, nil } @@ -4351,9 +4350,11 @@ func (r *rpcServer) DebugLevel(ctx context.Context, // Otherwise, we'll attempt to set the logging level using the // specified level spec. + /*TODO(guggero) fix if err := parseAndSetDebugLevels(req.LevelSpec); err != nil { return nil, err } + */ return &lnrpc.DebugLevelResponse{}, nil }