zap icon indicating copy to clipboard operation
zap copied to clipboard

add new fields with hooks

Open schmurfy opened this issue 5 years ago • 3 comments

I am trying to find the most elegant way to dynamically add data stored in the context to log entries as they are written, in my mind it would be as simple as:

// init
logger = logger.WithOptions(
	zap.Wrapper(func(entry zap.Whatever) zap.Whatever {
		return entry.With(
			zap.String("value_from_context", "...")
		)
	})
)

// and later
logger.Info("started",
  zap.Contex(ctx),
)

The value I wanna log can change at any point between the start of the call being handled and the actual log lines, this is why I am looking fo some kind of hooks but so far I found two promising tracks which led me to a wall:

  • Hooks: as far as I can tell by playing with them they cannot change anything
  • Core: I can create a new core and use WrapCore to replace the original core but if I do that my core needs to completely replace the original core and do the writing, I have still to do some tests by embedding the original core and try t overload what I need but that's ugly.

Is there any supported way to do that ?

One of the reasons I am trying to do this is adding trace_id and span_id from opentelemetry, I would also love to add span attributes to the log instead of having to write it twice (one for logger and one for the span).

Edit: the other missing piece is a way to pass the context, I edited my example accordingly

schmurfy avatar Dec 26 '20 09:12 schmurfy

@schmurfy I'm interested in the same and I saw your comments in #654 .... What's your current clean way to do that? Maybe we should write a wrapper while the design discussion holds...?

I will definitely need the support for OpenTelemetry as well...

marcellodesales avatar Jan 18 '21 02:01 marcellodesales

I am really not sure how to do that cleanly at the moment, I have put that on pause as for now we use generated code to fill the gap. I have looked at zap internal but found nothing on which to base any work toward this.

schmurfy avatar Jan 18 '21 19:01 schmurfy

Hi, this would be really nice to have, I'm currently using a function that returns a slice of zap log fields:

func GetLogFields(ctx context.Context, fields ...zap.Field) []zap.Field {
    // get fields from passed context and convert to zap.String fields
}

Then I just use it when logging:

log.Info("my log message", GetLogFields(ctx)...)

The problem with this is that the user can forget to call GetLogFields etc. so it would be much nicer if zap provides a wrapper.

pete911 avatar Jan 28 '22 15:01 pete911