log/initialization.go (53 lines of code) (raw):

package log import ( "io" "log" "os" "os/signal" "syscall" "github.com/sirupsen/logrus" "gitlab.com/gitlab-org/go/reopen" ) type nopCloser struct{} func (nopCloser) Close() error { return nil } // Initialize will configure the logger based on the options passed. It will // validate the options and if validation fails drop to the defaults while // logging a message to STDERR. func Initialize(opts ...LoggerOption) (io.Closer, error) { conf := applyLoggerOptions(opts) // Being unable to open the output file will cause an error writer, closer, err := getOutputWriter(conf) if err != nil { return closer, err } conf.logger.SetFormatter(conf.buildFormatter()) conf.logger.SetLevel(conf.level) conf.logger.SetOutput(writer) // Only output the warnings _after_ the logger has been configured for _, warning := range conf.warnings { conf.logger.Warn(warning) } return closer, nil } func getOutputWriter(conf *loggerConfig) (io.Writer, io.Closer, error) { if conf.writer != nil { return conf.writer, nopCloser{}, nil } // When writing to a file, use `reopen` so that we can // reopen the file on SIGHUP signals f, err := reopen.NewFileWriterMode(conf.outputPath, 0644) if err != nil { return f, nopCloser{}, err } isMainLogger := conf.logger == logger sighup := make(chan os.Signal, 1) signal.Notify(sighup, syscall.SIGHUP) go listenForSignalHangup(f, isMainLogger, conf.outputPath, sighup) return f, f, nil } // Will listen for SIGHUP signals and reopen the underlying file. func listenForSignalHangup(l reopen.Reopener, isMainLogger bool, logFilePath string, sighup chan os.Signal) { for v := range sighup { // Specifically, do _not_ write to the log that is being reopened, // but log this to the _main_ log file instead as the actual log // might be specialised, eg: an access logger leading to an incorrect entry logger.WithFields(logrus.Fields{"signal": v, "path": logFilePath}).Print("Reopening log file on signal") err := l.Reopen() if err != nil { if isMainLogger { // Main logger failed to reopen, last ditch effort to notify the user, but don't // do this for auxiliary loggers, since we may get double-logs log.Printf("Unable to reopen log file '%s' after %v. Error %v", logFilePath, v, err) } else { logger.WithError(err).WithFields(logrus.Fields{"signal": v, "path": logFilePath}).Print("Failed to reopen log file") } } } }