github.com/neatlab/neatio@v1.7.3-0.20220425043230-d903e92fcc75/chain/log/logger.go (about) 1 package log 2 3 import ( 4 "fmt" 5 "os" 6 "time" 7 8 "github.com/go-stack/stack" 9 ) 10 11 const timeKey = "t" 12 const lvlKey = "lvl" 13 const msgKey = "msg" 14 const ctxKey = "ctx" 15 const errorKey = "LOG15_ERROR" 16 const skipLevel = 2 17 18 type Lvl int 19 20 const ( 21 LvlCrit Lvl = iota 22 LvlError 23 LvlWarn 24 LvlInfo 25 LvlDebug 26 LvlTrace 27 ) 28 29 func (l Lvl) AlignedString() string { 30 switch l { 31 case LvlTrace: 32 return "TRACE" 33 case LvlDebug: 34 return "DEBUG" 35 case LvlInfo: 36 return "INFO " 37 case LvlWarn: 38 return "WARN " 39 case LvlError: 40 return "ERROR" 41 case LvlCrit: 42 return "CRIT " 43 default: 44 panic("bad level") 45 } 46 } 47 48 func (l Lvl) String() string { 49 switch l { 50 case LvlTrace: 51 return "trce" 52 case LvlDebug: 53 return "dbug" 54 case LvlInfo: 55 return "info" 56 case LvlWarn: 57 return "warn" 58 case LvlError: 59 return "eror" 60 case LvlCrit: 61 return "crit" 62 default: 63 panic("bad level") 64 } 65 } 66 67 func LvlFromString(lvlString string) (Lvl, error) { 68 switch lvlString { 69 case "trace", "trce": 70 return LvlTrace, nil 71 case "debug", "dbug": 72 return LvlDebug, nil 73 case "info": 74 return LvlInfo, nil 75 case "warn": 76 return LvlWarn, nil 77 case "error", "eror": 78 return LvlError, nil 79 case "crit": 80 return LvlCrit, nil 81 default: 82 return LvlDebug, fmt.Errorf("Unknown level: %v", lvlString) 83 } 84 } 85 86 type Record struct { 87 Time time.Time 88 Lvl Lvl 89 Msg string 90 Ctx []interface{} 91 Call stack.Call 92 KeyNames RecordKeyNames 93 } 94 95 type RecordKeyNames struct { 96 Time string 97 Msg string 98 Lvl string 99 Ctx string 100 } 101 102 type Logger interface { 103 New(ctx ...interface{}) Logger 104 105 GetHandler() Handler 106 107 SetHandler(h Handler) 108 109 Trace(msg string, ctx ...interface{}) 110 Debug(msg string, ctx ...interface{}) 111 Info(msg string, ctx ...interface{}) 112 Warn(msg string, ctx ...interface{}) 113 Error(msg string, ctx ...interface{}) 114 Crit(msg string, ctx ...interface{}) 115 116 Debugf(format string, args ...interface{}) 117 Infof(format string, args ...interface{}) 118 Warnf(format string, args ...interface{}) 119 Errorf(format string, args ...interface{}) 120 Critf(msg string, ctx ...interface{}) 121 } 122 123 type logger struct { 124 ctx []interface{} 125 h *swapHandler 126 } 127 128 func (l *logger) write(msg string, lvl Lvl, ctx []interface{}, skip int) { 129 l.h.Log(&Record{ 130 Time: time.Now(), 131 Lvl: lvl, 132 Msg: msg, 133 Ctx: newContext(l.ctx, ctx), 134 Call: stack.Caller(skip), 135 KeyNames: RecordKeyNames{ 136 Time: timeKey, 137 Msg: msgKey, 138 Lvl: lvlKey, 139 Ctx: ctxKey, 140 }, 141 }) 142 } 143 144 func (l *logger) New(ctx ...interface{}) Logger { 145 side := &logger{newContext(l.ctx, ctx), new(swapHandler)} 146 side.SetHandler(l.h) 147 return side 148 } 149 150 func newContext(prefix []interface{}, suffix []interface{}) []interface{} { 151 normalizedSuffix := normalize(suffix) 152 newCtx := make([]interface{}, len(prefix)+len(normalizedSuffix)) 153 n := copy(newCtx, prefix) 154 copy(newCtx[n:], normalizedSuffix) 155 return newCtx 156 } 157 158 func (l *logger) Trace(msg string, ctx ...interface{}) { 159 l.write(msg, LvlTrace, ctx, skipLevel) 160 } 161 162 func (l *logger) Debug(msg string, ctx ...interface{}) { 163 l.write(msg, LvlDebug, ctx, skipLevel) 164 } 165 166 func (l *logger) Info(msg string, ctx ...interface{}) { 167 l.write(msg, LvlInfo, ctx, skipLevel) 168 } 169 170 func (l *logger) Warn(msg string, ctx ...interface{}) { 171 l.write(msg, LvlWarn, ctx, skipLevel) 172 } 173 174 func (l *logger) Error(msg string, ctx ...interface{}) { 175 l.write(msg, LvlError, ctx, skipLevel) 176 } 177 178 func (l *logger) Crit(msg string, ctx ...interface{}) { 179 l.write(msg, LvlCrit, ctx, skipLevel) 180 os.Exit(1) 181 } 182 183 func (l *logger) Debugf(format string, args ...interface{}) { 184 l.write(fmt.Sprintf(format, args...), LvlDebug, nil, skipLevel) 185 } 186 187 func (l *logger) Infof(format string, args ...interface{}) { 188 l.write(fmt.Sprintf(format, args...), LvlInfo, nil, skipLevel) 189 } 190 191 func (l *logger) Warnf(format string, args ...interface{}) { 192 l.write(fmt.Sprintf(format, args...), LvlWarn, nil, skipLevel) 193 } 194 195 func (l *logger) Errorf(format string, args ...interface{}) { 196 l.write(fmt.Sprintf(format, args...), LvlError, nil, skipLevel) 197 } 198 199 func (l *logger) Critf(format string, args ...interface{}) { 200 l.write(fmt.Sprintf(format, args...), LvlCrit, nil, skipLevel) 201 } 202 203 func (l *logger) GetHandler() Handler { 204 return l.h.Get() 205 } 206 207 func (l *logger) SetHandler(h Handler) { 208 l.h.Swap(h) 209 } 210 211 func normalize(ctx []interface{}) []interface{} { 212 213 if len(ctx) == 1 { 214 if ctxMap, ok := ctx[0].(Ctx); ok { 215 ctx = ctxMap.toArray() 216 } 217 } 218 219 if len(ctx)%2 != 0 { 220 ctx = append(ctx, nil, errorKey, "Normalized odd number of arguments by adding nil") 221 } 222 223 return ctx 224 } 225 226 type Lazy struct { 227 Fn interface{} 228 } 229 230 type Ctx map[string]interface{} 231 232 func (c Ctx) toArray() []interface{} { 233 arr := make([]interface{}, len(c)*2) 234 235 i := 0 236 for k, v := range c { 237 arr[i] = k 238 arr[i+1] = v 239 i += 2 240 } 241 242 return arr 243 }