1package utils 2 3import ( 4 "fmt" 5 "log" 6 "os" 7 "strings" 8 "time" 9) 10 11// LogLevel of quic-go 12type LogLevel uint8 13 14const ( 15 // LogLevelNothing disables 16 LogLevelNothing LogLevel = iota 17 // LogLevelError enables err logs 18 LogLevelError 19 // LogLevelInfo enables info logs (e.g. packets) 20 LogLevelInfo 21 // LogLevelDebug enables debug logs (e.g. packet contents) 22 LogLevelDebug 23) 24 25const logEnv = "QUIC_GO_LOG_LEVEL" 26 27// A Logger logs. 28type Logger interface { 29 SetLogLevel(LogLevel) 30 SetLogTimeFormat(format string) 31 WithPrefix(prefix string) Logger 32 Debug() bool 33 34 Errorf(format string, args ...interface{}) 35 Infof(format string, args ...interface{}) 36 Debugf(format string, args ...interface{}) 37} 38 39// DefaultLogger is used by quic-go for logging. 40var DefaultLogger Logger 41 42type defaultLogger struct { 43 prefix string 44 45 logLevel LogLevel 46 timeFormat string 47} 48 49var _ Logger = &defaultLogger{} 50 51// SetLogLevel sets the log level 52func (l *defaultLogger) SetLogLevel(level LogLevel) { 53 l.logLevel = level 54} 55 56// SetLogTimeFormat sets the format of the timestamp 57// an empty string disables the logging of timestamps 58func (l *defaultLogger) SetLogTimeFormat(format string) { 59 log.SetFlags(0) // disable timestamp logging done by the log package 60 l.timeFormat = format 61} 62 63// Debugf logs something 64func (l *defaultLogger) Debugf(format string, args ...interface{}) { 65 if l.logLevel == LogLevelDebug { 66 l.logMessage(format, args...) 67 } 68} 69 70// Infof logs something 71func (l *defaultLogger) Infof(format string, args ...interface{}) { 72 if l.logLevel >= LogLevelInfo { 73 l.logMessage(format, args...) 74 } 75} 76 77// Errorf logs something 78func (l *defaultLogger) Errorf(format string, args ...interface{}) { 79 if l.logLevel >= LogLevelError { 80 l.logMessage(format, args...) 81 } 82} 83 84func (l *defaultLogger) logMessage(format string, args ...interface{}) { 85 var pre string 86 87 if len(l.timeFormat) > 0 { 88 pre = time.Now().Format(l.timeFormat) + " " 89 } 90 if len(l.prefix) > 0 { 91 pre += l.prefix + " " 92 } 93 log.Printf(pre+format, args...) 94} 95 96func (l *defaultLogger) WithPrefix(prefix string) Logger { 97 if len(l.prefix) > 0 { 98 prefix = l.prefix + " " + prefix 99 } 100 return &defaultLogger{ 101 logLevel: l.logLevel, 102 timeFormat: l.timeFormat, 103 prefix: prefix, 104 } 105} 106 107// Debug returns true if the log level is LogLevelDebug 108func (l *defaultLogger) Debug() bool { 109 return l.logLevel == LogLevelDebug 110} 111 112func init() { 113 DefaultLogger = &defaultLogger{} 114 DefaultLogger.SetLogLevel(readLoggingEnv()) 115} 116 117func readLoggingEnv() LogLevel { 118 switch strings.ToLower(os.Getenv(logEnv)) { 119 case "": 120 return LogLevelNothing 121 case "debug": 122 return LogLevelDebug 123 case "info": 124 return LogLevelInfo 125 case "error": 126 return LogLevelError 127 default: 128 fmt.Fprintln(os.Stderr, "invalid quic-go log level, see https://github.com/lucas-clemente/quic-go/wiki/Logging") 129 return LogLevelNothing 130 } 131} 132