1package zerolog 2 3import ( 4 "io/ioutil" 5 "math" 6 "net" 7 "time" 8) 9 10// Context configures a new sub-logger with contextual fields. 11type Context struct { 12 l Logger 13} 14 15// Logger returns the logger with the context previously set. 16func (c Context) Logger() Logger { 17 return c.l 18} 19 20// Fields is a helper function to use a map to set fields using type assertion. 21func (c Context) Fields(fields map[string]interface{}) Context { 22 c.l.context = appendFields(c.l.context, fields) 23 return c 24} 25 26// Dict adds the field key with the dict to the logger context. 27func (c Context) Dict(key string, dict *Event) Context { 28 dict.buf = enc.AppendEndMarker(dict.buf) 29 c.l.context = append(enc.AppendKey(c.l.context, key), dict.buf...) 30 putEvent(dict) 31 return c 32} 33 34// Array adds the field key with an array to the event context. 35// Use zerolog.Arr() to create the array or pass a type that 36// implement the LogArrayMarshaler interface. 37func (c Context) Array(key string, arr LogArrayMarshaler) Context { 38 c.l.context = enc.AppendKey(c.l.context, key) 39 if arr, ok := arr.(*Array); ok { 40 c.l.context = arr.write(c.l.context) 41 return c 42 } 43 var a *Array 44 if aa, ok := arr.(*Array); ok { 45 a = aa 46 } else { 47 a = Arr() 48 arr.MarshalZerologArray(a) 49 } 50 c.l.context = a.write(c.l.context) 51 return c 52} 53 54// Object marshals an object that implement the LogObjectMarshaler interface. 55func (c Context) Object(key string, obj LogObjectMarshaler) Context { 56 e := newEvent(levelWriterAdapter{ioutil.Discard}, 0) 57 e.Object(key, obj) 58 c.l.context = enc.AppendObjectData(c.l.context, e.buf) 59 putEvent(e) 60 return c 61} 62 63// EmbedObject marshals and Embeds an object that implement the LogObjectMarshaler interface. 64func (c Context) EmbedObject(obj LogObjectMarshaler) Context { 65 e := newEvent(levelWriterAdapter{ioutil.Discard}, 0) 66 e.EmbedObject(obj) 67 c.l.context = enc.AppendObjectData(c.l.context, e.buf) 68 putEvent(e) 69 return c 70} 71 72// Str adds the field key with val as a string to the logger context. 73func (c Context) Str(key, val string) Context { 74 c.l.context = enc.AppendString(enc.AppendKey(c.l.context, key), val) 75 return c 76} 77 78// Strs adds the field key with val as a string to the logger context. 79func (c Context) Strs(key string, vals []string) Context { 80 c.l.context = enc.AppendStrings(enc.AppendKey(c.l.context, key), vals) 81 return c 82} 83 84// Bytes adds the field key with val as a []byte to the logger context. 85func (c Context) Bytes(key string, val []byte) Context { 86 c.l.context = enc.AppendBytes(enc.AppendKey(c.l.context, key), val) 87 return c 88} 89 90// Hex adds the field key with val as a hex string to the logger context. 91func (c Context) Hex(key string, val []byte) Context { 92 c.l.context = enc.AppendHex(enc.AppendKey(c.l.context, key), val) 93 return c 94} 95 96// RawJSON adds already encoded JSON to context. 97// 98// No sanity check is performed on b; it must not contain carriage returns and 99// be valid JSON. 100func (c Context) RawJSON(key string, b []byte) Context { 101 c.l.context = appendJSON(enc.AppendKey(c.l.context, key), b) 102 return c 103} 104 105// AnErr adds the field key with serialized err to the logger context. 106func (c Context) AnErr(key string, err error) Context { 107 switch m := ErrorMarshalFunc(err).(type) { 108 case nil: 109 return c 110 case LogObjectMarshaler: 111 return c.Object(key, m) 112 case error: 113 if m == nil || isNilValue(m) { 114 return c 115 } else { 116 return c.Str(key, m.Error()) 117 } 118 case string: 119 return c.Str(key, m) 120 default: 121 return c.Interface(key, m) 122 } 123} 124 125// Errs adds the field key with errs as an array of serialized errors to the 126// logger context. 127func (c Context) Errs(key string, errs []error) Context { 128 arr := Arr() 129 for _, err := range errs { 130 switch m := ErrorMarshalFunc(err).(type) { 131 case LogObjectMarshaler: 132 arr = arr.Object(m) 133 case error: 134 if m == nil || isNilValue(m) { 135 arr = arr.Interface(nil) 136 } else { 137 arr = arr.Str(m.Error()) 138 } 139 case string: 140 arr = arr.Str(m) 141 default: 142 arr = arr.Interface(m) 143 } 144 } 145 146 return c.Array(key, arr) 147} 148 149// Err adds the field "error" with serialized err to the logger context. 150func (c Context) Err(err error) Context { 151 return c.AnErr(ErrorFieldName, err) 152} 153 154// Bool adds the field key with val as a bool to the logger context. 155func (c Context) Bool(key string, b bool) Context { 156 c.l.context = enc.AppendBool(enc.AppendKey(c.l.context, key), b) 157 return c 158} 159 160// Bools adds the field key with val as a []bool to the logger context. 161func (c Context) Bools(key string, b []bool) Context { 162 c.l.context = enc.AppendBools(enc.AppendKey(c.l.context, key), b) 163 return c 164} 165 166// Int adds the field key with i as a int to the logger context. 167func (c Context) Int(key string, i int) Context { 168 c.l.context = enc.AppendInt(enc.AppendKey(c.l.context, key), i) 169 return c 170} 171 172// Ints adds the field key with i as a []int to the logger context. 173func (c Context) Ints(key string, i []int) Context { 174 c.l.context = enc.AppendInts(enc.AppendKey(c.l.context, key), i) 175 return c 176} 177 178// Int8 adds the field key with i as a int8 to the logger context. 179func (c Context) Int8(key string, i int8) Context { 180 c.l.context = enc.AppendInt8(enc.AppendKey(c.l.context, key), i) 181 return c 182} 183 184// Ints8 adds the field key with i as a []int8 to the logger context. 185func (c Context) Ints8(key string, i []int8) Context { 186 c.l.context = enc.AppendInts8(enc.AppendKey(c.l.context, key), i) 187 return c 188} 189 190// Int16 adds the field key with i as a int16 to the logger context. 191func (c Context) Int16(key string, i int16) Context { 192 c.l.context = enc.AppendInt16(enc.AppendKey(c.l.context, key), i) 193 return c 194} 195 196// Ints16 adds the field key with i as a []int16 to the logger context. 197func (c Context) Ints16(key string, i []int16) Context { 198 c.l.context = enc.AppendInts16(enc.AppendKey(c.l.context, key), i) 199 return c 200} 201 202// Int32 adds the field key with i as a int32 to the logger context. 203func (c Context) Int32(key string, i int32) Context { 204 c.l.context = enc.AppendInt32(enc.AppendKey(c.l.context, key), i) 205 return c 206} 207 208// Ints32 adds the field key with i as a []int32 to the logger context. 209func (c Context) Ints32(key string, i []int32) Context { 210 c.l.context = enc.AppendInts32(enc.AppendKey(c.l.context, key), i) 211 return c 212} 213 214// Int64 adds the field key with i as a int64 to the logger context. 215func (c Context) Int64(key string, i int64) Context { 216 c.l.context = enc.AppendInt64(enc.AppendKey(c.l.context, key), i) 217 return c 218} 219 220// Ints64 adds the field key with i as a []int64 to the logger context. 221func (c Context) Ints64(key string, i []int64) Context { 222 c.l.context = enc.AppendInts64(enc.AppendKey(c.l.context, key), i) 223 return c 224} 225 226// Uint adds the field key with i as a uint to the logger context. 227func (c Context) Uint(key string, i uint) Context { 228 c.l.context = enc.AppendUint(enc.AppendKey(c.l.context, key), i) 229 return c 230} 231 232// Uints adds the field key with i as a []uint to the logger context. 233func (c Context) Uints(key string, i []uint) Context { 234 c.l.context = enc.AppendUints(enc.AppendKey(c.l.context, key), i) 235 return c 236} 237 238// Uint8 adds the field key with i as a uint8 to the logger context. 239func (c Context) Uint8(key string, i uint8) Context { 240 c.l.context = enc.AppendUint8(enc.AppendKey(c.l.context, key), i) 241 return c 242} 243 244// Uints8 adds the field key with i as a []uint8 to the logger context. 245func (c Context) Uints8(key string, i []uint8) Context { 246 c.l.context = enc.AppendUints8(enc.AppendKey(c.l.context, key), i) 247 return c 248} 249 250// Uint16 adds the field key with i as a uint16 to the logger context. 251func (c Context) Uint16(key string, i uint16) Context { 252 c.l.context = enc.AppendUint16(enc.AppendKey(c.l.context, key), i) 253 return c 254} 255 256// Uints16 adds the field key with i as a []uint16 to the logger context. 257func (c Context) Uints16(key string, i []uint16) Context { 258 c.l.context = enc.AppendUints16(enc.AppendKey(c.l.context, key), i) 259 return c 260} 261 262// Uint32 adds the field key with i as a uint32 to the logger context. 263func (c Context) Uint32(key string, i uint32) Context { 264 c.l.context = enc.AppendUint32(enc.AppendKey(c.l.context, key), i) 265 return c 266} 267 268// Uints32 adds the field key with i as a []uint32 to the logger context. 269func (c Context) Uints32(key string, i []uint32) Context { 270 c.l.context = enc.AppendUints32(enc.AppendKey(c.l.context, key), i) 271 return c 272} 273 274// Uint64 adds the field key with i as a uint64 to the logger context. 275func (c Context) Uint64(key string, i uint64) Context { 276 c.l.context = enc.AppendUint64(enc.AppendKey(c.l.context, key), i) 277 return c 278} 279 280// Uints64 adds the field key with i as a []uint64 to the logger context. 281func (c Context) Uints64(key string, i []uint64) Context { 282 c.l.context = enc.AppendUints64(enc.AppendKey(c.l.context, key), i) 283 return c 284} 285 286// Float32 adds the field key with f as a float32 to the logger context. 287func (c Context) Float32(key string, f float32) Context { 288 c.l.context = enc.AppendFloat32(enc.AppendKey(c.l.context, key), f) 289 return c 290} 291 292// Floats32 adds the field key with f as a []float32 to the logger context. 293func (c Context) Floats32(key string, f []float32) Context { 294 c.l.context = enc.AppendFloats32(enc.AppendKey(c.l.context, key), f) 295 return c 296} 297 298// Float64 adds the field key with f as a float64 to the logger context. 299func (c Context) Float64(key string, f float64) Context { 300 c.l.context = enc.AppendFloat64(enc.AppendKey(c.l.context, key), f) 301 return c 302} 303 304// Floats64 adds the field key with f as a []float64 to the logger context. 305func (c Context) Floats64(key string, f []float64) Context { 306 c.l.context = enc.AppendFloats64(enc.AppendKey(c.l.context, key), f) 307 return c 308} 309 310type timestampHook struct{} 311 312func (ts timestampHook) Run(e *Event, level Level, msg string) { 313 e.Timestamp() 314} 315 316var th = timestampHook{} 317 318// Timestamp adds the current local time as UNIX timestamp to the logger context with the "time" key. 319// To customize the key name, change zerolog.TimestampFieldName. 320// 321// NOTE: It won't dedupe the "time" key if the *Context has one already. 322func (c Context) Timestamp() Context { 323 c.l = c.l.Hook(th) 324 return c 325} 326 327// Time adds the field key with t formated as string using zerolog.TimeFieldFormat. 328func (c Context) Time(key string, t time.Time) Context { 329 c.l.context = enc.AppendTime(enc.AppendKey(c.l.context, key), t, TimeFieldFormat) 330 return c 331} 332 333// Times adds the field key with t formated as string using zerolog.TimeFieldFormat. 334func (c Context) Times(key string, t []time.Time) Context { 335 c.l.context = enc.AppendTimes(enc.AppendKey(c.l.context, key), t, TimeFieldFormat) 336 return c 337} 338 339// Dur adds the fields key with d divided by unit and stored as a float. 340func (c Context) Dur(key string, d time.Duration) Context { 341 c.l.context = enc.AppendDuration(enc.AppendKey(c.l.context, key), d, DurationFieldUnit, DurationFieldInteger) 342 return c 343} 344 345// Durs adds the fields key with d divided by unit and stored as a float. 346func (c Context) Durs(key string, d []time.Duration) Context { 347 c.l.context = enc.AppendDurations(enc.AppendKey(c.l.context, key), d, DurationFieldUnit, DurationFieldInteger) 348 return c 349} 350 351// Interface adds the field key with obj marshaled using reflection. 352func (c Context) Interface(key string, i interface{}) Context { 353 c.l.context = enc.AppendInterface(enc.AppendKey(c.l.context, key), i) 354 return c 355} 356 357type callerHook struct { 358 callerSkipFrameCount int 359} 360 361func newCallerHook(skipFrameCount int) callerHook { 362 return callerHook{callerSkipFrameCount: skipFrameCount} 363} 364 365func (ch callerHook) Run(e *Event, level Level, msg string) { 366 switch ch.callerSkipFrameCount { 367 case useGlobalSkipFrameCount: 368 // Extra frames to skip (added by hook infra). 369 e.caller(CallerSkipFrameCount + contextCallerSkipFrameCount) 370 default: 371 // Extra frames to skip (added by hook infra). 372 e.caller(ch.callerSkipFrameCount + contextCallerSkipFrameCount) 373 } 374} 375 376// useGlobalSkipFrameCount acts as a flag to informat callerHook.Run 377// to use the global CallerSkipFrameCount. 378const useGlobalSkipFrameCount = math.MinInt32 379 380// ch is the default caller hook using the global CallerSkipFrameCount. 381var ch = newCallerHook(useGlobalSkipFrameCount) 382 383// Caller adds the file:line of the caller with the zerolog.CallerFieldName key. 384func (c Context) Caller() Context { 385 c.l = c.l.Hook(ch) 386 return c 387} 388 389// CallerWithSkipFrameCount adds the file:line of the caller with the zerolog.CallerFieldName key. 390// The specified skipFrameCount int will override the global CallerSkipFrameCount for this context's respective logger. 391// If set to -1 the global CallerSkipFrameCount will be used. 392func (c Context) CallerWithSkipFrameCount(skipFrameCount int) Context { 393 c.l = c.l.Hook(newCallerHook(skipFrameCount)) 394 return c 395} 396 397type stackTraceHook struct{} 398 399func (sh stackTraceHook) Run(e *Event, level Level, msg string) { 400 e.Stack() 401} 402 403var sh = stackTraceHook{} 404 405// Stack enables stack trace printing for the error passed to Err(). 406func (c Context) Stack() Context { 407 c.l = c.l.Hook(sh) 408 return c 409} 410 411// IPAddr adds IPv4 or IPv6 Address to the context 412func (c Context) IPAddr(key string, ip net.IP) Context { 413 c.l.context = enc.AppendIPAddr(enc.AppendKey(c.l.context, key), ip) 414 return c 415} 416 417// IPPrefix adds IPv4 or IPv6 Prefix (address and mask) to the context 418func (c Context) IPPrefix(key string, pfx net.IPNet) Context { 419 c.l.context = enc.AppendIPPrefix(enc.AppendKey(c.l.context, key), pfx) 420 return c 421} 422 423// MACAddr adds MAC address to the context 424func (c Context) MACAddr(key string, ha net.HardwareAddr) Context { 425 c.l.context = enc.AppendMACAddr(enc.AppendKey(c.l.context, key), ha) 426 return c 427} 428