github.com/shoshinnikita/budget-manager@v0.7.1-0.20220131195411-8c46ff1c6778/internal/logger/dev_format.go (about) 1 package logger 2 3 import ( 4 "bytes" 5 "fmt" 6 "reflect" 7 "sort" 8 9 "github.com/fatih/color" 10 "github.com/sirupsen/logrus" 11 12 "github.com/ShoshinNikita/budget-manager/internal/pkg/caller" 13 ) 14 15 // {year}-{month}-{day} {hour}:{minute}:{second} 16 const timeLayout = "2006-01-02 15:04:05" 17 18 // devFormatter is used as a log formatter in the developer mode 19 type devFormatter struct{} 20 21 var _ logrus.Formatter = devFormatter{} 22 23 // Format formats '*logrus.Entry' 24 func (devFormatter) Format(entry *logrus.Entry) ([]byte, error) { 25 buff := &bytes.Buffer{} 26 if entry.Buffer != nil { 27 buff = entry.Buffer 28 } 29 30 // Time 31 buff.WriteString(color.HiGreenString(entry.Time.Format(timeLayout))) 32 buff.WriteByte(' ') 33 34 // Level 35 buff.Write(logLevelToString(entry.Level)) 36 buff.WriteByte(' ') 37 38 // Message 39 buff.WriteString(entry.Message) 40 buff.WriteByte(' ') 41 42 // Fields 43 44 // Add the caller to fields 45 if entry.HasCaller() { 46 entry.Data["func"] = caller.FormatCaller(entry.Caller.Func) 47 } 48 49 // Sort field keys 50 keys := make([]string, 0, len(entry.Data)) 51 for k := range entry.Data { 52 keys = append(keys, k) 53 } 54 sort.Strings(keys) 55 56 // Write 57 coloredPrintf := logLevelToPrintfFunction(entry.Level) 58 for i, k := range keys { 59 v := entry.Data[k] 60 if isEmptyString(v) { 61 v = `""` 62 } 63 64 buff.WriteString(coloredPrintf(k)) 65 buff.WriteByte('=') 66 fmt.Fprint(buff, v) 67 if i+1 != len(keys) { 68 buff.WriteByte(' ') 69 } 70 } 71 72 buff.WriteByte('\n') 73 return buff.Bytes(), nil 74 } 75 76 // Ready to print colored log levels 77 // 78 //nolint:gochecknoglobals 79 var ( 80 coloredTraceLvl = []byte(color.HiMagentaString("[TRC]")) 81 coloredDebugLvl = []byte(color.HiMagentaString("[DBG]")) 82 coloredInfoLvl = []byte(color.CyanString("[INF]")) 83 coloredWarnLvl = []byte(color.YellowString("[WRN]")) 84 coloredErrLvl = []byte(color.RedString("[ERR]")) 85 coloredPanicLvl = []byte(color.New(color.BgRed).Sprint("[PNC]")) 86 coloredFatalLvl = []byte(color.New(color.BgRed).Sprint("[FAT]")) 87 ) 88 89 // logLevelToString converts logrus log level to colored string 90 // It returns bytes for greater convenience 91 func logLevelToString(lvl logrus.Level) []byte { 92 switch lvl { 93 case logrus.TraceLevel: 94 return coloredTraceLvl 95 case logrus.DebugLevel: 96 return coloredDebugLvl 97 case logrus.InfoLevel: 98 return coloredInfoLvl 99 case logrus.WarnLevel: 100 return coloredWarnLvl 101 case logrus.ErrorLevel: 102 return coloredErrLvl 103 case logrus.PanicLevel: 104 return coloredPanicLvl 105 case logrus.FatalLevel: 106 return coloredFatalLvl 107 default: 108 return []byte("[...]") 109 } 110 } 111 112 // logLevelToPrintfFunction returns a function to print colored output according to 113 // passed logrus log level 114 func logLevelToPrintfFunction(lvl logrus.Level) func(format string, a ...interface{}) string { 115 switch lvl { 116 case logrus.TraceLevel: 117 return color.YellowString 118 case logrus.DebugLevel: 119 return color.HiMagentaString 120 case logrus.InfoLevel: 121 return color.CyanString 122 case logrus.WarnLevel: 123 return color.YellowString 124 case logrus.ErrorLevel: 125 return color.RedString 126 case logrus.FatalLevel: 127 return color.New(color.BgRed).Sprintf 128 case logrus.PanicLevel: 129 return color.New(color.BgRed).Sprintf 130 default: 131 return color.New().Sprintf 132 } 133 } 134 135 func isEmptyString(i interface{}) bool { 136 v := reflect.ValueOf(i) 137 return v.Kind() == reflect.String && v.String() == "" 138 }