diff --git a/build/handler_sets.go b/build/handler_sets.go index f37fdc22b..d9786a858 100644 --- a/build/handler_sets.go +++ b/build/handler_sets.go @@ -175,3 +175,27 @@ func (r *reducedSet) WithGroup(name string) slog.Handler { // A compile-time check to ensure that handlerSet implements slog.Handler. var _ slog.Handler = (*reducedSet)(nil) + +// subLogGenerator implements the SubLogCreator backed by a Handler. +type subLogGenerator struct { + handler btclog.Handler +} + +// newSubLogGenerator constructs a new subLogGenerator from a Handler. +func newSubLogGenerator(handler btclog.Handler) *subLogGenerator { + return &subLogGenerator{ + handler: handler, + } +} + +// Logger returns a new logger for a particular sub-system. +// +// NOTE: this is part of the SubLogCreator interface. +func (b *subLogGenerator) Logger(subsystemTag string) btclog.Logger { + handler := b.handler.SubSystem(subsystemTag) + + return btclog.NewSLogger(handler) +} + +// A compile-time check to ensure that handlerSet implements slog.Handler. +var _ SubLogCreator = (*subLogGenerator)(nil) diff --git a/build/log.go b/build/log.go index 579a0d50f..568f9f618 100644 --- a/build/log.go +++ b/build/log.go @@ -1,9 +1,9 @@ package build import ( - "io" + "os" - "github.com/btcsuite/btclog" + "github.com/btcsuite/btclog/v2" ) // LogType is an indicating the type of logging specified by the build flag. @@ -60,17 +60,6 @@ func SuportedLogCompressor(logCompressor string) bool { return ok } -// LogWriter is a stub type whose behavior can be changed using the build flags -// "stdlog" and "nolog". The default behavior is to write to both stdout and the -// RotatorPipe. Passing "stdlog" will cause it only to write to stdout, and -// "nolog" implements Write as a no-op. -type LogWriter struct { - // RotatorPipe is the write-end pipe for writing to the log rotator. It - // is written to by the Write method of the LogWriter type. This only - // needs to be set if neither the stdlog or nolog builds are set. - RotatorPipe *io.PipeWriter -} - // NewSubLogger constructs a new subsystem log from the current LogWriter // implementation. This is primarily intended for use with stdlog, as the actual // writer is shared amongst all instantiations. @@ -104,8 +93,10 @@ func NewSubLogger(subsystem string, // that they share the same backend, since all output is written // to std out. case LogTypeStdOut: - backend := btclog.NewBackend(&LogWriter{}) - logger := backend.Logger(subsystem) + backend := btclog.NewDefaultHandler(os.Stdout) + logger := btclog.NewSLogger( + backend.SubSystem(subsystem), + ) // Set the logging level of the stdout logger to use the // configured logging level specified by build flags. diff --git a/build/log_default.go b/build/log_default.go index bbb6d4c39..6e027e0dd 100644 --- a/build/log_default.go +++ b/build/log_default.go @@ -3,17 +3,6 @@ package build -import "os" - // LoggingType is a log type that writes to both stdout and the log rotator, if // present. const LoggingType = LogTypeDefault - -// Write writes the byte slice to both stdout and the log rotator, if present. -func (w *LogWriter) Write(b []byte) (int, error) { - os.Stdout.Write(b) - if w.RotatorPipe != nil { - w.RotatorPipe.Write(b) - } - return len(b), nil -} diff --git a/build/log_nolog.go b/build/log_nolog.go index 32199ada0..75f17bf66 100644 --- a/build/log_nolog.go +++ b/build/log_nolog.go @@ -5,8 +5,3 @@ package build // LoggingType is a log type that writes no logs. const LoggingType = LogTypeNone - -// Write is a noop. -func (w *LogWriter) Write(b []byte) (int, error) { - return len(b), nil -} diff --git a/build/log_shutdown.go b/build/log_shutdown.go index e5a63410b..4d7605780 100644 --- a/build/log_shutdown.go +++ b/build/log_shutdown.go @@ -1,7 +1,7 @@ package build import ( - "github.com/btcsuite/btclog" + "github.com/btcsuite/btclog/v2" ) // ShutdownLogger wraps an existing logger with a shutdown function which will diff --git a/build/log_stdlog.go b/build/log_stdlog.go index 34a8c1bf0..461474376 100644 --- a/build/log_stdlog.go +++ b/build/log_stdlog.go @@ -3,13 +3,5 @@ package build -import "os" - // LoggingType is a log type that only writes to stdout. const LoggingType = LogTypeStdOut - -// Write writes the provided byte slice to stdout. -func (w *LogWriter) Write(b []byte) (int, error) { - os.Stdout.Write(b) - return len(b), nil -} diff --git a/build/log_test.go b/build/log_test.go index 001b8e08b..dbce428e4 100644 --- a/build/log_test.go +++ b/build/log_test.go @@ -3,7 +3,7 @@ package build_test import ( "testing" - "github.com/btcsuite/btclog" + "github.com/btcsuite/btclog/v2" "github.com/lightningnetwork/lnd/build" "github.com/stretchr/testify/require" ) diff --git a/build/logrotator.go b/build/logrotator.go index e517a0d03..2ae105fde 100644 --- a/build/logrotator.go +++ b/build/logrotator.go @@ -14,7 +14,8 @@ import ( // RotatingLogWriter is a wrapper around the LogWriter that supports log file // rotation. type RotatingLogWriter struct { - logWriter *LogWriter + // pipe is the write-end pipe for writing to the log rotator. + pipe *io.PipeWriter rotator *rotator.Rotator } @@ -23,8 +24,8 @@ type RotatingLogWriter struct { // // NOTE: `InitLogRotator` must be called to set up log rotation after creating // the writer. -func NewRotatingLogWriter(w *LogWriter) *RotatingLogWriter { - return &RotatingLogWriter{logWriter: w} +func NewRotatingLogWriter() *RotatingLogWriter { + return &RotatingLogWriter{} } // InitLogRotator initializes the log file rotator to write logs to logFile and @@ -80,11 +81,20 @@ func (r *RotatingLogWriter) InitLogRotator(logFile, logCompressor string, } }() - r.logWriter.RotatorPipe = pw + r.pipe = pw return nil } +// Write writes the byte slice to the log rotator, if present. +func (r *RotatingLogWriter) Write(b []byte) (int, error) { + if r.rotator != nil { + return r.rotator.Write(b) + } + + return len(b), nil +} + // Close closes the underlying log rotator if it has already been created. func (r *RotatingLogWriter) Close() error { if r.rotator != nil { diff --git a/build/sub_logger.go b/build/sub_logger.go index c1d28fe60..2a68e6cd5 100644 --- a/build/sub_logger.go +++ b/build/sub_logger.go @@ -2,12 +2,11 @@ package build import ( "fmt" - "io" "sort" "strings" "sync" - "github.com/btcsuite/btclog" + "github.com/btcsuite/btclog/v2" ) // SubLogCreator can be used to create a new logger for a particular subsystem. @@ -30,10 +29,12 @@ type SubLoggerManager struct { var _ LeveledSubLogger = (*SubLoggerManager)(nil) // NewSubLoggerManager constructs a new SubLoggerManager. -func NewSubLoggerManager(w io.Writer) *SubLoggerManager { +func NewSubLoggerManager(handlers ...btclog.Handler) *SubLoggerManager { return &SubLoggerManager{ - loggers: SubLoggers{}, - genLogger: btclog.NewBackend(w), + loggers: make(SubLoggers), + genLogger: newSubLogGenerator( + newHandlerSet(btclog.LevelInfo, handlers...), + ), } } diff --git a/config.go b/config.go index 6cfd4941f..2f989ec93 100644 --- a/config.go +++ b/config.go @@ -21,6 +21,7 @@ import ( "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btclog/v2" flags "github.com/jessevdk/go-flags" "github.com/lightninglabs/neutrino" "github.com/lightningnetwork/lnd/autopilot" @@ -497,7 +498,6 @@ type Config struct { // SubLogMgr is the root logger that all the daemon's subloggers are // hooked up to. SubLogMgr *build.SubLoggerManager - LogWriter *build.LogWriter LogRotator *build.RotatingLogWriter // networkDir is the path to the directory of the currently active @@ -716,7 +716,7 @@ func DefaultConfig() Config { MaxChannelFeeAllocation: htlcswitch.DefaultMaxLinkFeeAllocation, MaxCommitFeeRateAnchors: lnwallet.DefaultAnchorsCommitMaxFeeRateSatPerVByte, MaxFeeExposure: uint64(htlcswitch.DefaultMaxFeeExposure.ToSatoshis()), - LogWriter: &build.LogWriter{}, + LogRotator: build.NewRotatingLogWriter(), DB: lncfg.DefaultDB(), Cluster: lncfg.DefaultCluster(), RPCMiddleware: lncfg.DefaultRPCMiddleware(), @@ -1402,10 +1402,18 @@ func ValidateConfig(cfg Config, interceptor signal.Interceptor, fileParser, lncfg.NormalizeNetwork(cfg.ActiveNetParams.Name), ) - // A log writer must be passed in, otherwise we can't function and would - // run into a panic later on. - if cfg.LogWriter == nil { - return nil, mkErr("log writer missing in config") + var ( + consoleLogHander = btclog.NewDefaultHandler(os.Stdout) + logHandlers []btclog.Handler + ) + switch build.LoggingType { + case build.LogTypeStdOut: + logHandlers = []btclog.Handler{consoleLogHander} + case build.LogTypeDefault: + logHandlers = []btclog.Handler{ + consoleLogHander, + btclog.NewDefaultHandler(cfg.LogRotator), + } } if !build.SuportedLogCompressor(cfg.LogCompressor) { @@ -1413,8 +1421,7 @@ func ValidateConfig(cfg Config, interceptor signal.Interceptor, fileParser, cfg.LogCompressor) } - cfg.LogRotator = build.NewRotatingLogWriter(cfg.LogWriter) - cfg.SubLogMgr = build.NewSubLoggerManager(cfg.LogWriter) + cfg.SubLogMgr = build.NewSubLoggerManager(logHandlers...) // Initialize logging at the default logging level. SetupLoggers(cfg.SubLogMgr, interceptor) diff --git a/log.go b/log.go index 748880447..88c31e105 100644 --- a/log.go +++ b/log.go @@ -3,7 +3,8 @@ package lnd import ( "github.com/btcsuite/btcd/connmgr" "github.com/btcsuite/btcd/rpcclient" - "github.com/btcsuite/btclog" + btclogv1 "github.com/btcsuite/btclog" + "github.com/btcsuite/btclog/v2" "github.com/lightninglabs/neutrino" sphinx "github.com/lightningnetwork/lightning-onion" "github.com/lightningnetwork/lnd/autopilot" @@ -116,6 +117,8 @@ func genSubLogger(root *build.SubLoggerManager, } // SetupLoggers initializes all package-global logger variables. +// +//nolint:lll func SetupLoggers(root *build.SubLoggerManager, interceptor signal.Interceptor) { genLogger := genSubLogger(root, interceptor) @@ -123,7 +126,7 @@ func SetupLoggers(root *build.SubLoggerManager, interceptor signal.Interceptor) // placeholder lnd package loggers. for _, l := range lndPkgLoggers { l.Logger = build.NewSubLogger(l.subsystem, genLogger) - SetSubLogger(root, l.subsystem, l.Logger) + SetV1SubLogger(root, l.subsystem, l.Logger) } // Initialize loggers from packages outside of `lnd` first. The @@ -132,69 +135,69 @@ func SetupLoggers(root *build.SubLoggerManager, interceptor signal.Interceptor) // `btcwallet.chain`, which is overwritten by `lnwallet`. To ensure the // overwriting works, we need to initialize the loggers here so they // can be overwritten later. - AddSubLogger(root, "BTCN", interceptor, neutrino.UseLogger) - AddSubLogger(root, "CMGR", interceptor, connmgr.UseLogger) - AddSubLogger(root, "RPCC", interceptor, rpcclient.UseLogger) + AddV1SubLogger(root, "BTCN", interceptor, neutrino.UseLogger) + AddV1SubLogger(root, "CMGR", interceptor, connmgr.UseLogger) + AddV1SubLogger(root, "RPCC", interceptor, rpcclient.UseLogger) // Some of the loggers declared in the main lnd package are also used // in sub packages. signal.UseLogger(ltndLog) autopilot.UseLogger(atplLog) - AddSubLogger(root, "LNWL", interceptor, lnwallet.UseLogger) - AddSubLogger(root, "DISC", interceptor, discovery.UseLogger) - AddSubLogger(root, "NTFN", interceptor, chainntnfs.UseLogger) - AddSubLogger(root, "CHDB", interceptor, channeldb.UseLogger) - AddSubLogger(root, "HSWC", interceptor, htlcswitch.UseLogger) - AddSubLogger(root, "CNCT", interceptor, contractcourt.UseLogger) - AddSubLogger(root, "UTXN", interceptor, contractcourt.UseNurseryLogger) - AddSubLogger(root, "BRAR", interceptor, contractcourt.UseBreachLogger) - AddSubLogger(root, "SPHX", interceptor, sphinx.UseLogger) - AddSubLogger(root, "SWPR", interceptor, sweep.UseLogger) - AddSubLogger(root, "SGNR", interceptor, signrpc.UseLogger) - AddSubLogger(root, "WLKT", interceptor, walletrpc.UseLogger) - AddSubLogger(root, "ARPC", interceptor, autopilotrpc.UseLogger) - AddSubLogger(root, "NRPC", interceptor, neutrinorpc.UseLogger) - AddSubLogger(root, "DRPC", interceptor, devrpc.UseLogger) - AddSubLogger(root, "INVC", interceptor, invoices.UseLogger) - AddSubLogger(root, "NANN", interceptor, netann.UseLogger) - AddSubLogger(root, "WTWR", interceptor, watchtower.UseLogger) - AddSubLogger(root, "NTFR", interceptor, chainrpc.UseLogger) - AddSubLogger(root, "IRPC", interceptor, invoicesrpc.UseLogger) - AddSubLogger(root, "CHNF", interceptor, channelnotifier.UseLogger) - AddSubLogger(root, "CHBU", interceptor, chanbackup.UseLogger) - AddSubLogger(root, "PROM", interceptor, monitoring.UseLogger) - AddSubLogger(root, "WTCL", interceptor, wtclient.UseLogger) - AddSubLogger(root, "PRNF", interceptor, peernotifier.UseLogger) - AddSubLogger(root, "CHFD", interceptor, chanfunding.UseLogger) - AddSubLogger(root, "PEER", interceptor, peer.UseLogger) - AddSubLogger(root, "CHCL", interceptor, chancloser.UseLogger) + AddV1SubLogger(root, "LNWL", interceptor, lnwallet.UseLogger) + AddV1SubLogger(root, "DISC", interceptor, discovery.UseLogger) + AddV1SubLogger(root, "NTFN", interceptor, chainntnfs.UseLogger) + AddV1SubLogger(root, "CHDB", interceptor, channeldb.UseLogger) + AddV1SubLogger(root, "HSWC", interceptor, htlcswitch.UseLogger) + AddV1SubLogger(root, "CNCT", interceptor, contractcourt.UseLogger) + AddV1SubLogger(root, "UTXN", interceptor, contractcourt.UseNurseryLogger) + AddV1SubLogger(root, "BRAR", interceptor, contractcourt.UseBreachLogger) + AddV1SubLogger(root, "SPHX", interceptor, sphinx.UseLogger) + AddV1SubLogger(root, "SWPR", interceptor, sweep.UseLogger) + AddV1SubLogger(root, "SGNR", interceptor, signrpc.UseLogger) + AddV1SubLogger(root, "WLKT", interceptor, walletrpc.UseLogger) + AddV1SubLogger(root, "ARPC", interceptor, autopilotrpc.UseLogger) + AddV1SubLogger(root, "NRPC", interceptor, neutrinorpc.UseLogger) + AddV1SubLogger(root, "DRPC", interceptor, devrpc.UseLogger) + AddV1SubLogger(root, "INVC", interceptor, invoices.UseLogger) + AddV1SubLogger(root, "NANN", interceptor, netann.UseLogger) + AddV1SubLogger(root, "WTWR", interceptor, watchtower.UseLogger) + AddV1SubLogger(root, "NTFR", interceptor, chainrpc.UseLogger) + AddV1SubLogger(root, "IRPC", interceptor, invoicesrpc.UseLogger) + AddV1SubLogger(root, "CHNF", interceptor, channelnotifier.UseLogger) + AddV1SubLogger(root, "CHBU", interceptor, chanbackup.UseLogger) + AddV1SubLogger(root, "PROM", interceptor, monitoring.UseLogger) + AddV1SubLogger(root, "WTCL", interceptor, wtclient.UseLogger) + AddV1SubLogger(root, "PRNF", interceptor, peernotifier.UseLogger) + AddV1SubLogger(root, "CHFD", interceptor, chanfunding.UseLogger) + AddV1SubLogger(root, "PEER", interceptor, peer.UseLogger) + AddV1SubLogger(root, "CHCL", interceptor, chancloser.UseLogger) - AddSubLogger(root, routing.Subsystem, interceptor, routing.UseLogger) - AddSubLogger(root, routerrpc.Subsystem, interceptor, routerrpc.UseLogger) - AddSubLogger(root, chanfitness.Subsystem, interceptor, chanfitness.UseLogger) - AddSubLogger(root, verrpc.Subsystem, interceptor, verrpc.UseLogger) - AddSubLogger(root, healthcheck.Subsystem, interceptor, healthcheck.UseLogger) - AddSubLogger(root, chainreg.Subsystem, interceptor, chainreg.UseLogger) - AddSubLogger(root, chanacceptor.Subsystem, interceptor, chanacceptor.UseLogger) - AddSubLogger(root, funding.Subsystem, interceptor, funding.UseLogger) - AddSubLogger(root, cluster.Subsystem, interceptor, cluster.UseLogger) - AddSubLogger(root, rpcperms.Subsystem, interceptor, rpcperms.UseLogger) - AddSubLogger(root, tor.Subsystem, interceptor, tor.UseLogger) - AddSubLogger(root, btcwallet.Subsystem, interceptor, btcwallet.UseLogger) - AddSubLogger(root, rpcwallet.Subsystem, interceptor, rpcwallet.UseLogger) - AddSubLogger(root, peersrpc.Subsystem, interceptor, peersrpc.UseLogger) - AddSubLogger(root, graph.Subsystem, interceptor, graph.UseLogger) - AddSubLogger(root, lncfg.Subsystem, interceptor, lncfg.UseLogger) - AddSubLogger( + AddV1SubLogger(root, routing.Subsystem, interceptor, routing.UseLogger) + AddV1SubLogger(root, routerrpc.Subsystem, interceptor, routerrpc.UseLogger) + AddV1SubLogger(root, chanfitness.Subsystem, interceptor, chanfitness.UseLogger) + AddV1SubLogger(root, verrpc.Subsystem, interceptor, verrpc.UseLogger) + AddV1SubLogger(root, healthcheck.Subsystem, interceptor, healthcheck.UseLogger) + AddV1SubLogger(root, chainreg.Subsystem, interceptor, chainreg.UseLogger) + AddV1SubLogger(root, chanacceptor.Subsystem, interceptor, chanacceptor.UseLogger) + AddV1SubLogger(root, funding.Subsystem, interceptor, funding.UseLogger) + AddV1SubLogger(root, cluster.Subsystem, interceptor, cluster.UseLogger) + AddV1SubLogger(root, rpcperms.Subsystem, interceptor, rpcperms.UseLogger) + AddV1SubLogger(root, tor.Subsystem, interceptor, tor.UseLogger) + AddV1SubLogger(root, btcwallet.Subsystem, interceptor, btcwallet.UseLogger) + AddV1SubLogger(root, rpcwallet.Subsystem, interceptor, rpcwallet.UseLogger) + AddV1SubLogger(root, peersrpc.Subsystem, interceptor, peersrpc.UseLogger) + AddV1SubLogger(root, graph.Subsystem, interceptor, graph.UseLogger) + AddV1SubLogger(root, lncfg.Subsystem, interceptor, lncfg.UseLogger) + AddV1SubLogger( root, blindedpath.Subsystem, interceptor, blindedpath.UseLogger, ) } -// AddSubLogger is a helper method to conveniently create and register the +// AddV1SubLogger is a helper method to conveniently create and register the // logger of one or more sub systems. -func AddSubLogger(root *build.SubLoggerManager, subsystem string, - interceptor signal.Interceptor, useLoggers ...func(btclog.Logger)) { +func AddV1SubLogger(root *build.SubLoggerManager, subsystem string, + interceptor signal.Interceptor, useLoggers ...func(btclogv1.Logger)) { // genSubLogger will return a callback for creating a logger instance, // which we will give to the root logger. @@ -203,13 +206,15 @@ func AddSubLogger(root *build.SubLoggerManager, subsystem string, // Create and register just a single logger to prevent them from // overwriting each other internally. logger := build.NewSubLogger(subsystem, genLogger) - SetSubLogger(root, subsystem, logger, useLoggers...) + SetV1SubLogger(root, subsystem, logger, useLoggers...) } -// SetSubLogger is a helper method to conveniently register the logger of a sub -// system. -func SetSubLogger(root *build.SubLoggerManager, subsystem string, - logger btclog.Logger, useLoggers ...func(btclog.Logger)) { +// SetV1SubLogger is a helper method to conveniently register the logger of a +// sub system. Note that the btclog v2 logger implements the btclog v1 logger +// which is why we can pass the v2 logger to the UseLogger call-backs that +// expect the v1 logger. +func SetV1SubLogger(root *build.SubLoggerManager, subsystem string, + logger btclog.Logger, useLoggers ...func(btclogv1.Logger)) { root.RegisterSubLogger(subsystem, logger) for _, useLogger := range useLoggers {