110 lines
2.1 KiB
Go
110 lines
2.1 KiB
Go
package flog
|
|
|
|
import (
|
|
"fmt"
|
|
"runtime"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// All log functions
|
|
var (
|
|
Debug = logFunc(LevelDebug)
|
|
Debugf = logfFunc(LevelDebug)
|
|
Info = logFunc(LevelInfo)
|
|
Infof = logfFunc(LevelInfo)
|
|
Warning = logFunc(LevelWarning)
|
|
Warningf = logfFunc(LevelWarning)
|
|
Error = logFunc(LevelError)
|
|
Errorf = logfFunc(LevelError)
|
|
Critical = logFunc(LevelCritical)
|
|
Criticalf = logfFunc(LevelCritical)
|
|
)
|
|
|
|
func logFunc(level LevelType) func(...interface{}) {
|
|
return func(message ...interface{}) {
|
|
writeMessage(level, ``, message)
|
|
}
|
|
}
|
|
|
|
func logfFunc(level LevelType) func(string, ...interface{}) {
|
|
return func(format string, a ...interface{}) {
|
|
writeMessage(level, format, a)
|
|
}
|
|
}
|
|
|
|
var mu sync.Mutex
|
|
|
|
func writeMessage(level LevelType, format string, message []interface{}) {
|
|
if MinLevel > level {
|
|
return
|
|
}
|
|
|
|
entry := LogEntry{
|
|
Level: level,
|
|
Time: time.Now(),
|
|
}
|
|
|
|
if format == `` {
|
|
entry.Message = fmt.Sprint(message...)
|
|
} else {
|
|
entry.Message = fmt.Sprintf(format, message...)
|
|
}
|
|
|
|
if MinStackLevel <= level {
|
|
entry.StackTrace = getStackTrace()
|
|
}
|
|
|
|
mu.Lock()
|
|
defer mu.Unlock()
|
|
|
|
Format.FormatMessage(getOutput(), entry)
|
|
}
|
|
|
|
func getStackTrace() (stackTrace []StackTraceEntry) {
|
|
_, filename, _, _ := runtime.Caller(1)
|
|
|
|
pc := make([]uintptr, 50)
|
|
entries := runtime.Callers(2, pc)
|
|
frames := runtime.CallersFrames(pc[:entries])
|
|
|
|
more, firstLine := true, false
|
|
for more {
|
|
var frame runtime.Frame
|
|
frame, more = frames.Next()
|
|
|
|
if !firstLine && frame.File == filename { // Skip frames from the flog cal
|
|
continue
|
|
}
|
|
firstLine = true
|
|
|
|
if frame.Function == `runtime.gopanic` { // If a panic occurred, start at the frame that called panic
|
|
stackTrace = nil
|
|
continue
|
|
}
|
|
|
|
stackTrace = append(stackTrace, StackTraceEntry{
|
|
Function: cleanFunction(frame.Function),
|
|
File: cleanFilename(frame.File),
|
|
Line: frame.Line,
|
|
})
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func cleanFunction(f string) string {
|
|
parts := strings.Split(f, `/vendor/`)
|
|
return parts[len(parts)-1]
|
|
}
|
|
|
|
func cleanFilename(file string) string {
|
|
parts := strings.Split(file, `/src/`)
|
|
if len(parts) < 2 {
|
|
return file
|
|
}
|
|
|
|
return strings.Join(parts[1:], `/`)
|
|
}
|