or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

fields.mdindex.mdintegrations.mdlogger.mdtesting.mdzapcore.md
tile.json

zapcore.mddocs/

Core Abstractions API

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.

Package Import

import "go.uber.org/zap/zapcore"

Core Interface

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
}

Core Constructors

// 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

Sampling Cores

// 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
)

Encoder Interface

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)
}

Encoder Constructors

// Create JSON encoder
func NewJSONEncoder(cfg EncoderConfig) Encoder

// Create human-readable console encoder
func NewConsoleEncoder(cfg EncoderConfig) Encoder

EncoderConfig

type 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:

  • MessageKey: Key for log message (use OmitKey to omit)
  • LevelKey: Key for log level
  • TimeKey: Key for timestamp
  • NameKey: Key for logger name
  • CallerKey: Key for caller information (file:line)
  • FunctionKey: Key for function name
  • StacktraceKey: Key for stack trace
  • SkipLineEnding: Omit line ending after each entry
  • LineEnding: Line ending character(s), defaults to DefaultLineEnding ("\n")
  • EncodeLevel: How to encode level to primitive type
  • EncodeTime: How to encode time.Time
  • EncodeDuration: How to encode time.Duration
  • EncodeCaller: How to encode caller information
  • EncodeName: How to encode logger name
  • NewReflectedEncoder: Constructor for reflection-based encoder
  • ConsoleSeparator: Separator between fields in console encoder

Encoder Constants

const DefaultLineEnding = "\n"
const OmitKey = ""

ObjectEncoder Interface

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

MapObjectEncoder is a testing implementation backed by map[string]interface{}.

type MapObjectEncoder struct {
    Fields map[string]interface{}
    // Has unexported fields
}

func NewMapObjectEncoder() *MapObjectEncoder

MapObjectEncoder implements the full ObjectEncoder interface with all Add* methods writing to the Fields map.

ArrayEncoder Interface

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 Interface

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)
}

Marshaler Interfaces

ObjectMarshaler

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) error

ObjectMarshalerFunc is an adapter to use functions as ObjectMarshalers.

ArrayMarshaler

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) error

ArrayMarshalerFunc is an adapter to use functions as ArrayMarshalers.

WriteSyncer Interface

WriteSyncer groups io.Writer with a Sync method for flushing.

type WriteSyncer interface {
    io.Writer
    Sync() error
}

WriteSyncer Constructors

// 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) WriteSyncer

BufferedWriteSyncer

BufferedWriteSyncer 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 Types

Level

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
)

Level Methods

// 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{}

Level Functions

// Parse level from string
func ParseLevel(text string) (Level, error)

// Get minimum enabled level from LevelEnabler
func LevelOf(enab LevelEnabler) Level

LevelEnabler Interface

type LevelEnabler interface {
    Enabled(Level) bool
}

LevelEnabler decides whether a given logging level is enabled.

Encoder Function Types

LevelEncoder

type LevelEncoder func(Level, PrimitiveArrayEncoder)

// Unmarshal text to LevelEncoder
func (e *LevelEncoder) UnmarshalText(text []byte) error

Predefined 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)

TimeEncoder

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) error

Predefined 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) TimeEncoder

DurationEncoder

type DurationEncoder func(time.Duration, PrimitiveArrayEncoder)

// Unmarshal text to DurationEncoder
func (e *DurationEncoder) UnmarshalText(text []byte) error

Predefined 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)

CallerEncoder

type CallerEncoder func(EntryCaller, PrimitiveArrayEncoder)

// Unmarshal text to CallerEncoder
func (e *CallerEncoder) UnmarshalText(text []byte) error

Predefined CallerEncoders:

func ShortCallerEncoder(caller EntryCaller, enc PrimitiveArrayEncoder)
func FullCallerEncoder(caller EntryCaller, enc PrimitiveArrayEncoder)

NameEncoder

type NameEncoder func(string, PrimitiveArrayEncoder)

// Unmarshal text to NameEncoder
func (e *NameEncoder) UnmarshalText(text []byte) error

Predefined NameEncoders:

func FullNameEncoder(loggerName string, enc PrimitiveArrayEncoder)

Entry Types

Entry

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

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() string

CheckedEntry

CheckedEntry 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) *CheckedEntry

CheckWriteAction

type CheckWriteAction uint8

const (
    WriteThenNoop   CheckWriteAction = iota
    WriteThenGoexit
    WriteThenPanic
    WriteThenFatal
)

// Implement OnWrite for compatibility with CheckWriteHook
func (a CheckWriteAction) OnWrite(ce *CheckedEntry, _ []Field)

CheckWriteHook

type CheckWriteHook interface {
    OnWrite(*CheckedEntry, []Field)
}

CheckWriteHook defines custom action after log entry is written.

Field Type

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) bool

FieldType

type 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
)

ReflectedEncoder Interface

type ReflectedEncoder interface {
    Encode(interface{}) error
}

ReflectedEncoder converts log fields using reflection.

Clock Interface

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.

Usage Examples

Custom Core

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()
}

Custom Object Marshaler

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))

Custom Array Marshaler

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))

Multi-Output Core

// 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)

Level-Split Logging

// 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)

Sampling 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()
        }
    }),
)

Custom Encoder Configuration

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)