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  }