// Based on https://github.com/gogap/logrus_mate under License Apache License 2.0 package file import ( "bytes" "fmt" "os" "path/filepath" "strings" "time" "github.com/juju/errors" "github.com/sirupsen/logrus" ) func NewHook(c *ConfigStruct) (logrus.Hook, error) { c.ApplyDefault() err := c.IsValid() if err != nil { return nil, errors.Trace(err) } dir := filepath.Dir(c.Filename) err = os.MkdirAll(dir, 0755) if err != nil { return nil, nil } w, err := InitFileLogWriter(c) if err != nil { return nil, errors.Trace(err) } return &FileHook{W: w}, nil } type FileHook struct { W *fileLogWriter } func (p *FileHook) Fire(entry *logrus.Entry) (err error) { message, err := getMessage(entry) if err != nil { fmt.Fprintf(os.Stderr, "Unable to read entry, %v", err) return err } now := time.Now() switch entry.Level { case logrus.PanicLevel: fallthrough case logrus.FatalLevel: fallthrough case logrus.ErrorLevel: return p.W.WriteMsg(now, fmt.Sprintf("[ERROR] %s", message), LevelError) case logrus.WarnLevel: return p.W.WriteMsg(now, fmt.Sprintf("[WARN] %s", message), LevelWarn) case logrus.InfoLevel: return p.W.WriteMsg(now, fmt.Sprintf("[INFO] %s", message), LevelInfo) case logrus.DebugLevel: return p.W.WriteMsg(now, fmt.Sprintf("[DEBUG] %s", message), LevelDebug) default: return nil } return } func (p *FileHook) Levels() []logrus.Level { return []logrus.Level{ logrus.PanicLevel, logrus.FatalLevel, logrus.ErrorLevel, logrus.WarnLevel, logrus.InfoLevel, logrus.DebugLevel, } } func getMessage(entry *logrus.Entry) (message string, err error) { message = message + fmt.Sprintf("%s", entry.Message) for k, v := range entry.Data { if !strings.HasPrefix(k, "err_") { message = message + fmt.Sprintf("\n%v:%v", k, v) } } if errCode, exist := entry.Data["err_code"]; exist { ns, _ := entry.Data["err_ns"] ctx, _ := entry.Data["err_ctx"] id, _ := entry.Data["err_id"] tSt, _ := entry.Data["err_stack"] st, _ := tSt.(string) st = strings.Replace(st, "\n", "\n\t\t", -1) buf := bytes.NewBuffer(nil) buf.WriteString(fmt.Sprintf("\tid:\n\t\t%s#%d:%s\n", ns, errCode, id)) buf.WriteString(fmt.Sprintf("\tcontext:\n\t\t%s\n", ctx)) buf.WriteString(fmt.Sprintf("\tstacktrace:\n\t\t%s", st)) message = message + fmt.Sprintf("%v", buf.String()) } return }