gitee.com/hongliu9527/go-tools@v0.0.8/logger/formatter.go (about) 1 /* 2 * @Author: hongliu 3 * @Date: 2022-04-26 09:39:39 4 * @LastEditors: hongliu 5 * @LastEditTime: 2022-04-26 09:42:51 6 * @FilePath: \go-tools\logger\formatter.go 7 * @Description: 8 * 9 * Copyright (c) 2022 by 洪流, All Rights Reserved. 10 */ 11 12 package logger 13 14 import ( 15 "bytes" 16 "fmt" 17 "sort" 18 "strings" 19 "time" 20 21 "github.com/sirupsen/logrus" 22 ) 23 24 // 对应终端字体颜色 25 const ( 26 colorRed = 31 27 colorGreen = 32 28 colorYellow = 33 29 colorBlue = 36 30 ) 31 32 // getColorByLevel 定义不同日志等级颜色 33 func getColorByLevel(level logrus.Level) int { 34 switch level { 35 case logrus.DebugLevel: 36 return colorGreen 37 case logrus.WarnLevel: 38 return colorYellow 39 case logrus.ErrorLevel, logrus.FatalLevel, logrus.PanicLevel: 40 return colorRed 41 default: 42 return colorBlue 43 } 44 } 45 46 // Formatter 自定义格式控制选项 47 type Formatter struct { 48 FieldsOrder []string // default: fields sorted alphabetically 49 TimestampFormat string // default: time.StampMilli = "Jan _2 15:04:05.000" 50 HideKeys bool // show [fieldValue] instead of [fieldKey:fieldValue] 51 NoColors bool // disable colors 52 NoFieldsColors bool // color only level, default is level + fields 53 ShowFullLevel bool // true to show full level [WARNING] instead [WARN] 54 TrimMessages bool // true to trim whitespace on messages 55 } 56 57 // Format 自定义格式函数 58 func (f *Formatter) Format(entry *logrus.Entry) ([]byte, error) { 59 b := &bytes.Buffer{} 60 61 // 设置时间字符串格式 62 timestampFormat := f.TimestampFormat 63 if timestampFormat == "" { 64 timestampFormat = time.RFC3339 65 } 66 67 // 按照日志等级填充ASC-II颜色特殊符号 68 levelColor := getColorByLevel(entry.Level) 69 level := strings.ToUpper(entry.Level.String()) 70 if !f.NoColors { 71 fmt.Fprintf(b, "\x1b[%dm", levelColor) 72 } 73 74 // 填充日志等级,使用"[]"包裹 75 b.WriteString(" [") 76 if f.ShowFullLevel { 77 b.WriteString(level) 78 } else { 79 b.WriteString(level[:4]) 80 } 81 b.WriteString("] ") 82 83 if !f.NoColors && f.NoFieldsColors { 84 b.WriteString("\x1b[0m") 85 } 86 87 // 填充时间格式字符串,使用"[]"包裹 88 b.WriteString("[") 89 b.WriteString(entry.Time.Format(timestampFormat)) 90 b.WriteString("] ") 91 92 // 填充消息字段,用于结构化日志 93 if f.FieldsOrder == nil { 94 f.writeFields(b, entry) 95 } else { 96 f.writeOrderedFields(b, entry) 97 } 98 99 // 填充日志内容 100 if f.TrimMessages { 101 b.WriteString(strings.TrimSpace(entry.Message)) 102 } else { 103 b.WriteString(entry.Message) 104 } 105 b.WriteByte('\n') 106 107 if !f.NoColors && !f.NoFieldsColors { 108 b.WriteString("\x1b[0m") 109 } 110 111 return b.Bytes(), nil 112 } 113 114 // writeFields 写入每个日志字段 115 func (f *Formatter) writeFields(b *bytes.Buffer, entry *logrus.Entry) { 116 if len(entry.Data) != 0 { 117 fields := make([]string, 0, len(entry.Data)) 118 for field := range entry.Data { 119 fields = append(fields, field) 120 } 121 122 sort.Strings(fields) 123 124 for _, field := range fields { 125 f.writeField(b, entry, field) 126 } 127 } 128 } 129 130 // writeOrderedFields 按顺序写入日志字段 131 func (f *Formatter) writeOrderedFields(b *bytes.Buffer, entry *logrus.Entry) { 132 length := len(entry.Data) 133 foundFieldsMap := map[string]bool{} 134 for _, field := range f.FieldsOrder { 135 if _, ok := entry.Data[field]; ok { 136 foundFieldsMap[field] = true 137 length-- 138 f.writeField(b, entry, field) 139 } 140 } 141 142 if length > 0 { 143 notFoundFields := make([]string, 0, length) 144 for field := range entry.Data { 145 if foundFieldsMap[field] == false { 146 notFoundFields = append(notFoundFields, field) 147 } 148 } 149 150 sort.Strings(notFoundFields) 151 152 for _, field := range notFoundFields { 153 f.writeField(b, entry, field) 154 } 155 } 156 } 157 158 func (f *Formatter) writeField(b *bytes.Buffer, entry *logrus.Entry, field string) { 159 if f.HideKeys { 160 fmt.Fprintf(b, "[%v] ", entry.Data[field]) 161 } else { 162 fmt.Fprintf(b, "[%s:%v] ", field, entry.Data[field]) 163 } 164 }