gitlab.com/gitlab-org/labkit@v1.21.0/log/initialization.go (about) 1 package log 2 3 import ( 4 "io" 5 "log" 6 "os" 7 "os/signal" 8 "syscall" 9 10 "github.com/client9/reopen" 11 "github.com/sirupsen/logrus" 12 ) 13 14 type nopCloser struct{} 15 16 func (nopCloser) Close() error { return nil } 17 18 // Initialize will configure the logger based on the options passed. It will 19 // validate the options and if validation fails drop to the defaults while 20 // logging a message to STDERR. 21 func Initialize(opts ...LoggerOption) (io.Closer, error) { 22 conf := applyLoggerOptions(opts) 23 24 // Being unable to open the output file will cause an error 25 writer, closer, err := getOutputWriter(conf) 26 if err != nil { 27 return closer, err 28 } 29 30 conf.logger.SetFormatter(conf.buildFormatter()) 31 conf.logger.SetLevel(conf.level) 32 conf.logger.SetOutput(writer) 33 34 // Only output the warnings _after_ the logger has been configured 35 for _, warning := range conf.warnings { 36 conf.logger.Warn(warning) 37 } 38 39 return closer, nil 40 } 41 42 func getOutputWriter(conf *loggerConfig) (io.Writer, io.Closer, error) { 43 if conf.writer != nil { 44 return conf.writer, nopCloser{}, nil 45 } 46 47 // When writing to a file, use `reopen` so that we can 48 // reopen the file on SIGHUP signals 49 f, err := reopen.NewFileWriterMode(conf.outputPath, 0644) 50 if err != nil { 51 return f, nopCloser{}, err 52 } 53 54 isMainLogger := conf.logger == logger 55 56 sighup := make(chan os.Signal, 1) 57 signal.Notify(sighup, syscall.SIGHUP) 58 go listenForSignalHangup(f, isMainLogger, conf.outputPath, sighup) 59 60 return f, f, nil 61 } 62 63 // Will listen for SIGHUP signals and reopen the underlying file. 64 func listenForSignalHangup(l reopen.Reopener, isMainLogger bool, logFilePath string, sighup chan os.Signal) { 65 for v := range sighup { 66 // Specifically, do _not_ write to the log that is being reopened, 67 // but log this to the _main_ log file instead as the actual log 68 // might be specialised, eg: an access logger leading to an incorrect entry 69 logger.WithFields(logrus.Fields{"signal": v, "path": logFilePath}).Print("Reopening log file on signal") 70 71 err := l.Reopen() 72 if err != nil { 73 if isMainLogger { 74 // Main logger failed to reopen, last ditch effort to notify the user, but don't 75 // do this for auxiliary loggers, since we may get double-logs 76 log.Printf("Unable to reopen log file '%s' after %v. Error %v", logFilePath, v, err) 77 } else { 78 logger.WithError(err).WithFields(logrus.Fields{"signal": v, "path": logFilePath}).Print("Failed to reopen log file") 79 } 80 } 81 } 82 }