The zapcore package defines low-level interfaces and implementations that power zap's logging capabilities. It enables extending zap with custom encoders, cores, and write destinations.
import "go.uber.org/zap/zapcore"The Core interface is the minimal, fast logger interface around which zap is built.
type Core interface {
LevelEnabler
// With adds structured context to the Core
With([]Field) Core
// Check determines whether the supplied Entry should be logged
Check(Entry, *CheckedEntry) *CheckedEntry
// Write serializes the Entry and any Fields supplied
Write(Entry, []Field) error
// Sync flushes buffered logs
Sync() error
}// Create Core that writes to WriteSyncer
func NewCore(enc Encoder, ws WriteSyncer, enab LevelEnabler) Core
// Create no-op Core that never logs
func NewNopCore() Core
// Create Core that duplicates entries to multiple Cores
func NewTee(cores ...Core) Core
// Wrap Core with level filter that increases minimum level
func NewIncreaseLevelCore(core Core, level LevelEnabler) (Core, error)
// Wrap Core with lazy field evaluation
func NewLazyWith(core Core, fields []Field) Core
// Wrap Core with hooks called for each entry
func RegisterHooks(core Core, hooks ...func(Entry) error) Core// Create sampling Core (deprecated: use NewSamplerWithOptions)
func NewSampler(core Core, tick time.Duration, first, thereafter int) Core
// Create sampling Core with options
func NewSamplerWithOptions(
core Core,
tick time.Duration,
first int,
thereafter int,
opts ...SamplerOption,
) Core// SamplerOption configures a Sampler
type SamplerOption interface {
// Has unexported methods
}
// Register callback for sampling decisions
func SamplerHook(hook func(entry Entry, dec SamplingDecision)) SamplerOption// SamplingDecision represents sampler's decision as bit field
type SamplingDecision uint32
const (
LogDropped SamplingDecision = 1 << iota // Entry was dropped
LogSampled // Entry was sampled
)Encoders transform log entries into byte streams. Zap includes JSON and console encoders.
type Encoder interface {
ObjectEncoder
// Clone creates an independent copy
Clone() Encoder
// EncodeEntry encodes an entry and fields to bytes
EncodeEntry(Entry, []Field) (*buffer.Buffer, error)
}// Create JSON encoder
func NewJSONEncoder(cfg EncoderConfig) Encoder
// Create human-readable console encoder
func NewConsoleEncoder(cfg EncoderConfig) Encodertype EncoderConfig struct {
MessageKey string `json:"messageKey" yaml:"messageKey"`
LevelKey string `json:"levelKey" yaml:"levelKey"`
TimeKey string `json:"timeKey" yaml:"timeKey"`
NameKey string `json:"nameKey" yaml:"nameKey"`
CallerKey string `json:"callerKey" yaml:"callerKey"`
FunctionKey string `json:"functionKey" yaml:"functionKey"`
StacktraceKey string `json:"stacktraceKey" yaml:"stacktraceKey"`
SkipLineEnding bool `json:"skipLineEnding" yaml:"skipLineEnding"`
LineEnding string `json:"lineEnding" yaml:"lineEnding"`
EncodeLevel LevelEncoder `json:"levelEncoder" yaml:"levelEncoder"`
EncodeTime TimeEncoder `json:"timeEncoder" yaml:"timeEncoder"`
EncodeDuration DurationEncoder `json:"durationEncoder" yaml:"durationEncoder"`
EncodeCaller CallerEncoder `json:"callerEncoder" yaml:"callerEncoder"`
EncodeName NameEncoder `json:"nameEncoder" yaml:"nameEncoder"`
NewReflectedEncoder func(io.Writer) ReflectedEncoder `json:"-" yaml:"-"`
ConsoleSeparator string `json:"consoleSeparator" yaml:"consoleSeparator"`
}Field Descriptions:
OmitKey to omit)DefaultLineEnding ("\n")const DefaultLineEnding = "\n"
const OmitKey = ""ObjectEncoder adds map-like objects to logging context.
type ObjectEncoder interface {
// Add fields with various types
AddArray(key string, marshaler ArrayMarshaler) error
AddObject(key string, marshaler ObjectMarshaler) error
AddBinary(key string, value []byte)
AddByteString(key string, value []byte)
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(key string, value interface{}) error
// Open a namespace for subsequent fields
OpenNamespace(key string)
}MapObjectEncoder is a testing implementation backed by map[string]interface{}.
type MapObjectEncoder struct {
Fields map[string]interface{}
// Has unexported fields
}
func NewMapObjectEncoder() *MapObjectEncoderMapObjectEncoder implements the full ObjectEncoder interface with all Add* methods writing to the Fields map.
ArrayEncoder adds array-like objects to logging context.
type ArrayEncoder interface {
PrimitiveArrayEncoder
AppendDuration(time.Duration)
AppendTime(time.Time)
AppendArray(ArrayMarshaler) error
AppendObject(ObjectMarshaler) error
AppendReflected(value interface{}) error
}PrimitiveArrayEncoder appends Go built-in types to arrays.
type PrimitiveArrayEncoder interface {
AppendBool(bool)
AppendByteString([]byte)
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)
}type ObjectMarshaler interface {
MarshalLogObject(ObjectEncoder) error
}ObjectMarshaler allows custom types to efficiently add themselves to logging context.
type ObjectMarshalerFunc func(ObjectEncoder) error
func (f ObjectMarshalerFunc) MarshalLogObject(enc ObjectEncoder) errorObjectMarshalerFunc is an adapter to use functions as ObjectMarshalers.
type ArrayMarshaler interface {
MarshalLogArray(ArrayEncoder) error
}ArrayMarshaler allows custom types to efficiently serialize arrays.
type ArrayMarshalerFunc func(ArrayEncoder) error
func (f ArrayMarshalerFunc) MarshalLogArray(enc ArrayEncoder) errorArrayMarshalerFunc is an adapter to use functions as ArrayMarshalers.
WriteSyncer groups io.Writer with a Sync method for flushing.
type WriteSyncer interface {
io.Writer
Sync() error
}// Convert io.Writer to WriteSyncer
func AddSync(w io.Writer) WriteSyncer
// Wrap WriteSyncer with mutex for thread-safety
func Lock(ws WriteSyncer) WriteSyncer
// Duplicate writes to multiple WriteSyncers
func NewMultiWriteSyncer(ws ...WriteSyncer) WriteSyncerBufferedWriteSyncer buffers writes in-memory before flushing.
type BufferedWriteSyncer struct {
WS WriteSyncer // Underlying WriteSyncer
Size int // Buffer size in bytes
FlushInterval time.Duration // Maximum time between flushes
Clock Clock // Time source for flush timing
// Has unexported fields
}
// Close and flush buffer
func (s *BufferedWriteSyncer) Stop() error
// Flush buffered data
func (s *BufferedWriteSyncer) Sync() error
// Write to buffer
func (s *BufferedWriteSyncer) Write(bs []byte) (int, error)Level represents logging priority. Higher levels are more important.
type Level int8
const (
DebugLevel Level = iota - 1 // -1
InfoLevel // 0
WarnLevel // 1
ErrorLevel // 2
DPanicLevel // 3
PanicLevel // 4
FatalLevel // 5
InvalidLevel = _maxLevel + 1
)// Get lowercase string representation
func (l Level) String() string
// Get uppercase string representation
func (l Level) CapitalString() string
// Check if given level is enabled (implements LevelEnabler)
func (l Level) Enabled(lvl Level) bool
// Marshal to text
func (l Level) MarshalText() ([]byte, error)
// Unmarshal from text
func (l *Level) UnmarshalText(text []byte) error
// Set level from string (for flag.Value)
func (l *Level) Set(s string) error
// Get level value (for flag.Getter)
func (l *Level) Get() interface{}// Parse level from string
func ParseLevel(text string) (Level, error)
// Get minimum enabled level from LevelEnabler
func LevelOf(enab LevelEnabler) Leveltype LevelEnabler interface {
Enabled(Level) bool
}LevelEnabler decides whether a given logging level is enabled.
type LevelEncoder func(Level, PrimitiveArrayEncoder)
// Unmarshal text to LevelEncoder
func (e *LevelEncoder) UnmarshalText(text []byte) errorPredefined LevelEncoders:
func LowercaseLevelEncoder(l Level, enc PrimitiveArrayEncoder)
func LowercaseColorLevelEncoder(l Level, enc PrimitiveArrayEncoder)
func CapitalLevelEncoder(l Level, enc PrimitiveArrayEncoder)
func CapitalColorLevelEncoder(l Level, enc PrimitiveArrayEncoder)type TimeEncoder func(time.Time, PrimitiveArrayEncoder)
// Unmarshal text to TimeEncoder
func (e *TimeEncoder) UnmarshalText(text []byte) error
// Unmarshal YAML to TimeEncoder
func (e *TimeEncoder) UnmarshalYAML(unmarshal func(interface{}) error) error
// Unmarshal JSON to TimeEncoder
func (e *TimeEncoder) UnmarshalJSON(data []byte) errorPredefined TimeEncoders:
func EpochTimeEncoder(t time.Time, enc PrimitiveArrayEncoder)
func EpochMillisTimeEncoder(t time.Time, enc PrimitiveArrayEncoder)
func EpochNanosTimeEncoder(t time.Time, enc PrimitiveArrayEncoder)
func ISO8601TimeEncoder(t time.Time, enc PrimitiveArrayEncoder)
func RFC3339TimeEncoder(t time.Time, enc PrimitiveArrayEncoder)
func RFC3339NanoTimeEncoder(t time.Time, enc PrimitiveArrayEncoder)
// Create TimeEncoder with custom layout
func TimeEncoderOfLayout(layout string) TimeEncodertype DurationEncoder func(time.Duration, PrimitiveArrayEncoder)
// Unmarshal text to DurationEncoder
func (e *DurationEncoder) UnmarshalText(text []byte) errorPredefined DurationEncoders:
func SecondsDurationEncoder(d time.Duration, enc PrimitiveArrayEncoder)
func NanosDurationEncoder(d time.Duration, enc PrimitiveArrayEncoder)
func MillisDurationEncoder(d time.Duration, enc PrimitiveArrayEncoder)
func StringDurationEncoder(d time.Duration, enc PrimitiveArrayEncoder)type CallerEncoder func(EntryCaller, PrimitiveArrayEncoder)
// Unmarshal text to CallerEncoder
func (e *CallerEncoder) UnmarshalText(text []byte) errorPredefined CallerEncoders:
func ShortCallerEncoder(caller EntryCaller, enc PrimitiveArrayEncoder)
func FullCallerEncoder(caller EntryCaller, enc PrimitiveArrayEncoder)type NameEncoder func(string, PrimitiveArrayEncoder)
// Unmarshal text to NameEncoder
func (e *NameEncoder) UnmarshalText(text []byte) errorPredefined NameEncoders:
func FullNameEncoder(loggerName string, enc PrimitiveArrayEncoder)Entry represents a complete log message with metadata.
type Entry struct {
Level Level
Time time.Time
LoggerName string
Message string
Caller EntryCaller
Stack string
}EntryCaller represents the caller of a logging function.
type EntryCaller struct {
Defined bool
PC uintptr
File string
Line int
Function string
}
// Create EntryCaller from runtime.Caller results
func NewEntryCaller(pc uintptr, file string, line int, ok bool) EntryCaller
// Get string representation (file:line)
func (ec EntryCaller) String() string
// Get full path representation
func (ec EntryCaller) FullPath() string
// Get package/file:line representation
func (ec EntryCaller) TrimmedPath() stringCheckedEntry is an Entry together with Cores that agreed to log it.
type CheckedEntry struct {
Entry
ErrorOutput WriteSyncer
// Has unexported fields
}
// Add Core that agreed to log this entry
func (ce *CheckedEntry) AddCore(ent Entry, core Core) *CheckedEntry
// Set CheckWriteHook to execute after writing
func (ce *CheckedEntry) After(ent Entry, hook CheckWriteHook) *CheckedEntry
// Write entry to all stored Cores
func (ce *CheckedEntry) Write(fields ...Field)
// Deprecated: use After
func (ce *CheckedEntry) Should(ent Entry, should CheckWriteAction) *CheckedEntrytype CheckWriteAction uint8
const (
WriteThenNoop CheckWriteAction = iota
WriteThenGoexit
WriteThenPanic
WriteThenFatal
)
// Implement OnWrite for compatibility with CheckWriteHook
func (a CheckWriteAction) OnWrite(ce *CheckedEntry, _ []Field)type CheckWriteHook interface {
OnWrite(*CheckedEntry, []Field)
}CheckWriteHook defines custom action after log entry is written.
Field represents a marshaling operation for a key-value pair.
type Field struct {
Key string
Type FieldType
Integer int64
String string
Interface interface{}
}
// Export field through ObjectEncoder
func (f Field) AddTo(enc ObjectEncoder)
// Check if two fields are equal
func (f Field) Equals(other Field) booltype FieldType uint8
const (
UnknownType FieldType = iota
ArrayMarshalerType
ObjectMarshalerType
BinaryType
BoolType
ByteStringType
Complex128Type
Complex64Type
DurationType
Float64Type
Float32Type
Int64Type
Int32Type
Int16Type
Int8Type
StringType
TimeType
TimeFullType
Uint64Type
Uint32Type
Uint16Type
Uint8Type
UintptrType
ReflectType
NamespaceType
StringerType
ErrorType
SkipType
InlineMarshalerType
)type ReflectedEncoder interface {
Encode(interface{}) error
}ReflectedEncoder converts log fields using reflection.
Clock provides time source for log entries.
type Clock interface {
Now() time.Time
NewTicker(time.Duration) *time.Ticker
}
var DefaultClock = systemClock{}DefaultClock is the default clock used by zap for all time operations.
type CustomCore struct {
zapcore.LevelEnabler
encoder zapcore.Encoder
out zapcore.WriteSyncer
}
func (c *CustomCore) With(fields []zapcore.Field) zapcore.Core {
clone := c.encoder.Clone()
for _, f := range fields {
f.AddTo(clone)
}
return &CustomCore{
LevelEnabler: c.LevelEnabler,
encoder: clone,
out: c.out,
}
}
func (c *CustomCore) Check(ent zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry {
if c.Enabled(ent.Level) {
return ce.AddCore(ent, c)
}
return ce
}
func (c *CustomCore) Write(ent zapcore.Entry, fields []zapcore.Field) error {
buf, err := c.encoder.EncodeEntry(ent, fields)
if err != nil {
return err
}
_, err = c.out.Write(buf.Bytes())
buf.Free()
return err
}
func (c *CustomCore) Sync() error {
return c.out.Sync()
}type User struct {
ID int
Username string
Email string
}
func (u User) MarshalLogObject(enc zapcore.ObjectEncoder) error {
enc.AddInt("id", u.ID)
enc.AddString("username", u.Username)
enc.AddString("email", u.Email)
return nil
}
// Use in logging
logger.Info("user created", zap.Object("user", user))type Users []User
func (us Users) MarshalLogArray(enc zapcore.ArrayEncoder) error {
for _, u := range us {
if err := enc.AppendObject(u); err != nil {
return err
}
}
return nil
}
// Use in logging
logger.Info("batch created", zap.Array("users", users))// Log to both stdout and file
encoder := zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig())
fileWriter, _, _ := zap.Open("/var/log/app.log")
stdoutWriter := zapcore.Lock(os.Stdout)
core := zapcore.NewTee(
zapcore.NewCore(encoder, fileWriter, zapcore.InfoLevel),
zapcore.NewCore(encoder, stdoutWriter, zapcore.ErrorLevel),
)
logger := zap.New(core)// Info+ to stdout, Error+ to stderr
encoderCfg := zap.NewProductionEncoderConfig()
encoder := zapcore.NewJSONEncoder(encoderCfg)
infoLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
return lvl >= zapcore.InfoLevel && lvl < zapcore.ErrorLevel
})
errorLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
return lvl >= zapcore.ErrorLevel
})
core := zapcore.NewTee(
zapcore.NewCore(encoder, zapcore.Lock(os.Stdout), infoLevel),
zapcore.NewCore(encoder, zapcore.Lock(os.Stderr), errorLevel),
)
logger := zap.New(core)// Allow first 100/sec, then sample 1 in 10
core := zapcore.NewSamplerWithOptions(
zapcore.NewCore(encoder, syncer, zapcore.InfoLevel),
time.Second,
100, // first
10, // thereafter
zapcore.SamplerHook(func(entry zapcore.Entry, decision zapcore.SamplingDecision) {
if decision&zapcore.LogDropped != 0 {
droppedCounter.Inc()
}
}),
)config := zapcore.EncoderConfig{
TimeKey: "timestamp",
LevelKey: "severity",
NameKey: "logger",
CallerKey: "caller",
FunctionKey: zapcore.OmitKey,
MessageKey: "message",
StacktraceKey: "stacktrace",
LineEnding: zapcore.DefaultLineEnding,
EncodeLevel: zapcore.CapitalLevelEncoder,
EncodeTime: zapcore.RFC3339TimeEncoder,
EncodeDuration: zapcore.StringDurationEncoder,
EncodeCaller: zapcore.ShortCallerEncoder,
}
encoder := zapcore.NewJSONEncoder(config)