Skip to content

Instantly share code, notes, and snippets.

@sanbornm
Created November 25, 2019 20:25
Show Gist options
  • Save sanbornm/a459510125b29ebf15dab014dcb1b8aa to your computer and use it in GitHub Desktop.
Save sanbornm/a459510125b29ebf15dab014dcb1b8aa to your computer and use it in GitHub Desktop.
logrus filename hook
package filename
import (
"fmt"
"runtime"
"strings"
"github.com/sirupsen/logrus"
)
// adds hook to logrus so it can support file/line location
type Hook struct {
Field string
Skip int
levels []logrus.Level
Formatter func(file, function string, line int) string
}
func (hook *Hook) Levels() []logrus.Level {
return hook.levels
}
func (hook *Hook) Fire(entry *logrus.Entry) error {
entry.Data[hook.Field] = hook.Formatter(findCaller(hook.Skip))
return nil
}
func NewHook(levels ...logrus.Level) *Hook {
hook := Hook{
Field: "source",
Skip: 5,
levels: levels,
Formatter: func(file, function string, line int) string {
return fmt.Sprintf("%s:%d", file, line)
},
}
if len(hook.levels) == 0 {
hook.levels = logrus.AllLevels
}
return &hook
}
func findCaller(skip int) (string, string, int) {
var (
pc uintptr
file string
function string
line int
)
for i := 0; i < 10; i++ {
pc, file, line = getCaller(skip + i)
if !strings.HasPrefix(file, "logrus") {
break
}
}
if pc != 0 {
frames := runtime.CallersFrames([]uintptr{pc})
frame, _ := frames.Next()
function = frame.Function
}
return file, function, line
}
func getCaller(skip int) (uintptr, string, int) {
pc, file, line, ok := runtime.Caller(skip)
if !ok {
return 0, "", 0
}
n := 0
for i := len(file) - 1; i > 0; i-- {
if file[i] == '/' {
n += 1
if n >= 2 {
file = file[i+1:]
break
}
}
}
return pc, file, line
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment