/** @author: xuhanlin @date: 2022/6/28 @note: 基础线性格式日志 **/ package log import ( "bytes" "fmt" "github.com/sirupsen/logrus" "runtime" "strconv" "strings" ) // GetGid 获取协程ID func GetGid() uint64 { b := make([]byte, 64) b = b[:runtime.Stack(b, false)] b = bytes.TrimPrefix(b, []byte("goroutine ")) b = b[:bytes.IndexByte(b, ' ')] n, err := strconv.ParseUint(string(b), 10, 64) if err != nil { return 0 } return n } type LineFormatter struct { Skip int } func (f *LineFormatter) Format(entry *logrus.Entry) ([]byte, error) { data := "" // 毫秒时间 data += entry.Time.Format("2006-01-02 15:04:05.000") // 日志等级 data += "|" + strings.ToUpper(entry.Level.String()) // 调用信息 data += "|" + findCaller(f.Skip) // 线程信息 data += "|" + strconv.FormatUint(GetGid(), 10) // 日志内容 data += "|" + entry.Message return append([]byte(data), '\n'), nil } func findCaller(skip int) string { file, line, pc := getCaller(skip) fullFnName := runtime.FuncForPC(pc) fnName := "" if fullFnName != nil { fnNameStr := fullFnName.Name() parts := strings.Split(fnNameStr, ".") fnName = parts[len(parts)-1] } tmp := strings.Split(file, "/") return fmt.Sprintf("%s:%s:%d", tmp[len(tmp)-1], fnName, line) } func getCaller(skip int) (string, int, uintptr) { pc, file, line, ok := runtime.Caller(skip) if !ok { return "", 0, pc } n := 0 for i := len(file) - 1; i > 0; i-- { if file[i] == '/' { n++ if n >= 2 { file = file[i+1:] break } } } return file, line, pc }