create a logger interface and use it everywhere

This commit is contained in:
Marten Seemann
2018-03-28 07:30:36 +07:00
parent 1e9b3f0bb2
commit 948eef3e42
52 changed files with 411 additions and 281 deletions

View File

@@ -11,8 +11,6 @@ import (
// LogLevel of quic-go
type LogLevel uint8
const logEnv = "QUIC_GO_LOG_LEVEL"
const (
// LogLevelNothing disables
LogLevelNothing LogLevel = iota
@@ -24,72 +22,92 @@ const (
LogLevelDebug
)
var (
logLevel = LogLevelNothing
timeFormat = ""
)
const logEnv = "QUIC_GO_LOG_LEVEL"
// A Logger logs.
type Logger interface {
SetLogLevel(LogLevel)
SetLogTimeFormat(format string)
Debug() bool
Errorf(format string, args ...interface{})
Infof(format string, args ...interface{})
Debugf(format string, args ...interface{})
}
// DefaultLogger is used by quic-go for logging.
var DefaultLogger Logger
type defaultLogger struct {
logLevel LogLevel
timeFormat string
}
var _ Logger = &defaultLogger{}
// SetLogLevel sets the log level
func SetLogLevel(level LogLevel) {
logLevel = level
func (l *defaultLogger) SetLogLevel(level LogLevel) {
l.logLevel = level
}
// SetLogTimeFormat sets the format of the timestamp
// an empty string disables the logging of timestamps
func SetLogTimeFormat(format string) {
func (l *defaultLogger) SetLogTimeFormat(format string) {
log.SetFlags(0) // disable timestamp logging done by the log package
timeFormat = format
l.timeFormat = format
}
// Debugf logs something
func Debugf(format string, args ...interface{}) {
if logLevel == LogLevelDebug {
logMessage(format, args...)
func (l *defaultLogger) Debugf(format string, args ...interface{}) {
if l.logLevel == LogLevelDebug {
l.logMessage(format, args...)
}
}
// Infof logs something
func Infof(format string, args ...interface{}) {
if logLevel >= LogLevelInfo {
logMessage(format, args...)
func (l *defaultLogger) Infof(format string, args ...interface{}) {
if l.logLevel >= LogLevelInfo {
l.logMessage(format, args...)
}
}
// Errorf logs something
func Errorf(format string, args ...interface{}) {
if logLevel >= LogLevelError {
logMessage(format, args...)
func (l *defaultLogger) Errorf(format string, args ...interface{}) {
if l.logLevel >= LogLevelError {
l.logMessage(format, args...)
}
}
func logMessage(format string, args ...interface{}) {
if len(timeFormat) > 0 {
log.Printf(time.Now().Format(timeFormat)+" "+format, args...)
func (l *defaultLogger) logMessage(format string, args ...interface{}) {
if len(l.timeFormat) > 0 {
log.Printf(time.Now().Format(l.timeFormat)+" "+format, args...)
} else {
log.Printf(format, args...)
}
}
// Debug returns true if the log level is LogLevelDebug
func Debug() bool {
return logLevel == LogLevelDebug
func (l *defaultLogger) Debug() bool {
return l.logLevel == LogLevelDebug
}
func init() {
readLoggingEnv()
DefaultLogger = &defaultLogger{}
DefaultLogger.SetLogLevel(readLoggingEnv())
}
func readLoggingEnv() {
func readLoggingEnv() LogLevel {
switch strings.ToLower(os.Getenv(logEnv)) {
case "":
return
return LogLevelNothing
case "debug":
logLevel = LogLevelDebug
return LogLevelDebug
case "info":
logLevel = LogLevelInfo
return LogLevelInfo
case "error":
logLevel = LogLevelError
return LogLevelError
default:
fmt.Fprintln(os.Stderr, "invalid quic-go log level, see https://github.com/lucas-clemente/quic-go/wiki/Logging")
return LogLevelNothing
}
}

View File

@@ -11,22 +11,16 @@ import (
)
var _ = Describe("Log", func() {
var (
b *bytes.Buffer
initialTimeFormat string
)
var b *bytes.Buffer
BeforeEach(func() {
b = bytes.NewBuffer([]byte{})
b = &bytes.Buffer{}
log.SetOutput(b)
initialTimeFormat = timeFormat
})
AfterEach(func() {
log.SetOutput(os.Stdout)
SetLogLevel(LogLevelNothing)
timeFormat = initialTimeFormat
DefaultLogger.SetLogLevel(LogLevelNothing)
})
It("the log level has the correct numeric value", func() {
@@ -37,103 +31,97 @@ var _ = Describe("Log", func() {
})
It("log level nothing", func() {
SetLogLevel(LogLevelNothing)
Debugf("debug")
Infof("info")
Errorf("err")
DefaultLogger.SetLogLevel(LogLevelNothing)
DefaultLogger.Debugf("debug")
DefaultLogger.Infof("info")
DefaultLogger.Errorf("err")
Expect(b.Bytes()).To(Equal([]byte("")))
})
It("log level err", func() {
SetLogLevel(LogLevelError)
Debugf("debug")
Infof("info")
Errorf("err")
DefaultLogger.SetLogLevel(LogLevelError)
DefaultLogger.Debugf("debug")
DefaultLogger.Infof("info")
DefaultLogger.Errorf("err")
Expect(b.Bytes()).To(ContainSubstring("err\n"))
Expect(b.Bytes()).ToNot(ContainSubstring("info"))
Expect(b.Bytes()).ToNot(ContainSubstring("debug"))
})
It("log level info", func() {
SetLogLevel(LogLevelInfo)
Debugf("debug")
Infof("info")
Errorf("err")
DefaultLogger.SetLogLevel(LogLevelInfo)
DefaultLogger.Debugf("debug")
DefaultLogger.Infof("info")
DefaultLogger.Errorf("err")
Expect(b.Bytes()).To(ContainSubstring("err\n"))
Expect(b.Bytes()).To(ContainSubstring("info\n"))
Expect(b.Bytes()).ToNot(ContainSubstring("debug"))
})
It("log level debug", func() {
SetLogLevel(LogLevelDebug)
Debugf("debug")
Infof("info")
Errorf("err")
DefaultLogger.SetLogLevel(LogLevelDebug)
DefaultLogger.Debugf("debug")
DefaultLogger.Infof("info")
DefaultLogger.Errorf("err")
Expect(b.Bytes()).To(ContainSubstring("err\n"))
Expect(b.Bytes()).To(ContainSubstring("info\n"))
Expect(b.Bytes()).To(ContainSubstring("debug\n"))
})
It("doesn't add a timestamp if the time format is empty", func() {
SetLogLevel(LogLevelDebug)
SetLogTimeFormat("")
Debugf("debug")
DefaultLogger.SetLogLevel(LogLevelDebug)
DefaultLogger.SetLogTimeFormat("")
DefaultLogger.Debugf("debug")
Expect(b.Bytes()).To(Equal([]byte("debug\n")))
})
It("adds a timestamp", func() {
format := "Jan 2, 2006"
SetLogTimeFormat(format)
SetLogLevel(LogLevelInfo)
Infof("info")
DefaultLogger.SetLogTimeFormat(format)
DefaultLogger.SetLogLevel(LogLevelInfo)
DefaultLogger.Infof("info")
t, err := time.Parse(format, string(b.Bytes()[:b.Len()-6]))
Expect(err).ToNot(HaveOccurred())
Expect(t).To(BeTemporally("~", time.Now(), 25*time.Hour))
})
It("says whether debug is enabled", func() {
Expect(Debug()).To(BeFalse())
SetLogLevel(LogLevelDebug)
Expect(Debug()).To(BeTrue())
Expect(DefaultLogger.Debug()).To(BeFalse())
DefaultLogger.SetLogLevel(LogLevelDebug)
Expect(DefaultLogger.Debug()).To(BeTrue())
})
Context("reading from env", func() {
BeforeEach(func() {
Expect(logLevel).To(Equal(LogLevelNothing))
Expect(DefaultLogger.(*defaultLogger).logLevel).To(Equal(LogLevelNothing))
})
It("reads DEBUG", func() {
os.Setenv(logEnv, "DEBUG")
readLoggingEnv()
Expect(logLevel).To(Equal(LogLevelDebug))
Expect(readLoggingEnv()).To(Equal(LogLevelDebug))
})
It("reads debug", func() {
os.Setenv(logEnv, "debug")
readLoggingEnv()
Expect(logLevel).To(Equal(LogLevelDebug))
Expect(readLoggingEnv()).To(Equal(LogLevelDebug))
})
It("reads INFO", func() {
os.Setenv(logEnv, "INFO")
readLoggingEnv()
Expect(logLevel).To(Equal(LogLevelInfo))
Expect(readLoggingEnv()).To(Equal(LogLevelInfo))
})
It("reads ERROR", func() {
os.Setenv(logEnv, "ERROR")
readLoggingEnv()
Expect(logLevel).To(Equal(LogLevelError))
Expect(readLoggingEnv()).To(Equal(LogLevelError))
})
It("does not error reading invalid log levels from env", func() {
Expect(logLevel).To(Equal(LogLevelNothing))
os.Setenv(logEnv, "")
readLoggingEnv()
Expect(logLevel).To(Equal(LogLevelNothing))
Expect(readLoggingEnv()).To(Equal(LogLevelNothing))
os.Setenv(logEnv, "asdf")
readLoggingEnv()
Expect(logLevel).To(Equal(LogLevelNothing))
Expect(readLoggingEnv()).To(Equal(LogLevelNothing))
})
})
})