From f9922c7305b2fe74ae0a15f5a8ec8e27a58d1dd1 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 12 Feb 2014 15:43:27 -0600 Subject: [PATCH] Add --logdir option to specify logging directory. This commit adds a new option, --logdir, which works in the same fashion as the --datadir option. Consequently, the logging directory is name "namespaced" by the network as well. This resolves the issue where two btcd instances running (one for mainnet and one for testnet) would overwrite each other's log files by default. It also provides the user with a method to change the logging location to non-default locations if they prefer. For example, it enables multiple btcd instances on the same network to specify unique logging directories (even though running multiple btcd instances on the same network is not the most sane configuration). Closes #95. --- btcd.go | 8 +++----- config.go | 33 +++++++++++++++++++++++---------- log.go | 16 +++++----------- 3 files changed, 31 insertions(+), 26 deletions(-) diff --git a/btcd.go b/btcd.go index 3df423cd3..064721b64 100644 --- a/btcd.go +++ b/btcd.go @@ -30,16 +30,14 @@ var winServiceMain func() (bool, error) // notified with the server once it is setup so it can gracefully stop it when // requested from the service control manager. func btcdMain(serverChan chan<- *server) error { - // Initialize logging at the default logging level. - setLogLevels(defaultLogLevel) - defer backendLog.Flush() - - // Load configuration and parse command line. + // Load configuration and parse command line. This function also + // initializes logging and configures it accordingly. tcfg, _, err := loadConfig() if err != nil { return err } cfg = tcfg + defer backendLog.Flush() // Show version at startup. btcdLog.Infof("Version %s", version()) diff --git a/config.go b/config.go index a1b11b694..a54c83fc4 100644 --- a/config.go +++ b/config.go @@ -28,6 +28,8 @@ const ( defaultConfigFilename = "btcd.conf" defaultDataDirname = "data" defaultLogLevel = "info" + defaultLogDirname = "logs" + defaultLogFilename = "btcd.log" defaultBtcnet = btcwire.MainNet defaultMaxPeers = 125 defaultBanDuration = time.Hour * 24 @@ -43,7 +45,7 @@ var ( knownDbTypes = btcdb.SupportedDBs() defaultRPCKeyFile = filepath.Join(btcdHomeDir, "rpc.key") defaultRPCCertFile = filepath.Join(btcdHomeDir, "rpc.cert") - defaultLogFile = filepath.Join(btcdHomeDir, "logs", "btcd.log") + defaultLogDir = filepath.Join(btcdHomeDir, defaultLogDirname) ) // runServiceCommand is only set to a real function on Windows. It is used @@ -57,6 +59,7 @@ type config struct { ShowVersion bool `short:"V" long:"version" description:"Display version information and exit"` ConfigFile string `short:"C" long:"configfile" description:"Path to configuration file"` DataDir string `short:"b" long:"datadir" description:"Directory to store data"` + LogDir string `long:"logdir" description:"Directory to log output."` AddPeers []string `short:"a" long:"addpeer" description:"Add a peer to connect with at startup"` ConnectPeers []string `long:"connect" description:"Connect only to the specified peers at startup"` DisableListen bool `long:"nolisten" description:"Disable listening for incoming connections -- NOTE: Listening is automatically disabled if the --connect or --proxy options are used without also specifying listen interfaces via --listen"` @@ -280,6 +283,7 @@ func loadConfig() (*config, []string, error) { BanDuration: defaultBanDuration, ConfigFile: defaultConfigFile, DataDir: defaultDataDir, + LogDir: defaultLogDir, DbType: defaultDbType, RPCKey: defaultRPCKeyFile, RPCCert: defaultRPCCertFile, @@ -368,12 +372,30 @@ func loadConfig() (*config, []string, error) { activeNetParams = netParams(btcwire.TestNet) } + // Append the network type to the data directory so it is "namespaced" + // per network. In addition to the block database, there are other + // pieces of data that are saved to disk such as address manager state. + // All data is specific to a network, so namespacing the data directory + // means each individual piece of serialized data does not have to + // worry about changing names per network and such. + cfg.DataDir = cleanAndExpandPath(cfg.DataDir) + cfg.DataDir = filepath.Join(cfg.DataDir, activeNetParams.netName) + + // Append the network type to the log directory so it is "namespaced" + // per network in the same fashion as the data directory. + cfg.LogDir = cleanAndExpandPath(cfg.LogDir) + cfg.LogDir = filepath.Join(cfg.LogDir, activeNetParams.netName) + // Special show command to list supported subsystems and exit. if cfg.DebugLevel == "show" { fmt.Println("Supported subsystems", supportedSubsystems()) os.Exit(0) } + // Initialize logging at the default logging level. + initSeelogLogger(filepath.Join(cfg.LogDir, defaultLogFilename)) + setLogLevels(defaultLogLevel) + // Parse, validate, and set debug log level(s). if err := parseAndSetDebugLevels(cfg.DebugLevel); err != nil { err := fmt.Errorf("%s: %v", "loadConfig", err.Error()) @@ -404,15 +426,6 @@ func loadConfig() (*config, []string, error) { } } - // Append the network type to the data directory so it is "namespaced" - // per network. In addition to the block database, there are other - // pieces of data that are saved to disk such as address manager state. - // All data is specific to a network, so namespacing the data directory - // means each individual piece of serialized data does not have to - // worry about changing names per network and such. - cfg.DataDir = cleanAndExpandPath(cfg.DataDir) - cfg.DataDir = filepath.Join(cfg.DataDir, activeNetParams.netName) - // Don't allow ban durations that are too short. if cfg.BanDuration < time.Duration(time.Second) { str := "%s: The banduration option may not be less than 1s -- parsed [%v]" diff --git a/log.go b/log.go index 35b513744..0229da4be 100644 --- a/log.go +++ b/log.go @@ -122,10 +122,9 @@ func useLogger(subsystemID string, logger btclog.Logger) { } } -// newSeelogLogger creates a new seelog logger. -func newSeelogLogger() seelog.LoggerInterface { - // - +// initSeelogLogger initializes a new seelog logger that is used as the backend +// for all logging subsytems. +func initSeelogLogger(logFile string) { config := ` @@ -137,7 +136,7 @@ func newSeelogLogger() seelog.LoggerInterface { ` - config = fmt.Sprintf(config, defaultLogFile) + config = fmt.Sprintf(config, logFile) logger, err := seelog.LoggerFromConfigAsString(config) if err != nil { @@ -145,18 +144,13 @@ func newSeelogLogger() seelog.LoggerInterface { os.Exit(1) } - return logger + 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) { - // Create the backend seelog logger if needed. - if backendLog == seelog.Disabled { - backendLog = newSeelogLogger() - } - // Ignore invalid subsystems. logger, ok := subsystemLoggers[subsystemID] if !ok {