Merge pull request #3532 from guggero/refactor-log-writer
build+lnd: refactor reusable log file rotator code into build package
This commit is contained in:
commit
c10eacaa24
105
build/log.go
105
build/log.go
@ -1,7 +1,9 @@
|
|||||||
package build
|
package build
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/btcsuite/btclog"
|
"github.com/btcsuite/btclog"
|
||||||
)
|
)
|
||||||
@ -93,3 +95,106 @@ func NewSubLogger(subsystem string,
|
|||||||
// For any other configurations, we'll disable logging.
|
// For any other configurations, we'll disable logging.
|
||||||
return btclog.Disabled
|
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
|
||||||
|
}
|
||||||
|
151
build/logrotator.go
Normal file
151
build/logrotator.go
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
package build
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"github.com/btcsuite/btclog"
|
||||||
|
"github.com/jrick/logrotate/rotator"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RotatingLogWriter is a wrapper around the LogWriter that supports log file
|
||||||
|
// rotation.
|
||||||
|
type RotatingLogWriter struct {
|
||||||
|
// GenSubLogger is a function that returns a new logger for a subsystem
|
||||||
|
// belonging to the current RotatingLogWriter.
|
||||||
|
GenSubLogger func(string) btclog.Logger
|
||||||
|
|
||||||
|
logWriter *LogWriter
|
||||||
|
|
||||||
|
backendLog *btclog.Backend
|
||||||
|
|
||||||
|
logRotator *rotator.Rotator
|
||||||
|
|
||||||
|
subsystemLoggers SubLoggers
|
||||||
|
}
|
||||||
|
|
||||||
|
// A compile time check to ensure RotatingLogWriter implements the
|
||||||
|
// LeveledSubLogger interface.
|
||||||
|
var _ LeveledSubLogger = (*RotatingLogWriter)(nil)
|
||||||
|
|
||||||
|
// NewRotatingLogWriter creates a new file rotating log writer.
|
||||||
|
//
|
||||||
|
// NOTE: `InitLogRotator` must be called to set up log rotation after creating
|
||||||
|
// the writer.
|
||||||
|
func NewRotatingLogWriter() *RotatingLogWriter {
|
||||||
|
logWriter := &LogWriter{}
|
||||||
|
backendLog := btclog.NewBackend(logWriter)
|
||||||
|
return &RotatingLogWriter{
|
||||||
|
GenSubLogger: backendLog.Logger,
|
||||||
|
logWriter: logWriter,
|
||||||
|
backendLog: backendLog,
|
||||||
|
subsystemLoggers: SubLoggers{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterSubLogger registers a new subsystem logger.
|
||||||
|
func (r *RotatingLogWriter) RegisterSubLogger(subsystem string,
|
||||||
|
logger btclog.Logger) {
|
||||||
|
|
||||||
|
r.subsystemLoggers[subsystem] = logger
|
||||||
|
}
|
||||||
|
|
||||||
|
// InitLogRotator initializes the log file rotator to write logs to logFile and
|
||||||
|
// create roll files in the same directory. It should be called as early on
|
||||||
|
// startup and possible and must be closed on shutdown by calling `Close`.
|
||||||
|
func (r *RotatingLogWriter) InitLogRotator(logFile string, maxLogFileSize int,
|
||||||
|
maxLogFiles int) error {
|
||||||
|
|
||||||
|
logDir, _ := filepath.Split(logFile)
|
||||||
|
err := os.MkdirAll(logDir, 0700)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create log directory: %v", err)
|
||||||
|
}
|
||||||
|
r.logRotator, err = rotator.New(
|
||||||
|
logFile, int64(maxLogFileSize*1024), false, maxLogFiles,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create file rotator: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run rotator as a goroutine now but make sure we catch any errors
|
||||||
|
// that happen in case something with the rotation goes wrong during
|
||||||
|
// runtime (like running out of disk space or not being allowed to
|
||||||
|
// create a new logfile for whatever reason).
|
||||||
|
pr, pw := io.Pipe()
|
||||||
|
go func() {
|
||||||
|
err := r.logRotator.Run(pr)
|
||||||
|
if err != nil {
|
||||||
|
_, _ = fmt.Fprintf(os.Stderr,
|
||||||
|
"failed to run file rotator: %v\n", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
r.logWriter.RotatorPipe = pw
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes the underlying log rotator if it has already been created.
|
||||||
|
func (r *RotatingLogWriter) Close() error {
|
||||||
|
if r.logRotator != nil {
|
||||||
|
return r.logRotator.Close()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SubLoggers returns all currently registered subsystem loggers for this log
|
||||||
|
// writer.
|
||||||
|
//
|
||||||
|
// NOTE: This is part of the LeveledSubLogger interface.
|
||||||
|
func (r *RotatingLogWriter) SubLoggers() SubLoggers {
|
||||||
|
return r.subsystemLoggers
|
||||||
|
}
|
||||||
|
|
||||||
|
// SupportedSubsystems returns a sorted string slice of all keys in the
|
||||||
|
// subsystems map, corresponding to the names of the subsystems.
|
||||||
|
//
|
||||||
|
// NOTE: This is part of the LeveledSubLogger interface.
|
||||||
|
func (r *RotatingLogWriter) SupportedSubsystems() []string {
|
||||||
|
// Convert the subsystemLoggers map keys to a string slice.
|
||||||
|
subsystems := make([]string, 0, len(r.subsystemLoggers))
|
||||||
|
for subsysID := range r.subsystemLoggers {
|
||||||
|
subsystems = append(subsystems, subsysID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort the subsystems for stable display.
|
||||||
|
sort.Strings(subsystems)
|
||||||
|
return subsystems
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLogLevel sets the logging level for provided subsystem. Invalid
|
||||||
|
// subsystems are ignored. Uninitialized subsystems are dynamically created as
|
||||||
|
// needed.
|
||||||
|
//
|
||||||
|
// NOTE: This is part of the LeveledSubLogger interface.
|
||||||
|
func (r *RotatingLogWriter) SetLogLevel(subsystemID string, logLevel string) {
|
||||||
|
// Ignore invalid subsystems.
|
||||||
|
logger, ok := r.subsystemLoggers[subsystemID]
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defaults to info if the log level is invalid.
|
||||||
|
level, _ := btclog.LevelFromString(logLevel)
|
||||||
|
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.
|
||||||
|
//
|
||||||
|
// NOTE: This is part of the LeveledSubLogger interface.
|
||||||
|
func (r *RotatingLogWriter) SetLogLevels(logLevel string) {
|
||||||
|
// Configure all sub-systems with the new logging level. Dynamically
|
||||||
|
// create loggers as needed.
|
||||||
|
for subsystemID := range r.subsystemLoggers {
|
||||||
|
r.SetLogLevel(subsystemID, logLevel)
|
||||||
|
}
|
||||||
|
}
|
103
config.go
103
config.go
@ -14,7 +14,6 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"sort"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -953,19 +952,27 @@ func loadConfig() (*config, error) {
|
|||||||
|
|
||||||
// Special show command to list supported subsystems and exit.
|
// Special show command to list supported subsystems and exit.
|
||||||
if cfg.DebugLevel == "show" {
|
if cfg.DebugLevel == "show" {
|
||||||
fmt.Println("Supported subsystems", supportedSubsystems())
|
fmt.Println("Supported subsystems",
|
||||||
|
logWriter.SupportedSubsystems())
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize logging at the default logging level.
|
// Initialize logging at the default logging level.
|
||||||
initLogRotator(
|
err = logWriter.InitLogRotator(
|
||||||
filepath.Join(cfg.LogDir, defaultLogFilename),
|
filepath.Join(cfg.LogDir, defaultLogFilename),
|
||||||
cfg.MaxLogFileSize, cfg.MaxLogFiles,
|
cfg.MaxLogFileSize, cfg.MaxLogFiles,
|
||||||
)
|
)
|
||||||
|
if err != nil {
|
||||||
|
str := "%s: log rotation setup failed: %v"
|
||||||
|
err = fmt.Errorf(str, funcName, err.Error())
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// Parse, validate, and set debug log level(s).
|
// Parse, validate, and set debug log level(s).
|
||||||
if err := parseAndSetDebugLevels(cfg.DebugLevel); err != nil {
|
err = build.ParseAndSetDebugLevels(cfg.DebugLevel, logWriter)
|
||||||
err := fmt.Errorf("%s: %v", funcName, err.Error())
|
if err != nil {
|
||||||
|
err = fmt.Errorf("%s: %v", funcName, err.Error())
|
||||||
fmt.Fprintln(os.Stderr, err)
|
fmt.Fprintln(os.Stderr, err)
|
||||||
fmt.Fprintln(os.Stderr, usageMessage)
|
fmt.Fprintln(os.Stderr, usageMessage)
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -1140,92 +1147,6 @@ func cleanAndExpandPath(path string) string {
|
|||||||
return filepath.Clean(os.ExpandEnv(path))
|
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,
|
func parseRPCParams(cConfig *chainConfig, nodeConfig interface{}, net chainCode,
|
||||||
funcName string) error {
|
funcName string) error {
|
||||||
|
|
||||||
|
5
lnd.go
5
lnd.go
@ -124,9 +124,10 @@ func Main(lisCfg ListenerCfg) error {
|
|||||||
}
|
}
|
||||||
cfg = loadedConfig
|
cfg = loadedConfig
|
||||||
defer func() {
|
defer func() {
|
||||||
if logRotator != nil {
|
|
||||||
ltndLog.Info("Shutdown complete")
|
ltndLog.Info("Shutdown complete")
|
||||||
logRotator.Close()
|
err := logWriter.Close()
|
||||||
|
if err != nil {
|
||||||
|
ltndLog.Errorf("Could not close log rotator: %v", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
222
log.go
222
log.go
@ -2,14 +2,9 @@ package lnd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/connmgr"
|
"github.com/btcsuite/btcd/connmgr"
|
||||||
"github.com/btcsuite/btclog"
|
"github.com/btcsuite/btclog"
|
||||||
"github.com/jrick/logrotate/rotator"
|
|
||||||
"github.com/lightninglabs/neutrino"
|
"github.com/lightninglabs/neutrino"
|
||||||
sphinx "github.com/lightningnetwork/lightning-onion"
|
sphinx "github.com/lightningnetwork/lightning-onion"
|
||||||
"github.com/lightningnetwork/lnd/autopilot"
|
"github.com/lightningnetwork/lnd/autopilot"
|
||||||
@ -48,177 +43,78 @@ import (
|
|||||||
//
|
//
|
||||||
// Loggers can not be used before the log rotator has been initialized with a
|
// Loggers can not be used before the log rotator has been initialized with a
|
||||||
// log file. This must be performed early during application startup by
|
// log file. This must be performed early during application startup by
|
||||||
// calling initLogRotator.
|
// calling logWriter.InitLogRotator.
|
||||||
var (
|
var (
|
||||||
logWriter = &build.LogWriter{}
|
logWriter = build.NewRotatingLogWriter()
|
||||||
|
|
||||||
// backendLog is the logging backend used to create all subsystem
|
// Loggers that need to be accessible from the lnd package can be placed
|
||||||
// loggers. The backend must not be used before the log rotator has
|
// here. Loggers that are only used in sub modules can be added directly
|
||||||
// been initialized, or data races and/or nil pointer dereferences will
|
// by using the addSubLogger method.
|
||||||
// occur.
|
ltndLog = build.NewSubLogger("LTND", logWriter.GenSubLogger)
|
||||||
backendLog = btclog.NewBackend(logWriter)
|
peerLog = build.NewSubLogger("PEER", logWriter.GenSubLogger)
|
||||||
|
rpcsLog = build.NewSubLogger("RPCS", logWriter.GenSubLogger)
|
||||||
// logRotator is one of the logging outputs. It should be closed on
|
srvrLog = build.NewSubLogger("SRVR", logWriter.GenSubLogger)
|
||||||
// application shutdown.
|
fndgLog = build.NewSubLogger("FNDG", logWriter.GenSubLogger)
|
||||||
logRotator *rotator.Rotator
|
utxnLog = build.NewSubLogger("UTXN", logWriter.GenSubLogger)
|
||||||
|
brarLog = build.NewSubLogger("BRAR", logWriter.GenSubLogger)
|
||||||
ltndLog = build.NewSubLogger("LTND", backendLog.Logger)
|
atplLog = build.NewSubLogger("ATPL", logWriter.GenSubLogger)
|
||||||
lnwlLog = build.NewSubLogger("LNWL", backendLog.Logger)
|
|
||||||
peerLog = build.NewSubLogger("PEER", backendLog.Logger)
|
|
||||||
discLog = build.NewSubLogger("DISC", backendLog.Logger)
|
|
||||||
rpcsLog = build.NewSubLogger("RPCS", backendLog.Logger)
|
|
||||||
srvrLog = build.NewSubLogger("SRVR", backendLog.Logger)
|
|
||||||
ntfnLog = build.NewSubLogger("NTFN", backendLog.Logger)
|
|
||||||
chdbLog = build.NewSubLogger("CHDB", backendLog.Logger)
|
|
||||||
fndgLog = build.NewSubLogger("FNDG", backendLog.Logger)
|
|
||||||
hswcLog = build.NewSubLogger("HSWC", backendLog.Logger)
|
|
||||||
utxnLog = build.NewSubLogger("UTXN", backendLog.Logger)
|
|
||||||
brarLog = build.NewSubLogger("BRAR", backendLog.Logger)
|
|
||||||
cmgrLog = build.NewSubLogger("CMGR", backendLog.Logger)
|
|
||||||
crtrLog = build.NewSubLogger("CRTR", backendLog.Logger)
|
|
||||||
btcnLog = build.NewSubLogger("BTCN", backendLog.Logger)
|
|
||||||
atplLog = build.NewSubLogger("ATPL", backendLog.Logger)
|
|
||||||
cnctLog = build.NewSubLogger("CNCT", backendLog.Logger)
|
|
||||||
sphxLog = build.NewSubLogger("SPHX", backendLog.Logger)
|
|
||||||
swprLog = build.NewSubLogger("SWPR", backendLog.Logger)
|
|
||||||
sgnrLog = build.NewSubLogger("SGNR", backendLog.Logger)
|
|
||||||
wlktLog = build.NewSubLogger("WLKT", backendLog.Logger)
|
|
||||||
arpcLog = build.NewSubLogger("ARPC", backendLog.Logger)
|
|
||||||
invcLog = build.NewSubLogger("INVC", backendLog.Logger)
|
|
||||||
nannLog = build.NewSubLogger("NANN", backendLog.Logger)
|
|
||||||
wtwrLog = build.NewSubLogger("WTWR", backendLog.Logger)
|
|
||||||
ntfrLog = build.NewSubLogger("NTFR", backendLog.Logger)
|
|
||||||
irpcLog = build.NewSubLogger("IRPC", backendLog.Logger)
|
|
||||||
chnfLog = build.NewSubLogger("CHNF", backendLog.Logger)
|
|
||||||
chbuLog = build.NewSubLogger("CHBU", backendLog.Logger)
|
|
||||||
promLog = build.NewSubLogger("PROM", backendLog.Logger)
|
|
||||||
wtclLog = build.NewSubLogger("WTCL", backendLog.Logger)
|
|
||||||
prnfLog = build.NewSubLogger("PRNF", backendLog.Logger)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Initialize package-global logger variables.
|
// Initialize package-global logger variables.
|
||||||
func init() {
|
func init() {
|
||||||
lnwallet.UseLogger(lnwlLog)
|
setSubLogger("LTND", ltndLog, signal.UseLogger)
|
||||||
discovery.UseLogger(discLog)
|
setSubLogger("ATPL", atplLog, autopilot.UseLogger)
|
||||||
chainntnfs.UseLogger(ntfnLog)
|
setSubLogger("PEER", peerLog, nil)
|
||||||
channeldb.UseLogger(chdbLog)
|
setSubLogger("RPCS", rpcsLog, nil)
|
||||||
htlcswitch.UseLogger(hswcLog)
|
setSubLogger("SRVR", srvrLog, nil)
|
||||||
connmgr.UseLogger(cmgrLog)
|
setSubLogger("FNDG", fndgLog, nil)
|
||||||
routing.UseLogger(crtrLog)
|
setSubLogger("UTXN", utxnLog, nil)
|
||||||
neutrino.UseLogger(btcnLog)
|
setSubLogger("BRAR", brarLog, nil)
|
||||||
autopilot.UseLogger(atplLog)
|
|
||||||
contractcourt.UseLogger(cnctLog)
|
addSubLogger("LNWL", lnwallet.UseLogger)
|
||||||
sphinx.UseLogger(sphxLog)
|
addSubLogger("DISC", discovery.UseLogger)
|
||||||
signal.UseLogger(ltndLog)
|
addSubLogger("NTFN", chainntnfs.UseLogger)
|
||||||
sweep.UseLogger(swprLog)
|
addSubLogger("CHDB", channeldb.UseLogger)
|
||||||
signrpc.UseLogger(sgnrLog)
|
addSubLogger("HSWC", htlcswitch.UseLogger)
|
||||||
walletrpc.UseLogger(wlktLog)
|
addSubLogger("CMGR", connmgr.UseLogger)
|
||||||
autopilotrpc.UseLogger(arpcLog)
|
addSubLogger("CRTR", routing.UseLogger)
|
||||||
invoices.UseLogger(invcLog)
|
addSubLogger("BTCN", neutrino.UseLogger)
|
||||||
netann.UseLogger(nannLog)
|
addSubLogger("CNCT", contractcourt.UseLogger)
|
||||||
watchtower.UseLogger(wtwrLog)
|
addSubLogger("SPHX", sphinx.UseLogger)
|
||||||
chainrpc.UseLogger(ntfrLog)
|
addSubLogger("SWPR", sweep.UseLogger)
|
||||||
invoicesrpc.UseLogger(irpcLog)
|
addSubLogger("SGNR", signrpc.UseLogger)
|
||||||
channelnotifier.UseLogger(chnfLog)
|
addSubLogger("WLKT", walletrpc.UseLogger)
|
||||||
chanbackup.UseLogger(chbuLog)
|
addSubLogger("ARPC", autopilotrpc.UseLogger)
|
||||||
monitoring.UseLogger(promLog)
|
addSubLogger("INVC", invoices.UseLogger)
|
||||||
wtclient.UseLogger(wtclLog)
|
addSubLogger("NANN", netann.UseLogger)
|
||||||
peernotifier.UseLogger(prnfLog)
|
addSubLogger("WTWR", watchtower.UseLogger)
|
||||||
|
addSubLogger("NTFR", chainrpc.UseLogger)
|
||||||
|
addSubLogger("IRPC", invoicesrpc.UseLogger)
|
||||||
|
addSubLogger("CHNF", channelnotifier.UseLogger)
|
||||||
|
addSubLogger("CHBU", chanbackup.UseLogger)
|
||||||
|
addSubLogger("PROM", monitoring.UseLogger)
|
||||||
|
addSubLogger("WTCL", wtclient.UseLogger)
|
||||||
|
addSubLogger("PRNF", peernotifier.UseLogger)
|
||||||
|
|
||||||
addSubLogger(routerrpc.Subsystem, routerrpc.UseLogger)
|
addSubLogger(routerrpc.Subsystem, routerrpc.UseLogger)
|
||||||
addSubLogger(wtclientrpc.Subsystem, wtclientrpc.UseLogger)
|
addSubLogger(wtclientrpc.Subsystem, wtclientrpc.UseLogger)
|
||||||
}
|
}
|
||||||
|
|
||||||
// addSubLogger is a helper method to conveniently register the logger of a sub
|
// addSubLogger is a helper method to conveniently create and register the
|
||||||
// system.
|
// logger of a sub system.
|
||||||
func addSubLogger(subsystem string, useLogger func(btclog.Logger)) {
|
func addSubLogger(subsystem string, useLogger func(btclog.Logger)) {
|
||||||
logger := build.NewSubLogger(subsystem, backendLog.Logger)
|
logger := build.NewSubLogger(subsystem, logWriter.GenSubLogger)
|
||||||
|
setSubLogger(subsystem, logger, useLogger)
|
||||||
|
}
|
||||||
|
|
||||||
|
// setSubLogger is a helper method to conveniently register the logger of a sub
|
||||||
|
// system.
|
||||||
|
func setSubLogger(subsystem string, logger btclog.Logger,
|
||||||
|
useLogger func(btclog.Logger)) {
|
||||||
|
|
||||||
|
logWriter.RegisterSubLogger(subsystem, logger)
|
||||||
|
if useLogger != nil {
|
||||||
useLogger(logger)
|
useLogger(logger)
|
||||||
subsystemLoggers[subsystem] = logger
|
|
||||||
}
|
|
||||||
|
|
||||||
// subsystemLoggers maps each subsystem identifier to its associated logger.
|
|
||||||
var subsystemLoggers = map[string]btclog.Logger{
|
|
||||||
"LTND": ltndLog,
|
|
||||||
"LNWL": lnwlLog,
|
|
||||||
"PEER": peerLog,
|
|
||||||
"DISC": discLog,
|
|
||||||
"RPCS": rpcsLog,
|
|
||||||
"SRVR": srvrLog,
|
|
||||||
"NTFN": ntfnLog,
|
|
||||||
"CHDB": chdbLog,
|
|
||||||
"FNDG": fndgLog,
|
|
||||||
"HSWC": hswcLog,
|
|
||||||
"UTXN": utxnLog,
|
|
||||||
"BRAR": brarLog,
|
|
||||||
"CMGR": cmgrLog,
|
|
||||||
"CRTR": crtrLog,
|
|
||||||
"BTCN": btcnLog,
|
|
||||||
"ATPL": atplLog,
|
|
||||||
"CNCT": cnctLog,
|
|
||||||
"SPHX": sphxLog,
|
|
||||||
"SWPR": swprLog,
|
|
||||||
"SGNR": sgnrLog,
|
|
||||||
"WLKT": wlktLog,
|
|
||||||
"ARPC": arpcLog,
|
|
||||||
"INVC": invcLog,
|
|
||||||
"NANN": nannLog,
|
|
||||||
"WTWR": wtwrLog,
|
|
||||||
"NTFR": ntfrLog,
|
|
||||||
"IRPC": irpcLog,
|
|
||||||
"CHNF": chnfLog,
|
|
||||||
"CHBU": chbuLog,
|
|
||||||
"PROM": promLog,
|
|
||||||
"WTCL": wtclLog,
|
|
||||||
"PRNF": prnfLog,
|
|
||||||
}
|
|
||||||
|
|
||||||
// initLogRotator initializes the logging rotator to write logs to logFile and
|
|
||||||
// create roll files in the same directory. It must be called before the
|
|
||||||
// package-global log rotator variables are used.
|
|
||||||
func initLogRotator(logFile string, MaxLogFileSize int, MaxLogFiles int) {
|
|
||||||
logDir, _ := filepath.Split(logFile)
|
|
||||||
err := os.MkdirAll(logDir, 0700)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "failed to create log directory: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
r, err := rotator.New(logFile, int64(MaxLogFileSize*1024), false, MaxLogFiles)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "failed to create file rotator: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
pr, pw := io.Pipe()
|
|
||||||
go r.Run(pr)
|
|
||||||
|
|
||||||
logWriter.RotatorPipe = pw
|
|
||||||
logRotator = r
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
|
||||||
|
|
||||||
// Defaults to info if the log level is invalid.
|
|
||||||
level, _ := btclog.LevelFromString(logLevel)
|
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4348,7 +4348,9 @@ func (r *rpcServer) DebugLevel(ctx context.Context,
|
|||||||
// sub-systems.
|
// sub-systems.
|
||||||
if req.Show {
|
if req.Show {
|
||||||
return &lnrpc.DebugLevelResponse{
|
return &lnrpc.DebugLevelResponse{
|
||||||
SubSystems: strings.Join(supportedSubsystems(), " "),
|
SubSystems: strings.Join(
|
||||||
|
logWriter.SupportedSubsystems(), " ",
|
||||||
|
),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4356,7 +4358,8 @@ func (r *rpcServer) DebugLevel(ctx context.Context,
|
|||||||
|
|
||||||
// Otherwise, we'll attempt to set the logging level using the
|
// Otherwise, we'll attempt to set the logging level using the
|
||||||
// specified level spec.
|
// specified level spec.
|
||||||
if err := parseAndSetDebugLevels(req.LevelSpec); err != nil {
|
err := build.ParseAndSetDebugLevels(req.LevelSpec, logWriter)
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user