sirupsen / logrus

Structured, pluggable logging for Go.
MIT License
24.66k stars 2.27k forks source link

Writer with fields #692

Closed maja42 closed 5 years ago

maja42 commented 6 years ago

Currently, it is not possible to get a writer from a logger, and log messages with fields.

My use case: I have my own wrapper around logrus.Logger, which stores a list of fields that are automatically attached to each log level. It looks like this:

type MyLogger struct {
    innerLogger *logrus.Logger
    Fields   map[string]interface{}
}
func (l *MyLogger ) Debug(args ...interface{}) {
    l.innerLogger.WithFields(l.Fields).Debug(args...)
}

Now, when I want to forward log messages from the go standard logging package, I want to set the field "source = golangStd", so that is is clear where these messages come from. Currently, this is not possible.

Solution: Add the following API method to "writer.go":

func (logger *Logger) WriterFields(level Level, fields Fields) *io.PipeWriter {
    return NewEntry(logger).WithFields(fields).WriterLevel(level)
}
gguridi commented 6 years ago

I think you need to create a hook instead of a writer. But #729 has to be fixed before you can modify log entries in one hook and expect the change to be propagated to the other hooks.

maja42 commented 6 years ago

Is logrus still being maintained?

dgsb commented 6 years ago

Yes it is, we just have fixed #729 in #764

dgsb commented 6 years ago

Hello @maja42, I think I don't get it. Can't you use the Entry returned by the WithFields method to then add dynamically the source field when needed ?

emansom commented 5 years ago

Currently facing the same issue. I'd like to use logrus together with SQLBoiler's debug logging, with an extra query field containing the bytes written.

Using a wrapper struct for now, feels like a nasty hack though.

type boilLogger struct {
    *log.Logger
}

func (l boilLogger) Write(p []byte) (n int, err error) {
    l.WithField("query", string(p)).Debug("Executing query")
    return len(p), nil
}
boil.DebugMode = true
boil.DebugWriter = boilLogger{log.StandardLogger()}
richpoirier commented 5 years ago

@emansom that doesn't look like a hack to me. Wrapping logrus makes perfect sense -- ideally you have a logger interface that you pass around your application rather than depending on logrus everywhere directly. That way, if you wanted to switch loggers, you'd only have to change the implementation of your own interface and not every call to logrus.

Closing this as it's been a while and we haven't heard from @maja42 for more info.

maja42 commented 5 years ago

Today I worked on my code again and took a look at that function. You're right, it's actually possible, I'm not sure how I missed it. I'm now doing this:

func (l *MyLogger) WriterLevel(level logrus.Level) *io.PipeWriter {
    return l.innerLogger.WithFields(l.logFields).WriterLevel(level)
}