From 8feb86c4aae1279038422f033d25f6d08c3f881b Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 22 Mar 2016 18:43:10 -0700 Subject: [PATCH] multi: create lnd's logging infrastructure --- chainntfs/log.go | 54 +++++++++++++++++++ channeldb/log.go | 53 +++++++++++++++++++ lnwallet/log.go | 56 ++++++++++++++++++++ log.go | 132 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 295 insertions(+) create mode 100644 chainntfs/log.go create mode 100644 lnwallet/log.go diff --git a/chainntfs/log.go b/chainntfs/log.go new file mode 100644 index 00000000..92acc585 --- /dev/null +++ b/chainntfs/log.go @@ -0,0 +1,54 @@ +package chainntnfs + +import ( + "errors" + "io" + + "github.com/btcsuite/btclog" +) + +// log is a logger that is initialized with no output filters. This +// means the package will not perform any logging by default until the caller +// requests it. +var log btclog.Logger + +// The default amount of logging is none. +func init() { + DisableLog() +} + +// DisableLog disables all library log output. Logging output is disabled +// by default until either UseLogger or SetLogWriter are called. +func DisableLog() { + log = btclog.Disabled +} + +// UseLogger uses a specified Logger to output package logging info. +// This should be used in preference to SetLogWriter if the caller is also +// using btclog. +func UseLogger(logger btclog.Logger) { + log = logger +} + +// SetLogWriter uses a specified io.Writer to output package logging info. +// This allows a caller to direct package logging output without needing a +// dependency on seelog. If the caller is also using btclog, UseLogger should +// be used instead. +func SetLogWriter(w io.Writer, level string) error { + if w == nil { + return errors.New("nil writer") + } + + lvl, ok := btclog.LogLevelFromString(level) + if !ok { + return errors.New("invalid log level") + } + + l, err := btclog.NewLoggerFromWriter(w, lvl) + if err != nil { + return err + } + + UseLogger(l) + return nil +} diff --git a/channeldb/log.go b/channeldb/log.go index d03b3406..e13a0e5c 100644 --- a/channeldb/log.go +++ b/channeldb/log.go @@ -1 +1,54 @@ package channeldb + +import ( + "errors" + "io" + + "github.com/btcsuite/btclog" +) + +// log is a logger that is initialized with no output filters. This +// means the package will not perform any logging by default until the caller +// requests it. +var log btclog.Logger + +// The default amount of logging is none. +func init() { + DisableLog() +} + +// DisableLog disables all library log output. Logging output is disabled +// by default until either UseLogger or SetLogWriter are called. +func DisableLog() { + log = btclog.Disabled +} + +// UseLogger uses a specified Logger to output package logging info. +// This should be used in preference to SetLogWriter if the caller is also +// using btclog. +func UseLogger(logger btclog.Logger) { + log = logger +} + +// SetLogWriter uses a specified io.Writer to output package logging info. +// This allows a caller to direct package logging output without needing a +// dependency on seelog. If the caller is also using btclog, UseLogger should +// be used instead. +func SetLogWriter(w io.Writer, level string) error { + if w == nil { + return errors.New("nil writer") + } + + lvl, ok := btclog.LogLevelFromString(level) + if !ok { + return errors.New("invalid log level") + } + + l, err := btclog.NewLoggerFromWriter(w, lvl) + if err != nil { + return err + } + + UseLogger(l) + return nil +} diff --git a/lnwallet/log.go b/lnwallet/log.go new file mode 100644 index 00000000..b8f4080f --- /dev/null +++ b/lnwallet/log.go @@ -0,0 +1,56 @@ +package lnwallet + +import ( + "errors" + "io" + + "github.com/btcsuite/btclog" + btcwallet "github.com/btcsuite/btcwallet/wallet" +) + +// log is a logger that is initialized with no output filters. This +// means the package will not perform any logging by default until the caller +// requests it. +var log btclog.Logger + +// The default amount of logging is none. +func init() { + DisableLog() +} + +// DisableLog disables all library log output. Logging output is disabled +// by default until either UseLogger or SetLogWriter are called. +func DisableLog() { + log = btclog.Disabled +} + +// UseLogger uses a specified Logger to output package logging info. +// This should be used in preference to SetLogWriter if the caller is also +// using btclog. +func UseLogger(logger btclog.Logger) { + log = logger + btcwallet.UseLogger(logger) +} + +// SetLogWriter uses a specified io.Writer to output package logging info. +// This allows a caller to direct package logging output without needing a +// dependency on seelog. If the caller is also using btclog, UseLogger should +// be used instead. +func SetLogWriter(w io.Writer, level string) error { + if w == nil { + return errors.New("nil writer") + } + + lvl, ok := btclog.LogLevelFromString(level) + if !ok { + return errors.New("invalid log level") + } + + l, err := btclog.NewLoggerFromWriter(w, lvl) + if err != nil { + return err + } + + UseLogger(l) + return nil +} diff --git a/log.go b/log.go index 06ab7d0f..9f532d0f 100644 --- a/log.go +++ b/log.go @@ -1 +1,133 @@ package main + +import ( + "fmt" + "os" + + "github.com/btcsuite/btclog" + "github.com/btcsuite/seelog" + "github.com/lightningnetwork/lnd/chainntfs" + "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/lnwallet" +) + +// Loggers per subsystem. Note that backendLog is a seelog logger that all of +// the subsystem loggers route their messages to. When adding new subsystems, +// add a reference here, to the subsystemLoggers map, and the useLogger +// function. +var ( + backendLog = seelog.Disabled + ltndLog = btclog.Disabled + lnwlLog = btclog.Disabled + peerLog = btclog.Disabled + rpcsLog = btclog.Disabled + srvrLog = btclog.Disabled + ntfnLog = btclog.Disabled + chdbLog = btclog.Disabled +) + +// subsystemLoggers maps each subsystem identifier to its associated logger. +var subsystemLoggers = map[string]btclog.Logger{ + "LTND": ltndLog, + "LNWL": lnwlLog, + "PEER": peerLog, + "RPCS": rpcsLog, + "SRVR": srvrLog, + "NTFN": ntfnLog, + "CHDB": chdbLog, +} + +// useLogger updates the logger references for subsystemID to logger. Invalid +// subsystems are ignored. +func useLogger(subsystemID string, logger btclog.Logger) { + if _, ok := subsystemLoggers[subsystemID]; !ok { + return + } + subsystemLoggers[subsystemID] = logger + + switch subsystemID { + case "LTND": + ltndLog = logger + + case "LNWL": + lnwlLog = logger + lnwallet.UseLogger(logger) + + case "PEER": + peerLog = logger + + case "RPCS": + rpcsLog = logger + + case "SRVR": + srvrLog = logger + + case "NTFN": + ntfnLog = logger + chainntnfs.UseLogger(logger) + + case "CHDB": + chdbLog = logger + channeldb.UseLogger(logger) + } +} + +// initSeelogLogger initializes a new seelog logger that is used as the backend +// for all logging subsystems. +func initSeelogLogger(logFile string) { + config := ` + + + + + + + + + ` + config = fmt.Sprintf(config, logFile) + + logger, err := seelog.LoggerFromConfigAsString(config) + if err != nil { + fmt.Fprintf(os.Stderr, "failed to create logger: %v", err) + os.Exit(1) + } + + backendLog = logger +} + +// setLogLevel sets the logging level for provided subsystem. Invalid +// subsystems are ignored. Uninitialized subsystems are dynamically created as +// needed. +func setLogLevel(subsystemID string, logLevel string) { + // Ignore invalid subsystems. + logger, ok := subsystemLoggers[subsystemID] + if !ok { + return + } + + // Default to info if the log level is invalid. + level, ok := btclog.LogLevelFromString(logLevel) + if !ok { + level = btclog.InfoLvl + } + + // Create new logger for the subsystem if needed. + if logger == btclog.Disabled { + logger = btclog.NewSubsystemLogger(backendLog, subsystemID+": ") + useLogger(subsystemID, logger) + } + logger.SetLevel(level) +} + +// setLogLevels sets the log level for all subsystem loggers to the passed +// level. It also dynamically creates the subsystem loggers as needed, so it +// can be used to initialize the logging system. +func setLogLevels(logLevel string) { + // Configure all sub-systems with the new logging level. Dynamically + // create loggers as needed. + for subsystemID := range subsystemLoggers { + setLogLevel(subsystemID, logLevel) + } +}