github.com/lbryio/lbcd@v0.22.119/log.go (about)

     1  // Copyright (c) 2013-2017 The btcsuite developers
     2  // Copyright (c) 2017 The Decred developers
     3  // Use of this source code is governed by an ISC
     4  // license that can be found in the LICENSE file.
     5  
     6  package main
     7  
     8  import (
     9  	"fmt"
    10  	"os"
    11  	"path/filepath"
    12  
    13  	"github.com/lbryio/lbcd/addrmgr"
    14  	"github.com/lbryio/lbcd/blockchain"
    15  	"github.com/lbryio/lbcd/blockchain/indexers"
    16  	"github.com/lbryio/lbcd/claimtrie/node"
    17  	"github.com/lbryio/lbcd/connmgr"
    18  	"github.com/lbryio/lbcd/database"
    19  	"github.com/lbryio/lbcd/fees"
    20  	"github.com/lbryio/lbcd/mempool"
    21  	"github.com/lbryio/lbcd/mining"
    22  	"github.com/lbryio/lbcd/mining/cpuminer"
    23  	"github.com/lbryio/lbcd/netsync"
    24  	"github.com/lbryio/lbcd/peer"
    25  	"github.com/lbryio/lbcd/txscript"
    26  
    27  	"github.com/btcsuite/btclog"
    28  	"github.com/jrick/logrotate/rotator"
    29  )
    30  
    31  // logWriter implements an io.Writer that outputs to both standard output and
    32  // the write-end pipe of an initialized log rotator.
    33  type logWriter struct{}
    34  
    35  func (logWriter) Write(p []byte) (n int, err error) {
    36  	os.Stdout.Write(p)
    37  	logRotator.Write(p)
    38  	return len(p), nil
    39  }
    40  
    41  // Loggers per subsystem.  A single backend logger is created and all subsytem
    42  // loggers created from it will write to the backend.  When adding new
    43  // subsystems, add the subsystem logger variable here and to the
    44  // subsystemLoggers map.
    45  //
    46  // Loggers can not be used before the log rotator has been initialized with a
    47  // log file.  This must be performed early during application startup by calling
    48  // initLogRotator.
    49  var (
    50  	// backendLog is the logging backend used to create all subsystem loggers.
    51  	// The backend must not be used before the log rotator has been initialized,
    52  	// or data races and/or nil pointer dereferences will occur.
    53  	backendLog = btclog.NewBackend(logWriter{})
    54  
    55  	// logRotator is one of the logging outputs.  It should be closed on
    56  	// application shutdown.
    57  	logRotator *rotator.Rotator
    58  
    59  	adxrLog = backendLog.Logger("ADXR")
    60  	amgrLog = backendLog.Logger("AMGR")
    61  	bcdbLog = backendLog.Logger("BCDB")
    62  	btcdLog = backendLog.Logger("MAIN")
    63  	chanLog = backendLog.Logger("CHAN")
    64  	cmgrLog = backendLog.Logger("CMGR")
    65  	discLog = backendLog.Logger("DISC")
    66  	feesLog = backendLog.Logger("FEES")
    67  	indxLog = backendLog.Logger("INDX")
    68  	lbryLog = backendLog.Logger("LBRY")
    69  	minrLog = backendLog.Logger("MINR")
    70  	peerLog = backendLog.Logger("PEER")
    71  	rpcsLog = backendLog.Logger("RPCS")
    72  	scrpLog = backendLog.Logger("SCRP")
    73  	srvrLog = backendLog.Logger("SRVR")
    74  	syncLog = backendLog.Logger("SYNC")
    75  	txmpLog = backendLog.Logger("TXMP")
    76  )
    77  
    78  // Initialize package-global logger variables.
    79  func init() {
    80  	addrmgr.UseLogger(amgrLog)
    81  	blockchain.UseLogger(chanLog)
    82  	connmgr.UseLogger(cmgrLog)
    83  	cpuminer.UseLogger(minrLog)
    84  	database.UseLogger(bcdbLog)
    85  	fees.UseLogger(feesLog)
    86  	indexers.UseLogger(indxLog)
    87  	mempool.UseLogger(txmpLog)
    88  	mining.UseLogger(minrLog)
    89  	netsync.UseLogger(syncLog)
    90  	node.UseLogger(lbryLog)
    91  	peer.UseLogger(peerLog)
    92  	txscript.UseLogger(scrpLog)
    93  }
    94  
    95  // subsystemLoggers maps each subsystem identifier to its associated logger.
    96  var subsystemLoggers = map[string]btclog.Logger{
    97  	"ADXR": adxrLog,
    98  	"AMGR": amgrLog,
    99  	"BCDB": bcdbLog,
   100  	"CHAN": chanLog,
   101  	"CMGR": cmgrLog,
   102  	"DISC": discLog,
   103  	"INDX": indxLog,
   104  	"LBRY": lbryLog,
   105  	"MAIN": btcdLog,
   106  	"MINR": minrLog,
   107  	"PEER": peerLog,
   108  	"RPCS": rpcsLog,
   109  	"SCRP": scrpLog,
   110  	"SRVR": srvrLog,
   111  	"SYNC": syncLog,
   112  	"TXMP": txmpLog,
   113  }
   114  
   115  // initLogRotator initializes the logging rotater to write logs to logFile and
   116  // create roll files in the same directory.  It must be called before the
   117  // package-global log rotater variables are used.
   118  func initLogRotator(logFile string) {
   119  	logDir, _ := filepath.Split(logFile)
   120  	err := os.MkdirAll(logDir, 0700)
   121  	if err != nil {
   122  		fmt.Fprintf(os.Stderr, "failed to create log directory: %v\n", err)
   123  		os.Exit(1)
   124  	}
   125  	r, err := rotator.New(logFile, 40*1024, false, 3)
   126  	if err != nil {
   127  		fmt.Fprintf(os.Stderr, "failed to create file rotator: %v\n", err)
   128  		os.Exit(1)
   129  	}
   130  
   131  	logRotator = r
   132  }
   133  
   134  // setLogLevel sets the logging level for provided subsystem.  Invalid
   135  // subsystems are ignored.  Uninitialized subsystems are dynamically created as
   136  // needed.
   137  func setLogLevel(subsystemID string, logLevel string) {
   138  	// Ignore invalid subsystems.
   139  	logger, ok := subsystemLoggers[subsystemID]
   140  	if !ok {
   141  		return
   142  	}
   143  
   144  	// Defaults to info if the log level is invalid.
   145  	level, _ := btclog.LevelFromString(logLevel)
   146  	logger.SetLevel(level)
   147  }
   148  
   149  // setLogLevels sets the log level for all subsystem loggers to the passed
   150  // level.  It also dynamically creates the subsystem loggers as needed, so it
   151  // can be used to initialize the logging system.
   152  func setLogLevels(logLevel string) {
   153  	// Configure all sub-systems with the new logging level.  Dynamically
   154  	// create loggers as needed.
   155  	for subsystemID := range subsystemLoggers {
   156  		setLogLevel(subsystemID, logLevel)
   157  	}
   158  }
   159  
   160  // directionString is a helper function that returns a string that represents
   161  // the direction of a connection (inbound or outbound).
   162  func directionString(inbound bool) string {
   163  	if inbound {
   164  		return "inbound"
   165  	}
   166  	return "outbound"
   167  }
   168  
   169  // pickNoun returns the singular or plural form of a noun depending
   170  // on the count n.
   171  func pickNoun(n uint64, singular, plural string) string {
   172  	if n == 1 {
   173  		return singular
   174  	}
   175  	return plural
   176  }