github.com/johnnyeven/libtools@v0.0.0-20191126065708-61829c1adf46/log/hooks/call_stack.go (about)

     1  package hooks
     2  
     3  import (
     4  	"fmt"
     5  	"runtime"
     6  	"strings"
     7  
     8  	"github.com/sirupsen/logrus"
     9  )
    10  
    11  func NewCallStackHook() *CallStackHook {
    12  	return &CallStackHook{}
    13  }
    14  
    15  type CallStackHook struct {
    16  }
    17  
    18  func (hook *CallStackHook) Fire(entry *logrus.Entry) error {
    19  	inFunc, file, line := findCaller()
    20  	entry.Data["file"] = fmt.Sprintf("%s:%d (%s)", file, line, inFunc)
    21  	return nil
    22  }
    23  
    24  func (hook *CallStackHook) Levels() []logrus.Level {
    25  	return logrus.AllLevels
    26  }
    27  
    28  func findCaller() (inFunc string, file string, line int) {
    29  	pc := uintptr(0)
    30  	skip := 5
    31  
    32  	for i := 0; i < 10; i++ {
    33  		pc, file, line = getCaller(skip + i)
    34  		if !(strings.HasPrefix(file, "logrus")) {
    35  			inFunc = runtime.FuncForPC(pc).Name()
    36  			break
    37  		}
    38  	}
    39  
    40  	return
    41  }
    42  
    43  func getGoPkgName(file string) string {
    44  	n := 0
    45  	for i := len(file) - 1; i > 0; i-- {
    46  		if file[i] == '/' {
    47  			n += 1
    48  			if n >= 2 {
    49  				file = file[i+1:]
    50  				break
    51  			}
    52  		}
    53  	}
    54  	return file
    55  }
    56  
    57  func getCaller(skip int) (uintptr, string, int) {
    58  	pc, file, line, ok := runtime.Caller(skip)
    59  
    60  	if !ok {
    61  		return 0, "", 0
    62  	}
    63  
    64  	return pc, getGoPkgName(file), line
    65  }