乐趣区

关于golang:聊聊golang的zap的marshaler

本文次要钻研一下 golang 的 zap 的 marshaler

ObjectMarshaler

zap@v1.16.0/zapcore/marshaler.go

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

ObjectMarshaler 接口定义了 MarshalLogObject 办法;ObjectMarshalerFunc 类型定义了 MarshalLogObject 办法,使得 ObjectMarshalerFunc 实现 ObjectMarshaler 接口

ArrayMarshaler

zap@v1.16.0/zapcore/marshaler.go

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

ArrayMarshaler 接口定义了 MarshalLogArray 办法;ArrayMarshalerFunc 类型定义了 MarshalLogArray 办法,使得 ArrayMarshalerFunc 实现了 MarshalLogArray 接口

ObjectEncoder

zap@v1.16.0/zapcore/encoder.go

type ObjectEncoder interface {
    // Logging-specific marshalers.
    AddArray(key string, marshaler ArrayMarshaler) error
    AddObject(key string, marshaler ObjectMarshaler) error

    // Built-in types.
    AddBinary(key string, value []byte)     // for arbitrary bytes
    AddByteString(key string, value []byte) // for UTF-8 encoded bytes
    AddBool(key string, value bool)
    AddComplex128(key string, value complex128)
    AddComplex64(key string, value complex64)
    AddDuration(key string, value time.Duration)
    AddFloat64(key string, value float64)
    AddFloat32(key string, value float32)
    AddInt(key string, value int)
    AddInt64(key string, value int64)
    AddInt32(key string, value int32)
    AddInt16(key string, value int16)
    AddInt8(key string, value int8)
    AddString(key, value string)
    AddTime(key string, value time.Time)
    AddUint(key string, value uint)
    AddUint64(key string, value uint64)
    AddUint32(key string, value uint32)
    AddUint16(key string, value uint16)
    AddUint8(key string, value uint8)
    AddUintptr(key string, value uintptr)

    // AddReflected uses reflection to serialize arbitrary objects, so it can be
    // slow and allocation-heavy.
    AddReflected(key string, value interface{}) error
    // OpenNamespace opens an isolated namespace where all subsequent fields will
    // be added. Applications can use namespaces to prevent key collisions when
    // injecting loggers into sub-components or third-party libraries.
    OpenNamespace(key string)
}

ObjectEncoder 的 AddArray 办法须要 ArrayMarshaler 参数,AddObject 办法须要 ObjectMarshaler 参数

zap.Object

zap@v1.16.0/field.go

// Object constructs a field with the given key and ObjectMarshaler. It
// provides a flexible, but still type-safe and efficient, way to add map- or
// struct-like user-defined types to the logging context. The struct's
// MarshalLogObject method is called lazily.
func Object(key string, val zapcore.ObjectMarshaler) Field {return Field{Key: key, Type: zapcore.ObjectMarshalerType, Interface: val}
}

zap.Object 办法要求 value 实现 zapcore.ObjectMarshaler 接口

zap.Array

zap@v1.16.0/array.go

// Array constructs a field with the given key and ArrayMarshaler. It provides
// a flexible, but still type-safe and efficient, way to add array-like types
// to the logging context. The struct's MarshalLogArray method is called lazily.
func Array(key string, val zapcore.ArrayMarshaler) Field {return Field{Key: key, Type: zapcore.ArrayMarshalerType, Interface: val}
}

zap.Array 办法要求 value 实现了 zapcore.ArrayMarshaler 接口

实例

type User struct {
    Name      string
    Email     string
    CreatedAt time.Time
}

func (u *User) MarshalLogObject(enc zapcore.ObjectEncoder) error {enc.AddString("name", u.Name)
    enc.AddString("email", u.Email)
    enc.AddInt64("created_at", u.CreatedAt.UnixNano())
    return nil
}

type Users []*User

func (uu Users) MarshalLogArray(arr zapcore.ArrayEncoder) error {
    var err error
    for i := range uu {err = multierr.Append(err, arr.AppendObject(uu[i]))
    }
    return err
}

func marshalerDemo() {logger, err := zap.NewProduction()
    defer logger.Sync()
    if err != nil {panic(err)
    }
    var user = &User{
        Name:      "hello1",
        Email:     "hello1@test.com",
        CreatedAt: time.Date(2020, 12, 19, 8, 0, 0, 0, time.UTC),
    }
    var users Users
    users = append(users, &User{
        Name:      "hello2",
        Email:     "hello2@test.com",
        CreatedAt: time.Date(2020, 12, 19, 9, 0, 0, 0, time.UTC),
    }, &User{
        Name:      "hello3",
        Email:     "hello3@test.com",
        CreatedAt: time.Date(2020, 12, 20, 10, 0, 0, 0, time.UTC),
    })
    logger.Info("marshaler", zap.Object("user", user))
    logger.Info("marshaler", zap.Array("users", users))
}

User 类型实现了 MarshalLogObject 办法;Users 类型实现了 MarshalLogArray 办法;之后在 logger 增加 Field 的时候,就能够应用 zap.Object 或者 zap.Array 办法

输入

{"level":"info","ts":1608348349.487255,"caller":"zap/zap_demo.go:66","msg":"marshaler","user":{"name":"hello1","email":"hello1@test.com","created_at":1608364800000000000}}
{"level":"info","ts":1608348349.4873412,"caller":"zap/zap_demo.go:67","msg":"marshaler","users":[{"name":"hello2","email":"hello2@test.com","created_at":1608368400000000000},{"name":"hello3","email":"hello3@test.com","created_at":1608458400000000000}]}

小结

zap 的 marshaler 定义了 ObjectMarshaler(MarshalLogObject) 及 ArrayMarshaler(MarshalLogArray) 接口;在 logger 若想应用 zap.Object 或者 zap.Array 办法就要求对应的类型实现对应的接口。

doc

  • zap
退出移动版