mirror of
https://github.com/cwinfo/matterbridge.git
synced 2025-07-06 16:34:04 +00:00
Update direct dependencies where possible
This commit is contained in:
147
vendor/go.uber.org/zap/zapcore/console_encoder.go
generated
vendored
Normal file
147
vendor/go.uber.org/zap/zapcore/console_encoder.go
generated
vendored
Normal file
@ -0,0 +1,147 @@
|
||||
// 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 {
|
||||
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 && c.CallerKey != "" && c.EncodeCaller != nil {
|
||||
c.EncodeCaller(ent.Caller, arr)
|
||||
}
|
||||
for i := range arr.elems {
|
||||
if i > 0 {
|
||||
line.AppendByte('\t')
|
||||
}
|
||||
fmt.Fprint(line, arr.elems[i])
|
||||
}
|
||||
putSliceEncoder(arr)
|
||||
|
||||
// Add the message itself.
|
||||
if c.MessageKey != "" {
|
||||
c.addTabIfNecessary(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 context.buf.Free()
|
||||
|
||||
addFields(context, extra)
|
||||
context.closeOpenNamespaces()
|
||||
if context.buf.Len() == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
c.addTabIfNecessary(line)
|
||||
line.AppendByte('{')
|
||||
line.Write(context.buf.Bytes())
|
||||
line.AppendByte('}')
|
||||
}
|
||||
|
||||
func (c consoleEncoder) addTabIfNecessary(line *buffer.Buffer) {
|
||||
if line.Len() > 0 {
|
||||
line.AppendByte('\t')
|
||||
}
|
||||
}
|
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"
|
348
vendor/go.uber.org/zap/zapcore/encoder.go
generated
vendored
Normal file
348
vendor/go.uber.org/zap/zapcore/encoder.go
generated
vendored
Normal file
@ -0,0 +1,348 @@
|
||||
// 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/zap/buffer"
|
||||
)
|
||||
|
||||
// DefaultLineEnding defines the default line ending when writing logs.
|
||||
// Alternate line endings specified in EncoderConfig can override this
|
||||
// behavior.
|
||||
const DefaultLineEnding = "\n"
|
||||
|
||||
// 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())
|
||||
}
|
||||
|
||||
// ISO8601TimeEncoder serializes a time.Time to an ISO8601-formatted string
|
||||
// with millisecond precision.
|
||||
func ISO8601TimeEncoder(t time.Time, enc PrimitiveArrayEncoder) {
|
||||
enc.AppendString(t.Format("2006-01-02T15:04:05.000Z0700"))
|
||||
}
|
||||
|
||||
// UnmarshalText unmarshals text to a TimeEncoder. "iso8601" and "ISO8601" are
|
||||
// unmarshaled to ISO8601TimeEncoder, "millis" is unmarshaled to
|
||||
// EpochMillisTimeEncoder, and anything else is unmarshaled to EpochTimeEncoder.
|
||||
func (e *TimeEncoder) UnmarshalText(text []byte) error {
|
||||
switch string(text) {
|
||||
case "iso8601", "ISO8601":
|
||||
*e = ISO8601TimeEncoder
|
||||
case "millis":
|
||||
*e = EpochMillisTimeEncoder
|
||||
case "nanos":
|
||||
*e = EpochNanosTimeEncoder
|
||||
default:
|
||||
*e = EpochTimeEncoder
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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))
|
||||
}
|
||||
|
||||
// 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
|
||||
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"`
|
||||
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"`
|
||||
}
|
||||
|
||||
// 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's 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.
|
||||
EncodeEntry(Entry, []Field) (*buffer.Buffer, error)
|
||||
}
|
257
vendor/go.uber.org/zap/zapcore/entry.go
generated
vendored
Normal file
257
vendor/go.uber.org/zap/zapcore/entry.go
generated
vendored
Normal file
@ -0,0 +1,257 @@
|
||||
// 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"
|
||||
"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
|
||||
}
|
||||
|
||||
// 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.
|
||||
//
|
||||
// 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
|
||||
// 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", time.Now(), 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 ce.ErrorOutput != nil {
|
||||
if err != nil {
|
||||
fmt.Fprintf(ce.ErrorOutput, "%v write error: %v\n", time.Now(), err)
|
||||
ce.ErrorOutput.Sync()
|
||||
}
|
||||
}
|
||||
|
||||
should, msg := ce.should, ce.Message
|
||||
putCheckedEntry(ce)
|
||||
|
||||
switch should {
|
||||
case WriteThenPanic:
|
||||
panic(msg)
|
||||
case WriteThenFatal:
|
||||
exit.Exit()
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
120
vendor/go.uber.org/zap/zapcore/error.go
generated
vendored
Normal file
120
vendor/go.uber.org/zap/zapcore/error.go
generated
vendored
Normal file
@ -0,0 +1,120 @@
|
||||
// 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"
|
||||
"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) error {
|
||||
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
|
||||
}
|
||||
|
||||
type causer interface {
|
||||
// Provides access to the error that caused this error.
|
||||
Cause() error
|
||||
}
|
||||
|
||||
// Note that errArry 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)
|
||||
}
|
201
vendor/go.uber.org/zap/zapcore/field.go
generated
vendored
Normal file
201
vendor/go.uber.org/zap/zapcore/field.go
generated
vendored
Normal file
@ -0,0 +1,201 @@
|
||||
// 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.
|
||||
TimeType
|
||||
// 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
|
||||
)
|
||||
|
||||
// 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 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 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:
|
||||
enc.AddString(f.Key, f.Interface.(fmt.Stringer).String())
|
||||
case ErrorType:
|
||||
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)
|
||||
}
|
||||
}
|
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
|
||||
}
|
502
vendor/go.uber.org/zap/zapcore/json_encoder.go
generated
vendored
Normal file
502
vendor/go.uber.org/zap/zapcore/json_encoder.go
generated
vendored
Normal file
@ -0,0 +1,502 @@
|
||||
// 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) 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)
|
||||
} else {
|
||||
enc.reflectBuf.Reset()
|
||||
}
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) AddReflected(key string, obj interface{}) error {
|
||||
enc.resetReflectBuf()
|
||||
err := enc.reflectEnc.Encode(obj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
enc.reflectBuf.TrimNewline()
|
||||
enc.addKey(key)
|
||||
_, err = enc.buf.Write(enc.reflectBuf.Bytes())
|
||||
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)
|
||||
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()
|
||||
enc.EncodeDuration(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 {
|
||||
enc.resetReflectBuf()
|
||||
err := enc.reflectEnc.Encode(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
enc.reflectBuf.TrimNewline()
|
||||
enc.addElementSeparator()
|
||||
_, err = enc.buf.Write(enc.reflectBuf.Bytes())
|
||||
return err
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) AppendString(val string) {
|
||||
enc.addElementSeparator()
|
||||
enc.buf.AppendByte('"')
|
||||
enc.safeAddString(val)
|
||||
enc.buf.AppendByte('"')
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) AppendTime(val time.Time) {
|
||||
cur := enc.buf.Len()
|
||||
enc.EncodeTime(val, enc)
|
||||
if cur == enc.buf.Len() {
|
||||
// User-supplied EncodeTime is a no-op. Fall back to nanos since epoch to keep
|
||||
// output JSON valid.
|
||||
enc.AppendInt64(val.UnixNano())
|
||||
}
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) AppendUint64(val uint64) {
|
||||
enc.addElementSeparator()
|
||||
enc.buf.AppendUint(val)
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) AddComplex64(k string, v complex64) { enc.AddComplex128(k, complex128(v)) }
|
||||
func (enc *jsonEncoder) AddFloat32(k string, v float32) { enc.AddFloat64(k, float64(v)) }
|
||||
func (enc *jsonEncoder) AddInt(k string, v int) { enc.AddInt64(k, int64(v)) }
|
||||
func (enc *jsonEncoder) AddInt32(k string, v int32) { enc.AddInt64(k, int64(v)) }
|
||||
func (enc *jsonEncoder) AddInt16(k string, v int16) { enc.AddInt64(k, int64(v)) }
|
||||
func (enc *jsonEncoder) AddInt8(k string, v int8) { enc.AddInt64(k, int64(v)) }
|
||||
func (enc *jsonEncoder) AddUint(k string, v uint) { enc.AddUint64(k, uint64(v)) }
|
||||
func (enc *jsonEncoder) AddUint32(k string, v uint32) { enc.AddUint64(k, uint64(v)) }
|
||||
func (enc *jsonEncoder) AddUint16(k string, v uint16) { enc.AddUint64(k, uint64(v)) }
|
||||
func (enc *jsonEncoder) AddUint8(k string, v uint8) { enc.AddUint64(k, uint64(v)) }
|
||||
func (enc *jsonEncoder) AddUintptr(k string, v uintptr) { enc.AddUint64(k, uint64(v)) }
|
||||
func (enc *jsonEncoder) AppendComplex64(v complex64) { enc.AppendComplex128(complex128(v)) }
|
||||
func (enc *jsonEncoder) AppendFloat64(v float64) { enc.appendFloat(v, 64) }
|
||||
func (enc *jsonEncoder) AppendFloat32(v float32) { enc.appendFloat(float64(v), 32) }
|
||||
func (enc *jsonEncoder) AppendInt(v int) { enc.AppendInt64(int64(v)) }
|
||||
func (enc *jsonEncoder) AppendInt32(v int32) { enc.AppendInt64(int64(v)) }
|
||||
func (enc *jsonEncoder) AppendInt16(v int16) { enc.AppendInt64(int64(v)) }
|
||||
func (enc *jsonEncoder) AppendInt8(v int8) { enc.AppendInt64(int64(v)) }
|
||||
func (enc *jsonEncoder) AppendUint(v uint) { enc.AppendUint64(uint64(v)) }
|
||||
func (enc *jsonEncoder) AppendUint32(v uint32) { enc.AppendUint64(uint64(v)) }
|
||||
func (enc *jsonEncoder) AppendUint16(v uint16) { enc.AppendUint64(uint64(v)) }
|
||||
func (enc *jsonEncoder) AppendUint8(v uint8) { enc.AppendUint64(uint64(v)) }
|
||||
func (enc *jsonEncoder) AppendUintptr(v uintptr) { enc.AppendUint64(uint64(v)) }
|
||||
|
||||
func (enc *jsonEncoder) Clone() 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 && 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.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())
|
||||
}
|
||||
}
|
53
vendor/go.uber.org/zap/zapcore/marshaler.go
generated
vendored
Normal file
53
vendor/go.uber.org/zap/zapcore/marshaler.go
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
// 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).
|
||||
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).
|
||||
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, 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) }
|
134
vendor/go.uber.org/zap/zapcore/sampler.go
generated
vendored
Normal file
134
vendor/go.uber.org/zap/zapcore/sampler.go
generated
vendored
Normal file
@ -0,0 +1,134 @@
|
||||
// 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
|
||||
}
|
||||
|
||||
type sampler struct {
|
||||
Core
|
||||
|
||||
counts *counters
|
||||
tick time.Duration
|
||||
first, thereafter uint64
|
||||
}
|
||||
|
||||
// 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.
|
||||
func NewSampler(core Core, tick time.Duration, first, thereafter int) Core {
|
||||
return &sampler{
|
||||
Core: core,
|
||||
tick: tick,
|
||||
counts: newCounters(),
|
||||
first: uint64(first),
|
||||
thereafter: uint64(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,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *sampler) Check(ent Entry, ce *CheckedEntry) *CheckedEntry {
|
||||
if !s.Enabled(ent.Level) {
|
||||
return ce
|
||||
}
|
||||
|
||||
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 {
|
||||
return ce
|
||||
}
|
||||
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
|
||||
}
|
123
vendor/go.uber.org/zap/zapcore/write_syncer.go
generated
vendored
Normal file
123
vendor/go.uber.org/zap/zapcore/write_syncer.go
generated
vendored
Normal file
@ -0,0 +1,123 @@
|
||||
// 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]
|
||||
}
|
||||
// Copy to protect against https://github.com/golang/go/issues/7809
|
||||
return multiWriteSyncer(append([]WriteSyncer(nil), 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