2015-12-26 09:09:17 +03:00
|
|
|
package main
|
2016-03-23 04:43:10 +03:00
|
|
|
|
|
|
|
import (
|
|
|
|
"os"
|
|
|
|
|
2017-06-21 18:07:44 +03:00
|
|
|
"io"
|
|
|
|
|
|
|
|
"fmt"
|
|
|
|
"path/filepath"
|
|
|
|
|
2016-03-23 04:43:10 +03:00
|
|
|
"github.com/btcsuite/btclog"
|
2017-06-21 18:07:44 +03:00
|
|
|
"github.com/jrick/logrotate/rotator"
|
2017-05-18 21:48:10 +03:00
|
|
|
"github.com/lightninglabs/neutrino"
|
2016-08-04 22:37:50 +03:00
|
|
|
"github.com/lightningnetwork/lnd/chainntnfs"
|
2016-03-23 04:43:10 +03:00
|
|
|
"github.com/lightningnetwork/lnd/channeldb"
|
2017-03-19 21:40:25 +03:00
|
|
|
"github.com/lightningnetwork/lnd/discovery"
|
2017-05-02 23:04:58 +03:00
|
|
|
"github.com/lightningnetwork/lnd/htlcswitch"
|
2016-03-23 04:43:10 +03:00
|
|
|
"github.com/lightningnetwork/lnd/lnwallet"
|
2016-12-27 08:42:23 +03:00
|
|
|
"github.com/lightningnetwork/lnd/routing"
|
2017-01-06 01:05:12 +03:00
|
|
|
"github.com/roasbeef/btcd/connmgr"
|
2016-03-23 04:43:10 +03:00
|
|
|
)
|
|
|
|
|
2017-06-21 18:07:44 +03:00
|
|
|
// logWriter implements an io.Writer that outputs to both standard output and
|
|
|
|
// the write-end pipe of an initialized log rotator.
|
|
|
|
type logWriter struct{}
|
|
|
|
|
|
|
|
func (logWriter) Write(p []byte) (n int, err error) {
|
|
|
|
os.Stdout.Write(p)
|
|
|
|
logRotatorPipe.Write(p)
|
|
|
|
return len(p), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Loggers per subsystem. A single backend logger is created and all subsytem
|
|
|
|
// loggers created from it will write to the backend. When adding new
|
|
|
|
// subsystems, add the subsystem logger variable here and to the
|
|
|
|
// subsystemLoggers map.
|
|
|
|
//
|
|
|
|
// Loggers can not be used before the log rotator has been initialized with a
|
2017-07-31 02:01:44 +03:00
|
|
|
// log file. This must be performed early during application startup by
|
|
|
|
// calling initLogRotator.
|
2016-03-23 04:43:10 +03:00
|
|
|
var (
|
2017-07-31 02:01:44 +03:00
|
|
|
// backendLog is the logging backend used to create all subsystem
|
|
|
|
// loggers. The backend must not be used before the log rotator has
|
|
|
|
// been initialized, or data races and/or nil pointer dereferences will
|
|
|
|
// occur.
|
2017-06-21 18:07:44 +03:00
|
|
|
backendLog = btclog.NewBackend(logWriter{})
|
|
|
|
|
|
|
|
// logRotator is one of the logging outputs. It should be closed on
|
|
|
|
// application shutdown.
|
|
|
|
logRotator *rotator.Rotator
|
|
|
|
|
2017-07-31 02:01:44 +03:00
|
|
|
// logRotatorPipe is the write-end pipe for writing to the log rotator.
|
|
|
|
// It is written to by the Write method of the logWriter type.
|
2017-06-21 18:07:44 +03:00
|
|
|
logRotatorPipe *io.PipeWriter
|
|
|
|
|
|
|
|
ltndLog = backendLog.Logger("LTND")
|
|
|
|
lnwlLog = backendLog.Logger("LNWL")
|
|
|
|
peerLog = backendLog.Logger("PEER")
|
|
|
|
discLog = backendLog.Logger("DISC")
|
|
|
|
rpcsLog = backendLog.Logger("RPCS")
|
|
|
|
srvrLog = backendLog.Logger("SRVR")
|
|
|
|
ntfnLog = backendLog.Logger("NTFN")
|
|
|
|
chdbLog = backendLog.Logger("CHDB")
|
|
|
|
fndgLog = backendLog.Logger("FNDG")
|
|
|
|
hswcLog = backendLog.Logger("HSWC")
|
|
|
|
utxnLog = backendLog.Logger("UTXN")
|
|
|
|
brarLog = backendLog.Logger("BRAR")
|
|
|
|
cmgrLog = backendLog.Logger("CMGR")
|
|
|
|
crtrLog = backendLog.Logger("CRTR")
|
|
|
|
btcnLog = backendLog.Logger("BTCN")
|
2016-03-23 04:43:10 +03:00
|
|
|
)
|
|
|
|
|
2017-06-21 18:07:44 +03:00
|
|
|
// Initialize package-global logger variables.
|
|
|
|
func init() {
|
|
|
|
lnwallet.UseLogger(lnwlLog)
|
|
|
|
discovery.UseLogger(discLog)
|
|
|
|
chainntnfs.UseLogger(ntfnLog)
|
|
|
|
channeldb.UseLogger(chdbLog)
|
|
|
|
htlcswitch.UseLogger(hswcLog)
|
|
|
|
connmgr.UseLogger(cmgrLog)
|
|
|
|
routing.UseLogger(crtrLog)
|
|
|
|
neutrino.UseLogger(btcnLog)
|
|
|
|
}
|
|
|
|
|
2016-03-23 04:43:10 +03:00
|
|
|
// subsystemLoggers maps each subsystem identifier to its associated logger.
|
|
|
|
var subsystemLoggers = map[string]btclog.Logger{
|
|
|
|
"LTND": ltndLog,
|
|
|
|
"LNWL": lnwlLog,
|
|
|
|
"PEER": peerLog,
|
2017-03-19 21:40:25 +03:00
|
|
|
"DISC": discLog,
|
2016-03-23 04:43:10 +03:00
|
|
|
"RPCS": rpcsLog,
|
|
|
|
"SRVR": srvrLog,
|
|
|
|
"NTFN": ntfnLog,
|
|
|
|
"CHDB": chdbLog,
|
2016-06-21 21:32:07 +03:00
|
|
|
"FNDG": fndgLog,
|
2016-07-10 02:41:06 +03:00
|
|
|
"HSWC": hswcLog,
|
2016-09-12 22:37:51 +03:00
|
|
|
"UTXN": utxnLog,
|
2016-11-29 06:43:57 +03:00
|
|
|
"BRAR": brarLog,
|
2016-12-15 05:11:31 +03:00
|
|
|
"CMGR": cmgrLog,
|
2016-12-27 08:42:23 +03:00
|
|
|
"CRTR": crtrLog,
|
2017-05-18 21:48:10 +03:00
|
|
|
"BTCN": btcnLog,
|
2016-03-23 04:43:10 +03:00
|
|
|
}
|
|
|
|
|
2017-07-31 02:01:44 +03:00
|
|
|
// initLogRotator initializes the logging rotator to write logs to logFile and
|
2017-06-21 18:07:44 +03:00
|
|
|
// create roll files in the same directory. It must be called before the
|
2017-07-31 02:01:44 +03:00
|
|
|
// package-global log rotator variables are used.
|
2017-06-21 18:07:44 +03:00
|
|
|
func initLogRotator(logFile string) {
|
|
|
|
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)
|
2016-03-23 04:43:10 +03:00
|
|
|
}
|
2017-07-07 00:36:55 +03:00
|
|
|
r, err := rotator.New(logFile, 10*1024, false, 3)
|
2016-03-23 04:43:10 +03:00
|
|
|
if err != nil {
|
2017-06-21 18:07:44 +03:00
|
|
|
fmt.Fprintf(os.Stderr, "failed to create file rotator: %v\n", err)
|
2016-03-23 04:43:10 +03:00
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
|
2017-07-07 00:36:55 +03:00
|
|
|
pr, pw := io.Pipe()
|
|
|
|
go r.Run(pr)
|
2017-06-21 18:07:44 +03:00
|
|
|
|
|
|
|
logRotator = r
|
|
|
|
logRotatorPipe = pw
|
2016-03-23 04:43:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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
|
|
|
|
}
|
|
|
|
|
2017-06-21 18:07:44 +03:00
|
|
|
// Defaults to info if the log level is invalid.
|
|
|
|
level, _ := btclog.LevelFromString(logLevel)
|
2016-03-23 04:43:10 +03:00
|
|
|
logger.SetLevel(level)
|
|
|
|
}
|
|
|
|
|
|
|
|
// setLogLevels sets the log level for all subsystem loggers to the passed
|
2016-06-21 21:32:07 +03:00
|
|
|
// level. It also dynamically creates the subsystem loggers as needed, so it
|
2016-03-23 04:43:10 +03:00
|
|
|
// can be used to initialize the logging system.
|
|
|
|
func setLogLevels(logLevel string) {
|
2017-06-21 18:07:44 +03:00
|
|
|
// Configure all sub-systems with the new logging level. Dynamically
|
2016-03-23 04:43:10 +03:00
|
|
|
// create loggers as needed.
|
|
|
|
for subsystemID := range subsystemLoggers {
|
|
|
|
setLogLevel(subsystemID, logLevel)
|
|
|
|
}
|
|
|
|
}
|
2016-06-21 21:32:07 +03:00
|
|
|
|
2017-07-31 02:01:44 +03:00
|
|
|
// logClosure is used to provide a closure over expensive logging operations so
|
|
|
|
// don't have to be performed when the logging level doesn't warrant it.
|
2016-06-21 21:32:07 +03:00
|
|
|
type logClosure func() string
|
|
|
|
|
|
|
|
// String invokes the underlying function and returns the result.
|
|
|
|
func (c logClosure) String() string {
|
|
|
|
return c()
|
|
|
|
}
|
|
|
|
|
|
|
|
// newLogClosure returns a new closure over a function that returns a string
|
|
|
|
// which itself provides a Stringer interface so that it can be used with the
|
|
|
|
// logging system.
|
|
|
|
func newLogClosure(c func() string) logClosure {
|
|
|
|
return logClosure(c)
|
|
|
|
}
|