1package log 2 3import ( 4 "fmt" 5 "io" 6 "os" 7 8 "github.com/sirupsen/logrus" 9) 10 11type loggerConfig struct { 12 logger *logrus.Logger 13 level logrus.Level 14 formatter logrus.Formatter 15 outputPath string 16 writer io.Writer 17 18 // A list of warnings that will be emitted once the logger is configured 19 warnings []string 20} 21 22// LoggerOption will configure a new logrus Logger. 23type LoggerOption func(*loggerConfig) 24 25func applyLoggerOptions(opts []LoggerOption) *loggerConfig { 26 conf := loggerConfig{ 27 logger: logger, 28 level: logrus.InfoLevel, 29 formatter: &logrus.TextFormatter{}, 30 writer: os.Stdout, 31 } 32 33 for _, v := range opts { 34 v(&conf) 35 } 36 37 return &conf 38} 39 40// WithFormatter allows setting the format to `text`, `json`, `color` or `combined`. In case 41// the input is not recognized it defaults to text with a warning. 42// More details of these formats: 43// * `text` - human readable. 44// * `json` - computer readable, new-line delimited JSON. 45// * `color` - human readable, in color. Useful for development. 46// * `combined` - httpd access logs. Good for legacy access log parsers. 47func WithFormatter(format string) LoggerOption { 48 return func(conf *loggerConfig) { 49 switch format { 50 case "text": 51 conf.formatter = &logrus.TextFormatter{} 52 case "color": 53 conf.formatter = &logrus.TextFormatter{ForceColors: true, EnvironmentOverrideColors: true} 54 case "json": 55 conf.formatter = &logrus.JSONFormatter{} 56 case "combined": 57 conf.formatter = newCombinedcombinedAccessLogFormatter() 58 default: 59 conf.warnings = append(conf.warnings, fmt.Sprintf("unknown logging format %s, ignoring option", format)) 60 } 61 } 62} 63 64// WithLogLevel is used to set the log level when defaulting to `info` is not 65// wanted. Other options are: `debug`, `warn`, `error`, `fatal`, and `panic`. 66func WithLogLevel(level string) LoggerOption { 67 return func(conf *loggerConfig) { 68 logrusLevel, err := logrus.ParseLevel(level) 69 if err != nil { 70 conf.warnings = append(conf.warnings, fmt.Sprintf("unknown log level, ignoring option: %v", err)) 71 } else { 72 conf.level = logrusLevel 73 } 74 } 75} 76 77// WithOutputName allows customization of the sink of the logger. Output is either: 78// `stdout`, `stderr`, or a path to a file. 79func WithOutputName(outputName string) LoggerOption { 80 return func(conf *loggerConfig) { 81 switch outputName { 82 case "stdout": 83 conf.writer = os.Stdout 84 case "stderr": 85 conf.writer = os.Stderr 86 default: 87 conf.writer = nil 88 conf.outputPath = outputName 89 } 90 } 91} 92 93// WithWriter allows the writer to be customized. The application is responsible for closing the writer manually. 94func WithWriter(writer io.Writer) LoggerOption { 95 return func(conf *loggerConfig) { 96 conf.writer = writer 97 } 98} 99 100// WithLogger allows you to configure a proprietary logger using the `Initialize` method. 101func WithLogger(logger *logrus.Logger) LoggerOption { 102 return func(conf *loggerConfig) { 103 conf.logger = logger 104 } 105} 106