Add support for typed array.
This commit is contained in:
parent
6cdd9977c4
commit
614d88bbf8
|
@ -0,0 +1,169 @@
|
|||
package zerolog
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog/internal/json"
|
||||
)
|
||||
|
||||
var arrayPool = &sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &Array{
|
||||
buf: make([]byte, 0, 500),
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
type Array struct {
|
||||
buf []byte
|
||||
}
|
||||
|
||||
// Arr creates an array to be added to an Event or Context.
|
||||
func Arr() *Array {
|
||||
a := arrayPool.Get().(*Array)
|
||||
a.buf = a.buf[:0]
|
||||
return a
|
||||
}
|
||||
|
||||
func (*Array) MarshalZerologArray(*Array) {
|
||||
}
|
||||
|
||||
func (a *Array) write(dst []byte) []byte {
|
||||
if len(a.buf) == 0 {
|
||||
dst = append(dst, `[]`...)
|
||||
} else {
|
||||
a.buf[0] = '['
|
||||
dst = append(append(dst, a.buf...), ']')
|
||||
}
|
||||
arrayPool.Put(a)
|
||||
return dst
|
||||
}
|
||||
|
||||
// Object marshals an object that implement the LogObjectMarshaler
|
||||
// interface and append it to the array.
|
||||
func (a *Array) Object(obj LogObjectMarshaler) *Array {
|
||||
a.buf = append(a.buf, ',')
|
||||
e := Dict()
|
||||
obj.MarshalZerologObject(e)
|
||||
e.buf = append(e.buf, '}')
|
||||
a.buf = append(a.buf, e.buf...)
|
||||
return a
|
||||
}
|
||||
|
||||
// Str append the val as a string to the array.
|
||||
func (a *Array) Str(val string) *Array {
|
||||
a.buf = json.AppendString(append(a.buf, ','), val)
|
||||
return a
|
||||
}
|
||||
|
||||
// Bytes append the val as a string to the array.
|
||||
func (a *Array) Bytes(val []byte) *Array {
|
||||
a.buf = json.AppendBytes(append(a.buf, ','), val)
|
||||
return a
|
||||
}
|
||||
|
||||
// Err append the err as a string to the array.
|
||||
func (a *Array) Err(err error) *Array {
|
||||
a.buf = json.AppendError(append(a.buf, ','), err)
|
||||
return a
|
||||
}
|
||||
|
||||
// Bool append the val as a bool to the array.
|
||||
func (a *Array) Bool(b bool) *Array {
|
||||
a.buf = json.AppendBool(append(a.buf, ','), b)
|
||||
return a
|
||||
}
|
||||
|
||||
// Int append i as a int to the array.
|
||||
func (a *Array) Int(i int) *Array {
|
||||
a.buf = json.AppendInt(append(a.buf, ','), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Int8 append i as a int8 to the array.
|
||||
func (a *Array) Int8(i int8) *Array {
|
||||
a.buf = json.AppendInt8(append(a.buf, ','), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Int16 append i as a int16 to the array.
|
||||
func (a *Array) Int16(i int16) *Array {
|
||||
a.buf = json.AppendInt16(append(a.buf, ','), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Int32 append i as a int32 to the array.
|
||||
func (a *Array) Int32(i int32) *Array {
|
||||
a.buf = json.AppendInt32(append(a.buf, ','), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Int64 append i as a int64 to the array.
|
||||
func (a *Array) Int64(i int64) *Array {
|
||||
a.buf = json.AppendInt64(append(a.buf, ','), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Uint append i as a uint to the array.
|
||||
func (a *Array) Uint(i uint) *Array {
|
||||
a.buf = json.AppendUint(append(a.buf, ','), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Uint8 append i as a uint8 to the array.
|
||||
func (a *Array) Uint8(i uint8) *Array {
|
||||
a.buf = json.AppendUint8(append(a.buf, ','), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Uint16 append i as a uint16 to the array.
|
||||
func (a *Array) Uint16(i uint16) *Array {
|
||||
a.buf = json.AppendUint16(append(a.buf, ','), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Uint32 append i as a uint32 to the array.
|
||||
func (a *Array) Uint32(i uint32) *Array {
|
||||
a.buf = json.AppendUint32(append(a.buf, ','), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Uint64 append i as a uint64 to the array.
|
||||
func (a *Array) Uint64(i uint64) *Array {
|
||||
a.buf = json.AppendUint64(append(a.buf, ','), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Float32 append f as a float32 to the array.
|
||||
func (a *Array) Float32(f float32) *Array {
|
||||
a.buf = json.AppendFloat32(append(a.buf, ','), f)
|
||||
return a
|
||||
}
|
||||
|
||||
// Float64 append f as a float64 to the array.
|
||||
func (a *Array) Float64(f float64) *Array {
|
||||
a.buf = json.AppendFloat64(append(a.buf, ','), f)
|
||||
return a
|
||||
}
|
||||
|
||||
// Time append t formated as string using zerolog.TimeFieldFormat.
|
||||
func (a *Array) Time(t time.Time) *Array {
|
||||
a.buf = json.AppendTime(append(a.buf, ','), t, TimeFieldFormat)
|
||||
return a
|
||||
}
|
||||
|
||||
// Dur append d to the array.
|
||||
func (a *Array) Dur(d time.Duration) *Array {
|
||||
a.buf = json.AppendDuration(append(a.buf, ','), d, DurationFieldUnit, DurationFieldInteger)
|
||||
return a
|
||||
}
|
||||
|
||||
// Interface append i marshaled using reflection.
|
||||
func (a *Array) Interface(i interface{}) *Array {
|
||||
if obj, ok := i.(LogObjectMarshaler); ok {
|
||||
return a.Object(obj)
|
||||
}
|
||||
a.buf = json.AppendInterface(append(a.buf, ','), i)
|
||||
return a
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package zerolog
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestArray(t *testing.T) {
|
||||
a := Arr().
|
||||
Bool(true).
|
||||
Int(1).
|
||||
Int8(2).
|
||||
Int16(3).
|
||||
Int32(4).
|
||||
Int64(5).
|
||||
Uint(6).
|
||||
Uint8(7).
|
||||
Uint16(8).
|
||||
Uint32(9).
|
||||
Uint64(10).
|
||||
Float32(11).
|
||||
Float64(12).
|
||||
Str("a").
|
||||
Time(time.Time{}).
|
||||
Dur(0)
|
||||
want := `[true,1,2,3,4,5,6,7,8,9,10,11,12,"a","0001-01-01T00:00:00Z",0]`
|
||||
if got := string(a.write([]byte{})); got != want {
|
||||
t.Errorf("Array.write()\ngot: %s\nwant: %s", got, want)
|
||||
}
|
||||
}
|
20
context.go
20
context.go
|
@ -31,6 +31,26 @@ func (c Context) Dict(key string, dict *Event) Context {
|
|||
return c
|
||||
}
|
||||
|
||||
// Array adds the field key with an array to the event context.
|
||||
// Use zerolog.Arr() to create the array or pass a type that
|
||||
// implement the LogArrayMarshaler interface.
|
||||
func (c Context) Array(key string, arr LogArrayMarshaler) Context {
|
||||
c.l.context = json.AppendKey(c.l.context, key)
|
||||
if arr, ok := arr.(*Array); ok {
|
||||
c.l.context = arr.write(c.l.context)
|
||||
return c
|
||||
}
|
||||
var a *Array
|
||||
if aa, ok := arr.(*Array); ok {
|
||||
a = aa
|
||||
} else {
|
||||
a = Arr()
|
||||
arr.MarshalZerologArray(a)
|
||||
}
|
||||
c.l.context = a.write(c.l.context)
|
||||
return c
|
||||
}
|
||||
|
||||
// Object marshals an object that implement the LogObjectMarshaler interface.
|
||||
func (c Context) Object(key string, obj LogObjectMarshaler) Context {
|
||||
e := newEvent(levelWriterAdapter{ioutil.Discard}, 0, true)
|
||||
|
|
32
event.go
32
event.go
|
@ -28,10 +28,18 @@ type Event struct {
|
|||
done func(msg string)
|
||||
}
|
||||
|
||||
// LogObjectMarshaler provides a strongly-typed and encoding-agnostic interface
|
||||
// to be implemented by types used with Event/Context's Object methods.
|
||||
type LogObjectMarshaler interface {
|
||||
MarshalZerologObject(e *Event)
|
||||
}
|
||||
|
||||
// LogArrayMarshaler provides a strongly-typed and encoding-agnostic interface
|
||||
// to be implemented by types used with Event/Context's Array methods.
|
||||
type LogArrayMarshaler interface {
|
||||
MarshalZerologArray(a *Array)
|
||||
}
|
||||
|
||||
func newEvent(w LevelWriter, level Level, enabled bool) *Event {
|
||||
if !enabled {
|
||||
return &Event{}
|
||||
|
@ -127,6 +135,25 @@ func Dict() *Event {
|
|||
return newEvent(levelWriterAdapter{ioutil.Discard}, 0, true)
|
||||
}
|
||||
|
||||
// Array adds the field key with an array to the event context.
|
||||
// Use zerolog.Arr() to create the array or pass a type that
|
||||
// implement the LogArrayMarshaler interface.
|
||||
func (e *Event) Array(key string, arr LogArrayMarshaler) *Event {
|
||||
if !e.enabled {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendKey(e.buf, key)
|
||||
var a *Array
|
||||
if aa, ok := arr.(*Array); ok {
|
||||
a = aa
|
||||
} else {
|
||||
a = Arr()
|
||||
arr.MarshalZerologArray(a)
|
||||
}
|
||||
e.buf = a.write(e.buf)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *Event) appendObject(obj LogObjectMarshaler) {
|
||||
pos := len(e.buf)
|
||||
obj.MarshalZerologObject(e)
|
||||
|
@ -143,6 +170,9 @@ func (e *Event) appendObject(obj LogObjectMarshaler) {
|
|||
|
||||
// Object marshals an object that implement the LogObjectMarshaler interface.
|
||||
func (e *Event) Object(key string, obj LogObjectMarshaler) *Event {
|
||||
if !e.enabled {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendKey(e.buf, key)
|
||||
e.appendObject(obj)
|
||||
return e
|
||||
|
@ -166,7 +196,7 @@ func (e *Event) Strs(key string, vals []string) *Event {
|
|||
return e
|
||||
}
|
||||
|
||||
// Bytes adds the field key with val as a []byte to the *Event context.
|
||||
// Bytes adds the field key with val as a string to the *Event context.
|
||||
func (e *Event) Bytes(key string, val []byte) *Event {
|
||||
if !e.enabled {
|
||||
return e
|
||||
|
|
|
@ -150,9 +150,49 @@ func (u User) MarshalZerologObject(e *zerolog.Event) {
|
|||
Time("created", u.Created)
|
||||
}
|
||||
|
||||
type Users []User
|
||||
|
||||
func (uu Users) MarshalZerologArray(a *zerolog.Array) {
|
||||
for _, u := range uu {
|
||||
a.Object(u)
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleEvent_Array() {
|
||||
log := zerolog.New(os.Stdout)
|
||||
|
||||
log.Log().
|
||||
Str("foo", "bar").
|
||||
Array("array", zerolog.Arr().
|
||||
Str("baz").
|
||||
Int(1),
|
||||
).
|
||||
Msg("hello world")
|
||||
|
||||
// Output: {"foo":"bar","array":["baz",1],"message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleEvent_Array_object() {
|
||||
log := zerolog.New(os.Stdout)
|
||||
|
||||
// Users implements zerolog.LogArrayMarshaler
|
||||
u := Users{
|
||||
User{"John", 35, time.Time{}},
|
||||
User{"Bob", 55, time.Time{}},
|
||||
}
|
||||
|
||||
log.Log().
|
||||
Str("foo", "bar").
|
||||
Array("users", u).
|
||||
Msg("hello world")
|
||||
|
||||
// Output: {"foo":"bar","users":[{"name":"John","age":35,"created":"0001-01-01T00:00:00Z"},{"name":"Bob","age":55,"created":"0001-01-01T00:00:00Z"}],"message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleEvent_Object() {
|
||||
log := zerolog.New(os.Stdout)
|
||||
|
||||
// User implements zerolog.LogObjectMarshaler
|
||||
u := User{"John", 35, time.Time{}}
|
||||
|
||||
log.Log().
|
||||
|
@ -222,7 +262,38 @@ func ExampleContext_Dict() {
|
|||
// Output: {"foo":"bar","dict":{"bar":"baz","n":1},"message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleContext_Array() {
|
||||
log := zerolog.New(os.Stdout).With().
|
||||
Str("foo", "bar").
|
||||
Array("array", zerolog.Arr().
|
||||
Str("baz").
|
||||
Int(1),
|
||||
).Logger()
|
||||
|
||||
log.Log().Msg("hello world")
|
||||
|
||||
// Output: {"foo":"bar","array":["baz",1],"message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleContext_Array_object() {
|
||||
// Users implements zerolog.LogArrayMarshaler
|
||||
u := Users{
|
||||
User{"John", 35, time.Time{}},
|
||||
User{"Bob", 55, time.Time{}},
|
||||
}
|
||||
|
||||
log := zerolog.New(os.Stdout).With().
|
||||
Str("foo", "bar").
|
||||
Array("users", u).
|
||||
Logger()
|
||||
|
||||
log.Log().Msg("hello world")
|
||||
|
||||
// Output: {"foo":"bar","users":[{"name":"John","age":35,"created":"0001-01-01T00:00:00Z"},{"name":"Bob","age":55,"created":"0001-01-01T00:00:00Z"}],"message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleContext_Object() {
|
||||
// User implements zerolog.LogObjectMarshaler
|
||||
u := User{"John", 35, time.Time{}}
|
||||
|
||||
log := zerolog.New(os.Stdout).With().
|
||||
|
|
Loading…
Reference in New Issue