refactor: log with zap
This commit is contained in:
		
							
								
								
									
										188
									
								
								vendor/go.uber.org/zap/zapcore/buffered_write_syncer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										188
									
								
								vendor/go.uber.org/zap/zapcore/buffered_write_syncer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,188 @@
 | 
			
		||||
// Copyright (c) 2021 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 zapcore
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"go.uber.org/multierr"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// _defaultBufferSize specifies the default size used by Buffer.
 | 
			
		||||
	_defaultBufferSize = 256 * 1024 // 256 kB
 | 
			
		||||
 | 
			
		||||
	// _defaultFlushInterval specifies the default flush interval for
 | 
			
		||||
	// Buffer.
 | 
			
		||||
	_defaultFlushInterval = 30 * time.Second
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// A BufferedWriteSyncer is a WriteSyncer that buffers writes in-memory before
 | 
			
		||||
// flushing them to a wrapped WriteSyncer after reaching some limit, or at some
 | 
			
		||||
// fixed interval--whichever comes first.
 | 
			
		||||
//
 | 
			
		||||
// BufferedWriteSyncer is safe for concurrent use. You don't need to use
 | 
			
		||||
// zapcore.Lock for WriteSyncers with BufferedWriteSyncer.
 | 
			
		||||
type BufferedWriteSyncer struct {
 | 
			
		||||
	// WS is the WriteSyncer around which BufferedWriteSyncer will buffer
 | 
			
		||||
	// writes.
 | 
			
		||||
	//
 | 
			
		||||
	// This field is required.
 | 
			
		||||
	WS WriteSyncer
 | 
			
		||||
 | 
			
		||||
	// Size specifies the maximum amount of data the writer will buffered
 | 
			
		||||
	// before flushing.
 | 
			
		||||
	//
 | 
			
		||||
	// Defaults to 256 kB if unspecified.
 | 
			
		||||
	Size int
 | 
			
		||||
 | 
			
		||||
	// FlushInterval specifies how often the writer should flush data if
 | 
			
		||||
	// there have been no writes.
 | 
			
		||||
	//
 | 
			
		||||
	// Defaults to 30 seconds if unspecified.
 | 
			
		||||
	FlushInterval time.Duration
 | 
			
		||||
 | 
			
		||||
	// Clock, if specified, provides control of the source of time for the
 | 
			
		||||
	// writer.
 | 
			
		||||
	//
 | 
			
		||||
	// Defaults to the system clock.
 | 
			
		||||
	Clock Clock
 | 
			
		||||
 | 
			
		||||
	// unexported fields for state
 | 
			
		||||
	mu          sync.Mutex
 | 
			
		||||
	initialized bool // whether initialize() has run
 | 
			
		||||
	stopped     bool // whether Stop() has run
 | 
			
		||||
	writer      *bufio.Writer
 | 
			
		||||
	ticker      *time.Ticker
 | 
			
		||||
	stop        chan struct{} // closed when flushLoop should stop
 | 
			
		||||
	done        chan struct{} // closed when flushLoop has stopped
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *BufferedWriteSyncer) initialize() {
 | 
			
		||||
	size := s.Size
 | 
			
		||||
	if size == 0 {
 | 
			
		||||
		size = _defaultBufferSize
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	flushInterval := s.FlushInterval
 | 
			
		||||
	if flushInterval == 0 {
 | 
			
		||||
		flushInterval = _defaultFlushInterval
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if s.Clock == nil {
 | 
			
		||||
		s.Clock = DefaultClock
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s.ticker = s.Clock.NewTicker(flushInterval)
 | 
			
		||||
	s.writer = bufio.NewWriterSize(s.WS, size)
 | 
			
		||||
	s.stop = make(chan struct{})
 | 
			
		||||
	s.done = make(chan struct{})
 | 
			
		||||
	s.initialized = true
 | 
			
		||||
	go s.flushLoop()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Write writes log data into buffer syncer directly, multiple Write calls will be batched,
 | 
			
		||||
// and log data will be flushed to disk when the buffer is full or periodically.
 | 
			
		||||
func (s *BufferedWriteSyncer) Write(bs []byte) (int, error) {
 | 
			
		||||
	s.mu.Lock()
 | 
			
		||||
	defer s.mu.Unlock()
 | 
			
		||||
 | 
			
		||||
	if !s.initialized {
 | 
			
		||||
		s.initialize()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// To avoid partial writes from being flushed, we manually flush the existing buffer if:
 | 
			
		||||
	// * The current write doesn't fit into the buffer fully, and
 | 
			
		||||
	// * The buffer is not empty (since bufio will not split large writes when the buffer is empty)
 | 
			
		||||
	if len(bs) > s.writer.Available() && s.writer.Buffered() > 0 {
 | 
			
		||||
		if err := s.writer.Flush(); err != nil {
 | 
			
		||||
			return 0, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return s.writer.Write(bs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Sync flushes buffered log data into disk directly.
 | 
			
		||||
func (s *BufferedWriteSyncer) Sync() error {
 | 
			
		||||
	s.mu.Lock()
 | 
			
		||||
	defer s.mu.Unlock()
 | 
			
		||||
 | 
			
		||||
	var err error
 | 
			
		||||
	if s.initialized {
 | 
			
		||||
		err = s.writer.Flush()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return multierr.Append(err, s.WS.Sync())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// flushLoop flushes the buffer at the configured interval until Stop is
 | 
			
		||||
// called.
 | 
			
		||||
func (s *BufferedWriteSyncer) flushLoop() {
 | 
			
		||||
	defer close(s.done)
 | 
			
		||||
 | 
			
		||||
	for {
 | 
			
		||||
		select {
 | 
			
		||||
		case <-s.ticker.C:
 | 
			
		||||
			// we just simply ignore error here
 | 
			
		||||
			// because the underlying bufio writer stores any errors
 | 
			
		||||
			// and we return any error from Sync() as part of the close
 | 
			
		||||
			_ = s.Sync()
 | 
			
		||||
		case <-s.stop:
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Stop closes the buffer, cleans up background goroutines, and flushes
 | 
			
		||||
// remaining unwritten data.
 | 
			
		||||
func (s *BufferedWriteSyncer) Stop() (err error) {
 | 
			
		||||
	var stopped bool
 | 
			
		||||
 | 
			
		||||
	// Critical section.
 | 
			
		||||
	func() {
 | 
			
		||||
		s.mu.Lock()
 | 
			
		||||
		defer s.mu.Unlock()
 | 
			
		||||
 | 
			
		||||
		if !s.initialized {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		stopped = s.stopped
 | 
			
		||||
		if stopped {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		s.stopped = true
 | 
			
		||||
 | 
			
		||||
		s.ticker.Stop()
 | 
			
		||||
		close(s.stop) // tell flushLoop to stop
 | 
			
		||||
		<-s.done      // and wait until it has
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	// Don't call Sync on consecutive Stops.
 | 
			
		||||
	if !stopped {
 | 
			
		||||
		err = s.Sync()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										50
									
								
								vendor/go.uber.org/zap/zapcore/clock.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								vendor/go.uber.org/zap/zapcore/clock.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,50 @@
 | 
			
		||||
// Copyright (c) 2021 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 zapcore
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// DefaultClock is the default clock used by Zap in operations that require
 | 
			
		||||
// time. This clock uses the system clock for all operations.
 | 
			
		||||
var DefaultClock = systemClock{}
 | 
			
		||||
 | 
			
		||||
// Clock is a source of time for logged entries.
 | 
			
		||||
type Clock interface {
 | 
			
		||||
	// Now returns the current local time.
 | 
			
		||||
	Now() time.Time
 | 
			
		||||
 | 
			
		||||
	// NewTicker returns *time.Ticker that holds a channel
 | 
			
		||||
	// that delivers "ticks" of a clock.
 | 
			
		||||
	NewTicker(time.Duration) *time.Ticker
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// systemClock implements default Clock that uses system time.
 | 
			
		||||
type systemClock struct{}
 | 
			
		||||
 | 
			
		||||
func (systemClock) Now() time.Time {
 | 
			
		||||
	return time.Now()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (systemClock) NewTicker(duration time.Duration) *time.Ticker {
 | 
			
		||||
	return time.NewTicker(duration)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										161
									
								
								vendor/go.uber.org/zap/zapcore/console_encoder.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										161
									
								
								vendor/go.uber.org/zap/zapcore/console_encoder.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,161 @@
 | 
			
		||||
// 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 zapcore
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"sync"
 | 
			
		||||
 | 
			
		||||
	"go.uber.org/zap/buffer"
 | 
			
		||||
	"go.uber.org/zap/internal/bufferpool"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
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 EncoderConfig) 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() Encoder {
 | 
			
		||||
	return consoleEncoder{c.jsonEncoder.Clone().(*jsonEncoder)}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c consoleEncoder) EncodeEntry(ent Entry, fields []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 = FullNameEncoder
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		nameEncoder(ent.LoggerName, arr)
 | 
			
		||||
	}
 | 
			
		||||
	if ent.Caller.Defined {
 | 
			
		||||
		if c.CallerKey != "" && c.EncodeCaller != nil {
 | 
			
		||||
			c.EncodeCaller(ent.Caller, arr)
 | 
			
		||||
		}
 | 
			
		||||
		if c.FunctionKey != "" {
 | 
			
		||||
			arr.AppendString(ent.Caller.Function)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	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 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)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if c.LineEnding != "" {
 | 
			
		||||
		line.AppendString(c.LineEnding)
 | 
			
		||||
	} else {
 | 
			
		||||
		line.AppendString(DefaultLineEnding)
 | 
			
		||||
	}
 | 
			
		||||
	return line, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c consoleEncoder) writeContext(line *buffer.Buffer, extra []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)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										113
									
								
								vendor/go.uber.org/zap/zapcore/core.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								vendor/go.uber.org/zap/zapcore/core.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,113 @@
 | 
			
		||||
// 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 zapcore
 | 
			
		||||
 | 
			
		||||
// Core is a minimal, fast logger interface. It's designed for library authors
 | 
			
		||||
// to wrap in a more user-friendly API.
 | 
			
		||||
type Core interface {
 | 
			
		||||
	LevelEnabler
 | 
			
		||||
 | 
			
		||||
	// With adds structured context to the Core.
 | 
			
		||||
	With([]Field) Core
 | 
			
		||||
	// Check determines whether the supplied Entry should be logged (using the
 | 
			
		||||
	// embedded LevelEnabler and possibly some extra logic). If the entry
 | 
			
		||||
	// should be logged, the Core adds itself to the CheckedEntry and returns
 | 
			
		||||
	// the result.
 | 
			
		||||
	//
 | 
			
		||||
	// Callers must use Check before calling Write.
 | 
			
		||||
	Check(Entry, *CheckedEntry) *CheckedEntry
 | 
			
		||||
	// Write serializes the Entry and any Fields supplied at the log site and
 | 
			
		||||
	// writes them to their destination.
 | 
			
		||||
	//
 | 
			
		||||
	// If called, Write should always log the Entry and Fields; it should not
 | 
			
		||||
	// replicate the logic of Check.
 | 
			
		||||
	Write(Entry, []Field) error
 | 
			
		||||
	// Sync flushes buffered logs (if any).
 | 
			
		||||
	Sync() error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type nopCore struct{}
 | 
			
		||||
 | 
			
		||||
// NewNopCore returns a no-op Core.
 | 
			
		||||
func NewNopCore() Core                                        { return nopCore{} }
 | 
			
		||||
func (nopCore) Enabled(Level) bool                            { return false }
 | 
			
		||||
func (n nopCore) With([]Field) Core                           { return n }
 | 
			
		||||
func (nopCore) Check(_ Entry, ce *CheckedEntry) *CheckedEntry { return ce }
 | 
			
		||||
func (nopCore) Write(Entry, []Field) error                    { return nil }
 | 
			
		||||
func (nopCore) Sync() error                                   { return nil }
 | 
			
		||||
 | 
			
		||||
// NewCore creates a Core that writes logs to a WriteSyncer.
 | 
			
		||||
func NewCore(enc Encoder, ws WriteSyncer, enab LevelEnabler) Core {
 | 
			
		||||
	return &ioCore{
 | 
			
		||||
		LevelEnabler: enab,
 | 
			
		||||
		enc:          enc,
 | 
			
		||||
		out:          ws,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ioCore struct {
 | 
			
		||||
	LevelEnabler
 | 
			
		||||
	enc Encoder
 | 
			
		||||
	out WriteSyncer
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ioCore) With(fields []Field) Core {
 | 
			
		||||
	clone := c.clone()
 | 
			
		||||
	addFields(clone.enc, fields)
 | 
			
		||||
	return clone
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ioCore) Check(ent Entry, ce *CheckedEntry) *CheckedEntry {
 | 
			
		||||
	if c.Enabled(ent.Level) {
 | 
			
		||||
		return ce.AddCore(ent, c)
 | 
			
		||||
	}
 | 
			
		||||
	return ce
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ioCore) Write(ent Entry, fields []Field) error {
 | 
			
		||||
	buf, err := c.enc.EncodeEntry(ent, fields)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	_, err = c.out.Write(buf.Bytes())
 | 
			
		||||
	buf.Free()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if ent.Level > ErrorLevel {
 | 
			
		||||
		// Since we may be crashing the program, sync the output. Ignore Sync
 | 
			
		||||
		// errors, pending a clean solution to issue #370.
 | 
			
		||||
		c.Sync()
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ioCore) Sync() error {
 | 
			
		||||
	return c.out.Sync()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ioCore) clone() *ioCore {
 | 
			
		||||
	return &ioCore{
 | 
			
		||||
		LevelEnabler: c.LevelEnabler,
 | 
			
		||||
		enc:          c.enc.Clone(),
 | 
			
		||||
		out:          c.out,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								vendor/go.uber.org/zap/zapcore/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								vendor/go.uber.org/zap/zapcore/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
// 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 zapcore defines and implements the low-level interfaces upon which
 | 
			
		||||
// zap is built. By providing alternate implementations of these interfaces,
 | 
			
		||||
// external packages can extend zap's capabilities.
 | 
			
		||||
package zapcore // import "go.uber.org/zap/zapcore"
 | 
			
		||||
							
								
								
									
										443
									
								
								vendor/go.uber.org/zap/zapcore/encoder.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										443
									
								
								vendor/go.uber.org/zap/zapcore/encoder.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,443 @@
 | 
			
		||||
// 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 zapcore
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"go.uber.org/zap/buffer"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// DefaultLineEnding defines the default line ending when writing logs.
 | 
			
		||||
// Alternate line endings specified in EncoderConfig can override this
 | 
			
		||||
// behavior.
 | 
			
		||||
const DefaultLineEnding = "\n"
 | 
			
		||||
 | 
			
		||||
// OmitKey defines the key to use when callers want to remove a key from log output.
 | 
			
		||||
const OmitKey = ""
 | 
			
		||||
 | 
			
		||||
// A LevelEncoder serializes a Level to a primitive type.
 | 
			
		||||
type LevelEncoder func(Level, PrimitiveArrayEncoder)
 | 
			
		||||
 | 
			
		||||
// LowercaseLevelEncoder serializes a Level to a lowercase string. For example,
 | 
			
		||||
// InfoLevel is serialized to "info".
 | 
			
		||||
func LowercaseLevelEncoder(l Level, enc PrimitiveArrayEncoder) {
 | 
			
		||||
	enc.AppendString(l.String())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LowercaseColorLevelEncoder serializes a Level to a lowercase string and adds coloring.
 | 
			
		||||
// For example, InfoLevel is serialized to "info" and colored blue.
 | 
			
		||||
func LowercaseColorLevelEncoder(l Level, enc PrimitiveArrayEncoder) {
 | 
			
		||||
	s, ok := _levelToLowercaseColorString[l]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		s = _unknownLevelColor.Add(l.String())
 | 
			
		||||
	}
 | 
			
		||||
	enc.AppendString(s)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CapitalLevelEncoder serializes a Level to an all-caps string. For example,
 | 
			
		||||
// InfoLevel is serialized to "INFO".
 | 
			
		||||
func CapitalLevelEncoder(l Level, enc PrimitiveArrayEncoder) {
 | 
			
		||||
	enc.AppendString(l.CapitalString())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CapitalColorLevelEncoder serializes a Level to an all-caps string and adds color.
 | 
			
		||||
// For example, InfoLevel is serialized to "INFO" and colored blue.
 | 
			
		||||
func CapitalColorLevelEncoder(l Level, enc PrimitiveArrayEncoder) {
 | 
			
		||||
	s, ok := _levelToCapitalColorString[l]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		s = _unknownLevelColor.Add(l.CapitalString())
 | 
			
		||||
	}
 | 
			
		||||
	enc.AppendString(s)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UnmarshalText unmarshals text to a LevelEncoder. "capital" is unmarshaled to
 | 
			
		||||
// CapitalLevelEncoder, "coloredCapital" is unmarshaled to CapitalColorLevelEncoder,
 | 
			
		||||
// "colored" is unmarshaled to LowercaseColorLevelEncoder, and anything else
 | 
			
		||||
// is unmarshaled to LowercaseLevelEncoder.
 | 
			
		||||
func (e *LevelEncoder) UnmarshalText(text []byte) error {
 | 
			
		||||
	switch string(text) {
 | 
			
		||||
	case "capital":
 | 
			
		||||
		*e = CapitalLevelEncoder
 | 
			
		||||
	case "capitalColor":
 | 
			
		||||
		*e = CapitalColorLevelEncoder
 | 
			
		||||
	case "color":
 | 
			
		||||
		*e = LowercaseColorLevelEncoder
 | 
			
		||||
	default:
 | 
			
		||||
		*e = LowercaseLevelEncoder
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A TimeEncoder serializes a time.Time to a primitive type.
 | 
			
		||||
type TimeEncoder func(time.Time, PrimitiveArrayEncoder)
 | 
			
		||||
 | 
			
		||||
// EpochTimeEncoder serializes a time.Time to a floating-point number of seconds
 | 
			
		||||
// since the Unix epoch.
 | 
			
		||||
func EpochTimeEncoder(t time.Time, enc PrimitiveArrayEncoder) {
 | 
			
		||||
	nanos := t.UnixNano()
 | 
			
		||||
	sec := float64(nanos) / float64(time.Second)
 | 
			
		||||
	enc.AppendFloat64(sec)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EpochMillisTimeEncoder serializes a time.Time to a floating-point number of
 | 
			
		||||
// milliseconds since the Unix epoch.
 | 
			
		||||
func EpochMillisTimeEncoder(t time.Time, enc PrimitiveArrayEncoder) {
 | 
			
		||||
	nanos := t.UnixNano()
 | 
			
		||||
	millis := float64(nanos) / float64(time.Millisecond)
 | 
			
		||||
	enc.AppendFloat64(millis)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EpochNanosTimeEncoder serializes a time.Time to an integer number of
 | 
			
		||||
// nanoseconds since the Unix epoch.
 | 
			
		||||
func EpochNanosTimeEncoder(t time.Time, enc PrimitiveArrayEncoder) {
 | 
			
		||||
	enc.AppendInt64(t.UnixNano())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func encodeTimeLayout(t time.Time, layout string, enc PrimitiveArrayEncoder) {
 | 
			
		||||
	type appendTimeEncoder interface {
 | 
			
		||||
		AppendTimeLayout(time.Time, string)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if enc, ok := enc.(appendTimeEncoder); ok {
 | 
			
		||||
		enc.AppendTimeLayout(t, layout)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	enc.AppendString(t.Format(layout))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ISO8601TimeEncoder serializes a time.Time to an ISO8601-formatted string
 | 
			
		||||
// with millisecond precision.
 | 
			
		||||
//
 | 
			
		||||
// If enc supports AppendTimeLayout(t time.Time,layout string), it's used
 | 
			
		||||
// instead of appending a pre-formatted string value.
 | 
			
		||||
func ISO8601TimeEncoder(t time.Time, enc PrimitiveArrayEncoder) {
 | 
			
		||||
	encodeTimeLayout(t, "2006-01-02T15:04:05.000Z0700", enc)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RFC3339TimeEncoder serializes a time.Time to an RFC3339-formatted string.
 | 
			
		||||
//
 | 
			
		||||
// If enc supports AppendTimeLayout(t time.Time,layout string), it's used
 | 
			
		||||
// instead of appending a pre-formatted string value.
 | 
			
		||||
func RFC3339TimeEncoder(t time.Time, enc PrimitiveArrayEncoder) {
 | 
			
		||||
	encodeTimeLayout(t, time.RFC3339, enc)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RFC3339NanoTimeEncoder serializes a time.Time to an RFC3339-formatted string
 | 
			
		||||
// with nanosecond precision.
 | 
			
		||||
//
 | 
			
		||||
// If enc supports AppendTimeLayout(t time.Time,layout string), it's used
 | 
			
		||||
// instead of appending a pre-formatted string value.
 | 
			
		||||
func RFC3339NanoTimeEncoder(t time.Time, enc PrimitiveArrayEncoder) {
 | 
			
		||||
	encodeTimeLayout(t, time.RFC3339Nano, enc)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TimeEncoderOfLayout returns TimeEncoder which serializes a time.Time using
 | 
			
		||||
// given layout.
 | 
			
		||||
func TimeEncoderOfLayout(layout string) TimeEncoder {
 | 
			
		||||
	return func(t time.Time, enc PrimitiveArrayEncoder) {
 | 
			
		||||
		encodeTimeLayout(t, layout, enc)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UnmarshalText unmarshals text to a TimeEncoder.
 | 
			
		||||
// "rfc3339nano" and "RFC3339Nano" are unmarshaled to RFC3339NanoTimeEncoder.
 | 
			
		||||
// "rfc3339" and "RFC3339" are unmarshaled to RFC3339TimeEncoder.
 | 
			
		||||
// "iso8601" and "ISO8601" are unmarshaled to ISO8601TimeEncoder.
 | 
			
		||||
// "millis" is unmarshaled to EpochMillisTimeEncoder.
 | 
			
		||||
// "nanos" is unmarshaled to EpochNanosEncoder.
 | 
			
		||||
// Anything else is unmarshaled to EpochTimeEncoder.
 | 
			
		||||
func (e *TimeEncoder) UnmarshalText(text []byte) error {
 | 
			
		||||
	switch string(text) {
 | 
			
		||||
	case "rfc3339nano", "RFC3339Nano":
 | 
			
		||||
		*e = RFC3339NanoTimeEncoder
 | 
			
		||||
	case "rfc3339", "RFC3339":
 | 
			
		||||
		*e = RFC3339TimeEncoder
 | 
			
		||||
	case "iso8601", "ISO8601":
 | 
			
		||||
		*e = ISO8601TimeEncoder
 | 
			
		||||
	case "millis":
 | 
			
		||||
		*e = EpochMillisTimeEncoder
 | 
			
		||||
	case "nanos":
 | 
			
		||||
		*e = EpochNanosTimeEncoder
 | 
			
		||||
	default:
 | 
			
		||||
		*e = EpochTimeEncoder
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UnmarshalYAML unmarshals YAML to a TimeEncoder.
 | 
			
		||||
// If value is an object with a "layout" field, it will be unmarshaled to  TimeEncoder with given layout.
 | 
			
		||||
//     timeEncoder:
 | 
			
		||||
//       layout: 06/01/02 03:04pm
 | 
			
		||||
// If value is string, it uses UnmarshalText.
 | 
			
		||||
//     timeEncoder: iso8601
 | 
			
		||||
func (e *TimeEncoder) UnmarshalYAML(unmarshal func(interface{}) error) error {
 | 
			
		||||
	var o struct {
 | 
			
		||||
		Layout string `json:"layout" yaml:"layout"`
 | 
			
		||||
	}
 | 
			
		||||
	if err := unmarshal(&o); err == nil {
 | 
			
		||||
		*e = TimeEncoderOfLayout(o.Layout)
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var s string
 | 
			
		||||
	if err := unmarshal(&s); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return e.UnmarshalText([]byte(s))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UnmarshalJSON unmarshals JSON to a TimeEncoder as same way UnmarshalYAML does.
 | 
			
		||||
func (e *TimeEncoder) UnmarshalJSON(data []byte) error {
 | 
			
		||||
	return e.UnmarshalYAML(func(v interface{}) error {
 | 
			
		||||
		return json.Unmarshal(data, v)
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A DurationEncoder serializes a time.Duration to a primitive type.
 | 
			
		||||
type DurationEncoder func(time.Duration, PrimitiveArrayEncoder)
 | 
			
		||||
 | 
			
		||||
// SecondsDurationEncoder serializes a time.Duration to a floating-point number of seconds elapsed.
 | 
			
		||||
func SecondsDurationEncoder(d time.Duration, enc PrimitiveArrayEncoder) {
 | 
			
		||||
	enc.AppendFloat64(float64(d) / float64(time.Second))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NanosDurationEncoder serializes a time.Duration to an integer number of
 | 
			
		||||
// nanoseconds elapsed.
 | 
			
		||||
func NanosDurationEncoder(d time.Duration, enc PrimitiveArrayEncoder) {
 | 
			
		||||
	enc.AppendInt64(int64(d))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MillisDurationEncoder serializes a time.Duration to an integer number of
 | 
			
		||||
// milliseconds elapsed.
 | 
			
		||||
func MillisDurationEncoder(d time.Duration, enc PrimitiveArrayEncoder) {
 | 
			
		||||
	enc.AppendInt64(d.Nanoseconds() / 1e6)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StringDurationEncoder serializes a time.Duration using its built-in String
 | 
			
		||||
// method.
 | 
			
		||||
func StringDurationEncoder(d time.Duration, enc PrimitiveArrayEncoder) {
 | 
			
		||||
	enc.AppendString(d.String())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UnmarshalText unmarshals text to a DurationEncoder. "string" is unmarshaled
 | 
			
		||||
// to StringDurationEncoder, and anything else is unmarshaled to
 | 
			
		||||
// NanosDurationEncoder.
 | 
			
		||||
func (e *DurationEncoder) UnmarshalText(text []byte) error {
 | 
			
		||||
	switch string(text) {
 | 
			
		||||
	case "string":
 | 
			
		||||
		*e = StringDurationEncoder
 | 
			
		||||
	case "nanos":
 | 
			
		||||
		*e = NanosDurationEncoder
 | 
			
		||||
	case "ms":
 | 
			
		||||
		*e = MillisDurationEncoder
 | 
			
		||||
	default:
 | 
			
		||||
		*e = SecondsDurationEncoder
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A CallerEncoder serializes an EntryCaller to a primitive type.
 | 
			
		||||
type CallerEncoder func(EntryCaller, PrimitiveArrayEncoder)
 | 
			
		||||
 | 
			
		||||
// FullCallerEncoder serializes a caller in /full/path/to/package/file:line
 | 
			
		||||
// format.
 | 
			
		||||
func FullCallerEncoder(caller EntryCaller, enc PrimitiveArrayEncoder) {
 | 
			
		||||
	// TODO: consider using a byte-oriented API to save an allocation.
 | 
			
		||||
	enc.AppendString(caller.String())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ShortCallerEncoder serializes a caller in package/file:line format, trimming
 | 
			
		||||
// all but the final directory from the full path.
 | 
			
		||||
func ShortCallerEncoder(caller EntryCaller, enc PrimitiveArrayEncoder) {
 | 
			
		||||
	// TODO: consider using a byte-oriented API to save an allocation.
 | 
			
		||||
	enc.AppendString(caller.TrimmedPath())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UnmarshalText unmarshals text to a CallerEncoder. "full" is unmarshaled to
 | 
			
		||||
// FullCallerEncoder and anything else is unmarshaled to ShortCallerEncoder.
 | 
			
		||||
func (e *CallerEncoder) UnmarshalText(text []byte) error {
 | 
			
		||||
	switch string(text) {
 | 
			
		||||
	case "full":
 | 
			
		||||
		*e = FullCallerEncoder
 | 
			
		||||
	default:
 | 
			
		||||
		*e = ShortCallerEncoder
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A NameEncoder serializes a period-separated logger name to a primitive
 | 
			
		||||
// type.
 | 
			
		||||
type NameEncoder func(string, PrimitiveArrayEncoder)
 | 
			
		||||
 | 
			
		||||
// FullNameEncoder serializes the logger name as-is.
 | 
			
		||||
func FullNameEncoder(loggerName string, enc PrimitiveArrayEncoder) {
 | 
			
		||||
	enc.AppendString(loggerName)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UnmarshalText unmarshals text to a NameEncoder. Currently, everything is
 | 
			
		||||
// unmarshaled to FullNameEncoder.
 | 
			
		||||
func (e *NameEncoder) UnmarshalText(text []byte) error {
 | 
			
		||||
	switch string(text) {
 | 
			
		||||
	case "full":
 | 
			
		||||
		*e = FullNameEncoder
 | 
			
		||||
	default:
 | 
			
		||||
		*e = FullNameEncoder
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// An EncoderConfig allows users to configure the concrete encoders supplied by
 | 
			
		||||
// zapcore.
 | 
			
		||||
type EncoderConfig struct {
 | 
			
		||||
	// Set the keys used for each log entry. If any key is empty, that portion
 | 
			
		||||
	// of the entry is omitted.
 | 
			
		||||
	MessageKey    string `json:"messageKey" yaml:"messageKey"`
 | 
			
		||||
	LevelKey      string `json:"levelKey" yaml:"levelKey"`
 | 
			
		||||
	TimeKey       string `json:"timeKey" yaml:"timeKey"`
 | 
			
		||||
	NameKey       string `json:"nameKey" yaml:"nameKey"`
 | 
			
		||||
	CallerKey     string `json:"callerKey" yaml:"callerKey"`
 | 
			
		||||
	FunctionKey   string `json:"functionKey" yaml:"functionKey"`
 | 
			
		||||
	StacktraceKey string `json:"stacktraceKey" yaml:"stacktraceKey"`
 | 
			
		||||
	LineEnding    string `json:"lineEnding" yaml:"lineEnding"`
 | 
			
		||||
	// Configure the primitive representations of common complex types. For
 | 
			
		||||
	// example, some users may want all time.Times serialized as floating-point
 | 
			
		||||
	// seconds since epoch, while others may prefer ISO8601 strings.
 | 
			
		||||
	EncodeLevel    LevelEncoder    `json:"levelEncoder" yaml:"levelEncoder"`
 | 
			
		||||
	EncodeTime     TimeEncoder     `json:"timeEncoder" yaml:"timeEncoder"`
 | 
			
		||||
	EncodeDuration DurationEncoder `json:"durationEncoder" yaml:"durationEncoder"`
 | 
			
		||||
	EncodeCaller   CallerEncoder   `json:"callerEncoder" yaml:"callerEncoder"`
 | 
			
		||||
	// Unlike the other primitive type encoders, EncodeName is optional. The
 | 
			
		||||
	// zero value falls back to FullNameEncoder.
 | 
			
		||||
	EncodeName NameEncoder `json:"nameEncoder" yaml:"nameEncoder"`
 | 
			
		||||
	// Configures the field separator used by the console encoder. Defaults
 | 
			
		||||
	// to tab.
 | 
			
		||||
	ConsoleSeparator string `json:"consoleSeparator" yaml:"consoleSeparator"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ObjectEncoder is a strongly-typed, encoding-agnostic interface for adding a
 | 
			
		||||
// map- or struct-like object to the logging context. Like maps, ObjectEncoders
 | 
			
		||||
// aren't safe for concurrent use (though typical use shouldn't require locks).
 | 
			
		||||
type ObjectEncoder interface {
 | 
			
		||||
	// Logging-specific marshalers.
 | 
			
		||||
	AddArray(key string, marshaler ArrayMarshaler) error
 | 
			
		||||
	AddObject(key string, marshaler ObjectMarshaler) error
 | 
			
		||||
 | 
			
		||||
	// Built-in types.
 | 
			
		||||
	AddBinary(key string, value []byte)     // for arbitrary bytes
 | 
			
		||||
	AddByteString(key string, value []byte) // for UTF-8 encoded bytes
 | 
			
		||||
	AddBool(key string, value bool)
 | 
			
		||||
	AddComplex128(key string, value complex128)
 | 
			
		||||
	AddComplex64(key string, value complex64)
 | 
			
		||||
	AddDuration(key string, value time.Duration)
 | 
			
		||||
	AddFloat64(key string, value float64)
 | 
			
		||||
	AddFloat32(key string, value float32)
 | 
			
		||||
	AddInt(key string, value int)
 | 
			
		||||
	AddInt64(key string, value int64)
 | 
			
		||||
	AddInt32(key string, value int32)
 | 
			
		||||
	AddInt16(key string, value int16)
 | 
			
		||||
	AddInt8(key string, value int8)
 | 
			
		||||
	AddString(key, value string)
 | 
			
		||||
	AddTime(key string, value time.Time)
 | 
			
		||||
	AddUint(key string, value uint)
 | 
			
		||||
	AddUint64(key string, value uint64)
 | 
			
		||||
	AddUint32(key string, value uint32)
 | 
			
		||||
	AddUint16(key string, value uint16)
 | 
			
		||||
	AddUint8(key string, value uint8)
 | 
			
		||||
	AddUintptr(key string, value uintptr)
 | 
			
		||||
 | 
			
		||||
	// AddReflected uses reflection to serialize arbitrary objects, so it can be
 | 
			
		||||
	// slow and allocation-heavy.
 | 
			
		||||
	AddReflected(key string, value interface{}) error
 | 
			
		||||
	// OpenNamespace opens an isolated namespace where all subsequent fields will
 | 
			
		||||
	// be added. Applications can use namespaces to prevent key collisions when
 | 
			
		||||
	// injecting loggers into sub-components or third-party libraries.
 | 
			
		||||
	OpenNamespace(key string)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ArrayEncoder is a strongly-typed, encoding-agnostic interface for adding
 | 
			
		||||
// array-like objects to the logging context. Of note, it supports mixed-type
 | 
			
		||||
// arrays even though they aren't typical in Go. Like slices, ArrayEncoders
 | 
			
		||||
// aren't safe for concurrent use (though typical use shouldn't require locks).
 | 
			
		||||
type ArrayEncoder interface {
 | 
			
		||||
	// Built-in types.
 | 
			
		||||
	PrimitiveArrayEncoder
 | 
			
		||||
 | 
			
		||||
	// Time-related types.
 | 
			
		||||
	AppendDuration(time.Duration)
 | 
			
		||||
	AppendTime(time.Time)
 | 
			
		||||
 | 
			
		||||
	// Logging-specific marshalers.
 | 
			
		||||
	AppendArray(ArrayMarshaler) error
 | 
			
		||||
	AppendObject(ObjectMarshaler) error
 | 
			
		||||
 | 
			
		||||
	// AppendReflected uses reflection to serialize arbitrary objects, so it's
 | 
			
		||||
	// slow and allocation-heavy.
 | 
			
		||||
	AppendReflected(value interface{}) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PrimitiveArrayEncoder is the subset of the ArrayEncoder interface that deals
 | 
			
		||||
// only in Go's built-in types. It's included only so that Duration- and
 | 
			
		||||
// TimeEncoders cannot trigger infinite recursion.
 | 
			
		||||
type PrimitiveArrayEncoder interface {
 | 
			
		||||
	// Built-in types.
 | 
			
		||||
	AppendBool(bool)
 | 
			
		||||
	AppendByteString([]byte) // for UTF-8 encoded bytes
 | 
			
		||||
	AppendComplex128(complex128)
 | 
			
		||||
	AppendComplex64(complex64)
 | 
			
		||||
	AppendFloat64(float64)
 | 
			
		||||
	AppendFloat32(float32)
 | 
			
		||||
	AppendInt(int)
 | 
			
		||||
	AppendInt64(int64)
 | 
			
		||||
	AppendInt32(int32)
 | 
			
		||||
	AppendInt16(int16)
 | 
			
		||||
	AppendInt8(int8)
 | 
			
		||||
	AppendString(string)
 | 
			
		||||
	AppendUint(uint)
 | 
			
		||||
	AppendUint64(uint64)
 | 
			
		||||
	AppendUint32(uint32)
 | 
			
		||||
	AppendUint16(uint16)
 | 
			
		||||
	AppendUint8(uint8)
 | 
			
		||||
	AppendUintptr(uintptr)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Encoder is a format-agnostic interface for all log entry marshalers. Since
 | 
			
		||||
// log encoders don't need to support the same wide range of use cases as
 | 
			
		||||
// general-purpose marshalers, it's possible to make them faster and
 | 
			
		||||
// lower-allocation.
 | 
			
		||||
//
 | 
			
		||||
// Implementations of the ObjectEncoder interface's methods can, of course,
 | 
			
		||||
// freely modify the receiver. However, the Clone and EncodeEntry methods will
 | 
			
		||||
// be called concurrently and shouldn't modify the receiver.
 | 
			
		||||
type Encoder interface {
 | 
			
		||||
	ObjectEncoder
 | 
			
		||||
 | 
			
		||||
	// Clone copies the encoder, ensuring that adding fields to the copy doesn't
 | 
			
		||||
	// affect the original.
 | 
			
		||||
	Clone() Encoder
 | 
			
		||||
 | 
			
		||||
	// EncodeEntry encodes an entry and fields, along with any accumulated
 | 
			
		||||
	// context, into a byte buffer and returns it. Any fields that are empty,
 | 
			
		||||
	// including fields on the `Entry` type, should be omitted.
 | 
			
		||||
	EncodeEntry(Entry, []Field) (*buffer.Buffer, error)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										262
									
								
								vendor/go.uber.org/zap/zapcore/entry.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										262
									
								
								vendor/go.uber.org/zap/zapcore/entry.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,262 @@
 | 
			
		||||
// 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 zapcore
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"go.uber.org/zap/internal/bufferpool"
 | 
			
		||||
	"go.uber.org/zap/internal/exit"
 | 
			
		||||
 | 
			
		||||
	"go.uber.org/multierr"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	_cePool = sync.Pool{New: func() interface{} {
 | 
			
		||||
		// Pre-allocate some space for cores.
 | 
			
		||||
		return &CheckedEntry{
 | 
			
		||||
			cores: make([]Core, 4),
 | 
			
		||||
		}
 | 
			
		||||
	}}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func getCheckedEntry() *CheckedEntry {
 | 
			
		||||
	ce := _cePool.Get().(*CheckedEntry)
 | 
			
		||||
	ce.reset()
 | 
			
		||||
	return ce
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func putCheckedEntry(ce *CheckedEntry) {
 | 
			
		||||
	if ce == nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	_cePool.Put(ce)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewEntryCaller makes an EntryCaller from the return signature of
 | 
			
		||||
// runtime.Caller.
 | 
			
		||||
func NewEntryCaller(pc uintptr, file string, line int, ok bool) EntryCaller {
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return EntryCaller{}
 | 
			
		||||
	}
 | 
			
		||||
	return EntryCaller{
 | 
			
		||||
		PC:      pc,
 | 
			
		||||
		File:    file,
 | 
			
		||||
		Line:    line,
 | 
			
		||||
		Defined: true,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EntryCaller represents the caller of a logging function.
 | 
			
		||||
type EntryCaller struct {
 | 
			
		||||
	Defined  bool
 | 
			
		||||
	PC       uintptr
 | 
			
		||||
	File     string
 | 
			
		||||
	Line     int
 | 
			
		||||
	Function string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// String returns the full path and line number of the caller.
 | 
			
		||||
func (ec EntryCaller) String() string {
 | 
			
		||||
	return ec.FullPath()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FullPath returns a /full/path/to/package/file:line description of the
 | 
			
		||||
// caller.
 | 
			
		||||
func (ec EntryCaller) FullPath() string {
 | 
			
		||||
	if !ec.Defined {
 | 
			
		||||
		return "undefined"
 | 
			
		||||
	}
 | 
			
		||||
	buf := bufferpool.Get()
 | 
			
		||||
	buf.AppendString(ec.File)
 | 
			
		||||
	buf.AppendByte(':')
 | 
			
		||||
	buf.AppendInt(int64(ec.Line))
 | 
			
		||||
	caller := buf.String()
 | 
			
		||||
	buf.Free()
 | 
			
		||||
	return caller
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TrimmedPath returns a package/file:line description of the caller,
 | 
			
		||||
// preserving only the leaf directory name and file name.
 | 
			
		||||
func (ec EntryCaller) TrimmedPath() string {
 | 
			
		||||
	if !ec.Defined {
 | 
			
		||||
		return "undefined"
 | 
			
		||||
	}
 | 
			
		||||
	// nb. To make sure we trim the path correctly on Windows too, we
 | 
			
		||||
	// counter-intuitively need to use '/' and *not* os.PathSeparator here,
 | 
			
		||||
	// because the path given originates from Go stdlib, specifically
 | 
			
		||||
	// runtime.Caller() which (as of Mar/17) returns forward slashes even on
 | 
			
		||||
	// Windows.
 | 
			
		||||
	//
 | 
			
		||||
	// See https://github.com/golang/go/issues/3335
 | 
			
		||||
	// and https://github.com/golang/go/issues/18151
 | 
			
		||||
	//
 | 
			
		||||
	// for discussion on the issue on Go side.
 | 
			
		||||
	//
 | 
			
		||||
	// Find the last separator.
 | 
			
		||||
	//
 | 
			
		||||
	idx := strings.LastIndexByte(ec.File, '/')
 | 
			
		||||
	if idx == -1 {
 | 
			
		||||
		return ec.FullPath()
 | 
			
		||||
	}
 | 
			
		||||
	// Find the penultimate separator.
 | 
			
		||||
	idx = strings.LastIndexByte(ec.File[:idx], '/')
 | 
			
		||||
	if idx == -1 {
 | 
			
		||||
		return ec.FullPath()
 | 
			
		||||
	}
 | 
			
		||||
	buf := bufferpool.Get()
 | 
			
		||||
	// Keep everything after the penultimate separator.
 | 
			
		||||
	buf.AppendString(ec.File[idx+1:])
 | 
			
		||||
	buf.AppendByte(':')
 | 
			
		||||
	buf.AppendInt(int64(ec.Line))
 | 
			
		||||
	caller := buf.String()
 | 
			
		||||
	buf.Free()
 | 
			
		||||
	return caller
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// An Entry represents a complete log message. The entry's structured context
 | 
			
		||||
// is already serialized, but the log level, time, message, and call site
 | 
			
		||||
// information are available for inspection and modification. Any fields left
 | 
			
		||||
// empty will be omitted when encoding.
 | 
			
		||||
//
 | 
			
		||||
// Entries are pooled, so any functions that accept them MUST be careful not to
 | 
			
		||||
// retain references to them.
 | 
			
		||||
type Entry struct {
 | 
			
		||||
	Level      Level
 | 
			
		||||
	Time       time.Time
 | 
			
		||||
	LoggerName string
 | 
			
		||||
	Message    string
 | 
			
		||||
	Caller     EntryCaller
 | 
			
		||||
	Stack      string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CheckWriteAction indicates what action to take after a log entry is
 | 
			
		||||
// processed. Actions are ordered in increasing severity.
 | 
			
		||||
type CheckWriteAction uint8
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// WriteThenNoop indicates that nothing special needs to be done. It's the
 | 
			
		||||
	// default behavior.
 | 
			
		||||
	WriteThenNoop CheckWriteAction = iota
 | 
			
		||||
	// WriteThenGoexit runs runtime.Goexit after Write.
 | 
			
		||||
	WriteThenGoexit
 | 
			
		||||
	// WriteThenPanic causes a panic after Write.
 | 
			
		||||
	WriteThenPanic
 | 
			
		||||
	// WriteThenFatal causes a fatal os.Exit after Write.
 | 
			
		||||
	WriteThenFatal
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// CheckedEntry is an Entry together with a collection of Cores that have
 | 
			
		||||
// already agreed to log it.
 | 
			
		||||
//
 | 
			
		||||
// CheckedEntry references should be created by calling AddCore or Should on a
 | 
			
		||||
// nil *CheckedEntry. References are returned to a pool after Write, and MUST
 | 
			
		||||
// NOT be retained after calling their Write method.
 | 
			
		||||
type CheckedEntry struct {
 | 
			
		||||
	Entry
 | 
			
		||||
	ErrorOutput WriteSyncer
 | 
			
		||||
	dirty       bool // best-effort detection of pool misuse
 | 
			
		||||
	should      CheckWriteAction
 | 
			
		||||
	cores       []Core
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ce *CheckedEntry) reset() {
 | 
			
		||||
	ce.Entry = Entry{}
 | 
			
		||||
	ce.ErrorOutput = nil
 | 
			
		||||
	ce.dirty = false
 | 
			
		||||
	ce.should = WriteThenNoop
 | 
			
		||||
	for i := range ce.cores {
 | 
			
		||||
		// don't keep references to cores
 | 
			
		||||
		ce.cores[i] = nil
 | 
			
		||||
	}
 | 
			
		||||
	ce.cores = ce.cores[:0]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Write writes the entry to the stored Cores, returns any errors, and returns
 | 
			
		||||
// the CheckedEntry reference to a pool for immediate re-use. Finally, it
 | 
			
		||||
// executes any required CheckWriteAction.
 | 
			
		||||
func (ce *CheckedEntry) Write(fields ...Field) {
 | 
			
		||||
	if ce == nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ce.dirty {
 | 
			
		||||
		if ce.ErrorOutput != nil {
 | 
			
		||||
			// Make a best effort to detect unsafe re-use of this CheckedEntry.
 | 
			
		||||
			// If the entry is dirty, log an internal error; because the
 | 
			
		||||
			// CheckedEntry is being used after it was returned to the pool,
 | 
			
		||||
			// the message may be an amalgamation from multiple call sites.
 | 
			
		||||
			fmt.Fprintf(ce.ErrorOutput, "%v Unsafe CheckedEntry re-use near Entry %+v.\n", ce.Time, ce.Entry)
 | 
			
		||||
			ce.ErrorOutput.Sync()
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	ce.dirty = true
 | 
			
		||||
 | 
			
		||||
	var err error
 | 
			
		||||
	for i := range ce.cores {
 | 
			
		||||
		err = multierr.Append(err, ce.cores[i].Write(ce.Entry, fields))
 | 
			
		||||
	}
 | 
			
		||||
	if err != nil && ce.ErrorOutput != nil {
 | 
			
		||||
		fmt.Fprintf(ce.ErrorOutput, "%v write error: %v\n", ce.Time, err)
 | 
			
		||||
		ce.ErrorOutput.Sync()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	should, msg := ce.should, ce.Message
 | 
			
		||||
	putCheckedEntry(ce)
 | 
			
		||||
 | 
			
		||||
	switch should {
 | 
			
		||||
	case WriteThenPanic:
 | 
			
		||||
		panic(msg)
 | 
			
		||||
	case WriteThenFatal:
 | 
			
		||||
		exit.Exit()
 | 
			
		||||
	case WriteThenGoexit:
 | 
			
		||||
		runtime.Goexit()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AddCore adds a Core that has agreed to log this CheckedEntry. It's intended to be
 | 
			
		||||
// used by Core.Check implementations, and is safe to call on nil CheckedEntry
 | 
			
		||||
// references.
 | 
			
		||||
func (ce *CheckedEntry) AddCore(ent Entry, core Core) *CheckedEntry {
 | 
			
		||||
	if ce == nil {
 | 
			
		||||
		ce = getCheckedEntry()
 | 
			
		||||
		ce.Entry = ent
 | 
			
		||||
	}
 | 
			
		||||
	ce.cores = append(ce.cores, core)
 | 
			
		||||
	return ce
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Should sets this CheckedEntry's CheckWriteAction, which controls whether a
 | 
			
		||||
// Core will panic or fatal after writing this log entry. Like AddCore, it's
 | 
			
		||||
// safe to call on nil CheckedEntry references.
 | 
			
		||||
func (ce *CheckedEntry) Should(ent Entry, should CheckWriteAction) *CheckedEntry {
 | 
			
		||||
	if ce == nil {
 | 
			
		||||
		ce = getCheckedEntry()
 | 
			
		||||
		ce.Entry = ent
 | 
			
		||||
	}
 | 
			
		||||
	ce.should = should
 | 
			
		||||
	return ce
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										132
									
								
								vendor/go.uber.org/zap/zapcore/error.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								vendor/go.uber.org/zap/zapcore/error.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,132 @@
 | 
			
		||||
// Copyright (c) 2017 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 zapcore
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"sync"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Encodes the given error into fields of an object. A field with the given
 | 
			
		||||
// name is added for the error message.
 | 
			
		||||
//
 | 
			
		||||
// If the error implements fmt.Formatter, a field with the name ${key}Verbose
 | 
			
		||||
// is also added with the full verbose error message.
 | 
			
		||||
//
 | 
			
		||||
// Finally, if the error implements errorGroup (from go.uber.org/multierr) or
 | 
			
		||||
// causer (from github.com/pkg/errors), a ${key}Causes field is added with an
 | 
			
		||||
// array of objects containing the errors this error was comprised of.
 | 
			
		||||
//
 | 
			
		||||
//  {
 | 
			
		||||
//    "error": err.Error(),
 | 
			
		||||
//    "errorVerbose": fmt.Sprintf("%+v", err),
 | 
			
		||||
//    "errorCauses": [
 | 
			
		||||
//      ...
 | 
			
		||||
//    ],
 | 
			
		||||
//  }
 | 
			
		||||
func encodeError(key string, err error, enc ObjectEncoder) (retErr error) {
 | 
			
		||||
	// Try to capture panics (from nil references or otherwise) when calling
 | 
			
		||||
	// the Error() method
 | 
			
		||||
	defer func() {
 | 
			
		||||
		if rerr := recover(); rerr != nil {
 | 
			
		||||
			// If it's a nil pointer, just say "<nil>". The likeliest causes are a
 | 
			
		||||
			// error that fails to guard against nil or a nil pointer for a
 | 
			
		||||
			// value receiver, and in either case, "<nil>" is a nice result.
 | 
			
		||||
			if v := reflect.ValueOf(err); v.Kind() == reflect.Ptr && v.IsNil() {
 | 
			
		||||
				enc.AddString(key, "<nil>")
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			retErr = fmt.Errorf("PANIC=%v", rerr)
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	basic := err.Error()
 | 
			
		||||
	enc.AddString(key, basic)
 | 
			
		||||
 | 
			
		||||
	switch e := err.(type) {
 | 
			
		||||
	case errorGroup:
 | 
			
		||||
		return enc.AddArray(key+"Causes", errArray(e.Errors()))
 | 
			
		||||
	case fmt.Formatter:
 | 
			
		||||
		verbose := fmt.Sprintf("%+v", e)
 | 
			
		||||
		if verbose != basic {
 | 
			
		||||
			// This is a rich error type, like those produced by
 | 
			
		||||
			// github.com/pkg/errors.
 | 
			
		||||
			enc.AddString(key+"Verbose", verbose)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type errorGroup interface {
 | 
			
		||||
	// Provides read-only access to the underlying list of errors, preferably
 | 
			
		||||
	// without causing any allocs.
 | 
			
		||||
	Errors() []error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Note that errArray and errArrayElem are very similar to the version
 | 
			
		||||
// implemented in the top-level error.go file. We can't re-use this because
 | 
			
		||||
// that would require exporting errArray as part of the zapcore API.
 | 
			
		||||
 | 
			
		||||
// Encodes a list of errors using the standard error encoding logic.
 | 
			
		||||
type errArray []error
 | 
			
		||||
 | 
			
		||||
func (errs errArray) MarshalLogArray(arr ArrayEncoder) error {
 | 
			
		||||
	for i := range errs {
 | 
			
		||||
		if errs[i] == nil {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		el := newErrArrayElem(errs[i])
 | 
			
		||||
		arr.AppendObject(el)
 | 
			
		||||
		el.Free()
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _errArrayElemPool = sync.Pool{New: func() interface{} {
 | 
			
		||||
	return &errArrayElem{}
 | 
			
		||||
}}
 | 
			
		||||
 | 
			
		||||
// Encodes any error into a {"error": ...} re-using the same errors logic.
 | 
			
		||||
//
 | 
			
		||||
// May be passed in place of an array to build a single-element array.
 | 
			
		||||
type errArrayElem struct{ err error }
 | 
			
		||||
 | 
			
		||||
func newErrArrayElem(err error) *errArrayElem {
 | 
			
		||||
	e := _errArrayElemPool.Get().(*errArrayElem)
 | 
			
		||||
	e.err = err
 | 
			
		||||
	return e
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *errArrayElem) MarshalLogArray(arr ArrayEncoder) error {
 | 
			
		||||
	return arr.AppendObject(e)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *errArrayElem) MarshalLogObject(enc ObjectEncoder) error {
 | 
			
		||||
	return encodeError("error", e.err, enc)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *errArrayElem) Free() {
 | 
			
		||||
	e.err = nil
 | 
			
		||||
	_errArrayElemPool.Put(e)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										233
									
								
								vendor/go.uber.org/zap/zapcore/field.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										233
									
								
								vendor/go.uber.org/zap/zapcore/field.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,233 @@
 | 
			
		||||
// 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 zapcore
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"math"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// A FieldType indicates which member of the Field union struct should be used
 | 
			
		||||
// and how it should be serialized.
 | 
			
		||||
type FieldType uint8
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// UnknownType is the default field type. Attempting to add it to an encoder will panic.
 | 
			
		||||
	UnknownType FieldType = iota
 | 
			
		||||
	// ArrayMarshalerType indicates that the field carries an ArrayMarshaler.
 | 
			
		||||
	ArrayMarshalerType
 | 
			
		||||
	// ObjectMarshalerType indicates that the field carries an ObjectMarshaler.
 | 
			
		||||
	ObjectMarshalerType
 | 
			
		||||
	// BinaryType indicates that the field carries an opaque binary blob.
 | 
			
		||||
	BinaryType
 | 
			
		||||
	// BoolType indicates that the field carries a bool.
 | 
			
		||||
	BoolType
 | 
			
		||||
	// ByteStringType indicates that the field carries UTF-8 encoded bytes.
 | 
			
		||||
	ByteStringType
 | 
			
		||||
	// Complex128Type indicates that the field carries a complex128.
 | 
			
		||||
	Complex128Type
 | 
			
		||||
	// Complex64Type indicates that the field carries a complex128.
 | 
			
		||||
	Complex64Type
 | 
			
		||||
	// DurationType indicates that the field carries a time.Duration.
 | 
			
		||||
	DurationType
 | 
			
		||||
	// Float64Type indicates that the field carries a float64.
 | 
			
		||||
	Float64Type
 | 
			
		||||
	// Float32Type indicates that the field carries a float32.
 | 
			
		||||
	Float32Type
 | 
			
		||||
	// Int64Type indicates that the field carries an int64.
 | 
			
		||||
	Int64Type
 | 
			
		||||
	// Int32Type indicates that the field carries an int32.
 | 
			
		||||
	Int32Type
 | 
			
		||||
	// Int16Type indicates that the field carries an int16.
 | 
			
		||||
	Int16Type
 | 
			
		||||
	// Int8Type indicates that the field carries an int8.
 | 
			
		||||
	Int8Type
 | 
			
		||||
	// StringType indicates that the field carries a string.
 | 
			
		||||
	StringType
 | 
			
		||||
	// TimeType indicates that the field carries a time.Time that is
 | 
			
		||||
	// representable by a UnixNano() stored as an int64.
 | 
			
		||||
	TimeType
 | 
			
		||||
	// TimeFullType indicates that the field carries a time.Time stored as-is.
 | 
			
		||||
	TimeFullType
 | 
			
		||||
	// Uint64Type indicates that the field carries a uint64.
 | 
			
		||||
	Uint64Type
 | 
			
		||||
	// Uint32Type indicates that the field carries a uint32.
 | 
			
		||||
	Uint32Type
 | 
			
		||||
	// Uint16Type indicates that the field carries a uint16.
 | 
			
		||||
	Uint16Type
 | 
			
		||||
	// Uint8Type indicates that the field carries a uint8.
 | 
			
		||||
	Uint8Type
 | 
			
		||||
	// UintptrType indicates that the field carries a uintptr.
 | 
			
		||||
	UintptrType
 | 
			
		||||
	// ReflectType indicates that the field carries an interface{}, which should
 | 
			
		||||
	// be serialized using reflection.
 | 
			
		||||
	ReflectType
 | 
			
		||||
	// NamespaceType signals the beginning of an isolated namespace. All
 | 
			
		||||
	// subsequent fields should be added to the new namespace.
 | 
			
		||||
	NamespaceType
 | 
			
		||||
	// StringerType indicates that the field carries a fmt.Stringer.
 | 
			
		||||
	StringerType
 | 
			
		||||
	// ErrorType indicates that the field carries an error.
 | 
			
		||||
	ErrorType
 | 
			
		||||
	// SkipType indicates that the field is a no-op.
 | 
			
		||||
	SkipType
 | 
			
		||||
 | 
			
		||||
	// InlineMarshalerType indicates that the field carries an ObjectMarshaler
 | 
			
		||||
	// that should be inlined.
 | 
			
		||||
	InlineMarshalerType
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// A Field is a marshaling operation used to add a key-value pair to a logger's
 | 
			
		||||
// context. Most fields are lazily marshaled, so it's inexpensive to add fields
 | 
			
		||||
// to disabled debug-level log statements.
 | 
			
		||||
type Field struct {
 | 
			
		||||
	Key       string
 | 
			
		||||
	Type      FieldType
 | 
			
		||||
	Integer   int64
 | 
			
		||||
	String    string
 | 
			
		||||
	Interface interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AddTo exports a field through the ObjectEncoder interface. It's primarily
 | 
			
		||||
// useful to library authors, and shouldn't be necessary in most applications.
 | 
			
		||||
func (f Field) AddTo(enc ObjectEncoder) {
 | 
			
		||||
	var err error
 | 
			
		||||
 | 
			
		||||
	switch f.Type {
 | 
			
		||||
	case ArrayMarshalerType:
 | 
			
		||||
		err = enc.AddArray(f.Key, f.Interface.(ArrayMarshaler))
 | 
			
		||||
	case ObjectMarshalerType:
 | 
			
		||||
		err = enc.AddObject(f.Key, f.Interface.(ObjectMarshaler))
 | 
			
		||||
	case InlineMarshalerType:
 | 
			
		||||
		err = f.Interface.(ObjectMarshaler).MarshalLogObject(enc)
 | 
			
		||||
	case BinaryType:
 | 
			
		||||
		enc.AddBinary(f.Key, f.Interface.([]byte))
 | 
			
		||||
	case BoolType:
 | 
			
		||||
		enc.AddBool(f.Key, f.Integer == 1)
 | 
			
		||||
	case ByteStringType:
 | 
			
		||||
		enc.AddByteString(f.Key, f.Interface.([]byte))
 | 
			
		||||
	case Complex128Type:
 | 
			
		||||
		enc.AddComplex128(f.Key, f.Interface.(complex128))
 | 
			
		||||
	case Complex64Type:
 | 
			
		||||
		enc.AddComplex64(f.Key, f.Interface.(complex64))
 | 
			
		||||
	case DurationType:
 | 
			
		||||
		enc.AddDuration(f.Key, time.Duration(f.Integer))
 | 
			
		||||
	case Float64Type:
 | 
			
		||||
		enc.AddFloat64(f.Key, math.Float64frombits(uint64(f.Integer)))
 | 
			
		||||
	case Float32Type:
 | 
			
		||||
		enc.AddFloat32(f.Key, math.Float32frombits(uint32(f.Integer)))
 | 
			
		||||
	case Int64Type:
 | 
			
		||||
		enc.AddInt64(f.Key, f.Integer)
 | 
			
		||||
	case Int32Type:
 | 
			
		||||
		enc.AddInt32(f.Key, int32(f.Integer))
 | 
			
		||||
	case Int16Type:
 | 
			
		||||
		enc.AddInt16(f.Key, int16(f.Integer))
 | 
			
		||||
	case Int8Type:
 | 
			
		||||
		enc.AddInt8(f.Key, int8(f.Integer))
 | 
			
		||||
	case StringType:
 | 
			
		||||
		enc.AddString(f.Key, f.String)
 | 
			
		||||
	case TimeType:
 | 
			
		||||
		if f.Interface != nil {
 | 
			
		||||
			enc.AddTime(f.Key, time.Unix(0, f.Integer).In(f.Interface.(*time.Location)))
 | 
			
		||||
		} else {
 | 
			
		||||
			// Fall back to UTC if location is nil.
 | 
			
		||||
			enc.AddTime(f.Key, time.Unix(0, f.Integer))
 | 
			
		||||
		}
 | 
			
		||||
	case TimeFullType:
 | 
			
		||||
		enc.AddTime(f.Key, f.Interface.(time.Time))
 | 
			
		||||
	case Uint64Type:
 | 
			
		||||
		enc.AddUint64(f.Key, uint64(f.Integer))
 | 
			
		||||
	case Uint32Type:
 | 
			
		||||
		enc.AddUint32(f.Key, uint32(f.Integer))
 | 
			
		||||
	case Uint16Type:
 | 
			
		||||
		enc.AddUint16(f.Key, uint16(f.Integer))
 | 
			
		||||
	case Uint8Type:
 | 
			
		||||
		enc.AddUint8(f.Key, uint8(f.Integer))
 | 
			
		||||
	case UintptrType:
 | 
			
		||||
		enc.AddUintptr(f.Key, uintptr(f.Integer))
 | 
			
		||||
	case ReflectType:
 | 
			
		||||
		err = enc.AddReflected(f.Key, f.Interface)
 | 
			
		||||
	case NamespaceType:
 | 
			
		||||
		enc.OpenNamespace(f.Key)
 | 
			
		||||
	case StringerType:
 | 
			
		||||
		err = encodeStringer(f.Key, f.Interface, enc)
 | 
			
		||||
	case ErrorType:
 | 
			
		||||
		err = encodeError(f.Key, f.Interface.(error), enc)
 | 
			
		||||
	case SkipType:
 | 
			
		||||
		break
 | 
			
		||||
	default:
 | 
			
		||||
		panic(fmt.Sprintf("unknown field type: %v", f))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		enc.AddString(fmt.Sprintf("%sError", f.Key), err.Error())
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Equals returns whether two fields are equal. For non-primitive types such as
 | 
			
		||||
// errors, marshalers, or reflect types, it uses reflect.DeepEqual.
 | 
			
		||||
func (f Field) Equals(other Field) bool {
 | 
			
		||||
	if f.Type != other.Type {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	if f.Key != other.Key {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch f.Type {
 | 
			
		||||
	case BinaryType, ByteStringType:
 | 
			
		||||
		return bytes.Equal(f.Interface.([]byte), other.Interface.([]byte))
 | 
			
		||||
	case ArrayMarshalerType, ObjectMarshalerType, ErrorType, ReflectType:
 | 
			
		||||
		return reflect.DeepEqual(f.Interface, other.Interface)
 | 
			
		||||
	default:
 | 
			
		||||
		return f == other
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func addFields(enc ObjectEncoder, fields []Field) {
 | 
			
		||||
	for i := range fields {
 | 
			
		||||
		fields[i].AddTo(enc)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func encodeStringer(key string, stringer interface{}, enc ObjectEncoder) (retErr error) {
 | 
			
		||||
	// Try to capture panics (from nil references or otherwise) when calling
 | 
			
		||||
	// the String() method, similar to https://golang.org/src/fmt/print.go#L540
 | 
			
		||||
	defer func() {
 | 
			
		||||
		if err := recover(); err != nil {
 | 
			
		||||
			// If it's a nil pointer, just say "<nil>". The likeliest causes are a
 | 
			
		||||
			// Stringer that fails to guard against nil or a nil pointer for a
 | 
			
		||||
			// value receiver, and in either case, "<nil>" is a nice result.
 | 
			
		||||
			if v := reflect.ValueOf(stringer); v.Kind() == reflect.Ptr && v.IsNil() {
 | 
			
		||||
				enc.AddString(key, "<nil>")
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			retErr = fmt.Errorf("PANIC=%v", err)
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	enc.AddString(key, stringer.(fmt.Stringer).String())
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										68
									
								
								vendor/go.uber.org/zap/zapcore/hook.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								vendor/go.uber.org/zap/zapcore/hook.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,68 @@
 | 
			
		||||
// 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 zapcore
 | 
			
		||||
 | 
			
		||||
import "go.uber.org/multierr"
 | 
			
		||||
 | 
			
		||||
type hooked struct {
 | 
			
		||||
	Core
 | 
			
		||||
	funcs []func(Entry) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RegisterHooks wraps a Core and runs a collection of user-defined callback
 | 
			
		||||
// hooks each time a message is logged. Execution of the callbacks is blocking.
 | 
			
		||||
//
 | 
			
		||||
// This offers users an easy way to register simple callbacks (e.g., metrics
 | 
			
		||||
// collection) without implementing the full Core interface.
 | 
			
		||||
func RegisterHooks(core Core, hooks ...func(Entry) error) Core {
 | 
			
		||||
	funcs := append([]func(Entry) error{}, hooks...)
 | 
			
		||||
	return &hooked{
 | 
			
		||||
		Core:  core,
 | 
			
		||||
		funcs: funcs,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *hooked) Check(ent Entry, ce *CheckedEntry) *CheckedEntry {
 | 
			
		||||
	// Let the wrapped Core decide whether to log this message or not. This
 | 
			
		||||
	// also gives the downstream a chance to register itself directly with the
 | 
			
		||||
	// CheckedEntry.
 | 
			
		||||
	if downstream := h.Core.Check(ent, ce); downstream != nil {
 | 
			
		||||
		return downstream.AddCore(ent, h)
 | 
			
		||||
	}
 | 
			
		||||
	return ce
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *hooked) With(fields []Field) Core {
 | 
			
		||||
	return &hooked{
 | 
			
		||||
		Core:  h.Core.With(fields),
 | 
			
		||||
		funcs: h.funcs,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *hooked) Write(ent Entry, _ []Field) error {
 | 
			
		||||
	// Since our downstream had a chance to register itself directly with the
 | 
			
		||||
	// CheckedMessage, we don't need to call it here.
 | 
			
		||||
	var err error
 | 
			
		||||
	for i := range h.funcs {
 | 
			
		||||
		err = multierr.Append(err, h.funcs[i](ent))
 | 
			
		||||
	}
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										66
									
								
								vendor/go.uber.org/zap/zapcore/increase_level.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								vendor/go.uber.org/zap/zapcore/increase_level.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
			
		||||
// Copyright (c) 2020 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 zapcore
 | 
			
		||||
 | 
			
		||||
import "fmt"
 | 
			
		||||
 | 
			
		||||
type levelFilterCore struct {
 | 
			
		||||
	core  Core
 | 
			
		||||
	level LevelEnabler
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewIncreaseLevelCore creates a core that can be used to increase the level of
 | 
			
		||||
// an existing Core. It cannot be used to decrease the logging level, as it acts
 | 
			
		||||
// as a filter before calling the underlying core. If level decreases the log level,
 | 
			
		||||
// an error is returned.
 | 
			
		||||
func NewIncreaseLevelCore(core Core, level LevelEnabler) (Core, error) {
 | 
			
		||||
	for l := _maxLevel; l >= _minLevel; l-- {
 | 
			
		||||
		if !core.Enabled(l) && level.Enabled(l) {
 | 
			
		||||
			return nil, fmt.Errorf("invalid increase level, as level %q is allowed by increased level, but not by existing core", l)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &levelFilterCore{core, level}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *levelFilterCore) Enabled(lvl Level) bool {
 | 
			
		||||
	return c.level.Enabled(lvl)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *levelFilterCore) With(fields []Field) Core {
 | 
			
		||||
	return &levelFilterCore{c.core.With(fields), c.level}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *levelFilterCore) Check(ent Entry, ce *CheckedEntry) *CheckedEntry {
 | 
			
		||||
	if !c.Enabled(ent.Level) {
 | 
			
		||||
		return ce
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return c.core.Check(ent, ce)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *levelFilterCore) Write(ent Entry, fields []Field) error {
 | 
			
		||||
	return c.core.Write(ent, fields)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *levelFilterCore) Sync() error {
 | 
			
		||||
	return c.core.Sync()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										542
									
								
								vendor/go.uber.org/zap/zapcore/json_encoder.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										542
									
								
								vendor/go.uber.org/zap/zapcore/json_encoder.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,542 @@
 | 
			
		||||
// 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 zapcore
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/base64"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"math"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"time"
 | 
			
		||||
	"unicode/utf8"
 | 
			
		||||
 | 
			
		||||
	"go.uber.org/zap/buffer"
 | 
			
		||||
	"go.uber.org/zap/internal/bufferpool"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// 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 {
 | 
			
		||||
	*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 EncoderConfig) Encoder {
 | 
			
		||||
	return newJSONEncoder(cfg, false)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newJSONEncoder(cfg EncoderConfig, spaced bool) *jsonEncoder {
 | 
			
		||||
	return &jsonEncoder{
 | 
			
		||||
		EncoderConfig: &cfg,
 | 
			
		||||
		buf:           bufferpool.Get(),
 | 
			
		||||
		spaced:        spaced,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (enc *jsonEncoder) AddArray(key string, arr ArrayMarshaler) error {
 | 
			
		||||
	enc.addKey(key)
 | 
			
		||||
	return enc.AppendArray(arr)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (enc *jsonEncoder) AddObject(key string, obj 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) AddFloat32(key string, val float32) {
 | 
			
		||||
	enc.addKey(key)
 | 
			
		||||
	enc.AppendFloat32(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 ArrayMarshaler) error {
 | 
			
		||||
	enc.addElementSeparator()
 | 
			
		||||
	enc.buf.AppendByte('[')
 | 
			
		||||
	err := arr.MarshalLogArray(enc)
 | 
			
		||||
	enc.buf.AppendByte(']')
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (enc *jsonEncoder) AppendObject(obj 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)
 | 
			
		||||
	// If imaginary part is less than 0, minus (-) sign is added by default
 | 
			
		||||
	// by AppendFloat.
 | 
			
		||||
	if i >= 0 {
 | 
			
		||||
		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) 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() 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 Entry, fields []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 = 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(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
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										175
									
								
								vendor/go.uber.org/zap/zapcore/level.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								vendor/go.uber.org/zap/zapcore/level.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,175 @@
 | 
			
		||||
// 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 zapcore
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var errUnmarshalNilLevel = errors.New("can't unmarshal a nil *Level")
 | 
			
		||||
 | 
			
		||||
// A Level is a logging priority. Higher levels are more important.
 | 
			
		||||
type Level int8
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// DebugLevel logs are typically voluminous, and are usually disabled in
 | 
			
		||||
	// production.
 | 
			
		||||
	DebugLevel Level = iota - 1
 | 
			
		||||
	// InfoLevel is the default logging priority.
 | 
			
		||||
	InfoLevel
 | 
			
		||||
	// WarnLevel logs are more important than Info, but don't need individual
 | 
			
		||||
	// human review.
 | 
			
		||||
	WarnLevel
 | 
			
		||||
	// ErrorLevel logs are high-priority. If an application is running smoothly,
 | 
			
		||||
	// it shouldn't generate any error-level logs.
 | 
			
		||||
	ErrorLevel
 | 
			
		||||
	// DPanicLevel logs are particularly important errors. In development the
 | 
			
		||||
	// logger panics after writing the message.
 | 
			
		||||
	DPanicLevel
 | 
			
		||||
	// PanicLevel logs a message, then panics.
 | 
			
		||||
	PanicLevel
 | 
			
		||||
	// FatalLevel logs a message, then calls os.Exit(1).
 | 
			
		||||
	FatalLevel
 | 
			
		||||
 | 
			
		||||
	_minLevel = DebugLevel
 | 
			
		||||
	_maxLevel = FatalLevel
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// String returns a lower-case ASCII representation of the log level.
 | 
			
		||||
func (l Level) String() string {
 | 
			
		||||
	switch l {
 | 
			
		||||
	case DebugLevel:
 | 
			
		||||
		return "debug"
 | 
			
		||||
	case InfoLevel:
 | 
			
		||||
		return "info"
 | 
			
		||||
	case WarnLevel:
 | 
			
		||||
		return "warn"
 | 
			
		||||
	case ErrorLevel:
 | 
			
		||||
		return "error"
 | 
			
		||||
	case DPanicLevel:
 | 
			
		||||
		return "dpanic"
 | 
			
		||||
	case PanicLevel:
 | 
			
		||||
		return "panic"
 | 
			
		||||
	case FatalLevel:
 | 
			
		||||
		return "fatal"
 | 
			
		||||
	default:
 | 
			
		||||
		return fmt.Sprintf("Level(%d)", l)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CapitalString returns an all-caps ASCII representation of the log level.
 | 
			
		||||
func (l Level) CapitalString() string {
 | 
			
		||||
	// Printing levels in all-caps is common enough that we should export this
 | 
			
		||||
	// functionality.
 | 
			
		||||
	switch l {
 | 
			
		||||
	case DebugLevel:
 | 
			
		||||
		return "DEBUG"
 | 
			
		||||
	case InfoLevel:
 | 
			
		||||
		return "INFO"
 | 
			
		||||
	case WarnLevel:
 | 
			
		||||
		return "WARN"
 | 
			
		||||
	case ErrorLevel:
 | 
			
		||||
		return "ERROR"
 | 
			
		||||
	case DPanicLevel:
 | 
			
		||||
		return "DPANIC"
 | 
			
		||||
	case PanicLevel:
 | 
			
		||||
		return "PANIC"
 | 
			
		||||
	case FatalLevel:
 | 
			
		||||
		return "FATAL"
 | 
			
		||||
	default:
 | 
			
		||||
		return fmt.Sprintf("LEVEL(%d)", l)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MarshalText marshals the Level to text. Note that the text representation
 | 
			
		||||
// drops the -Level suffix (see example).
 | 
			
		||||
func (l Level) MarshalText() ([]byte, error) {
 | 
			
		||||
	return []byte(l.String()), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UnmarshalText unmarshals text to a level. Like MarshalText, UnmarshalText
 | 
			
		||||
// expects the text representation of a Level to drop the -Level suffix (see
 | 
			
		||||
// example).
 | 
			
		||||
//
 | 
			
		||||
// In particular, this makes it easy to configure logging levels using YAML,
 | 
			
		||||
// TOML, or JSON files.
 | 
			
		||||
func (l *Level) UnmarshalText(text []byte) error {
 | 
			
		||||
	if l == nil {
 | 
			
		||||
		return errUnmarshalNilLevel
 | 
			
		||||
	}
 | 
			
		||||
	if !l.unmarshalText(text) && !l.unmarshalText(bytes.ToLower(text)) {
 | 
			
		||||
		return fmt.Errorf("unrecognized level: %q", text)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l *Level) unmarshalText(text []byte) bool {
 | 
			
		||||
	switch string(text) {
 | 
			
		||||
	case "debug", "DEBUG":
 | 
			
		||||
		*l = DebugLevel
 | 
			
		||||
	case "info", "INFO", "": // make the zero value useful
 | 
			
		||||
		*l = InfoLevel
 | 
			
		||||
	case "warn", "WARN":
 | 
			
		||||
		*l = WarnLevel
 | 
			
		||||
	case "error", "ERROR":
 | 
			
		||||
		*l = ErrorLevel
 | 
			
		||||
	case "dpanic", "DPANIC":
 | 
			
		||||
		*l = DPanicLevel
 | 
			
		||||
	case "panic", "PANIC":
 | 
			
		||||
		*l = PanicLevel
 | 
			
		||||
	case "fatal", "FATAL":
 | 
			
		||||
		*l = FatalLevel
 | 
			
		||||
	default:
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Set sets the level for the flag.Value interface.
 | 
			
		||||
func (l *Level) Set(s string) error {
 | 
			
		||||
	return l.UnmarshalText([]byte(s))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get gets the level for the flag.Getter interface.
 | 
			
		||||
func (l *Level) Get() interface{} {
 | 
			
		||||
	return *l
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Enabled returns true if the given level is at or above this level.
 | 
			
		||||
func (l Level) Enabled(lvl Level) bool {
 | 
			
		||||
	return lvl >= l
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LevelEnabler decides whether a given logging level is enabled when logging a
 | 
			
		||||
// message.
 | 
			
		||||
//
 | 
			
		||||
// Enablers are intended to be used to implement deterministic filters;
 | 
			
		||||
// concerns like sampling are better implemented as a Core.
 | 
			
		||||
//
 | 
			
		||||
// Each concrete Level value implements a static LevelEnabler which returns
 | 
			
		||||
// true for itself and all higher logging levels. For example WarnLevel.Enabled()
 | 
			
		||||
// will return true for WarnLevel, ErrorLevel, DPanicLevel, PanicLevel, and
 | 
			
		||||
// FatalLevel, but return false for InfoLevel and DebugLevel.
 | 
			
		||||
type LevelEnabler interface {
 | 
			
		||||
	Enabled(Level) bool
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										46
									
								
								vendor/go.uber.org/zap/zapcore/level_strings.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								vendor/go.uber.org/zap/zapcore/level_strings.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
// 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 zapcore
 | 
			
		||||
 | 
			
		||||
import "go.uber.org/zap/internal/color"
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	_levelToColor = map[Level]color.Color{
 | 
			
		||||
		DebugLevel:  color.Magenta,
 | 
			
		||||
		InfoLevel:   color.Blue,
 | 
			
		||||
		WarnLevel:   color.Yellow,
 | 
			
		||||
		ErrorLevel:  color.Red,
 | 
			
		||||
		DPanicLevel: color.Red,
 | 
			
		||||
		PanicLevel:  color.Red,
 | 
			
		||||
		FatalLevel:  color.Red,
 | 
			
		||||
	}
 | 
			
		||||
	_unknownLevelColor = color.Red
 | 
			
		||||
 | 
			
		||||
	_levelToLowercaseColorString = make(map[Level]string, len(_levelToColor))
 | 
			
		||||
	_levelToCapitalColorString   = make(map[Level]string, len(_levelToColor))
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	for level, color := range _levelToColor {
 | 
			
		||||
		_levelToLowercaseColorString[level] = color.Add(level.String())
 | 
			
		||||
		_levelToCapitalColorString[level] = color.Add(level.CapitalString())
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										61
									
								
								vendor/go.uber.org/zap/zapcore/marshaler.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								vendor/go.uber.org/zap/zapcore/marshaler.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
			
		||||
// 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 zapcore
 | 
			
		||||
 | 
			
		||||
// ObjectMarshaler allows user-defined types to efficiently add themselves to the
 | 
			
		||||
// logging context, and to selectively omit information which shouldn't be
 | 
			
		||||
// included in logs (e.g., passwords).
 | 
			
		||||
//
 | 
			
		||||
// Note: ObjectMarshaler is only used when zap.Object is used or when
 | 
			
		||||
// passed directly to zap.Any. It is not used when reflection-based
 | 
			
		||||
// encoding is used.
 | 
			
		||||
type ObjectMarshaler interface {
 | 
			
		||||
	MarshalLogObject(ObjectEncoder) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ObjectMarshalerFunc is a type adapter that turns a function into an
 | 
			
		||||
// ObjectMarshaler.
 | 
			
		||||
type ObjectMarshalerFunc func(ObjectEncoder) error
 | 
			
		||||
 | 
			
		||||
// MarshalLogObject calls the underlying function.
 | 
			
		||||
func (f ObjectMarshalerFunc) MarshalLogObject(enc ObjectEncoder) error {
 | 
			
		||||
	return f(enc)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ArrayMarshaler allows user-defined types to efficiently add themselves to the
 | 
			
		||||
// logging context, and to selectively omit information which shouldn't be
 | 
			
		||||
// included in logs (e.g., passwords).
 | 
			
		||||
//
 | 
			
		||||
// Note: ArrayMarshaler is only used when zap.Array is used or when
 | 
			
		||||
// passed directly to zap.Any. It is not used when reflection-based
 | 
			
		||||
// encoding is used.
 | 
			
		||||
type ArrayMarshaler interface {
 | 
			
		||||
	MarshalLogArray(ArrayEncoder) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ArrayMarshalerFunc is a type adapter that turns a function into an
 | 
			
		||||
// ArrayMarshaler.
 | 
			
		||||
type ArrayMarshalerFunc func(ArrayEncoder) error
 | 
			
		||||
 | 
			
		||||
// MarshalLogArray calls the underlying function.
 | 
			
		||||
func (f ArrayMarshalerFunc) MarshalLogArray(enc ArrayEncoder) error {
 | 
			
		||||
	return f(enc)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										179
									
								
								vendor/go.uber.org/zap/zapcore/memory_encoder.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										179
									
								
								vendor/go.uber.org/zap/zapcore/memory_encoder.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,179 @@
 | 
			
		||||
// 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 zapcore
 | 
			
		||||
 | 
			
		||||
import "time"
 | 
			
		||||
 | 
			
		||||
// 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 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 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 ArrayMarshaler) error {
 | 
			
		||||
	enc := &sliceArrayEncoder{}
 | 
			
		||||
	err := v.MarshalLogArray(enc)
 | 
			
		||||
	s.elems = append(s.elems, enc.elems)
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *sliceArrayEncoder) AppendObject(v 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) }
 | 
			
		||||
							
								
								
									
										210
									
								
								vendor/go.uber.org/zap/zapcore/sampler.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								vendor/go.uber.org/zap/zapcore/sampler.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,210 @@
 | 
			
		||||
// 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 zapcore
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"go.uber.org/atomic"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	_numLevels        = _maxLevel - _minLevel + 1
 | 
			
		||||
	_countersPerLevel = 4096
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type counter struct {
 | 
			
		||||
	resetAt atomic.Int64
 | 
			
		||||
	counter atomic.Uint64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type counters [_numLevels][_countersPerLevel]counter
 | 
			
		||||
 | 
			
		||||
func newCounters() *counters {
 | 
			
		||||
	return &counters{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (cs *counters) get(lvl Level, key string) *counter {
 | 
			
		||||
	i := lvl - _minLevel
 | 
			
		||||
	j := fnv32a(key) % _countersPerLevel
 | 
			
		||||
	return &cs[i][j]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// fnv32a, adapted from "hash/fnv", but without a []byte(string) alloc
 | 
			
		||||
func fnv32a(s string) uint32 {
 | 
			
		||||
	const (
 | 
			
		||||
		offset32 = 2166136261
 | 
			
		||||
		prime32  = 16777619
 | 
			
		||||
	)
 | 
			
		||||
	hash := uint32(offset32)
 | 
			
		||||
	for i := 0; i < len(s); i++ {
 | 
			
		||||
		hash ^= uint32(s[i])
 | 
			
		||||
		hash *= prime32
 | 
			
		||||
	}
 | 
			
		||||
	return hash
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *counter) IncCheckReset(t time.Time, tick time.Duration) uint64 {
 | 
			
		||||
	tn := t.UnixNano()
 | 
			
		||||
	resetAfter := c.resetAt.Load()
 | 
			
		||||
	if resetAfter > tn {
 | 
			
		||||
		return c.counter.Inc()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	c.counter.Store(1)
 | 
			
		||||
 | 
			
		||||
	newResetAfter := tn + tick.Nanoseconds()
 | 
			
		||||
	if !c.resetAt.CAS(resetAfter, newResetAfter) {
 | 
			
		||||
		// We raced with another goroutine trying to reset, and it also reset
 | 
			
		||||
		// the counter to 1, so we need to reincrement the counter.
 | 
			
		||||
		return c.counter.Inc()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SamplingDecision is a decision represented as a bit field made by sampler.
 | 
			
		||||
// More decisions may be added in the future.
 | 
			
		||||
type SamplingDecision uint32
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// LogDropped indicates that the Sampler dropped a log entry.
 | 
			
		||||
	LogDropped SamplingDecision = 1 << iota
 | 
			
		||||
	// LogSampled indicates that the Sampler sampled a log entry.
 | 
			
		||||
	LogSampled
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// optionFunc wraps a func so it satisfies the SamplerOption interface.
 | 
			
		||||
type optionFunc func(*sampler)
 | 
			
		||||
 | 
			
		||||
func (f optionFunc) apply(s *sampler) {
 | 
			
		||||
	f(s)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SamplerOption configures a Sampler.
 | 
			
		||||
type SamplerOption interface {
 | 
			
		||||
	apply(*sampler)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// nopSamplingHook is the default hook used by sampler.
 | 
			
		||||
func nopSamplingHook(Entry, SamplingDecision) {}
 | 
			
		||||
 | 
			
		||||
// SamplerHook registers a function  which will be called when Sampler makes a
 | 
			
		||||
// decision.
 | 
			
		||||
//
 | 
			
		||||
// This hook may be used to get visibility into the performance of the sampler.
 | 
			
		||||
// For example, use it to track metrics of dropped versus sampled logs.
 | 
			
		||||
//
 | 
			
		||||
//  var dropped atomic.Int64
 | 
			
		||||
//  zapcore.SamplerHook(func(ent zapcore.Entry, dec zapcore.SamplingDecision) {
 | 
			
		||||
//    if dec&zapcore.LogDropped > 0 {
 | 
			
		||||
//      dropped.Inc()
 | 
			
		||||
//    }
 | 
			
		||||
//  })
 | 
			
		||||
func SamplerHook(hook func(entry Entry, dec SamplingDecision)) SamplerOption {
 | 
			
		||||
	return optionFunc(func(s *sampler) {
 | 
			
		||||
		s.hook = hook
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewSamplerWithOptions creates a Core that samples incoming entries, which
 | 
			
		||||
// caps the CPU and I/O load of logging while attempting to preserve a
 | 
			
		||||
// representative subset of your logs.
 | 
			
		||||
//
 | 
			
		||||
// Zap samples by logging the first N entries with a given level and message
 | 
			
		||||
// each tick. If more Entries with the same level and message are seen during
 | 
			
		||||
// the same interval, every Mth message is logged and the rest are dropped.
 | 
			
		||||
//
 | 
			
		||||
// Sampler can be configured to report sampling decisions with the SamplerHook
 | 
			
		||||
// option.
 | 
			
		||||
//
 | 
			
		||||
// Keep in mind that zap's sampling implementation is optimized for speed over
 | 
			
		||||
// absolute precision; under load, each tick may be slightly over- or
 | 
			
		||||
// under-sampled.
 | 
			
		||||
func NewSamplerWithOptions(core Core, tick time.Duration, first, thereafter int, opts ...SamplerOption) Core {
 | 
			
		||||
	s := &sampler{
 | 
			
		||||
		Core:       core,
 | 
			
		||||
		tick:       tick,
 | 
			
		||||
		counts:     newCounters(),
 | 
			
		||||
		first:      uint64(first),
 | 
			
		||||
		thereafter: uint64(thereafter),
 | 
			
		||||
		hook:       nopSamplingHook,
 | 
			
		||||
	}
 | 
			
		||||
	for _, opt := range opts {
 | 
			
		||||
		opt.apply(s)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return s
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type sampler struct {
 | 
			
		||||
	Core
 | 
			
		||||
 | 
			
		||||
	counts            *counters
 | 
			
		||||
	tick              time.Duration
 | 
			
		||||
	first, thereafter uint64
 | 
			
		||||
	hook              func(Entry, SamplingDecision)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewSampler creates a Core that samples incoming entries, which
 | 
			
		||||
// caps the CPU and I/O load of logging while attempting to preserve a
 | 
			
		||||
// representative subset of your logs.
 | 
			
		||||
//
 | 
			
		||||
// Zap samples by logging the first N entries with a given level and message
 | 
			
		||||
// each tick. If more Entries with the same level and message are seen during
 | 
			
		||||
// the same interval, every Mth message is logged and the rest are dropped.
 | 
			
		||||
//
 | 
			
		||||
// Keep in mind that zap's sampling implementation is optimized for speed over
 | 
			
		||||
// absolute precision; under load, each tick may be slightly over- or
 | 
			
		||||
// under-sampled.
 | 
			
		||||
//
 | 
			
		||||
// Deprecated: use NewSamplerWithOptions.
 | 
			
		||||
func NewSampler(core Core, tick time.Duration, first, thereafter int) Core {
 | 
			
		||||
	return NewSamplerWithOptions(core, tick, first, thereafter)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *sampler) With(fields []Field) Core {
 | 
			
		||||
	return &sampler{
 | 
			
		||||
		Core:       s.Core.With(fields),
 | 
			
		||||
		tick:       s.tick,
 | 
			
		||||
		counts:     s.counts,
 | 
			
		||||
		first:      s.first,
 | 
			
		||||
		thereafter: s.thereafter,
 | 
			
		||||
		hook:       s.hook,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *sampler) Check(ent Entry, ce *CheckedEntry) *CheckedEntry {
 | 
			
		||||
	if !s.Enabled(ent.Level) {
 | 
			
		||||
		return ce
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ent.Level >= _minLevel && ent.Level <= _maxLevel {
 | 
			
		||||
		counter := s.counts.get(ent.Level, ent.Message)
 | 
			
		||||
		n := counter.IncCheckReset(ent.Time, s.tick)
 | 
			
		||||
		if n > s.first && (n-s.first)%s.thereafter != 0 {
 | 
			
		||||
			s.hook(ent, LogDropped)
 | 
			
		||||
			return ce
 | 
			
		||||
		}
 | 
			
		||||
		s.hook(ent, LogSampled)
 | 
			
		||||
	}
 | 
			
		||||
	return s.Core.Check(ent, ce)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										81
									
								
								vendor/go.uber.org/zap/zapcore/tee.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								vendor/go.uber.org/zap/zapcore/tee.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,81 @@
 | 
			
		||||
// 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 zapcore
 | 
			
		||||
 | 
			
		||||
import "go.uber.org/multierr"
 | 
			
		||||
 | 
			
		||||
type multiCore []Core
 | 
			
		||||
 | 
			
		||||
// NewTee creates a Core that duplicates log entries into two or more
 | 
			
		||||
// underlying Cores.
 | 
			
		||||
//
 | 
			
		||||
// Calling it with a single Core returns the input unchanged, and calling
 | 
			
		||||
// it with no input returns a no-op Core.
 | 
			
		||||
func NewTee(cores ...Core) Core {
 | 
			
		||||
	switch len(cores) {
 | 
			
		||||
	case 0:
 | 
			
		||||
		return NewNopCore()
 | 
			
		||||
	case 1:
 | 
			
		||||
		return cores[0]
 | 
			
		||||
	default:
 | 
			
		||||
		return multiCore(cores)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (mc multiCore) With(fields []Field) Core {
 | 
			
		||||
	clone := make(multiCore, len(mc))
 | 
			
		||||
	for i := range mc {
 | 
			
		||||
		clone[i] = mc[i].With(fields)
 | 
			
		||||
	}
 | 
			
		||||
	return clone
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (mc multiCore) Enabled(lvl Level) bool {
 | 
			
		||||
	for i := range mc {
 | 
			
		||||
		if mc[i].Enabled(lvl) {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (mc multiCore) Check(ent Entry, ce *CheckedEntry) *CheckedEntry {
 | 
			
		||||
	for i := range mc {
 | 
			
		||||
		ce = mc[i].Check(ent, ce)
 | 
			
		||||
	}
 | 
			
		||||
	return ce
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (mc multiCore) Write(ent Entry, fields []Field) error {
 | 
			
		||||
	var err error
 | 
			
		||||
	for i := range mc {
 | 
			
		||||
		err = multierr.Append(err, mc[i].Write(ent, fields))
 | 
			
		||||
	}
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (mc multiCore) Sync() error {
 | 
			
		||||
	var err error
 | 
			
		||||
	for i := range mc {
 | 
			
		||||
		err = multierr.Append(err, mc[i].Sync())
 | 
			
		||||
	}
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										122
									
								
								vendor/go.uber.org/zap/zapcore/write_syncer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								vendor/go.uber.org/zap/zapcore/write_syncer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,122 @@
 | 
			
		||||
// 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 zapcore
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"io"
 | 
			
		||||
	"sync"
 | 
			
		||||
 | 
			
		||||
	"go.uber.org/multierr"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// A WriteSyncer is an io.Writer that can also flush any buffered data. Note
 | 
			
		||||
// that *os.File (and thus, os.Stderr and os.Stdout) implement WriteSyncer.
 | 
			
		||||
type WriteSyncer interface {
 | 
			
		||||
	io.Writer
 | 
			
		||||
	Sync() error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AddSync converts an io.Writer to a WriteSyncer. It attempts to be
 | 
			
		||||
// intelligent: if the concrete type of the io.Writer implements WriteSyncer,
 | 
			
		||||
// we'll use the existing Sync method. If it doesn't, we'll add a no-op Sync.
 | 
			
		||||
func AddSync(w io.Writer) WriteSyncer {
 | 
			
		||||
	switch w := w.(type) {
 | 
			
		||||
	case WriteSyncer:
 | 
			
		||||
		return w
 | 
			
		||||
	default:
 | 
			
		||||
		return writerWrapper{w}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type lockedWriteSyncer struct {
 | 
			
		||||
	sync.Mutex
 | 
			
		||||
	ws WriteSyncer
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Lock wraps a WriteSyncer in a mutex to make it safe for concurrent use. In
 | 
			
		||||
// particular, *os.Files must be locked before use.
 | 
			
		||||
func Lock(ws WriteSyncer) WriteSyncer {
 | 
			
		||||
	if _, ok := ws.(*lockedWriteSyncer); ok {
 | 
			
		||||
		// no need to layer on another lock
 | 
			
		||||
		return ws
 | 
			
		||||
	}
 | 
			
		||||
	return &lockedWriteSyncer{ws: ws}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *lockedWriteSyncer) Write(bs []byte) (int, error) {
 | 
			
		||||
	s.Lock()
 | 
			
		||||
	n, err := s.ws.Write(bs)
 | 
			
		||||
	s.Unlock()
 | 
			
		||||
	return n, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *lockedWriteSyncer) Sync() error {
 | 
			
		||||
	s.Lock()
 | 
			
		||||
	err := s.ws.Sync()
 | 
			
		||||
	s.Unlock()
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type writerWrapper struct {
 | 
			
		||||
	io.Writer
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w writerWrapper) Sync() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type multiWriteSyncer []WriteSyncer
 | 
			
		||||
 | 
			
		||||
// NewMultiWriteSyncer creates a WriteSyncer that duplicates its writes
 | 
			
		||||
// and sync calls, much like io.MultiWriter.
 | 
			
		||||
func NewMultiWriteSyncer(ws ...WriteSyncer) WriteSyncer {
 | 
			
		||||
	if len(ws) == 1 {
 | 
			
		||||
		return ws[0]
 | 
			
		||||
	}
 | 
			
		||||
	return multiWriteSyncer(ws)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// See https://golang.org/src/io/multi.go
 | 
			
		||||
// When not all underlying syncers write the same number of bytes,
 | 
			
		||||
// the smallest number is returned even though Write() is called on
 | 
			
		||||
// all of them.
 | 
			
		||||
func (ws multiWriteSyncer) Write(p []byte) (int, error) {
 | 
			
		||||
	var writeErr error
 | 
			
		||||
	nWritten := 0
 | 
			
		||||
	for _, w := range ws {
 | 
			
		||||
		n, err := w.Write(p)
 | 
			
		||||
		writeErr = multierr.Append(writeErr, err)
 | 
			
		||||
		if nWritten == 0 && n != 0 {
 | 
			
		||||
			nWritten = n
 | 
			
		||||
		} else if n < nWritten {
 | 
			
		||||
			nWritten = n
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nWritten, writeErr
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ws multiWriteSyncer) Sync() error {
 | 
			
		||||
	var err error
 | 
			
		||||
	for _, w := range ws {
 | 
			
		||||
		err = multierr.Append(err, w.Sync())
 | 
			
		||||
	}
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user