github.com/cranelv/ethereum_mpc@v0.0.0-20191031014521-23aeb1415092/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 errorKey = "LOG15_ERROR" 15 16 type Lvl int 17 18 const ( 19 LvlCrit Lvl = iota 20 LvlError 21 LvlWarn 22 LvlInfo 23 LvlDebug 24 LvlTrace 25 ) 26 27 // AlignedString returns a 5-character string containing the name of a Lvl. 28 func (l Lvl) AlignedString() string { 29 switch l { 30 case LvlTrace: 31 return "TRACE" 32 case LvlDebug: 33 return "DEBUG" 34 case LvlInfo: 35 return "INFO " 36 case LvlWarn: 37 return "WARN " 38 case LvlError: 39 return "ERROR" 40 case LvlCrit: 41 return "CRIT " 42 default: 43 panic("bad level") 44 } 45 } 46 47 // Strings returns the name of a Lvl. 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 // LvlFromString returns the appropriate Lvl from a string name. 68 // Useful for parsing command line args and configuration files. 69 func LvlFromString(lvlString string) (Lvl, error) { 70 switch lvlString { 71 case "trace", "trce": 72 return LvlTrace, nil 73 case "debug", "dbug": 74 return LvlDebug, nil 75 case "info": 76 return LvlInfo, nil 77 case "warn": 78 return LvlWarn, nil 79 case "error", "eror": 80 return LvlError, nil 81 case "crit": 82 return LvlCrit, nil 83 default: 84 return LvlDebug, fmt.Errorf("Unknown level: %v", lvlString) 85 } 86 } 87 88 // A Record is what a Logger asks its handler to write 89 type Record struct { 90 Time time.Time 91 Lvl Lvl 92 Msg string 93 Ctx []interface{} 94 Call stack.Call 95 Call1 stack.Call 96 Call2 stack.Call 97 KeyNames RecordKeyNames 98 } 99 100 // RecordKeyNames gets stored in a Record when the write function is executed. 101 type RecordKeyNames struct { 102 Time string 103 Msg string 104 Lvl string 105 } 106 107 // A Logger writes key/value pairs to a Handler 108 type Logger interface { 109 // New returns a new Logger that has this logger's context plus the given context 110 New(ctx ...interface{}) Logger 111 112 // GetHandler gets the handler associated with the logger. 113 GetHandler() Handler 114 115 // SetHandler updates the logger to write records to the specified handler. 116 SetHandler(h Handler) 117 118 // Log a message at the given level with context key/value pairs 119 Trace(msg string, ctx ...interface{}) 120 Debug(msg string, ctx ...interface{}) 121 Info(msg string, ctx ...interface{}) 122 Warn(msg string, ctx ...interface{}) 123 Error(msg string, ctx ...interface{}) 124 Crit(msg string, ctx ...interface{}) 125 } 126 127 type logger struct { 128 ctx []interface{} 129 h *swapHandler 130 } 131 132 func (l *logger) write(msg string, lvl Lvl, ctx []interface{}) { 133 l.h.Log(&Record{ 134 Time: time.Now(), 135 Lvl: lvl, 136 Msg: msg, 137 Ctx: newContext(l.ctx, ctx), 138 Call: stack.Caller(2), 139 Call1: stack.Caller(3), 140 Call2: stack.Caller(4), 141 KeyNames: RecordKeyNames{ 142 Time: timeKey, 143 Msg: msgKey, 144 Lvl: lvlKey, 145 }, 146 }) 147 } 148 149 func (l *logger) New(ctx ...interface{}) Logger { 150 child := &logger{newContext(l.ctx, ctx), new(swapHandler)} 151 child.SetHandler(l.h) 152 return child 153 } 154 155 func newContext(prefix []interface{}, suffix []interface{}) []interface{} { 156 normalizedSuffix := normalize(suffix) 157 newCtx := make([]interface{}, len(prefix)+len(normalizedSuffix)) 158 n := copy(newCtx, prefix) 159 copy(newCtx[n:], normalizedSuffix) 160 return newCtx 161 } 162 163 func (l *logger) Trace(msg string, ctx ...interface{}) { 164 l.write(msg, LvlTrace, ctx) 165 } 166 167 func (l *logger) Debug(msg string, ctx ...interface{}) { 168 l.write(msg, LvlDebug, ctx) 169 } 170 171 func (l *logger) Info(msg string, ctx ...interface{}) { 172 l.write(msg, LvlInfo, ctx) 173 } 174 175 func (l *logger) Warn(msg string, ctx ...interface{}) { 176 l.write(msg, LvlWarn, ctx) 177 } 178 179 func (l *logger) Error(msg string, ctx ...interface{}) { 180 l.write(msg, LvlError, ctx) 181 } 182 183 func (l *logger) Crit(msg string, ctx ...interface{}) { 184 l.write(msg, LvlCrit, ctx) 185 os.Exit(1) 186 } 187 188 func (l *logger) GetHandler() Handler { 189 return l.h.Get() 190 } 191 192 func (l *logger) SetHandler(h Handler) { 193 l.h.Swap(h) 194 } 195 196 func normalize(ctx []interface{}) []interface{} { 197 // if the caller passed a Ctx object, then expand it 198 if len(ctx) == 1 { 199 if ctxMap, ok := ctx[0].(Ctx); ok { 200 ctx = ctxMap.toArray() 201 } 202 } 203 204 // ctx needs to be even because it's a series of key/value pairs 205 // no one wants to check for errors on logging functions, 206 // so instead of erroring on bad input, we'll just make sure 207 // that things are the right length and users can fix bugs 208 // when they see the output looks wrong 209 if len(ctx)%2 != 0 { 210 ctx = append(ctx, nil, errorKey, "Normalized odd number of arguments by adding nil") 211 } 212 213 return ctx 214 } 215 216 // Lazy allows you to defer calculation of a logged value that is expensive 217 // to compute until it is certain that it must be evaluated with the given filters. 218 // 219 // Lazy may also be used in conjunction with a Logger's New() function 220 // to generate a child logger which always reports the current value of changing 221 // state. 222 // 223 // You may wrap any function which takes no arguments to Lazy. It may return any 224 // number of values of any type. 225 type Lazy struct { 226 Fn interface{} 227 } 228 229 // Ctx is a map of key/value pairs to pass as context to a log function 230 // Use this only if you really need greater safety around the arguments you pass 231 // to the logging functions. 232 type Ctx map[string]interface{} 233 234 func (c Ctx) toArray() []interface{} { 235 arr := make([]interface{}, len(c)*2) 236 237 i := 0 238 for k, v := range c { 239 arr[i] = k 240 arr[i+1] = v 241 i += 2 242 } 243 244 return arr 245 }