From ffbd37b8d75fc1407f70aab005c35f8e2d9ecd45 Mon Sep 17 00:00:00 2001 From: Marcus Watkins Date: Wed, 19 May 2021 17:33:11 -0600 Subject: [PATCH] Add Func log method (#321) This adds the Func log method to log using an anonymous function only if the level is currently enabled. The use case is for when you don't own an object and therefore can't create your own marshaller but need to do some translation prior to logging. For example, this: msg := log.Debug() if msg.Enabled() { msg.Str("complicated_thing", makeBinaryThingLoggable(thing)) } msg.Msg("Sending complicated thing") Turns into this: log.Debug(). Func(func(e *Event) { e.Str("complicated_thing", makeBinaryThingLoggable(thing)) }). Msg("Sending complicated thing") --- README.md | 1 + event.go | 8 ++++++++ log_test.go | 4 +++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 36ed93b..51e3e36 100644 --- a/README.md +++ b/README.md @@ -591,6 +591,7 @@ Some settings can be changed and will by applied to all loggers: ### Advanced Fields * `Err`: Takes an `error` and renders it as a string using the `zerolog.ErrorFieldName` field name. +* `Func`: Run a `func` only if the level is enabled. * `Timestamp`: Inserts a timestamp field with `zerolog.TimestampFieldName` field name, formatted using `zerolog.TimeFieldFormat`. * `Time`: Adds a field with time formatted with `zerolog.TimeFieldFormat`. * `Dur`: Adds a field with `time.Duration`. diff --git a/event.go b/event.go index ff6ff24..51ea4bb 100644 --- a/event.go +++ b/event.go @@ -211,6 +211,14 @@ func (e *Event) Object(key string, obj LogObjectMarshaler) *Event { return e } +// Func allows an anonymous func to run only if the event is enabled. +func (e *Event) Func(f func(e *Event)) *Event { + if e != nil && e.Enabled() { + f(e) + } + return e +} + // EmbedObject marshals an object that implement the LogObjectMarshaler interface. func (e *Event) EmbedObject(obj LogObjectMarshaler) *Event { if e == nil { diff --git a/log_test.go b/log_test.go index 82bcf8b..2d3d8fc 100644 --- a/log_test.go +++ b/log_test.go @@ -260,6 +260,7 @@ func TestFields(t *testing.T) { Bytes("bytes", []byte("bar")). Hex("hex", []byte{0x12, 0xef}). RawJSON("json", []byte(`{"some":"json"}`)). + Func(func(e *Event) { e.Str("func", "func_output") }). AnErr("some_err", nil). Err(errors.New("some error")). Bool("bool", true). @@ -283,7 +284,7 @@ func TestFields(t *testing.T) { Time("time", time.Time{}). TimeDiff("diff", now, now.Add(-10*time.Second)). Msg("") - if got, want := decodeIfBinaryToString(out.Bytes()), `{"caller":"`+caller+`","string":"foo","stringer":"127.0.0.1","stringer_nil":null,"bytes":"bar","hex":"12ef","json":{"some":"json"},"error":"some error","bool":true,"int":1,"int8":2,"int16":3,"int32":4,"int64":5,"uint":6,"uint8":7,"uint16":8,"uint32":9,"uint64":10,"IPv4":"192.168.0.100","IPv6":"2001:db8:85a3::8a2e:370:7334","Mac":"00:14:22:01:23:45","Prefix":"192.168.0.100/24","float32":11.1234,"float64":12.321321321,"dur":1000,"time":"0001-01-01T00:00:00Z","diff":10000}`+"\n"; got != want { + if got, want := decodeIfBinaryToString(out.Bytes()), `{"caller":"`+caller+`","string":"foo","stringer":"127.0.0.1","stringer_nil":null,"bytes":"bar","hex":"12ef","json":{"some":"json"},"func":"func_output","error":"some error","bool":true,"int":1,"int8":2,"int16":3,"int32":4,"int64":5,"uint":6,"uint8":7,"uint16":8,"uint32":9,"uint64":10,"IPv4":"192.168.0.100","IPv6":"2001:db8:85a3::8a2e:370:7334","Mac":"00:14:22:01:23:45","Prefix":"192.168.0.100/24","float32":11.1234,"float64":12.321321321,"dur":1000,"time":"0001-01-01T00:00:00Z","diff":10000}`+"\n"; got != want { t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want) } } @@ -379,6 +380,7 @@ func TestFieldsDisabled(t *testing.T) { Hex("hex", []byte{0x12, 0xef}). AnErr("some_err", nil). Err(errors.New("some error")). + Func(func(e *Event) { e.Str("func", "func_output") }). Bool("bool", true). Int("int", 1). Int8("int8", 2).