package log import ( "bytes" "encoding/json" "fmt" "log" "runtime" "strings" "sync" "time" "github.com/sirupsen/logrus" ) type levelSkip struct { SkipLogrus int SkipBasic int } // JSONFormatter formats logs into parsable json type JSONFormatter struct { skip []*levelSkip once sync.Once } // Format renders a single log entry func (h *JSONFormatter) Format(e *logrus.Entry) ([]byte, error) { skipOnce := h.skip[int(e.Level)] if skipOnce.SkipLogrus == 0 { var skipLogrus OpenClose for i := 4; i < 50; i++ { // log.Println(i) if pc, file, line, ok := runtime.Caller(i); ok { funcStruct := runtime.FuncForPC(pc) log.Println(funcStruct.Name(), file, line) skipLogrus.OpenFunc(func() bool { return strings.Contains(funcStruct.Name(), "github.com/sirupsen/logrus.") }, func() { // skip = i skipOnce.SkipLogrus = i i = 10000 }) } else { break } } } if skipOnce.SkipBasic == 0 { var skipBasic OpenClose for i := 4; i < 50; i++ { // log.Println(i) if pc, file, line, ok := runtime.Caller(i); ok { funcStruct := runtime.FuncForPC(pc) log.Println(funcStruct.Name(), file, line) skipBasic.OpenFunc(func() bool { return strings.Contains(funcStruct.Name(), "basic.(*Response).") }, func() { skipOnce.SkipBasic = i + 1 }) } else { break } } } var fileinfo string if pc, _, _, ok := runtime.Caller(skipOnce.SkipBasic - 1); ok { funcStruct := runtime.FuncForPC(pc) log.Println(funcStruct.Name()) if strings.Contains(funcStruct.Name(), "basic.(*Response).") { if _, file, line, ok := runtime.Caller(skipOnce.SkipBasic); ok { if e.Level == logrus.InfoLevel { fileinfo = fmt.Sprintf("%s:%d", file, line) } else { ps := strings.Split(file, "/") // ps = ps[len(ps)-4:] fileinfo = fmt.Sprintf("%s:%d", strings.Join(ps, "/"), line) } } } } if fileinfo != "" { if _, file, line, ok := runtime.Caller(skipOnce.SkipLogrus); ok { if e.Level == logrus.InfoLevel { fileinfo = fmt.Sprintf("%s:%d", file, line) } else { ps := strings.Split(file, "/") // ps = ps[len(ps)-4:] fileinfo = fmt.Sprintf("%s:%d", strings.Join(ps, "/"), line) } } } var Data map[string]any = make(map[string]any, 4) Data[logrus.FieldKeyTime] = e.Time.Format(time.RFC3339) Data[logrus.FieldKeyMsg] = e.Message Data[logrus.FieldKeyLevel] = e.Level Data[logrus.FieldKeyFile] = fileinfo var b *bytes.Buffer if e.Buffer != nil { b = e.Buffer } else { b = &bytes.Buffer{} } encoder := json.NewEncoder(b) encoder.SetEscapeHTML(false) if err := encoder.Encode(Data); err != nil { return nil, fmt.Errorf("failed to marshal fields to JSON, %w", err) } return b.Bytes(), nil }