github.com/weedge/lib@v0.0.0-20230424045628-a36dcc1d90e4/log/encoder/self_encoder.go (about) 1 // Copyright (c) 2016 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 // from zap json_encoder.go change to encoder 22 package encoder 23 24 import ( 25 "encoding/base64" 26 "encoding/json" 27 "math" 28 "sync" 29 "time" 30 "unicode/utf8" 31 32 "github.com/weedge/lib/log/internal/bufferpool" 33 34 "go.uber.org/zap/buffer" 35 "go.uber.org/zap/zapcore" 36 ) 37 38 // For JSON-escaping; see selfEncoder.safeAddString below. 39 const _hex = "0123456789abcdef" 40 41 var _selfPool = sync.Pool{New: func() interface{} { 42 return &selfEncoder{} 43 }} 44 45 func getSelfEncoder() *selfEncoder { 46 return _selfPool.Get().(*selfEncoder) 47 } 48 49 func putSelfEncoder(enc *selfEncoder) { 50 if enc.reflectBuf != nil { 51 enc.reflectBuf.Free() 52 } 53 enc.EncoderConfig = nil 54 enc.buf = nil 55 enc.spaced = false 56 enc.openNamespaces = 0 57 enc.reflectBuf = nil 58 enc.reflectEnc = nil 59 _selfPool.Put(enc) 60 } 61 62 type selfEncoder struct { 63 *zapcore.EncoderConfig 64 buf *buffer.Buffer 65 spaced bool // include spaces after colons and commas 66 openNamespaces int 67 68 // for encoding generic values by reflection 69 reflectBuf *buffer.Buffer 70 reflectEnc *json.Encoder 71 } 72 73 // NewSelfEncoder creates a fast, low-allocation JSON encoder. The encoder 74 // appropriately escapes all field keys and values. 75 // 76 // Note that the encoder doesn't deduplicate keys, so it's possible to produce 77 // a message like 78 // {"foo":"bar","foo":"baz"} 79 // This is permitted by the JSON specification, but not encouraged. Many 80 // libraries will ignore duplicate key-value pairs (typically keeping the last 81 // pair) when unmarshaling, but users should attempt to avoid adding duplicate 82 // keys. 83 func NewSelfEncoder(cfg zapcore.EncoderConfig) zapcore.Encoder { 84 return newSelfEncoder(cfg, false) 85 } 86 87 func newSelfEncoder(cfg zapcore.EncoderConfig, spaced bool) *selfEncoder { 88 return &selfEncoder{ 89 EncoderConfig: &cfg, 90 buf: bufferpool.Get(), 91 spaced: spaced, 92 } 93 } 94 95 func (enc *selfEncoder) AddArray(key string, arr zapcore.ArrayMarshaler) error { 96 enc.addKey(key) 97 enc.buf.AppendByte('[') 98 err := enc.AppendArray(arr) 99 enc.buf.AppendByte(']') 100 return err 101 } 102 103 func (enc *selfEncoder) AddObject(key string, obj zapcore.ObjectMarshaler) error { 104 enc.addKey(key) 105 enc.buf.AppendByte('[') 106 err := enc.AppendObject(obj) 107 enc.buf.AppendByte(']') 108 return err 109 } 110 111 func (enc *selfEncoder) AddBinary(key string, val []byte) { 112 enc.AddString(key, base64.StdEncoding.EncodeToString(val)) 113 } 114 115 func (enc *selfEncoder) AddByteString(key string, val []byte) { 116 enc.addKey(key) 117 enc.buf.AppendByte('[') 118 enc.AppendByteString(val) 119 enc.buf.AppendByte(']') 120 } 121 122 func (enc *selfEncoder) AddBool(key string, val bool) { 123 enc.addKey(key) 124 enc.buf.AppendByte('[') 125 enc.AppendBool(val) 126 enc.buf.AppendByte(']') 127 } 128 129 func (enc *selfEncoder) AddComplex128(key string, val complex128) { 130 enc.addKey(key) 131 enc.buf.AppendByte('[') 132 enc.AppendComplex128(val) 133 enc.buf.AppendByte(']') 134 } 135 136 func (enc *selfEncoder) AddDuration(key string, val time.Duration) { 137 enc.addKey(key) 138 enc.buf.AppendByte('[') 139 enc.AppendDuration(val) 140 enc.buf.AppendByte(']') 141 } 142 143 func (enc *selfEncoder) AddFloat64(key string, val float64) { 144 enc.addKey(key) 145 enc.buf.AppendByte('[') 146 enc.AppendFloat64(val) 147 enc.buf.AppendByte(']') 148 } 149 150 func (enc *selfEncoder) AddInt64(key string, val int64) { 151 enc.addKey(key) 152 enc.buf.AppendByte('[') 153 enc.AppendInt64(val) 154 enc.buf.AppendByte(']') 155 } 156 157 func (enc *selfEncoder) resetReflectBuf() { 158 if enc.reflectBuf == nil { 159 enc.reflectBuf = bufferpool.Get() 160 enc.reflectEnc = json.NewEncoder(enc.reflectBuf) 161 // For consistency with our custom JSON encoder. 162 enc.reflectEnc.SetEscapeHTML(false) 163 } else { 164 enc.reflectBuf.Reset() 165 } 166 } 167 168 var nullLiteralBytes = []byte("null") 169 170 // Only invoke the standard JSON encoder if there is actually something to 171 // encode; otherwise write JSON null literal directly. 172 func (enc *selfEncoder) encodeReflected(obj interface{}) ([]byte, error) { 173 if obj == nil { 174 return nullLiteralBytes, nil 175 } 176 enc.resetReflectBuf() 177 if err := enc.reflectEnc.Encode(obj); err != nil { 178 return nil, err 179 } 180 enc.reflectBuf.TrimNewline() 181 return enc.reflectBuf.Bytes(), nil 182 } 183 184 func (enc *selfEncoder) AddReflected(key string, obj interface{}) error { 185 enc.addKey(key) 186 valueBytes, err := enc.encodeReflected(obj) 187 if err != nil { 188 return err 189 } 190 _, err = enc.buf.Write(valueBytes) 191 return err 192 } 193 194 func (enc *selfEncoder) OpenNamespace(key string) { 195 enc.buf.AppendByte('{') 196 enc.openNamespaces++ 197 } 198 199 func (enc *selfEncoder) AddString(key, val string) { 200 enc.addKey(key) 201 enc.buf.AppendByte('[') 202 enc.AppendString(val) 203 enc.buf.AppendByte(']') 204 } 205 206 func (enc *selfEncoder) AddTime(key string, val time.Time) { 207 enc.addKey(key) 208 enc.buf.AppendByte('[') 209 enc.AppendTime(val) 210 enc.buf.AppendByte(']') 211 } 212 213 func (enc *selfEncoder) AddUint64(key string, val uint64) { 214 enc.addKey(key) 215 enc.buf.AppendByte('[') 216 enc.AppendUint64(val) 217 enc.buf.AppendByte(']') 218 } 219 220 func (enc *selfEncoder) AppendArray(arr zapcore.ArrayMarshaler) error { 221 enc.addElementSeparator() 222 enc.buf.AppendByte('[') 223 err := arr.MarshalLogArray(enc) 224 enc.buf.AppendByte(']') 225 return err 226 } 227 228 func (enc *selfEncoder) AppendObject(obj zapcore.ObjectMarshaler) error { 229 enc.addElementSeparator() 230 enc.buf.AppendByte('{') 231 err := obj.MarshalLogObject(enc) 232 enc.buf.AppendByte('}') 233 return err 234 } 235 236 func (enc *selfEncoder) AppendBool(val bool) { 237 enc.addElementSeparator() 238 enc.buf.AppendBool(val) 239 } 240 241 func (enc *selfEncoder) AppendByteString(val []byte) { 242 enc.addElementSeparator() 243 enc.buf.AppendByte('"') 244 enc.safeAddByteString(val) 245 enc.buf.AppendByte('"') 246 } 247 248 func (enc *selfEncoder) AppendComplex128(val complex128) { 249 enc.addElementSeparator() 250 // Cast to a platform-independent, fixed-size type. 251 r, i := float64(real(val)), float64(imag(val)) 252 enc.buf.AppendByte('"') 253 // Because we're always in a quoted string, we can use strconv without 254 // special-casing NaN and +/-Inf. 255 enc.buf.AppendFloat(r, 64) 256 enc.buf.AppendByte('+') 257 enc.buf.AppendFloat(i, 64) 258 enc.buf.AppendByte('i') 259 enc.buf.AppendByte('"') 260 } 261 262 func (enc *selfEncoder) AppendDuration(val time.Duration) { 263 cur := enc.buf.Len() 264 enc.EncodeDuration(val, enc) 265 if cur == enc.buf.Len() { 266 // User-supplied EncodeDuration is a no-op. Fall back to nanoseconds to keep 267 // JSON valid. 268 enc.AppendInt64(int64(val)) 269 } 270 } 271 272 func (enc *selfEncoder) AppendInt64(val int64) { 273 enc.addElementSeparator() 274 enc.buf.AppendInt(val) 275 } 276 277 func (enc *selfEncoder) AppendReflected(val interface{}) error { 278 valueBytes, err := enc.encodeReflected(val) 279 if err != nil { 280 return err 281 } 282 enc.addElementSeparator() 283 _, err = enc.buf.Write(valueBytes) 284 return err 285 } 286 287 func (enc *selfEncoder) AppendString(val string) { 288 enc.addElementSeparator() 289 enc.safeAddString(val) 290 } 291 292 func (enc *selfEncoder) AppendTime(val time.Time) { 293 cur := enc.buf.Len() 294 enc.EncodeTime(val, enc) 295 if cur == enc.buf.Len() { 296 // User-supplied EncodeTime is a no-op. Fall back to nanos since epoch to keep 297 // output JSON valid. 298 enc.AppendInt64(val.UnixNano()) 299 } 300 } 301 302 func (enc *selfEncoder) AppendUint64(val uint64) { 303 enc.addElementSeparator() 304 enc.buf.AppendUint(val) 305 } 306 307 func (enc *selfEncoder) AddComplex64(k string, v complex64) { enc.AddComplex128(k, complex128(v)) } 308 func (enc *selfEncoder) AddFloat32(k string, v float32) { enc.AddFloat64(k, float64(v)) } 309 func (enc *selfEncoder) AddInt(k string, v int) { enc.AddInt64(k, int64(v)) } 310 func (enc *selfEncoder) AddInt32(k string, v int32) { enc.AddInt64(k, int64(v)) } 311 func (enc *selfEncoder) AddInt16(k string, v int16) { enc.AddInt64(k, int64(v)) } 312 func (enc *selfEncoder) AddInt8(k string, v int8) { enc.AddInt64(k, int64(v)) } 313 func (enc *selfEncoder) AddUint(k string, v uint) { enc.AddUint64(k, uint64(v)) } 314 func (enc *selfEncoder) AddUint32(k string, v uint32) { enc.AddUint64(k, uint64(v)) } 315 func (enc *selfEncoder) AddUint16(k string, v uint16) { enc.AddUint64(k, uint64(v)) } 316 func (enc *selfEncoder) AddUint8(k string, v uint8) { enc.AddUint64(k, uint64(v)) } 317 func (enc *selfEncoder) AddUintptr(k string, v uintptr) { enc.AddUint64(k, uint64(v)) } 318 func (enc *selfEncoder) AppendComplex64(v complex64) { enc.AppendComplex128(complex128(v)) } 319 func (enc *selfEncoder) AppendFloat64(v float64) { enc.appendFloat(v, 64) } 320 func (enc *selfEncoder) AppendFloat32(v float32) { enc.appendFloat(float64(v), 32) } 321 func (enc *selfEncoder) AppendInt(v int) { enc.AppendInt64(int64(v)) } 322 func (enc *selfEncoder) AppendInt32(v int32) { enc.AppendInt64(int64(v)) } 323 func (enc *selfEncoder) AppendInt16(v int16) { enc.AppendInt64(int64(v)) } 324 func (enc *selfEncoder) AppendInt8(v int8) { enc.AppendInt64(int64(v)) } 325 func (enc *selfEncoder) AppendUint(v uint) { enc.AppendUint64(uint64(v)) } 326 func (enc *selfEncoder) AppendUint32(v uint32) { enc.AppendUint64(uint64(v)) } 327 func (enc *selfEncoder) AppendUint16(v uint16) { enc.AppendUint64(uint64(v)) } 328 func (enc *selfEncoder) AppendUint8(v uint8) { enc.AppendUint64(uint64(v)) } 329 func (enc *selfEncoder) AppendUintptr(v uintptr) { enc.AppendUint64(uint64(v)) } 330 331 func (enc *selfEncoder) Clone() zapcore.Encoder { 332 clone := enc.clone() 333 clone.buf.Write(enc.buf.Bytes()) 334 return clone 335 } 336 337 func (enc *selfEncoder) clone() *selfEncoder { 338 clone := getSelfEncoder() 339 clone.EncoderConfig = enc.EncoderConfig 340 clone.spaced = enc.spaced 341 clone.openNamespaces = enc.openNamespaces 342 clone.buf = bufferpool.Get() 343 return clone 344 } 345 346 func (enc *selfEncoder) EncodeEntry(ent zapcore.Entry, fields []zapcore.Field) (*buffer.Buffer, error) { 347 final := enc.clone() 348 349 if final.LevelKey != "" { 350 final.buf.AppendByte('[') 351 //final.addKey(final.LevelKey) 352 cur := final.buf.Len() 353 final.EncodeLevel(ent.Level, final) 354 if cur == final.buf.Len() { 355 // User-supplied EncodeLevel was a no-op. Fall back to strings to keep 356 // output JSON valid. 357 final.AppendString(ent.Level.String()) 358 } 359 final.buf.AppendByte(']') 360 } 361 if final.TimeKey != "" { 362 final.buf.AppendByte(' ') 363 final.AppendTime(ent.Time) 364 } 365 if ent.LoggerName != "" && final.NameKey != "" { 366 final.buf.AppendByte(' ') 367 cur := final.buf.Len() 368 nameEncoder := final.EncodeName 369 370 // if no name encoder provided, fall back to FullNameEncoder for backwards 371 // compatibility 372 if nameEncoder == nil { 373 nameEncoder = zapcore.FullNameEncoder 374 } 375 376 nameEncoder(ent.LoggerName, final) 377 if cur == final.buf.Len() { 378 // User-supplied EncodeName was a no-op. Fall back to strings to 379 // keep output JSON valid. 380 final.AppendString(ent.LoggerName) 381 } 382 } 383 if ent.Caller.Defined && final.CallerKey != "" { 384 final.buf.AppendByte(' ') 385 final.buf.AppendByte('[') 386 cur := final.buf.Len() 387 final.EncodeCaller(ent.Caller, final) 388 final.buf.AppendByte(']') 389 if cur == final.buf.Len() { 390 // User-supplied EncodeCaller was a no-op. Fall back to strings to 391 // keep output JSON valid. 392 final.AppendString(ent.Caller.String()) 393 } 394 } else { 395 final.buf.AppendString(" [access]") 396 } 397 if final.MessageKey != "" { 398 final.AppendString(ent.Message) 399 } 400 if enc.buf.Len() > 0 { 401 final.addElementSeparator() 402 final.buf.Write(enc.buf.Bytes()) 403 } 404 addFields(final, fields) 405 final.closeOpenNamespaces() 406 if ent.Stack != "" && final.StacktraceKey != "" { 407 final.AddString(final.StacktraceKey, ent.Stack) 408 } 409 if final.LineEnding != "" { 410 final.buf.AppendString(final.LineEnding) 411 } else { 412 final.buf.AppendString(zapcore.DefaultLineEnding) 413 } 414 415 ret := final.buf 416 putSelfEncoder(final) 417 return ret, nil 418 } 419 420 func (enc *selfEncoder) truncate() { 421 enc.buf.Reset() 422 } 423 424 func (enc *selfEncoder) closeOpenNamespaces() { 425 for i := 0; i < enc.openNamespaces; i++ { 426 enc.buf.AppendByte('}') 427 } 428 } 429 430 func (enc *selfEncoder) addKey(key string) { 431 enc.addElementSeparator() 432 enc.safeAddString(key) 433 } 434 435 func (enc *selfEncoder) addElementSeparator() { 436 last := enc.buf.Len() - 1 437 if last < 0 { 438 return 439 } 440 switch enc.buf.Bytes()[last] { 441 case '{', '[', ':', ',', ' ': 442 return 443 default: 444 enc.buf.AppendByte(' ') 445 } 446 } 447 448 func (enc *selfEncoder) appendFloat(val float64, bitSize int) { 449 enc.addElementSeparator() 450 switch { 451 case math.IsNaN(val): 452 enc.buf.AppendString(`"NaN"`) 453 case math.IsInf(val, 1): 454 enc.buf.AppendString(`"+Inf"`) 455 case math.IsInf(val, -1): 456 enc.buf.AppendString(`"-Inf"`) 457 default: 458 enc.buf.AppendFloat(val, bitSize) 459 } 460 } 461 462 // safeAddString JSON-escapes a string and appends it to the internal buffer. 463 // Unlike the standard library's encoder, it doesn't attempt to protect the 464 // user from browser vulnerabilities or JSONP-related problems. 465 func (enc *selfEncoder) safeAddString(s string) { 466 for i := 0; i < len(s); { 467 if enc.tryAddRuneSelf(s[i]) { 468 i++ 469 continue 470 } 471 r, size := utf8.DecodeRuneInString(s[i:]) 472 if enc.tryAddRuneError(r, size) { 473 i++ 474 continue 475 } 476 enc.buf.AppendString(s[i : i+size]) 477 i += size 478 } 479 } 480 481 // safeAddByteString is no-alloc equivalent of safeAddString(string(s)) for s []byte. 482 func (enc *selfEncoder) safeAddByteString(s []byte) { 483 for i := 0; i < len(s); { 484 if enc.tryAddRuneSelf(s[i]) { 485 i++ 486 continue 487 } 488 r, size := utf8.DecodeRune(s[i:]) 489 if enc.tryAddRuneError(r, size) { 490 i++ 491 continue 492 } 493 enc.buf.Write(s[i : i+size]) 494 i += size 495 } 496 } 497 498 // tryAddRuneSelf appends b if it is valid UTF-8 character represented in a single byte. 499 func (enc *selfEncoder) tryAddRuneSelf(b byte) bool { 500 if b >= utf8.RuneSelf { 501 return false 502 } 503 if 0x20 <= b && b != '\\' && b != '"' { 504 enc.buf.AppendByte(b) 505 return true 506 } 507 switch b { 508 case '\\', '"': 509 // enc.buf.AppendByte('\\') 510 enc.buf.AppendByte(b) 511 case '\n': 512 enc.buf.AppendByte('\\') 513 enc.buf.AppendByte('n') 514 case '\r': 515 enc.buf.AppendByte('\\') 516 enc.buf.AppendByte('r') 517 case '\t': 518 enc.buf.AppendByte('\\') 519 enc.buf.AppendByte('t') 520 default: 521 // Encode bytes < 0x20, except for the escape sequences above. 522 enc.buf.AppendString(`\u00`) 523 enc.buf.AppendByte(_hex[b>>4]) 524 enc.buf.AppendByte(_hex[b&0xF]) 525 } 526 return true 527 } 528 529 func (enc *selfEncoder) tryAddRuneError(r rune, size int) bool { 530 if r == utf8.RuneError && size == 1 { 531 enc.buf.AppendString(`\ufffd`) 532 return true 533 } 534 return false 535 } 536 537 func addFields(enc zapcore.ObjectEncoder, fields []zapcore.Field) { 538 for i := range fields { 539 fields[i].AddTo(enc) 540 } 541 }