First draft
diff --git a/jww_test.go b/jww_test.go new file mode 100644 index 0000000..4b122d5 --- /dev/null +++ b/jww_test.go
@@ -0,0 +1,49 @@ +// Copyright © 2014 Steve Francia <spf@spf13.com>. +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +package jwalterweatherman + +import ( + "bytes" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestLevels(t *testing.T) { + SetOutLevel(LevelError) + assert.Equal(t, OutLevel(), LevelError) + SetLogLevel(LevelCritical) + assert.Equal(t, LogLevel(), LevelCritical) + assert.NotEqual(t, OutLevel(), LevelCritical) + SetOutLevel(LevelWarn) + assert.Equal(t, OutLevel(), LevelWarn) +} + +func TestDefaultLogging(t *testing.T) { + outputBuf := new(bytes.Buffer) + logBuf := new(bytes.Buffer) + LogHandle = logBuf + OutHandle = outputBuf + + SetOutLevel(LevelInfo) + SetLogLevel(LevelWarn) + + CRITICAL.Println("critical err") + ERROR.Println("an error") + WARN.Println("a warning") + INFO.Println("information") + DEBUG.Println("debugging info") + + assert.Contains(t, logBuf.String(), "critical err") + assert.Contains(t, logBuf.String(), "an error") + assert.Contains(t, logBuf.String(), "information") + assert.Contains(t, logBuf.String(), "a warning") + assert.NotContains(t, logBuf.String(), "debugging info") + assert.Contains(t, outputBuf.String(), "critical err") + assert.Contains(t, outputBuf.String(), "an error") + assert.Contains(t, outputBuf.String(), "information") + assert.NotContains(t, outputBuf.String(), "a warning") + assert.NotContains(t, outputBuf.String(), "debugging info") +}
diff --git a/thatswhyyoualwaysleaveanote.go b/thatswhyyoualwaysleaveanote.go new file mode 100644 index 0000000..2470578 --- /dev/null +++ b/thatswhyyoualwaysleaveanote.go
@@ -0,0 +1,224 @@ +// Copyright © 2014 Steve Francia <spf@spf13.com>. +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +package jwalterweatherman + +import ( + "fmt" + "io" + "io/ioutil" + "log" + "os" +) + +// Level describes the chosen log level between +// debug and critical. +type Level int + +//TRACE +//DEBUG +//INFO +//WARN +//ERROR +//CRITICAL +//FATAL + +type JWWLevel struct { + Handle io.Writer + Level int + *log.Logger +} + +type Feedback struct{} + +// Log levels to control the logging output. +const ( + LevelDebug Level = iota + LevelWarn + LevelInfo + LevelError + LevelCritical +) + +var ( + DEBUG *log.Logger + WARN *log.Logger + INFO *log.Logger + LOG *log.Logger + ERROR *log.Logger + CRITICAL *log.Logger + FEEDBACK Feedback + DebugHandle io.Writer = os.Stdout + WarnHandle io.Writer = os.Stdout + InfoHandle io.Writer = os.Stdout + ErrorHandle io.Writer = os.Stdout + CriticalHandle io.Writer = os.Stdout + logLevel Level = LevelWarn // 1 + outLevel Level = LevelInfo // 2 + LogHandle io.Writer = ioutil.Discard + OutHandle io.Writer = os.Stdout + BothHandle io.Writer = io.MultiWriter(LogHandle, OutHandle) +) + +func init() { + SetOutLevel(LevelInfo) +} + +func Initialize() { + initWriters() + + DEBUG = log.New(DebugHandle, + "DEBUG: ", + log.Ldate|log.Ltime|log.Lshortfile) + + INFO = log.New(InfoHandle, + "INFO: ", + log.Ldate|log.Ltime|log.Lshortfile) + + LOG = log.New(LogHandle, + "LOG: ", + log.Ldate|log.Ltime|log.Lshortfile) + + WARN = log.New(WarnHandle, + "WARN: ", + log.Ldate|log.Ltime|log.Lshortfile) + + ERROR = log.New(ErrorHandle, + "ERROR: ", + log.Ldate|log.Ltime|log.Lshortfile) + + CRITICAL = log.New(CriticalHandle, + "CRITICAL: ", + log.Ldate|log.Ltime|log.Lshortfile) +} + +// Level returns the current log level. +func LogLevel() Level { + return logLevel +} + +func OutLevel() Level { + return outLevel +} + +func levelCheck(level Level) Level { + switch { + case level <= LevelDebug: + return LevelDebug + case level >= LevelCritical: + return LevelCritical + default: + return level + } +} + +// SetLevel switches to a new log level. +func SetLogLevel(level Level) { + logLevel = levelCheck(level) + Initialize() +} + +func SetLogFile(path string) { + file, err := os.OpenFile(path, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666) + fmt.Println("Logging to", file.Name()) + if err != nil { + CRITICAL.Println("Failed to open log file:", path, err) + os.Exit(-1) + } + + LogHandle = file + Initialize() +} + +func UseTempLogFile(prefix string) { + file, err := ioutil.TempFile(os.TempDir(), prefix) + if err != nil { + CRITICAL.Println(err) + } + + fmt.Println("Logging to", file.Name()) + + LogHandle = file + Initialize() +} + +func DiscardLogging() { + LogHandle = ioutil.Discard + Initialize() +} + +func SetOutLevel(level Level) { + outLevel = levelCheck(level) // 1 + Initialize() +} + +// Don't use if you have manually set the Handles of the different levels as it will overwrite them. +func initWriters() { + BothHandle = io.MultiWriter(LogHandle, OutHandle) + //DEBUG + if LevelDebug < outLevel && LevelDebug < logLevel { + DebugHandle = ioutil.Discard + } else if LevelDebug >= outLevel && LevelDebug >= logLevel { + DebugHandle = BothHandle + } else if LevelDebug >= outLevel && LevelDebug < logLevel { + DebugHandle = OutHandle + } else { + DebugHandle = LogHandle + } + + //WARN + if LevelWarn < outLevel && LevelWarn < logLevel { + WarnHandle = ioutil.Discard + } else if LevelWarn >= outLevel && LevelWarn >= logLevel { + WarnHandle = BothHandle + } else if LevelWarn >= outLevel && LevelWarn < logLevel { + WarnHandle = OutHandle + } else { + WarnHandle = LogHandle + } + + //INFO + if LevelInfo < outLevel && LevelInfo < logLevel { + InfoHandle = ioutil.Discard + } else if LevelInfo >= outLevel && LevelInfo >= logLevel { + InfoHandle = BothHandle + } else if LevelInfo >= outLevel && LevelInfo < logLevel { + InfoHandle = OutHandle + } else { + InfoHandle = LogHandle + } + + //ERROR + if LevelError < outLevel && LevelError < logLevel { + ErrorHandle = ioutil.Discard + } else if LevelError >= outLevel && LevelError >= logLevel { + ErrorHandle = BothHandle + } else if LevelError >= outLevel && LevelError < logLevel { + ErrorHandle = OutHandle + } else { + ErrorHandle = LogHandle + } + + //CRITICAL + if LevelCritical < outLevel && LevelCritical < logLevel { + CriticalHandle = ioutil.Discard + } else if LevelCritical >= outLevel && LevelCritical >= logLevel { + CriticalHandle = BothHandle + } else if LevelCritical >= outLevel && LevelCritical < logLevel { + CriticalHandle = OutHandle + } else { + CriticalHandle = LogHandle + } +} + +func (fb *Feedback) Println(v ...interface{}) { + fmt.Println(v...) + LOG.Println(v...) +} + +func (fb *Feedback) Printf(format string, v ...interface{}) { + fmt.Printf(format, v...) + LOG.Printf(format, v...) +}