sqldb-logger icon indicating copy to clipboard operation
sqldb-logger copied to clipboard

feat: add option for injecting additional log fields

Open dominicbarnes opened this issue 4 years ago • 2 comments

I wanted the ability to inject some additional log fields at init time. Building on Option seemed like a logic fit for this functionality, which I've called "additional fields".

This should allow a user to use something like this when initializing their logger:

// multiple fields
WithAdditionalFields(map[string]interface{}{"hello", "world"})

// single field
WithAdditionalField("hello", "world")

It should be noted that I intentionally append the user-defined fields first so that in the event of a conflict, the internal ones will take precedence, which seemed like the right thing to do behaviorally.

dominicbarnes avatar May 25 '21 05:05 dominicbarnes

I wanted the ability to inject some additional log fields at init time. Building on Option seemed like a logic fit for this functionality, which I've called "additional fields".

Hi @dominicbarnes, I think it's better (and simpler) that you create a custom Logger implementation rather than put it as an option. The goal is the same, you need to add additional fields in every log but not replacing internal log content if it has the same key.

Let's take zerolog adapter as a base and modify it:

type zerologAdapter struct {
	logger zerolog.Logger
	additionalFields map[string]interface{}
}

func NewWithAdditionalFields(logger zerolog.Logger, additionalFields map[string]interface{}) sqldblogger.Logger {
	return &zerologAdapter{logger: logger, additionalFields: additionalFields}
}

func (zl *zerologAdapter) Log(_ context.Context, level sqldblogger.Level, msg string, data map[string]interface{}) {
	var lvl zerolog.Level
	switch level {
	case sqldblogger.LevelError:
		lvl = zerolog.ErrorLevel
	case sqldblogger.LevelInfo:
		lvl = zerolog.InfoLevel
	case sqldblogger.LevelDebug:
		lvl = zerolog.DebugLevel
	case sqldblogger.LevelTrace:
		lvl = zerolog.TraceLevel
	default:
		lvl = zerolog.DebugLevel
	}
	for k, v := range zl.additionalFields {
		if _, ok := data[k]; !ok {
			data[k] = v
		}
	}
	zl.logger.WithLevel(lvl).Fields(data).Msg(msg)
}

simukti avatar May 25 '21 16:05 simukti

I think both options would be valuable, seems like being able to generalize for any logger is preferred to needing to inject for each individual logger. That being said, you would only ever need 1 logger for any implementation, so maybe it's a moot point.

dominicbarnes avatar Jun 09 '21 17:06 dominicbarnes