A golang package for logging to a file
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.

109 lines
2.1 KiB

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:], `/`)
}