@@ -0,0 +1,135 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
"videoweb/app/appg"
|
||||
"videoweb/pub/common/log/zapcorex"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
)
|
||||
|
||||
var (
|
||||
zapLogger *zap.Logger
|
||||
zapLoggerS *zap.SugaredLogger
|
||||
ZapLog *zap.Logger
|
||||
ZapLogS *zap.SugaredLogger
|
||||
Debug = zapLogger.Debug
|
||||
Info = zapLogger.Info
|
||||
Warn = zapLogger.Warn
|
||||
Error = zapLogger.Error
|
||||
Panic = zapLogger.Panic
|
||||
Fatal = zapLogger.Fatal
|
||||
Debugf = zapLoggerS.Debugf
|
||||
Infof = zapLoggerS.Infof
|
||||
Warnf = zapLoggerS.Warnf
|
||||
Errorf = zapLoggerS.Errorf
|
||||
Fatalf = zapLoggerS.Fatalf
|
||||
Debugw = zapLoggerS.Debugw
|
||||
Infow = zapLoggerS.Infow
|
||||
Warnw = zapLoggerS.Warnw
|
||||
Errorw = zapLoggerS.Errorw
|
||||
Fatalw = zapLoggerS.Fatalw
|
||||
TestLog = func(msg string, fields ...Field) {
|
||||
if appg.Conf.RunMod == "prod" {
|
||||
return
|
||||
}
|
||||
zapLogger.Info(msg, fields...)
|
||||
}
|
||||
)
|
||||
|
||||
func newEncoderConfig() zapcore.EncoderConfig {
|
||||
return zapcore.EncoderConfig{
|
||||
// Keys can be anything except the empty string.
|
||||
TimeKey: "T",
|
||||
LevelKey: "L",
|
||||
NameKey: "N",
|
||||
CallerKey: "C",
|
||||
MessageKey: "M",
|
||||
StacktraceKey: "S",
|
||||
FunctionKey: "F",
|
||||
LineEnding: zapcore.DefaultLineEnding,
|
||||
EncodeLevel: zapcore.CapitalColorLevelEncoder,
|
||||
EncodeTime: timeEncoder,
|
||||
EncodeDuration: zapcore.StringDurationEncoder,
|
||||
EncodeCaller: zapcore.ShortCallerEncoder,
|
||||
ConsoleSeparator: " ",
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
core := zapcore.NewCore(
|
||||
zapcorex.NewConsoleEncoder(newEncoderConfig()),
|
||||
zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout)),
|
||||
zap.DebugLevel,
|
||||
)
|
||||
zapLogger = zap.New(core, zap.AddCaller())
|
||||
zapLoggerS = zapLogger.Sugar()
|
||||
ZapLog = zapLogger
|
||||
ZapLogS = zapLoggerS
|
||||
Debug = zapLogger.Debug
|
||||
Info = zapLogger.Info
|
||||
Warn = zapLogger.Warn
|
||||
Error = zapLogger.Error
|
||||
Panic = zapLogger.Panic
|
||||
Fatal = zapLogger.Fatal
|
||||
Debugf = zapLoggerS.Debugf
|
||||
Infof = zapLoggerS.Infof
|
||||
Warnf = zapLoggerS.Warnf
|
||||
Errorf = zapLoggerS.Errorf
|
||||
Fatalf = zapLoggerS.Fatalf
|
||||
Debugw = zapLoggerS.Debugw
|
||||
Infow = zapLoggerS.Infow
|
||||
Warnw = zapLoggerS.Warnw
|
||||
Errorw = zapLoggerS.Errorw
|
||||
Fatalw = zapLoggerS.Fatalw
|
||||
}
|
||||
|
||||
func timeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
|
||||
enc.AppendString(t.In(time.Local).Format("2006-01-02 15:04:05"))
|
||||
}
|
||||
|
||||
type Field = zap.Field
|
||||
|
||||
func Any(key string, value interface{}) Field {
|
||||
return zap.Any(key, value)
|
||||
}
|
||||
|
||||
func E(err error) Field {
|
||||
return Any("err", err)
|
||||
}
|
||||
|
||||
type contextKey int64
|
||||
|
||||
var (
|
||||
loggerContextKey contextKey
|
||||
)
|
||||
|
||||
func ContextWithLogger(ctx context.Context, l *zap.SugaredLogger) context.Context {
|
||||
return context.WithValue(ctx, loggerContextKey, l)
|
||||
}
|
||||
|
||||
func LoggerFromContext(ctx context.Context) *zap.SugaredLogger {
|
||||
v := ctx.Value(loggerContextKey)
|
||||
if v == nil {
|
||||
return ZapLogS
|
||||
}
|
||||
return v.(*zap.SugaredLogger)
|
||||
}
|
||||
|
||||
type Logger struct{}
|
||||
|
||||
// Info logs routine messages about cron's operation.
|
||||
func (s *Logger) Info(msg string, keysAndValues ...interface{}) {
|
||||
_ = log.Default().Output(2, msg+" "+fmt.Sprint(keysAndValues...))
|
||||
}
|
||||
|
||||
// Error logs an error condition.
|
||||
func (s *Logger) Error(err error, msg string, keysAndValues ...interface{}) {
|
||||
line := fmt.Sprintf("%s %v %s", msg, err, fmt.Sprint(keysAndValues...))
|
||||
_ = log.Default().Output(2, line)
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright (c) 2016 Uber Technologies, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
// Package bufferpool houses zap's shared internal buffer pool. Third-party
|
||||
// packages can recreate the same functionality with buffers.NewPool.
|
||||
package bufferpool
|
||||
|
||||
import "go.uber.org/zap/buffer"
|
||||
|
||||
var (
|
||||
_pool = buffer.NewPool()
|
||||
// Get retrieves a buffer from the pool, creating one if necessary.
|
||||
Get = _pool.Get
|
||||
)
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright (c) 2016 Uber Technologies, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
// Package color adds coloring functionality for TTY output.
|
||||
package zapcorex
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Foreground colors.
|
||||
const (
|
||||
Black Color = iota + 30
|
||||
Red
|
||||
Green
|
||||
Yellow
|
||||
Blue
|
||||
Magenta
|
||||
Cyan
|
||||
White
|
||||
)
|
||||
|
||||
// Color represents a text color.
|
||||
type Color uint8
|
||||
|
||||
// Add adds the coloring to the given string.
|
||||
func (c Color) Add(s string) string {
|
||||
return fmt.Sprintf("\x1b[%dm%s\x1b[0m", uint8(c), s)
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
package zapcorex
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"videoweb/pub/common/log/zapcorex/bufferpool"
|
||||
|
||||
"go.uber.org/zap/buffer"
|
||||
"go.uber.org/zap/zapcore"
|
||||
)
|
||||
|
||||
var _sliceEncoderPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &sliceArrayEncoder{elems: make([]interface{}, 0, 2)}
|
||||
},
|
||||
}
|
||||
|
||||
func getSliceEncoder() *sliceArrayEncoder {
|
||||
return _sliceEncoderPool.Get().(*sliceArrayEncoder)
|
||||
}
|
||||
|
||||
func putSliceEncoder(e *sliceArrayEncoder) {
|
||||
e.elems = e.elems[:0]
|
||||
_sliceEncoderPool.Put(e)
|
||||
}
|
||||
|
||||
type consoleEncoder struct {
|
||||
*jsonEncoder
|
||||
}
|
||||
|
||||
// NewConsoleEncoder creates an encoder whose output is designed for human -
|
||||
// rather than machine - consumption. It serializes the core log entry data
|
||||
// (message, level, timestamp, etc.) in a plain-text format and leaves the
|
||||
// structured context as JSON.
|
||||
//
|
||||
// Note that although the console encoder doesn't use the keys specified in the
|
||||
// encoder configuration, it will omit any element whose key is set to the empty
|
||||
// string.
|
||||
func NewConsoleEncoder(cfg zapcore.EncoderConfig) zapcore.Encoder {
|
||||
if cfg.ConsoleSeparator == "" {
|
||||
// Use a default delimiter of '\t' for backwards compatibility
|
||||
cfg.ConsoleSeparator = "\t"
|
||||
}
|
||||
return consoleEncoder{newJSONEncoder(cfg, true)}
|
||||
}
|
||||
|
||||
func (c consoleEncoder) Clone() zapcore.Encoder {
|
||||
return consoleEncoder{c.jsonEncoder.Clone().(*jsonEncoder)}
|
||||
}
|
||||
|
||||
func (c consoleEncoder) EncodeEntry(ent zapcore.Entry, fields []zapcore.Field) (*buffer.Buffer, error) {
|
||||
line := bufferpool.Get()
|
||||
|
||||
// We don't want the entry's metadata to be quoted and escaped (if it's
|
||||
// encoded as strings), which means that we can't use the JSON encoder. The
|
||||
// simplest option is to use the memory encoder and fmt.Fprint.
|
||||
//
|
||||
// If this ever becomes a performance bottleneck, we can implement
|
||||
// ArrayEncoder for our plain-text format.
|
||||
arr := getSliceEncoder()
|
||||
if c.TimeKey != "" && c.EncodeTime != nil {
|
||||
c.EncodeTime(ent.Time, arr)
|
||||
}
|
||||
if c.LevelKey != "" && c.EncodeLevel != nil {
|
||||
c.EncodeLevel(ent.Level, arr)
|
||||
}
|
||||
if ent.LoggerName != "" && c.NameKey != "" {
|
||||
nameEncoder := c.EncodeName
|
||||
|
||||
if nameEncoder == nil {
|
||||
// Fall back to FullNameEncoder for backward compatibility.
|
||||
nameEncoder = zapcore.FullNameEncoder
|
||||
}
|
||||
|
||||
nameEncoder(ent.LoggerName, arr)
|
||||
}
|
||||
|
||||
for i := range arr.elems {
|
||||
if i > 0 {
|
||||
line.AppendString(c.ConsoleSeparator)
|
||||
}
|
||||
fmt.Fprint(line, arr.elems[i])
|
||||
}
|
||||
|
||||
putSliceEncoder(arr)
|
||||
|
||||
// Add the message itself.
|
||||
if c.MessageKey != "" {
|
||||
c.addSeparatorIfNecessary(line)
|
||||
line.AppendString(ent.Message)
|
||||
}
|
||||
|
||||
// Add any structured context.
|
||||
c.writeContext(line, fields)
|
||||
|
||||
if ent.Caller.Defined {
|
||||
if c.FunctionKey != "" {
|
||||
c.addSeparatorIfNecessary(line)
|
||||
if idx := strings.LastIndex(ent.Caller.Function, "/"); idx > 0 {
|
||||
line.AppendString(White.Add(ent.Caller.Function[idx+1:]))
|
||||
} else {
|
||||
line.AppendString(White.Add(ent.Caller.Function))
|
||||
}
|
||||
}
|
||||
|
||||
line.AppendString(c.ConsoleSeparator)
|
||||
if c.CallerKey != "" && c.EncodeCaller != nil {
|
||||
line.AppendString(White.Add(ent.Caller.TrimmedPath()))
|
||||
}
|
||||
}
|
||||
|
||||
// If there's no stacktrace key, honor that; this allows users to force
|
||||
// single-line output.
|
||||
if ent.Stack != "" && c.StacktraceKey != "" {
|
||||
line.AppendByte('\n')
|
||||
line.AppendString(ent.Stack)
|
||||
}
|
||||
|
||||
line.AppendString(c.LineEnding)
|
||||
return line, nil
|
||||
}
|
||||
|
||||
func (c consoleEncoder) writeContext(line *buffer.Buffer, extra []zapcore.Field) {
|
||||
context := c.jsonEncoder.Clone().(*jsonEncoder)
|
||||
defer func() {
|
||||
// putJSONEncoder assumes the buffer is still used, but we write out the buffer so
|
||||
// we can free it.
|
||||
context.buf.Free()
|
||||
putJSONEncoder(context)
|
||||
}()
|
||||
|
||||
addFields(context, extra)
|
||||
context.closeOpenNamespaces()
|
||||
if context.buf.Len() == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
c.addSeparatorIfNecessary(line)
|
||||
line.AppendByte('{')
|
||||
line.Write(context.buf.Bytes())
|
||||
line.AppendByte('}')
|
||||
}
|
||||
|
||||
func (c consoleEncoder) addSeparatorIfNecessary(line *buffer.Buffer) {
|
||||
if line.Len() > 0 {
|
||||
line.AppendString(c.ConsoleSeparator)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package zapcorex
|
||||
|
||||
import "go.uber.org/zap/zapcore"
|
||||
|
||||
func addFields(enc zapcore.ObjectEncoder, fields []zapcore.Field) {
|
||||
for i := range fields {
|
||||
fields[i].AddTo(enc)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,518 @@
|
||||
package zapcorex
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"math"
|
||||
"sync"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"videoweb/pub/common/log/zapcorex/bufferpool"
|
||||
|
||||
"go.uber.org/zap/buffer"
|
||||
"go.uber.org/zap/zapcore"
|
||||
)
|
||||
|
||||
// For JSON-escaping; see jsonEncoder.safeAddString below.
|
||||
const _hex = "0123456789abcdef"
|
||||
|
||||
var _jsonPool = sync.Pool{New: func() interface{} {
|
||||
return &jsonEncoder{}
|
||||
}}
|
||||
|
||||
func getJSONEncoder() *jsonEncoder {
|
||||
return _jsonPool.Get().(*jsonEncoder)
|
||||
}
|
||||
|
||||
func putJSONEncoder(enc *jsonEncoder) {
|
||||
if enc.reflectBuf != nil {
|
||||
enc.reflectBuf.Free()
|
||||
}
|
||||
enc.EncoderConfig = nil
|
||||
enc.buf = nil
|
||||
enc.spaced = false
|
||||
enc.openNamespaces = 0
|
||||
enc.reflectBuf = nil
|
||||
enc.reflectEnc = nil
|
||||
_jsonPool.Put(enc)
|
||||
}
|
||||
|
||||
type jsonEncoder struct {
|
||||
*zapcore.EncoderConfig
|
||||
buf *buffer.Buffer
|
||||
spaced bool // include spaces after colons and commas
|
||||
openNamespaces int
|
||||
|
||||
// for encoding generic values by reflection
|
||||
reflectBuf *buffer.Buffer
|
||||
reflectEnc *json.Encoder
|
||||
}
|
||||
|
||||
// NewJSONEncoder creates a fast, low-allocation JSON encoder. The encoder
|
||||
// appropriately escapes all field keys and values.
|
||||
//
|
||||
// Note that the encoder doesn't deduplicate keys, so it's possible to produce
|
||||
// a message like
|
||||
//
|
||||
// {"foo":"bar","foo":"baz"}
|
||||
//
|
||||
// This is permitted by the JSON specification, but not encouraged. Many
|
||||
// libraries will ignore duplicate key-value pairs (typically keeping the last
|
||||
// pair) when unmarshaling, but users should attempt to avoid adding duplicate
|
||||
// keys.
|
||||
func NewJSONEncoder(cfg zapcore.EncoderConfig) zapcore.Encoder {
|
||||
return newJSONEncoder(cfg, false)
|
||||
}
|
||||
|
||||
func newJSONEncoder(cfg zapcore.EncoderConfig, spaced bool) *jsonEncoder {
|
||||
return &jsonEncoder{
|
||||
EncoderConfig: &cfg,
|
||||
buf: bufferpool.Get(),
|
||||
spaced: spaced,
|
||||
}
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) AddArray(key string, arr zapcore.ArrayMarshaler) error {
|
||||
enc.addKey(key)
|
||||
return enc.AppendArray(arr)
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) AddObject(key string, obj zapcore.ObjectMarshaler) error {
|
||||
enc.addKey(key)
|
||||
return enc.AppendObject(obj)
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) AddBinary(key string, val []byte) {
|
||||
enc.AddString(key, base64.StdEncoding.EncodeToString(val))
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) AddByteString(key string, val []byte) {
|
||||
enc.addKey(key)
|
||||
enc.AppendByteString(val)
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) AddBool(key string, val bool) {
|
||||
enc.addKey(key)
|
||||
enc.AppendBool(val)
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) AddComplex128(key string, val complex128) {
|
||||
enc.addKey(key)
|
||||
enc.AppendComplex128(val)
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) AddDuration(key string, val time.Duration) {
|
||||
enc.addKey(key)
|
||||
enc.AppendDuration(val)
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) AddFloat64(key string, val float64) {
|
||||
enc.addKey(key)
|
||||
enc.AppendFloat64(val)
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) AddInt64(key string, val int64) {
|
||||
enc.addKey(key)
|
||||
enc.AppendInt64(val)
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) resetReflectBuf() {
|
||||
if enc.reflectBuf == nil {
|
||||
enc.reflectBuf = bufferpool.Get()
|
||||
enc.reflectEnc = json.NewEncoder(enc.reflectBuf)
|
||||
|
||||
// For consistency with our custom JSON encoder.
|
||||
enc.reflectEnc.SetEscapeHTML(false)
|
||||
} else {
|
||||
enc.reflectBuf.Reset()
|
||||
}
|
||||
}
|
||||
|
||||
var nullLiteralBytes = []byte("null")
|
||||
|
||||
// Only invoke the standard JSON encoder if there is actually something to
|
||||
// encode; otherwise write JSON null literal directly.
|
||||
func (enc *jsonEncoder) encodeReflected(obj interface{}) ([]byte, error) {
|
||||
if obj == nil {
|
||||
return nullLiteralBytes, nil
|
||||
}
|
||||
enc.resetReflectBuf()
|
||||
if err := enc.reflectEnc.Encode(obj); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
enc.reflectBuf.TrimNewline()
|
||||
return enc.reflectBuf.Bytes(), nil
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) AddReflected(key string, obj interface{}) error {
|
||||
valueBytes, err := enc.encodeReflected(obj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
enc.addKey(key)
|
||||
_, err = enc.buf.Write(valueBytes)
|
||||
return err
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) OpenNamespace(key string) {
|
||||
enc.addKey(key)
|
||||
enc.buf.AppendByte('{')
|
||||
enc.openNamespaces++
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) AddString(key, val string) {
|
||||
enc.addKey(key)
|
||||
enc.AppendString(val)
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) AddTime(key string, val time.Time) {
|
||||
enc.addKey(key)
|
||||
enc.AppendTime(val)
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) AddUint64(key string, val uint64) {
|
||||
enc.addKey(key)
|
||||
enc.AppendUint64(val)
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) AppendArray(arr zapcore.ArrayMarshaler) error {
|
||||
enc.addElementSeparator()
|
||||
enc.buf.AppendByte('[')
|
||||
err := arr.MarshalLogArray(enc)
|
||||
enc.buf.AppendByte(']')
|
||||
return err
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) AppendObject(obj zapcore.ObjectMarshaler) error {
|
||||
enc.addElementSeparator()
|
||||
enc.buf.AppendByte('{')
|
||||
err := obj.MarshalLogObject(enc)
|
||||
enc.buf.AppendByte('}')
|
||||
return err
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) AppendBool(val bool) {
|
||||
enc.addElementSeparator()
|
||||
enc.buf.AppendBool(val)
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) AppendByteString(val []byte) {
|
||||
enc.addElementSeparator()
|
||||
enc.buf.AppendByte('"')
|
||||
enc.safeAddByteString(val)
|
||||
enc.buf.AppendByte('"')
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) AppendComplex128(val complex128) {
|
||||
enc.addElementSeparator()
|
||||
// Cast to a platform-independent, fixed-size type.
|
||||
r, i := float64(real(val)), float64(imag(val))
|
||||
enc.buf.AppendByte('"')
|
||||
// Because we're always in a quoted string, we can use strconv without
|
||||
// special-casing NaN and +/-Inf.
|
||||
enc.buf.AppendFloat(r, 64)
|
||||
enc.buf.AppendByte('+')
|
||||
enc.buf.AppendFloat(i, 64)
|
||||
enc.buf.AppendByte('i')
|
||||
enc.buf.AppendByte('"')
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) AppendDuration(val time.Duration) {
|
||||
cur := enc.buf.Len()
|
||||
if e := enc.EncodeDuration; e != nil {
|
||||
e(val, enc)
|
||||
}
|
||||
if cur == enc.buf.Len() {
|
||||
// User-supplied EncodeDuration is a no-op. Fall back to nanoseconds to keep
|
||||
// JSON valid.
|
||||
enc.AppendInt64(int64(val))
|
||||
}
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) AppendInt64(val int64) {
|
||||
enc.addElementSeparator()
|
||||
enc.buf.AppendInt(val)
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) AppendReflected(val interface{}) error {
|
||||
valueBytes, err := enc.encodeReflected(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
enc.addElementSeparator()
|
||||
_, err = enc.buf.Write(valueBytes)
|
||||
return err
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) AppendString(val string) {
|
||||
enc.addElementSeparator()
|
||||
enc.buf.AppendByte('"')
|
||||
enc.safeAddString(val)
|
||||
enc.buf.AppendByte('"')
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) AppendTimeLayout(time time.Time, layout string) {
|
||||
enc.addElementSeparator()
|
||||
enc.buf.AppendByte('"')
|
||||
enc.buf.AppendTime(time, layout)
|
||||
enc.buf.AppendByte('"')
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) AppendTime(val time.Time) {
|
||||
cur := enc.buf.Len()
|
||||
if e := enc.EncodeTime; e != nil {
|
||||
e(val, enc)
|
||||
}
|
||||
if cur == enc.buf.Len() {
|
||||
// User-supplied EncodeTime is a no-op. Fall back to nanos since epoch to keep
|
||||
// output JSON valid.
|
||||
enc.AppendInt64(val.UnixNano())
|
||||
}
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) AppendUint64(val uint64) {
|
||||
enc.addElementSeparator()
|
||||
enc.buf.AppendUint(val)
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) AddComplex64(k string, v complex64) { enc.AddComplex128(k, complex128(v)) }
|
||||
func (enc *jsonEncoder) AddFloat32(k string, v float32) { enc.AddFloat64(k, float64(v)) }
|
||||
func (enc *jsonEncoder) AddInt(k string, v int) { enc.AddInt64(k, int64(v)) }
|
||||
func (enc *jsonEncoder) AddInt32(k string, v int32) { enc.AddInt64(k, int64(v)) }
|
||||
func (enc *jsonEncoder) AddInt16(k string, v int16) { enc.AddInt64(k, int64(v)) }
|
||||
func (enc *jsonEncoder) AddInt8(k string, v int8) { enc.AddInt64(k, int64(v)) }
|
||||
func (enc *jsonEncoder) AddUint(k string, v uint) { enc.AddUint64(k, uint64(v)) }
|
||||
func (enc *jsonEncoder) AddUint32(k string, v uint32) { enc.AddUint64(k, uint64(v)) }
|
||||
func (enc *jsonEncoder) AddUint16(k string, v uint16) { enc.AddUint64(k, uint64(v)) }
|
||||
func (enc *jsonEncoder) AddUint8(k string, v uint8) { enc.AddUint64(k, uint64(v)) }
|
||||
func (enc *jsonEncoder) AddUintptr(k string, v uintptr) { enc.AddUint64(k, uint64(v)) }
|
||||
func (enc *jsonEncoder) AppendComplex64(v complex64) { enc.AppendComplex128(complex128(v)) }
|
||||
func (enc *jsonEncoder) AppendFloat64(v float64) { enc.appendFloat(v, 64) }
|
||||
func (enc *jsonEncoder) AppendFloat32(v float32) { enc.appendFloat(float64(v), 32) }
|
||||
func (enc *jsonEncoder) AppendInt(v int) { enc.AppendInt64(int64(v)) }
|
||||
func (enc *jsonEncoder) AppendInt32(v int32) { enc.AppendInt64(int64(v)) }
|
||||
func (enc *jsonEncoder) AppendInt16(v int16) { enc.AppendInt64(int64(v)) }
|
||||
func (enc *jsonEncoder) AppendInt8(v int8) { enc.AppendInt64(int64(v)) }
|
||||
func (enc *jsonEncoder) AppendUint(v uint) { enc.AppendUint64(uint64(v)) }
|
||||
func (enc *jsonEncoder) AppendUint32(v uint32) { enc.AppendUint64(uint64(v)) }
|
||||
func (enc *jsonEncoder) AppendUint16(v uint16) { enc.AppendUint64(uint64(v)) }
|
||||
func (enc *jsonEncoder) AppendUint8(v uint8) { enc.AppendUint64(uint64(v)) }
|
||||
func (enc *jsonEncoder) AppendUintptr(v uintptr) { enc.AppendUint64(uint64(v)) }
|
||||
|
||||
func (enc *jsonEncoder) Clone() zapcore.Encoder {
|
||||
clone := enc.clone()
|
||||
clone.buf.Write(enc.buf.Bytes())
|
||||
return clone
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) clone() *jsonEncoder {
|
||||
clone := getJSONEncoder()
|
||||
clone.EncoderConfig = enc.EncoderConfig
|
||||
clone.spaced = enc.spaced
|
||||
clone.openNamespaces = enc.openNamespaces
|
||||
clone.buf = bufferpool.Get()
|
||||
return clone
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) EncodeEntry(ent zapcore.Entry, fields []zapcore.Field) (*buffer.Buffer, error) {
|
||||
final := enc.clone()
|
||||
final.buf.AppendByte('{')
|
||||
|
||||
if final.LevelKey != "" {
|
||||
final.addKey(final.LevelKey)
|
||||
cur := final.buf.Len()
|
||||
final.EncodeLevel(ent.Level, final)
|
||||
if cur == final.buf.Len() {
|
||||
// User-supplied EncodeLevel was a no-op. Fall back to strings to keep
|
||||
// output JSON valid.
|
||||
final.AppendString(ent.Level.String())
|
||||
}
|
||||
}
|
||||
if final.TimeKey != "" {
|
||||
final.AddTime(final.TimeKey, ent.Time)
|
||||
}
|
||||
if ent.LoggerName != "" && final.NameKey != "" {
|
||||
final.addKey(final.NameKey)
|
||||
cur := final.buf.Len()
|
||||
nameEncoder := final.EncodeName
|
||||
|
||||
// if no name encoder provided, fall back to FullNameEncoder for backwards
|
||||
// compatibility
|
||||
if nameEncoder == nil {
|
||||
nameEncoder = zapcore.FullNameEncoder
|
||||
}
|
||||
|
||||
nameEncoder(ent.LoggerName, final)
|
||||
if cur == final.buf.Len() {
|
||||
// User-supplied EncodeName was a no-op. Fall back to strings to
|
||||
// keep output JSON valid.
|
||||
final.AppendString(ent.LoggerName)
|
||||
}
|
||||
}
|
||||
if ent.Caller.Defined {
|
||||
if final.CallerKey != "" {
|
||||
final.addKey(final.CallerKey)
|
||||
cur := final.buf.Len()
|
||||
final.EncodeCaller(ent.Caller, final)
|
||||
if cur == final.buf.Len() {
|
||||
// User-supplied EncodeCaller was a no-op. Fall back to strings to
|
||||
// keep output JSON valid.
|
||||
final.AppendString(ent.Caller.String())
|
||||
}
|
||||
}
|
||||
if final.FunctionKey != "" {
|
||||
final.addKey(final.FunctionKey)
|
||||
final.AppendString(ent.Caller.Function)
|
||||
}
|
||||
}
|
||||
if final.MessageKey != "" {
|
||||
final.addKey(enc.MessageKey)
|
||||
final.AppendString(ent.Message)
|
||||
}
|
||||
if enc.buf.Len() > 0 {
|
||||
final.addElementSeparator()
|
||||
final.buf.Write(enc.buf.Bytes())
|
||||
}
|
||||
addFields(final, fields)
|
||||
final.closeOpenNamespaces()
|
||||
if ent.Stack != "" && final.StacktraceKey != "" {
|
||||
final.AddString(final.StacktraceKey, ent.Stack)
|
||||
}
|
||||
final.buf.AppendByte('}')
|
||||
if final.LineEnding != "" {
|
||||
final.buf.AppendString(final.LineEnding)
|
||||
} else {
|
||||
final.buf.AppendString(zapcore.DefaultLineEnding)
|
||||
}
|
||||
|
||||
ret := final.buf
|
||||
putJSONEncoder(final)
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) truncate() {
|
||||
enc.buf.Reset()
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) closeOpenNamespaces() {
|
||||
for i := 0; i < enc.openNamespaces; i++ {
|
||||
enc.buf.AppendByte('}')
|
||||
}
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) addKey(key string) {
|
||||
enc.addElementSeparator()
|
||||
enc.buf.AppendByte('"')
|
||||
enc.safeAddString(key)
|
||||
enc.buf.AppendByte('"')
|
||||
enc.buf.AppendByte(':')
|
||||
if enc.spaced {
|
||||
enc.buf.AppendByte(' ')
|
||||
}
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) addElementSeparator() {
|
||||
last := enc.buf.Len() - 1
|
||||
if last < 0 {
|
||||
return
|
||||
}
|
||||
switch enc.buf.Bytes()[last] {
|
||||
case '{', '[', ':', ',', ' ':
|
||||
return
|
||||
default:
|
||||
enc.buf.AppendByte(',')
|
||||
if enc.spaced {
|
||||
enc.buf.AppendByte(' ')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) appendFloat(val float64, bitSize int) {
|
||||
enc.addElementSeparator()
|
||||
switch {
|
||||
case math.IsNaN(val):
|
||||
enc.buf.AppendString(`"NaN"`)
|
||||
case math.IsInf(val, 1):
|
||||
enc.buf.AppendString(`"+Inf"`)
|
||||
case math.IsInf(val, -1):
|
||||
enc.buf.AppendString(`"-Inf"`)
|
||||
default:
|
||||
enc.buf.AppendFloat(val, bitSize)
|
||||
}
|
||||
}
|
||||
|
||||
// safeAddString JSON-escapes a string and appends it to the internal buffer.
|
||||
// Unlike the standard library's encoder, it doesn't attempt to protect the
|
||||
// user from browser vulnerabilities or JSONP-related problems.
|
||||
func (enc *jsonEncoder) safeAddString(s string) {
|
||||
for i := 0; i < len(s); {
|
||||
if enc.tryAddRuneSelf(s[i]) {
|
||||
i++
|
||||
continue
|
||||
}
|
||||
r, size := utf8.DecodeRuneInString(s[i:])
|
||||
if enc.tryAddRuneError(r, size) {
|
||||
i++
|
||||
continue
|
||||
}
|
||||
enc.buf.AppendString(s[i : i+size])
|
||||
i += size
|
||||
}
|
||||
}
|
||||
|
||||
// safeAddByteString is no-alloc equivalent of safeAddString(string(s)) for s []byte.
|
||||
func (enc *jsonEncoder) safeAddByteString(s []byte) {
|
||||
for i := 0; i < len(s); {
|
||||
if enc.tryAddRuneSelf(s[i]) {
|
||||
i++
|
||||
continue
|
||||
}
|
||||
r, size := utf8.DecodeRune(s[i:])
|
||||
if enc.tryAddRuneError(r, size) {
|
||||
i++
|
||||
continue
|
||||
}
|
||||
enc.buf.Write(s[i : i+size])
|
||||
i += size
|
||||
}
|
||||
}
|
||||
|
||||
// tryAddRuneSelf appends b if it is valid UTF-8 character represented in a single byte.
|
||||
func (enc *jsonEncoder) tryAddRuneSelf(b byte) bool {
|
||||
if b >= utf8.RuneSelf {
|
||||
return false
|
||||
}
|
||||
if 0x20 <= b && b != '\\' && b != '"' {
|
||||
enc.buf.AppendByte(b)
|
||||
return true
|
||||
}
|
||||
switch b {
|
||||
case '\\', '"':
|
||||
enc.buf.AppendByte('\\')
|
||||
enc.buf.AppendByte(b)
|
||||
case '\n':
|
||||
enc.buf.AppendByte('\\')
|
||||
enc.buf.AppendByte('n')
|
||||
case '\r':
|
||||
enc.buf.AppendByte('\\')
|
||||
enc.buf.AppendByte('r')
|
||||
case '\t':
|
||||
enc.buf.AppendByte('\\')
|
||||
enc.buf.AppendByte('t')
|
||||
default:
|
||||
// Encode bytes < 0x20, except for the escape sequences above.
|
||||
enc.buf.AppendString(`\u00`)
|
||||
enc.buf.AppendByte(_hex[b>>4])
|
||||
enc.buf.AppendByte(_hex[b&0xF])
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) tryAddRuneError(r rune, size int) bool {
|
||||
if r == utf8.RuneError && size == 1 {
|
||||
enc.buf.AppendString(`\ufffd`)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
// Copyright (c) 2016 Uber Technologies, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
package zapcorex
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"go.uber.org/zap/zapcore"
|
||||
)
|
||||
|
||||
// MapObjectEncoder is an ObjectEncoder backed by a simple
|
||||
// map[string]interface{}. It's not fast enough for production use, but it's
|
||||
// helpful in tests.
|
||||
type MapObjectEncoder struct {
|
||||
// Fields contains the entire encoded log context.
|
||||
Fields map[string]interface{}
|
||||
// cur is a pointer to the namespace we're currently writing to.
|
||||
cur map[string]interface{}
|
||||
}
|
||||
|
||||
// NewMapObjectEncoder creates a new map-backed ObjectEncoder.
|
||||
func NewMapObjectEncoder() *MapObjectEncoder {
|
||||
m := make(map[string]interface{})
|
||||
return &MapObjectEncoder{
|
||||
Fields: m,
|
||||
cur: m,
|
||||
}
|
||||
}
|
||||
|
||||
// AddArray implements ObjectEncoder.
|
||||
func (m *MapObjectEncoder) AddArray(key string, v zapcore.ArrayMarshaler) error {
|
||||
arr := &sliceArrayEncoder{elems: make([]interface{}, 0)}
|
||||
err := v.MarshalLogArray(arr)
|
||||
m.cur[key] = arr.elems
|
||||
return err
|
||||
}
|
||||
|
||||
// AddObject implements ObjectEncoder.
|
||||
func (m *MapObjectEncoder) AddObject(k string, v zapcore.ObjectMarshaler) error {
|
||||
newMap := NewMapObjectEncoder()
|
||||
m.cur[k] = newMap.Fields
|
||||
return v.MarshalLogObject(newMap)
|
||||
}
|
||||
|
||||
// AddBinary implements ObjectEncoder.
|
||||
func (m *MapObjectEncoder) AddBinary(k string, v []byte) { m.cur[k] = v }
|
||||
|
||||
// AddByteString implements ObjectEncoder.
|
||||
func (m *MapObjectEncoder) AddByteString(k string, v []byte) { m.cur[k] = string(v) }
|
||||
|
||||
// AddBool implements ObjectEncoder.
|
||||
func (m *MapObjectEncoder) AddBool(k string, v bool) { m.cur[k] = v }
|
||||
|
||||
// AddDuration implements ObjectEncoder.
|
||||
func (m MapObjectEncoder) AddDuration(k string, v time.Duration) { m.cur[k] = v }
|
||||
|
||||
// AddComplex128 implements ObjectEncoder.
|
||||
func (m *MapObjectEncoder) AddComplex128(k string, v complex128) { m.cur[k] = v }
|
||||
|
||||
// AddComplex64 implements ObjectEncoder.
|
||||
func (m *MapObjectEncoder) AddComplex64(k string, v complex64) { m.cur[k] = v }
|
||||
|
||||
// AddFloat64 implements ObjectEncoder.
|
||||
func (m *MapObjectEncoder) AddFloat64(k string, v float64) { m.cur[k] = v }
|
||||
|
||||
// AddFloat32 implements ObjectEncoder.
|
||||
func (m *MapObjectEncoder) AddFloat32(k string, v float32) { m.cur[k] = v }
|
||||
|
||||
// AddInt implements ObjectEncoder.
|
||||
func (m *MapObjectEncoder) AddInt(k string, v int) { m.cur[k] = v }
|
||||
|
||||
// AddInt64 implements ObjectEncoder.
|
||||
func (m *MapObjectEncoder) AddInt64(k string, v int64) { m.cur[k] = v }
|
||||
|
||||
// AddInt32 implements ObjectEncoder.
|
||||
func (m *MapObjectEncoder) AddInt32(k string, v int32) { m.cur[k] = v }
|
||||
|
||||
// AddInt16 implements ObjectEncoder.
|
||||
func (m *MapObjectEncoder) AddInt16(k string, v int16) { m.cur[k] = v }
|
||||
|
||||
// AddInt8 implements ObjectEncoder.
|
||||
func (m *MapObjectEncoder) AddInt8(k string, v int8) { m.cur[k] = v }
|
||||
|
||||
// AddString implements ObjectEncoder.
|
||||
func (m *MapObjectEncoder) AddString(k string, v string) { m.cur[k] = v }
|
||||
|
||||
// AddTime implements ObjectEncoder.
|
||||
func (m MapObjectEncoder) AddTime(k string, v time.Time) { m.cur[k] = v }
|
||||
|
||||
// AddUint implements ObjectEncoder.
|
||||
func (m *MapObjectEncoder) AddUint(k string, v uint) { m.cur[k] = v }
|
||||
|
||||
// AddUint64 implements ObjectEncoder.
|
||||
func (m *MapObjectEncoder) AddUint64(k string, v uint64) { m.cur[k] = v }
|
||||
|
||||
// AddUint32 implements ObjectEncoder.
|
||||
func (m *MapObjectEncoder) AddUint32(k string, v uint32) { m.cur[k] = v }
|
||||
|
||||
// AddUint16 implements ObjectEncoder.
|
||||
func (m *MapObjectEncoder) AddUint16(k string, v uint16) { m.cur[k] = v }
|
||||
|
||||
// AddUint8 implements ObjectEncoder.
|
||||
func (m *MapObjectEncoder) AddUint8(k string, v uint8) { m.cur[k] = v }
|
||||
|
||||
// AddUintptr implements ObjectEncoder.
|
||||
func (m *MapObjectEncoder) AddUintptr(k string, v uintptr) { m.cur[k] = v }
|
||||
|
||||
// AddReflected implements ObjectEncoder.
|
||||
func (m *MapObjectEncoder) AddReflected(k string, v interface{}) error {
|
||||
m.cur[k] = v
|
||||
return nil
|
||||
}
|
||||
|
||||
// OpenNamespace implements ObjectEncoder.
|
||||
func (m *MapObjectEncoder) OpenNamespace(k string) {
|
||||
ns := make(map[string]interface{})
|
||||
m.cur[k] = ns
|
||||
m.cur = ns
|
||||
}
|
||||
|
||||
// sliceArrayEncoder is an ArrayEncoder backed by a simple []interface{}. Like
|
||||
// the MapObjectEncoder, it's not designed for production use.
|
||||
type sliceArrayEncoder struct {
|
||||
elems []interface{}
|
||||
}
|
||||
|
||||
func (s *sliceArrayEncoder) AppendArray(v zapcore.ArrayMarshaler) error {
|
||||
enc := &sliceArrayEncoder{}
|
||||
err := v.MarshalLogArray(enc)
|
||||
s.elems = append(s.elems, enc.elems)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *sliceArrayEncoder) AppendObject(v zapcore.ObjectMarshaler) error {
|
||||
m := NewMapObjectEncoder()
|
||||
err := v.MarshalLogObject(m)
|
||||
s.elems = append(s.elems, m.Fields)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *sliceArrayEncoder) AppendReflected(v interface{}) error {
|
||||
s.elems = append(s.elems, v)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *sliceArrayEncoder) AppendBool(v bool) { s.elems = append(s.elems, v) }
|
||||
func (s *sliceArrayEncoder) AppendByteString(v []byte) { s.elems = append(s.elems, string(v)) }
|
||||
func (s *sliceArrayEncoder) AppendComplex128(v complex128) { s.elems = append(s.elems, v) }
|
||||
func (s *sliceArrayEncoder) AppendComplex64(v complex64) { s.elems = append(s.elems, v) }
|
||||
func (s *sliceArrayEncoder) AppendDuration(v time.Duration) { s.elems = append(s.elems, v) }
|
||||
func (s *sliceArrayEncoder) AppendFloat64(v float64) { s.elems = append(s.elems, v) }
|
||||
func (s *sliceArrayEncoder) AppendFloat32(v float32) { s.elems = append(s.elems, v) }
|
||||
func (s *sliceArrayEncoder) AppendInt(v int) { s.elems = append(s.elems, v) }
|
||||
func (s *sliceArrayEncoder) AppendInt64(v int64) { s.elems = append(s.elems, v) }
|
||||
func (s *sliceArrayEncoder) AppendInt32(v int32) { s.elems = append(s.elems, v) }
|
||||
func (s *sliceArrayEncoder) AppendInt16(v int16) { s.elems = append(s.elems, v) }
|
||||
func (s *sliceArrayEncoder) AppendInt8(v int8) { s.elems = append(s.elems, v) }
|
||||
func (s *sliceArrayEncoder) AppendString(v string) { s.elems = append(s.elems, v) }
|
||||
func (s *sliceArrayEncoder) AppendTime(v time.Time) { s.elems = append(s.elems, v) }
|
||||
func (s *sliceArrayEncoder) AppendUint(v uint) { s.elems = append(s.elems, v) }
|
||||
func (s *sliceArrayEncoder) AppendUint64(v uint64) { s.elems = append(s.elems, v) }
|
||||
func (s *sliceArrayEncoder) AppendUint32(v uint32) { s.elems = append(s.elems, v) }
|
||||
func (s *sliceArrayEncoder) AppendUint16(v uint16) { s.elems = append(s.elems, v) }
|
||||
func (s *sliceArrayEncoder) AppendUint8(v uint8) { s.elems = append(s.elems, v) }
|
||||
func (s *sliceArrayEncoder) AppendUintptr(v uintptr) { s.elems = append(s.elems, v) }
|
||||
Reference in New Issue
Block a user