internal/middleware/logger/logger.go (54 lines of code) (raw):

package logger import ( "context" "log" "net/http" "os" "github.com/sirupsen/logrus" ) type loggerKey string const contextKey loggerKey = "logger" var logger *logrus.Logger func Initialize(loggingVerbosity string) { level, err := logrus.ParseLevel(loggingVerbosity) // Signal that we are about to enter the desired verbosity log.Printf("Setting logging verbosity level to: %s (%d)\n", loggingVerbosity, level) if err != nil { log.Fatalf("Invalid logging verbosity: %v", err) } logger = logrus.New() // Set logrus formatter logger.SetFormatter(&logrus.JSONFormatter{}) // Set log level to output all levels logger.SetLevel(level) // Set log output to stdout logger.SetOutput(os.Stdout) } // InjectLogger injects logger in the requests' context func InjectLogger(next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { loggerObj := logger.WithFields(logrus.Fields{ "client-addr": r.RemoteAddr, }) // Add the logger to the request's context for easy access in handlers ctx := context.WithValue(r.Context(), contextKey, loggerObj) r = r.WithContext(ctx) next(w, r) } } // FromContext fetches the logger from the context otherwise it generates a new one func FromContext(ctx context.Context) *logrus.Entry { if logger, ok := ctx.Value(contextKey).(*logrus.Entry); ok { return logger } return logger.WithContext(ctx) } // CloneToNewIfPresent assigns the current logger to the returning ctx (useful when you want a different // deadline but want to preserve the logger) func CloneToNewIfPresent(originCtx context.Context, newCtx context.Context) context.Context { if logger, ok := originCtx.Value(contextKey).(*logrus.Entry); ok { return context.WithValue(newCtx, contextKey, logger) } return newCtx } func ContextWithField(ctx context.Context, keyValues ...interface{}) context.Context { var logWithField logrus.FieldLogger = FromContext(ctx) if len(keyValues)%2 != 0 { logWithField.Fatalf("Expected to have key-value pairs in log statement, got: %v", keyValues) } for i := 0; i < len(keyValues); i += 2 { logWithField = logWithField.WithField(keyValues[i].(string), keyValues[i+1]) } return context.WithValue(ctx, contextKey, logWithField) }