You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
93 lines
1.7 KiB
93 lines
1.7 KiB
package flog |
|
|
|
import ( |
|
"fmt" |
|
"runtime" |
|
"strings" |
|
"sync" |
|
"time" |
|
) |
|
|
|
// All log functions |
|
var ( |
|
Debug = logFunc(LevelDebug) |
|
Info = logFunc(LevelInfo) |
|
Warning = logFunc(LevelWarning) |
|
Error = logFunc(LevelError) |
|
Critical = logFunc(LevelCritical) |
|
) |
|
|
|
func logFunc(level LevelType) func(...interface{}) { |
|
return func(message ...interface{}) { |
|
writeMessage(level, message) |
|
} |
|
} |
|
|
|
var mu sync.Mutex |
|
|
|
func writeMessage(level LevelType, message []interface{}) { |
|
if MinLevel > level { |
|
return |
|
} |
|
|
|
entry := LogEntry{ |
|
Level: level, |
|
Time: time.Now(), |
|
Message: fmt.Sprint(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:], `/`) |
|
}
|
|
|