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 }