Newer
Older
"sync"
"time"
)
var logger *Logger
var once sync.Once
// Logger is a wrapper for log.Logger and provides
// methods to enable and disable logging.
type Logger struct {
DefaultWriter io.Writer
LoglevelWriter map[Level]io.Writer
Loglevel Level
lock sync.Mutex
builder strings.Builder
}
func (l *Logger) buildMessage(level Level, syslog bool, args ...interface{}) {
if !syslog {
l.builder.WriteString(time.Now().Format(time.RFC3339))
}
l.builder.WriteRune('\t')
l.builder.WriteString(prefix(level))
l.builder.WriteRune('\t')
function, line := callers()
functionSplitted := strings.SplitAfter(function, "/")
function = functionSplitted[len(functionSplitted)-1]
l.builder.WriteString(function)
l.builder.WriteRune(':')
l.builder.WriteString(strconv.Itoa(line))
l.builder.WriteRune('\t')
l.builder.WriteString(fmt.Sprint(args...))
l.builder.WriteRune('\n')
}
func get() *Logger {
once.Do(func() {
logger = &Logger{
DefaultWriter: os.Stderr,
LoglevelWriter: make(map[Level]io.Writer),
toSyslog: make(map[Level]bool),
Loglevel: INFO,
lock: sync.Mutex{},
// Loglevel sets the verbosity of the logger
// Defaults to INFO
func Loglevel(level Level) {
l := get()
l.lock.Lock()
defer l.lock.Unlock()
l.Loglevel = level
}
// Output defines the output of the logger
// Defaults to os.Stderr
func Output(out io.Writer) {
l := get()
l.lock.Lock()
defer l.lock.Unlock()
// LoglevelOutput defines a special output
// for a certain log level
func LoglevelOutput(level Level, out io.Writer) {
l := get()
l.lock.Lock()
defer l.lock.Unlock()
l.LoglevelWriter[level] = out
if reflect.TypeOf(out) == reflect.TypeOf(&syslog.Writer{}) {
l.toSyslog[level] = true
}
// Debug passes the DEBUG flag and a
// message to the logger
// Info passes the INFO flag and a
// message to the logger
// Warn passes the WARNING flag and a
// message to the logger
// Error passes the ERROR flag and a
// message to the logger
// Fatal passes the FATAL flag and a
// message to the logger and calls
// os.Exit(1)
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// Debugf passes the DEBUG flag,
// a formatted string and a
// message to the logger
func Debugf(format string, args ...interface{}) {
logf(DEBUG, format, args...)
}
// Infof passes the INFO flag,
// a formatted string and and a
// message to the logger
func Infof(format string, args ...interface{}) {
logf(INFO, format, args...)
}
// Warnf passes the WARNING flag,
// a formatted string and and a
// message to the logger
func Warnf(format string, args ...interface{}) {
logf(WARNING, format, args...)
}
// Errorf passes the ERROR flag,
// a formatted string and and a
// message to the logger
func Errorf(format string, args ...interface{}) {
logf(ERROR, format, args...)
}
// Fatalf passes the FATAL flag,
// a formatted string and and a
// message to the logger and calls
// os.Exit(1)
func Fatalf(format string, args ...interface{}) {
logf(FATAL, format, args...)
os.Exit(1)
}
func logf(level Level, format string, args ...interface{}) {
log(level, fmt.Sprintf(format, args...))
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered in f", r)
}
}()
l.buildMessage(level, l.toSyslog[level], args...)
msg := []byte(l.builder.String())
writer, ok := l.LoglevelWriter[level]
var err error
if !ok {
_, err = l.DefaultWriter.Write(msg)
} else {
_, err = writer.Write(msg)
}
frames := runtime.CallersFrames(pc[:n])
frame, _ := frames.Next()