or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

advanced-types.mdcontextual-logging.mdcore-logging.mddiode-writer.mdfield-methods.mdglobal-configuration.mdglobal-logger.mdhooks.mdhttp-middleware.mdindex.mdjournald-integration.mdpkgerrors-integration.mdsampling.mdwriters-and-output.md
tile.json

field-methods.mddocs/

Field Methods

Zerolog provides comprehensive, strongly-typed field methods for adding data to log events. All field methods are available on both Event and Context types, with identical signatures. Methods on Event return *Event for chaining, while methods on Context return Context.

Imports

import (
    "fmt"
    "net"
    "time"
    "github.com/rs/zerolog"
)

String Fields

Basic String Fields

// Add string field
func (e *Event) Str(key, val string) *Event
func (c Context) Str(key, val string) Context

// Add string array field
func (e *Event) Strs(key string, vals []string) *Event
func (c Context) Strs(key string, vals []string) Context

Example:

logger.Info().
    Str("username", "alice").
    Str("operation", "login").
    Msg("user action")

logger.Info().
    Strs("tags", []string{"api", "production", "critical"}).
    Msg("service started")

Stringer Interface

// Add fmt.Stringer field (or null if val is nil)
func (e *Event) Stringer(key string, val fmt.Stringer) *Event
func (c Context) Stringer(key string, val fmt.Stringer) Context

// Add fmt.Stringer array field
func (e *Event) Stringers(key string, vals []fmt.Stringer) *Event
func (c Context) Stringers(key string, vals []fmt.Stringer) Context

Example:

type UserID int
func (u UserID) String() string { return fmt.Sprintf("user_%d", u) }

logger.Info().
    Stringer("user_id", UserID(42)).
    Msg("user action")
// Output includes: "user_id":"user_42"

Binary Fields

// Add bytes as string field
func (e *Event) Bytes(key string, val []byte) *Event
func (c Context) Bytes(key string, val []byte) Context

// Add bytes as hex-encoded string field
func (e *Event) Hex(key string, val []byte) *Event
func (c Context) Hex(key string, val []byte) Context

// Add pre-encoded JSON field (not escaped)
func (e *Event) RawJSON(key string, b []byte) *Event
func (c Context) RawJSON(key string, b []byte) Context

// Add pre-encoded CBOR field
func (e *Event) RawCBOR(key string, b []byte) *Event
func (c Context) RawCBOR(key string, b []byte) Context

Example:

data := []byte("hello")
logger.Info().
    Bytes("data", data).
    Hex("data_hex", data).
    Msg("binary data")
// Output: "data":"hello","data_hex":"68656c6c6f"

// Pre-encoded JSON
jsonData := []byte(`{"nested":"value","count":42}`)
logger.Info().
    RawJSON("metadata", jsonData).
    Msg("with metadata")
// Output: "metadata":{"nested":"value","count":42}

Boolean Fields

// Add boolean field
func (e *Event) Bool(key string, b bool) *Event
func (c Context) Bool(key string, b bool) Context

// Add boolean array field
func (e *Event) Bools(key string, b []bool) *Event
func (c Context) Bools(key string, b []bool) Context

Example:

logger.Info().
    Bool("success", true).
    Bool("authenticated", false).
    Msg("operation result")

logger.Debug().
    Bools("flags", []bool{true, false, true}).
    Msg("feature flags")

Integer Fields

Signed Integers

// Add int field
func (e *Event) Int(key string, i int) *Event
func (c Context) Int(key string, i int) Context

// Add int8 field
func (e *Event) Int8(key string, i int8) *Event
func (c Context) Int8(key string, i int8) Context

// Add int16 field
func (e *Event) Int16(key string, i int16) *Event
func (c Context) Int16(key string, i int16) Context

// Add int32 field
func (e *Event) Int32(key string, i int32) *Event
func (c Context) Int32(key string, i int32) Context

// Add int64 field
func (e *Event) Int64(key string, i int64) *Event
func (c Context) Int64(key string, i int64) Context

Example:

logger.Info().
    Int("status_code", 200).
    Int32("user_id", 42).
    Int64("bytes_processed", 1234567890).
    Msg("request completed")

Signed Integer Arrays

// Add int array field
func (e *Event) Ints(key string, i []int) *Event
func (c Context) Ints(key string, i []int) Context

// Add int8 array field
func (e *Event) Ints8(key string, i []int8) *Event
func (c Context) Ints8(key string, i []int8) Context

// Add int16 array field
func (e *Event) Ints16(key string, i []int16) *Event
func (c Context) Ints16(key string, i []int16) Context

// Add int32 array field
func (e *Event) Ints32(key string, i []int32) *Event
func (c Context) Ints32(key string, i []int32) Context

// Add int64 array field
func (e *Event) Ints64(key string, i []int64) *Event
func (c Context) Ints64(key string, i []int64) Context

Example:

logger.Info().
    Ints("scores", []int{100, 95, 87, 92}).
    Ints64("timestamps", []int64{1234567890, 1234567900}).
    Msg("batch results")

Unsigned Integers

// Add uint field
func (e *Event) Uint(key string, i uint) *Event
func (c Context) Uint(key string, i uint) Context

// Add uint8 field
func (e *Event) Uint8(key string, i uint8) *Event
func (c Context) Uint8(key string, i uint8) Context

// Add uint16 field
func (e *Event) Uint16(key string, i uint16) *Event
func (c Context) Uint16(key string, i uint16) Context

// Add uint32 field
func (e *Event) Uint32(key string, i uint32) *Event
func (c Context) Uint32(key string, i uint32) Context

// Add uint64 field
func (e *Event) Uint64(key string, i uint64) *Event
func (c Context) Uint64(key string, i uint64) Context

Example:

logger.Info().
    Uint16("port", 8080).
    Uint32("process_id", 12345).
    Uint64("request_count", 1000000).
    Msg("server stats")

Unsigned Integer Arrays

// Add uint array field
func (e *Event) Uints(key string, i []uint) *Event
func (c Context) Uints(key string, i []uint) Context

// Add uint8 array field
func (e *Event) Uints8(key string, i []uint8) *Event
func (c Context) Uints8(key string, i []uint8) Context

// Add uint16 array field
func (e *Event) Uints16(key string, i []uint16) *Event
func (c Context) Uints16(key string, i []uint16) Context

// Add uint32 array field
func (e *Event) Uints32(key string, i []uint32) *Event
func (c Context) Uints32(key string, i []uint32) Context

// Add uint64 array field
func (e *Event) Uints64(key string, i []uint64) *Event
func (c Context) Uints64(key string, i []uint64) Context

Example:

logger.Info().
    Uints16("open_ports", []uint16{80, 443, 8080}).
    Uints64("metrics", []uint64{1000, 2000, 3000}).
    Msg("system info")

Float Fields

// Add float32 field
func (e *Event) Float32(key string, f float32) *Event
func (c Context) Float32(key string, f float32) Context

// Add float64 field
func (e *Event) Float64(key string, f float64) *Event
func (c Context) Float64(key string, f float64) Context

// Add float32 array field
func (e *Event) Floats32(key string, f []float32) *Event
func (c Context) Floats32(key string, f []float32) Context

// Add float64 array field
func (e *Event) Floats64(key string, f []float64) *Event
func (c Context) Floats64(key string, f []float64) Context

Example:

logger.Info().
    Float64("cpu_usage", 45.7).
    Float64("memory_percent", 78.3).
    Float32("temperature", 62.5).
    Msg("system metrics")

logger.Debug().
    Floats64("coordinates", []float64{37.7749, -122.4194}).
    Msg("location data")

Note: Float formatting precision is controlled by the global zerolog.FloatingPointPrecision variable. See Global Configuration.

Time Fields

Time Values

// Add time.Time field
func (e *Event) Time(key string, t time.Time) *Event
func (c Context) Time(key string, t time.Time) Context

// Add time.Time array field
func (e *Event) Times(key string, t []time.Time) *Event
func (c Context) Times(key string, t []time.Time) Context

// Add timestamp with configured field name (zerolog.TimestampFieldName)
func (e *Event) Timestamp() *Event
func (c Context) Timestamp() Context

Example:

now := time.Now()
created := time.Date(2024, 1, 15, 10, 30, 0, 0, time.UTC)

logger.Info().
    Time("created_at", created).
    Time("updated_at", now).
    Timestamp().
    Msg("record updated")

Note: Time formatting is controlled by the global zerolog.TimeFieldFormat variable. Default is RFC3339. Special values: "" (Unix seconds), "UNIXMS" (milliseconds), "UNIXMICRO" (microseconds), "UNIXNANO" (nanoseconds).

Duration Fields

// Add time.Duration field
func (e *Event) Dur(key string, d time.Duration) *Event
func (c Context) Dur(key string, d time.Duration) Context

// Add time.Duration array field
func (e *Event) Durs(key string, d []time.Duration) *Event
func (c Context) Durs(key string, d []time.Duration) Context

// Add time difference as duration
func (e *Event) TimeDiff(key string, t, start time.Time) *Event
func (c Context) TimeDiff(key string, t, start time.Time) Context

Example:

start := time.Now()
// ... do work ...
elapsed := time.Since(start)

logger.Info().
    Dur("elapsed", elapsed).
    TimeDiff("duration", time.Now(), start).
    Msg("operation completed")

logger.Debug().
    Durs("intervals", []time.Duration{
        100 * time.Millisecond,
        200 * time.Millisecond,
        150 * time.Millisecond,
    }).
    Msg("timing data")

Note: Duration formatting is controlled by:

  • zerolog.DurationFieldUnit - Unit for conversion (default: time.Millisecond)
  • zerolog.DurationFieldInteger - Render as integer vs float (default: false)

Network Fields

// Add IP address field
func (e *Event) IPAddr(key string, ip net.IP) *Event
func (c Context) IPAddr(key string, ip net.IP) Context

// Add IP prefix/CIDR field
func (e *Event) IPPrefix(key string, pfx net.IPNet) *Event
func (c Context) IPPrefix(key string, pfx net.IPNet) Context

// Add MAC address field
func (e *Event) MACAddr(key string, ha net.HardwareAddr) *Event
func (c Context) MACAddr(key string, ha net.HardwareAddr) Context

Example:

ip := net.ParseIP("192.168.1.100")
_, ipnet, _ := net.ParseCIDR("10.0.0.0/8")
mac, _ := net.ParseMAC("00:11:22:33:44:55")

logger.Info().
    IPAddr("client_ip", ip).
    IPPrefix("subnet", *ipnet).
    MACAddr("mac_address", mac).
    Msg("network event")
// Output: "client_ip":"192.168.1.100","subnet":"10.0.0.0/8","mac_address":"00:11:22:33:44:55"

Error Fields

// Add error with default error field name (zerolog.ErrorFieldName)
func (e *Event) Err(err error) *Event
func (c Context) Err(err error) Context

// Add error with custom key
func (e *Event) AnErr(key string, err error) *Event
func (c Context) AnErr(key string, err error) Context

// Add error array field
func (e *Event) Errs(key string, errs []error) *Event
func (c Context) Errs(key string, errs []error) Context

// Add stack trace (requires ErrorStackMarshaler to be set)
func (e *Event) Stack() *Event
func (c Context) Stack() Context

Example:

err := errors.New("connection failed")
validationErr := errors.New("invalid input")

logger.Error().
    Err(err).
    Msg("operation failed")
// Output: "level":"error","error":"connection failed","message":"operation failed"

logger.Warn().
    AnErr("primary_error", err).
    AnErr("secondary_error", validationErr).
    Msg("multiple errors")

logger.Error().
    Err(err).
    Stack().
    Msg("error with stack trace")
// Stack trace included if ErrorStackMarshaler is configured

Error Marshaling: Customize with zerolog.ErrorMarshalFunc. Extract stack traces with zerolog.ErrorStackMarshaler. See Package Errors Integration for stack trace support.

Complex Fields

Array Fields

// Add array field using LogArrayMarshaler
func (e *Event) Array(key string, arr LogArrayMarshaler) *Event
func (c Context) Array(key string, arr LogArrayMarshaler) Context

Example:

arr := zerolog.Arr().
    Str("first").
    Str("second").
    Int(42).
    Bool(true)

logger.Info().
    Array("items", arr).
    Msg("array example")
// Output: "items":["first","second",42,true]

See Advanced Types for complete Array API.

Dictionary Fields

// Add nested dictionary field
func (e *Event) Dict(key string, dict *Event) *Event
func (c Context) Dict(key string, dict *Event) Context

Example:

dict := zerolog.Dict().
    Str("name", "alice").
    Int("age", 30).
    Bool("active", true)

logger.Info().
    Dict("user", dict).
    Msg("user info")
// Output: "user":{"name":"alice","age":30,"active":true}

See Advanced Types for more on Dict.

Object Fields

// Add object field using LogObjectMarshaler interface
func (e *Event) Object(key string, obj LogObjectMarshaler) *Event
func (c Context) Object(key string, obj LogObjectMarshaler) Context

// Embed object fields at top level (no key)
func (e *Event) EmbedObject(obj LogObjectMarshaler) *Event
func (c Context) EmbedObject(obj LogObjectMarshaler) Context

Example:

type User struct {
    Name string
    Age  int
}

func (u User) MarshalZerologObject(e *zerolog.Event) {
    e.Str("name", u.Name).Int("age", u.Age)
}

user := User{Name: "alice", Age: 30}

logger.Info().
    Object("user", user).
    Msg("user action")
// Output: "user":{"name":"alice","age":30}

logger.Info().
    EmbedObject(user).
    Msg("user action")
// Output: "name":"alice","age":30 (no "user" key)

See Advanced Types for marshaler interfaces.

Interface Fields

// Add interface{} field using reflection
func (e *Event) Interface(key string, i interface{}) *Event
func (c Context) Interface(key string, i interface{}) Context

// Alias for Interface
func (e *Event) Any(key string, i interface{}) *Event
func (c Context) Any(key string, i interface{}) Context

Example:

data := map[string]interface{}{
    "name": "alice",
    "age":  30,
    "tags": []string{"user", "active"},
}

logger.Info().
    Interface("data", data).
    Msg("structured data")

// Any is identical to Interface
logger.Debug().
    Any("value", someValue).
    Msg("debug info")

Note: Interface() uses reflection and the marshaler specified by zerolog.InterfaceMarshalFunc (default: json.Marshal). This is less efficient than strongly-typed methods.

Multiple Fields

// Add multiple fields from map or struct
func (e *Event) Fields(fields interface{}) *Event
func (c Context) Fields(fields interface{}) Context

Example:

// With map
fields := map[string]interface{}{
    "service": "api",
    "version": "1.0.0",
    "port":    8080,
    "debug":   true,
}

logger.Info().
    Fields(fields).
    Msg("service started")

// With slice (alternating keys and values)
logger.Info().
    Fields([]interface{}{
        "key1", "value1",
        "key2", 42,
        "key3", true,
    }).
    Msg("multiple fields")

Note: Only map[string]interface{} and []interface{} are accepted. For slices, odd-length arrays ignore the last element.

Metadata Fields

Caller Information

// Add caller file and line information
func (e *Event) Caller(skip ...int) *Event

// Add caller with specific frame skip count
func (e *Event) CallerSkipFrame(skip int) *Event

Example:

logger.Info().Caller().Msg("log with caller")
// Output: "caller":"/path/to/file.go:42","message":"log with caller"

// Skip frames (useful when wrapping logger)
logger.Info().Caller(1).Msg("skip one frame")

Note: Default skip count is controlled by zerolog.CallerSkipFrameCount (default: 2). Customize caller format with zerolog.CallerMarshalFunc.

Type Information

// Add type name of value
func (e *Event) Type(key string, val interface{}) *Event

Example:

type CustomType struct{}
value := CustomType{}

logger.Debug().
    Type("value_type", value).
    Msg("type info")
// Output: "value_type":"main.CustomType"

Field Method Reference Table

CategoryMethodsTypes
StringStr, Strs, Stringer, Stringersstring, []string, fmt.Stringer, []fmt.Stringer
BinaryBytes, Hex, RawJSON, RawCBOR[]byte
BooleanBool, Boolsbool, []bool
Signed IntInt, Int8, Int16, Int32, Int64int, int8, int16, int32, int64
Signed Int ArrayInts, Ints8, Ints16, Ints32, Ints64[]int, []int8, []int16, []int32, []int64
Unsigned IntUint, Uint8, Uint16, Uint32, Uint64uint, uint8, uint16, uint32, uint64
Unsigned Int ArrayUints, Uints8, Uints16, Uints32, Uints64[]uint, []uint8, []uint16, []uint32, []uint64
FloatFloat32, Float64, Floats32, Floats64float32, float64, []float32, []float64
TimeTime, Times, Timestamptime.Time, []time.Time
DurationDur, Durs, TimeDifftime.Duration, []time.Duration
NetworkIPAddr, IPPrefix, MACAddrnet.IP, net.IPNet, net.HardwareAddr
ErrorErr, AnErr, Errs, Stackerror, []error
ComplexArray, Dict, Object, EmbedObjectLogArrayMarshaler, *Event, LogObjectMarshaler
GenericInterface, Any, Fieldsinterface{}
MetadataCaller, CallerSkipFrame, Type-

Best Practices

1. Use Strongly-Typed Methods

Prefer strongly-typed methods over Interface() for better performance:

// Good
logger.Info().Int("count", 42).Msg("result")

// Avoid (slower due to reflection)
logger.Info().Interface("count", 42).Msg("result")

2. Choose Appropriate Types

Use the narrowest type that fits your data:

// Good
logger.Info().Uint16("port", 8080).Msg("server started")

// Works but wastes bytes
logger.Info().Uint64("port", 8080).Msg("server started")

3. Use Err() for Errors

Always use Err() for error values to get proper error marshaling:

// Good
logger.Error().Err(err).Msg("failed")

// Avoid
logger.Error().Str("error", err.Error()).Msg("failed")

4. Pre-encode JSON When Possible

For nested JSON, use RawJSON() to avoid double-encoding:

jsonData := []byte(`{"key":"value"}`)

// Good
logger.Info().RawJSON("data", jsonData).Msg("message")

// Avoid (double-encoded)
logger.Info().Str("data", string(jsonData)).Msg("message")

5. Use Arrays for Homogeneous Data

Use typed array methods for arrays of the same type:

// Good
logger.Info().Ints("scores", []int{100, 95, 87}).Msg("results")

// Avoid (less efficient)
arr := zerolog.Arr().Int(100).Int(95).Int(87)
logger.Info().Array("scores", arr).Msg("results")

6. Consistent Field Names

Use consistent field names across your application:

// Good - consistent naming
logger.Info().Str("user_id", id).Msg("action")
logger.Debug().Str("user_id", id).Msg("debug")

// Avoid - inconsistent
logger.Info().Str("user_id", id).Msg("action")
logger.Debug().Str("userId", id).Msg("debug")

Performance Considerations

  • Strongly-typed methods are zero-allocation in the hot path
  • Interface() and Any() use reflection (slower)
  • Field evaluation is lazy (skipped if event disabled)
  • Array methods are efficient for homogeneous data
  • Use Enabled() check before expensive field computations

See Also