blob: 247057823cb345b736d5e7e9ba68ef4df2596bdc [file] [log] [blame]
// 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...)
}