| 
									
										
										
										
											2014-10-14 19:35:10 +02:00
										 |  |  | /* | 
					
						
							| 
									
										
										
										
											2014-10-31 12:56:05 +01:00
										 |  |  | Package logger implements a multi-output leveled logger. | 
					
						
							| 
									
										
										
										
											2014-10-14 19:35:10 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-15 11:15:59 +02:00
										 |  |  | Other packages use tagged logger to send log messages to shared | 
					
						
							|  |  |  | (process-wide) logging engine. The shared logging engine dispatches to | 
					
						
							|  |  |  | multiple log systems. The log level can be set separately per log | 
					
						
							|  |  |  | system. | 
					
						
							| 
									
										
										
										
											2014-10-14 19:35:10 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-16 12:11:17 +02:00
										 |  |  | Logging is asynchronous and does not block the caller. Message | 
					
						
							| 
									
										
										
										
											2014-10-14 19:35:10 +02:00
										 |  |  | formatting is performed by the caller goroutine to avoid incorrect | 
					
						
							|  |  |  | logging of mutable state. | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2014-10-31 12:56:05 +01:00
										 |  |  | package logger | 
					
						
							| 
									
										
										
										
											2014-06-23 12:49:04 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2014-06-26 18:45:57 +01:00
										 |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"io" | 
					
						
							|  |  |  | 	"log" | 
					
						
							|  |  |  | 	"os" | 
					
						
							|  |  |  | 	"sync" | 
					
						
							| 
									
										
										
										
											2014-10-14 14:35:54 +02:00
										 |  |  | 	"sync/atomic" | 
					
						
							| 
									
										
										
										
											2014-06-23 12:49:04 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-14 19:35:10 +02:00
										 |  |  | // LogSystem is implemented by log output devices. | 
					
						
							|  |  |  | // All methods can be called concurrently from multiple goroutines. | 
					
						
							| 
									
										
										
										
											2014-06-23 12:49:04 +01:00
										 |  |  | type LogSystem interface { | 
					
						
							| 
									
										
										
										
											2014-06-26 18:45:57 +01:00
										 |  |  | 	GetLogLevel() LogLevel | 
					
						
							|  |  |  | 	SetLogLevel(i LogLevel) | 
					
						
							| 
									
										
										
										
											2014-10-16 10:50:51 +02:00
										 |  |  | 	LogPrint(LogLevel, string) | 
					
						
							| 
									
										
										
										
											2014-06-23 12:49:04 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-16 10:50:51 +02:00
										 |  |  | type message struct { | 
					
						
							|  |  |  | 	level LogLevel | 
					
						
							|  |  |  | 	msg   string | 
					
						
							| 
									
										
										
										
											2014-06-23 12:49:04 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type LogLevel uint8 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const ( | 
					
						
							| 
									
										
										
										
											2014-10-14 19:35:10 +02:00
										 |  |  | 	// Standard log levels | 
					
						
							| 
									
										
										
										
											2014-06-26 18:45:57 +01:00
										 |  |  | 	Silence LogLevel = iota | 
					
						
							|  |  |  | 	ErrorLevel | 
					
						
							|  |  |  | 	WarnLevel | 
					
						
							|  |  |  | 	InfoLevel | 
					
						
							|  |  |  | 	DebugLevel | 
					
						
							|  |  |  | 	DebugDetailLevel | 
					
						
							| 
									
										
										
										
											2014-06-23 12:49:04 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-14 14:29:04 +02:00
										 |  |  | var ( | 
					
						
							| 
									
										
										
										
											2014-10-16 11:50:10 +02:00
										 |  |  | 	logMessageC = make(chan message) | 
					
						
							|  |  |  | 	addSystemC  = make(chan LogSystem) | 
					
						
							|  |  |  | 	flushC      = make(chan chan struct{}) | 
					
						
							|  |  |  | 	resetC      = make(chan chan struct{}) | 
					
						
							| 
									
										
										
										
											2014-10-14 14:29:04 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func init() { | 
					
						
							|  |  |  | 	go dispatchLoop() | 
					
						
							| 
									
										
										
										
											2014-07-14 18:37:01 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-16 11:50:10 +02:00
										 |  |  | // each system can buffer this many messages before | 
					
						
							|  |  |  | // blocking incoming log messages. | 
					
						
							|  |  |  | const sysBufferSize = 500 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-14 14:29:04 +02:00
										 |  |  | func dispatchLoop() { | 
					
						
							| 
									
										
										
										
											2014-10-16 11:50:10 +02:00
										 |  |  | 	var ( | 
					
						
							|  |  |  | 		systems  []LogSystem | 
					
						
							|  |  |  | 		systemIn []chan message | 
					
						
							|  |  |  | 		systemWG sync.WaitGroup | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	bootSystem := func(sys LogSystem) { | 
					
						
							|  |  |  | 		in := make(chan message, sysBufferSize) | 
					
						
							|  |  |  | 		systemIn = append(systemIn, in) | 
					
						
							|  |  |  | 		systemWG.Add(1) | 
					
						
							|  |  |  | 		go sysLoop(sys, in, &systemWG) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-26 18:45:57 +01:00
										 |  |  | 	for { | 
					
						
							|  |  |  | 		select { | 
					
						
							| 
									
										
										
										
											2014-10-16 11:50:10 +02:00
										 |  |  | 		case msg := <-logMessageC: | 
					
						
							|  |  |  | 			for _, c := range systemIn { | 
					
						
							|  |  |  | 				c <- msg | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case sys := <-addSystemC: | 
					
						
							|  |  |  | 			systems = append(systems, sys) | 
					
						
							|  |  |  | 			bootSystem(sys) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case waiter := <-resetC: | 
					
						
							|  |  |  | 			// reset means terminate all systems | 
					
						
							|  |  |  | 			for _, c := range systemIn { | 
					
						
							|  |  |  | 				close(c) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			systems = nil | 
					
						
							|  |  |  | 			systemIn = nil | 
					
						
							|  |  |  | 			systemWG.Wait() | 
					
						
							|  |  |  | 			close(waiter) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case waiter := <-flushC: | 
					
						
							|  |  |  | 			// flush means reboot all systems | 
					
						
							|  |  |  | 			for _, c := range systemIn { | 
					
						
							|  |  |  | 				close(c) | 
					
						
							| 
									
										
										
										
											2014-10-14 14:29:04 +02:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-10-16 11:50:10 +02:00
										 |  |  | 			systemIn = nil | 
					
						
							|  |  |  | 			systemWG.Wait() | 
					
						
							|  |  |  | 			for _, sys := range systems { | 
					
						
							|  |  |  | 				bootSystem(sys) | 
					
						
							| 
									
										
										
										
											2014-10-14 14:29:04 +02:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-10-16 11:50:10 +02:00
										 |  |  | 			close(waiter) | 
					
						
							| 
									
										
										
										
											2014-06-26 18:45:57 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-07-14 18:37:01 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-16 11:50:10 +02:00
										 |  |  | func sysLoop(sys LogSystem, in <-chan message, wg *sync.WaitGroup) { | 
					
						
							|  |  |  | 	for msg := range in { | 
					
						
							| 
									
										
										
										
											2014-10-16 10:50:51 +02:00
										 |  |  | 		if sys.GetLogLevel() >= msg.level { | 
					
						
							|  |  |  | 			sys.LogPrint(msg.level, msg.msg) | 
					
						
							| 
									
										
										
										
											2014-10-14 14:29:04 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-10-16 11:50:10 +02:00
										 |  |  | 	wg.Done() | 
					
						
							| 
									
										
										
										
											2014-10-14 14:29:04 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-14 19:35:10 +02:00
										 |  |  | // Reset removes all active log systems. | 
					
						
							| 
									
										
										
										
											2014-10-16 11:50:10 +02:00
										 |  |  | // It blocks until all current messages have been delivered. | 
					
						
							| 
									
										
										
										
											2014-07-05 18:36:22 +01:00
										 |  |  | func Reset() { | 
					
						
							| 
									
										
										
										
											2014-10-16 11:50:10 +02:00
										 |  |  | 	waiter := make(chan struct{}) | 
					
						
							|  |  |  | 	resetC <- waiter | 
					
						
							|  |  |  | 	<-waiter | 
					
						
							| 
									
										
										
										
											2014-07-05 18:36:22 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-14 14:29:04 +02:00
										 |  |  | // Flush waits until all current log messages have been dispatched to | 
					
						
							|  |  |  | // the active log systems. | 
					
						
							| 
									
										
										
										
											2014-07-05 18:36:22 +01:00
										 |  |  | func Flush() { | 
					
						
							| 
									
										
										
										
											2014-10-14 14:29:04 +02:00
										 |  |  | 	waiter := make(chan struct{}) | 
					
						
							| 
									
										
										
										
											2014-10-16 11:50:10 +02:00
										 |  |  | 	flushC <- waiter | 
					
						
							| 
									
										
										
										
											2014-10-14 14:29:04 +02:00
										 |  |  | 	<-waiter | 
					
						
							| 
									
										
										
										
											2014-06-23 12:49:04 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-14 19:35:10 +02:00
										 |  |  | // AddLogSystem starts printing messages to the given LogSystem. | 
					
						
							| 
									
										
										
										
											2014-10-16 11:50:10 +02:00
										 |  |  | func AddLogSystem(sys LogSystem) { | 
					
						
							|  |  |  | 	addSystemC <- sys | 
					
						
							| 
									
										
										
										
											2014-10-14 19:35:10 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-15 11:15:59 +02:00
										 |  |  | // A Logger prints messages prefixed by a given tag. It provides named | 
					
						
							|  |  |  | // Printf and Println style methods for all loglevels. Each ethereum | 
					
						
							|  |  |  | // component should have its own logger with a unique prefix. | 
					
						
							| 
									
										
										
										
											2014-06-23 12:49:04 +01:00
										 |  |  | type Logger struct { | 
					
						
							| 
									
										
										
										
											2014-06-26 18:45:57 +01:00
										 |  |  | 	tag string | 
					
						
							| 
									
										
										
										
											2014-06-23 12:49:04 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func NewLogger(tag string) *Logger { | 
					
						
							| 
									
										
										
										
											2014-10-16 10:50:51 +02:00
										 |  |  | 	return &Logger{"[" + tag + "] "} | 
					
						
							| 
									
										
										
										
											2014-06-23 12:49:04 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-26 18:45:57 +01:00
										 |  |  | func (logger *Logger) sendln(level LogLevel, v ...interface{}) { | 
					
						
							| 
									
										
										
										
											2014-10-16 11:50:10 +02:00
										 |  |  | 	logMessageC <- message{level, logger.tag + fmt.Sprintln(v...)} | 
					
						
							| 
									
										
										
										
											2014-06-23 12:49:04 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-26 18:45:57 +01:00
										 |  |  | func (logger *Logger) sendf(level LogLevel, format string, v ...interface{}) { | 
					
						
							| 
									
										
										
										
											2014-10-16 11:50:10 +02:00
										 |  |  | 	logMessageC <- message{level, logger.tag + fmt.Sprintf(format, v...)} | 
					
						
							| 
									
										
										
										
											2014-06-23 12:49:04 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-14 19:35:10 +02:00
										 |  |  | // Errorln writes a message with ErrorLevel. | 
					
						
							| 
									
										
										
										
											2014-06-26 18:45:57 +01:00
										 |  |  | func (logger *Logger) Errorln(v ...interface{}) { | 
					
						
							|  |  |  | 	logger.sendln(ErrorLevel, v...) | 
					
						
							| 
									
										
										
										
											2014-06-23 12:49:04 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-14 19:35:10 +02:00
										 |  |  | // Warnln writes a message with WarnLevel. | 
					
						
							| 
									
										
										
										
											2014-06-26 18:45:57 +01:00
										 |  |  | func (logger *Logger) Warnln(v ...interface{}) { | 
					
						
							|  |  |  | 	logger.sendln(WarnLevel, v...) | 
					
						
							| 
									
										
										
										
											2014-06-23 12:49:04 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-14 19:35:10 +02:00
										 |  |  | // Infoln writes a message with InfoLevel. | 
					
						
							| 
									
										
										
										
											2014-06-26 18:45:57 +01:00
										 |  |  | func (logger *Logger) Infoln(v ...interface{}) { | 
					
						
							|  |  |  | 	logger.sendln(InfoLevel, v...) | 
					
						
							| 
									
										
										
										
											2014-06-23 12:49:04 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-14 19:35:10 +02:00
										 |  |  | // Debugln writes a message with DebugLevel. | 
					
						
							| 
									
										
										
										
											2014-06-26 18:45:57 +01:00
										 |  |  | func (logger *Logger) Debugln(v ...interface{}) { | 
					
						
							|  |  |  | 	logger.sendln(DebugLevel, v...) | 
					
						
							| 
									
										
										
										
											2014-06-23 12:49:04 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-14 19:35:10 +02:00
										 |  |  | // DebugDetailln writes a message with DebugDetailLevel. | 
					
						
							| 
									
										
										
										
											2014-06-26 18:45:57 +01:00
										 |  |  | func (logger *Logger) DebugDetailln(v ...interface{}) { | 
					
						
							|  |  |  | 	logger.sendln(DebugDetailLevel, v...) | 
					
						
							| 
									
										
										
										
											2014-06-25 16:37:38 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-14 19:35:10 +02:00
										 |  |  | // Errorf writes a message with ErrorLevel. | 
					
						
							| 
									
										
										
										
											2014-06-26 18:45:57 +01:00
										 |  |  | func (logger *Logger) Errorf(format string, v ...interface{}) { | 
					
						
							|  |  |  | 	logger.sendf(ErrorLevel, format, v...) | 
					
						
							| 
									
										
										
										
											2014-06-23 12:49:04 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-14 19:35:10 +02:00
										 |  |  | // Warnf writes a message with WarnLevel. | 
					
						
							| 
									
										
										
										
											2014-06-26 18:45:57 +01:00
										 |  |  | func (logger *Logger) Warnf(format string, v ...interface{}) { | 
					
						
							|  |  |  | 	logger.sendf(WarnLevel, format, v...) | 
					
						
							| 
									
										
										
										
											2014-06-23 12:49:04 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-14 19:35:10 +02:00
										 |  |  | // Infof writes a message with InfoLevel. | 
					
						
							| 
									
										
										
										
											2014-06-26 18:45:57 +01:00
										 |  |  | func (logger *Logger) Infof(format string, v ...interface{}) { | 
					
						
							|  |  |  | 	logger.sendf(InfoLevel, format, v...) | 
					
						
							| 
									
										
										
										
											2014-06-23 12:49:04 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-14 19:35:10 +02:00
										 |  |  | // Debugf writes a message with DebugLevel. | 
					
						
							| 
									
										
										
										
											2014-06-26 18:45:57 +01:00
										 |  |  | func (logger *Logger) Debugf(format string, v ...interface{}) { | 
					
						
							|  |  |  | 	logger.sendf(DebugLevel, format, v...) | 
					
						
							| 
									
										
										
										
											2014-06-23 12:49:04 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-14 19:35:10 +02:00
										 |  |  | // DebugDetailf writes a message with DebugDetailLevel. | 
					
						
							| 
									
										
										
										
											2014-06-26 18:45:57 +01:00
										 |  |  | func (logger *Logger) DebugDetailf(format string, v ...interface{}) { | 
					
						
							|  |  |  | 	logger.sendf(DebugDetailLevel, format, v...) | 
					
						
							| 
									
										
										
										
											2014-06-25 16:37:38 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-14 19:35:10 +02:00
										 |  |  | // Fatalln writes a message with ErrorLevel and exits the program. | 
					
						
							| 
									
										
										
										
											2014-06-26 18:45:57 +01:00
										 |  |  | func (logger *Logger) Fatalln(v ...interface{}) { | 
					
						
							|  |  |  | 	logger.sendln(ErrorLevel, v...) | 
					
						
							|  |  |  | 	Flush() | 
					
						
							|  |  |  | 	os.Exit(0) | 
					
						
							| 
									
										
										
										
											2014-06-23 12:49:04 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-14 19:35:10 +02:00
										 |  |  | // Fatalf writes a message with ErrorLevel and exits the program. | 
					
						
							| 
									
										
										
										
											2014-06-26 18:45:57 +01:00
										 |  |  | func (logger *Logger) Fatalf(format string, v ...interface{}) { | 
					
						
							|  |  |  | 	logger.sendf(ErrorLevel, format, v...) | 
					
						
							|  |  |  | 	Flush() | 
					
						
							|  |  |  | 	os.Exit(0) | 
					
						
							| 
									
										
										
										
											2014-06-23 12:49:04 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-14 19:35:10 +02:00
										 |  |  | // NewStdLogSystem creates a LogSystem that prints to the given writer. | 
					
						
							|  |  |  | // The flag values are defined package log. | 
					
						
							|  |  |  | func NewStdLogSystem(writer io.Writer, flags int, level LogLevel) LogSystem { | 
					
						
							|  |  |  | 	logger := log.New(writer, "", flags) | 
					
						
							|  |  |  | 	return &stdLogSystem{logger, uint32(level)} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type stdLogSystem struct { | 
					
						
							| 
									
										
										
										
											2014-06-26 18:45:57 +01:00
										 |  |  | 	logger *log.Logger | 
					
						
							| 
									
										
										
										
											2014-10-14 14:35:54 +02:00
										 |  |  | 	level  uint32 | 
					
						
							| 
									
										
										
										
											2014-06-23 12:49:04 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-16 10:50:51 +02:00
										 |  |  | func (t *stdLogSystem) LogPrint(level LogLevel, msg string) { | 
					
						
							|  |  |  | 	t.logger.Print(msg) | 
					
						
							| 
									
										
										
										
											2014-06-23 12:49:04 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-14 19:35:10 +02:00
										 |  |  | func (t *stdLogSystem) SetLogLevel(i LogLevel) { | 
					
						
							| 
									
										
										
										
											2014-10-14 14:35:54 +02:00
										 |  |  | 	atomic.StoreUint32(&t.level, uint32(i)) | 
					
						
							| 
									
										
										
										
											2014-06-23 12:49:04 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-14 19:35:10 +02:00
										 |  |  | func (t *stdLogSystem) GetLogLevel() LogLevel { | 
					
						
							| 
									
										
										
										
											2014-10-14 14:35:54 +02:00
										 |  |  | 	return LogLevel(atomic.LoadUint32(&t.level)) | 
					
						
							| 
									
										
										
										
											2014-06-23 12:49:04 +01:00
										 |  |  | } |