package file import ( "fmt" "io" "os" "path/filepath" "time" "github.com/juju/errors" "github.com/sirupsen/logrus" rotatelogs "github.com/lestrrat-go/file-rotatelogs" ) // NewHook will create a File Hook for logrus. func NewHook(c *ConfigStruct) (logrus.Hook, error) { err := c.IsValid() if err != nil { return nil, errors.Trace(err) } outputFormat := OutputFormat_TEXT if c.OutputFormat != nil { outputFormat = OutputFormat(*c.OutputFormat) } var w io.Writer if c.Rotate { rotateTime, _ := time.ParseDuration(*c.RotateTime) // let's construct log rotator options rotateOptions := []rotatelogs.Option{ rotatelogs.WithLinkName(c.Filename), rotatelogs.WithRotationTime(rotateTime), } if c.RotateMaxAge != nil { rotateMaxAge, _ := time.ParseDuration(*c.RotateMaxAge) rotateOptions = append(rotateOptions, rotatelogs.WithMaxAge(rotateMaxAge)) } else if c.RotateMaxFile != nil { rotateOptions = append( rotateOptions, rotatelogs.WithRotationCount(uint(*c.RotateMaxFile)), rotatelogs.WithMaxAge(-1), ) } w, err = rotatelogs.New( fmt.Sprintf("%s.%%Y%%m%%d%%H%%M", c.Filename), rotateOptions..., ) if err != nil { return nil, errors.Trace(err) } } else { dirname := filepath.Dir(c.Filename) if err := os.MkdirAll(dirname, 0750); err != nil { return nil, errors.NewNotSupported(err, fmt.Sprintf("failed to create directory %s", dirname)) } // if we got here, then we need to create a file fh, err := os.OpenFile(c.Filename, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600) if err != nil { return nil, errors.NewNotSupported(err, fmt.Sprintf("failed to open file %s", c.Filename)) } w = fh } h := NewAsyncFileHook(w, handleFormat(outputFormat)) return h, nil } // handleFormat will take a OutputFormat and will transform it in a formatter. func handleFormat(of OutputFormat) logrus.Formatter { if of == OutputFormat_JSON { return &logrus.JSONFormatter{ PrettyPrint: false, TimestampFormat: time.RFC3339Nano, } } return &logrus.TextFormatter{ DisableColors: true, TimestampFormat: time.RFC3339Nano, QuoteEmptyFields: true, } }