zerolog icon indicating copy to clipboard operation
zerolog copied to clipboard

Get the log level in LogObjectMarshaler

Open 0xjac opened this issue 10 months ago • 1 comments

I have a custom type (struct) which implements LogObjectMarshaler. I would like to add extra field when logging my object but only at the debug level. However I can't get the level associated with the event passed to MarshalZerologObject(e *zerolog.Event).

Here is an example of what I am trying to do (modified from the doc) where on debug, I also log the user's age:

type User struct {
	Name    string
	Age     int
	Created time.Time
}

func (u User) MarshalZerologObject(e *zerolog.Event) {
	e.Str("name", u.Name).Time("created", u.Created)

	if e.level == zerolog.DebugLevel { // Doesn't really work since level is private.
		e.Int("age", u.Age)
	}
}

I'm open to any solution to get the level, some proposals:

  1. Modify LogObjectMarshaler to pass the event similar to hooks:

    type LogObjectMarshaler interface {
    	MarshalZerologObject(e *Event, level Level)
    }
    

    However, this would be a breaking change for a v2.

  2. Similarly, to the above but in a backwards compatible way, provide a new interface:

    type LogObjectLevelMarshaler interface {
    	MarshalLevelZerologObject(e *Event, level Level)
    }
    

    However, this would also require new methods on the event to use this new marshaler:

    func (e *Event) LevelObject(key string, obj LogObjectLevelMarshaler) *Event`
    func (e *Event) LevelEmbedObject(obj LogObjectLevelMarshaler) *Event
    
  3. Add a getter on the event to retrieve the level.

  4. Provide a standalone function which acts as a getter (to avoid polluting the API of the event), something like:

    func LevelFromEvent(e *Event) Level
    

0xjac avatar Jan 21 '25 20:01 0xjac

Anyone has any opinion on this? I feel like option 4 would be the least disruptive and the most flexible for now:

  1. It's a breaking change of the LogObjectMarshaler API.
  2. It's a larger change and increases the API surface. It can also lead to confusion as to which of LogObjectMarshaler or LogObjectLevelMarshaler to use.
  3. Can be confusing as it is a getter and most methods of the event are setters.

It is not exactly a new feature but it does extend the API surface somewhat as well, so I'd love some insights. If there are no oppositions, I am happy to submit a PR adding just that (documented) function (cc @rs).

In the future, I think option 1 is the cleanest and I am happy to submit a PR for it too when the time comes.

0xjac avatar Apr 09 '25 18:04 0xjac