diff --git a/config/config.go b/config/config.go index 26d2bc5e..ab059d5a 100644 --- a/config/config.go +++ b/config/config.go @@ -88,12 +88,14 @@ func LoadConfig(configPath string) error { file, err := os.Open(configPath) if err != nil { logger.Warn(logSender, "error loading configuration file: %v. Default configuration will be used: %+v", err, globalConf) + logger.WarnToConsole("error loading configuration file: %v. Default configuration will be used.", err) return err } defer file.Close() err = json.NewDecoder(file).Decode(&globalConf) if err != nil { - logger.Warn(logSender, "error parsing config file: %v. Default configuration will be used: %+v", err, globalConf) + logger.Warn(logSender, "error parsing configuration file: %v. Default configuration will be used: %+v", err, globalConf) + logger.WarnToConsole("error parsing configuration file: %v. Default configuration will be used.", err) return err } if strings.TrimSpace(globalConf.SFTPD.Banner) == "" { diff --git a/logger/logger.go b/logger/logger.go index c90082b9..f7e039f8 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -1,6 +1,8 @@ // Package logger provides logging capabilities. // It is a wrapper around zerolog for logging and lumberjack for log rotation. -// It provides a request logger to log the HTTP requests for REST API too. +// Logs are written to the specified log file. +// Logging on the console is provided to print initialization info, errors and warnings. +// The package provides a request logger to log the HTTP requests for REST API too. // The request logger uses chi.middleware.RequestLogger, // chi.middleware.LogFormatter and chi.middleware.LogEntry to build a structured // logger using zerlog @@ -8,6 +10,7 @@ package logger import ( "fmt" + "os" "github.com/rs/zerolog" lumberjack "gopkg.in/natefinch/lumberjack.v2" @@ -18,7 +21,8 @@ const ( ) var ( - logger zerolog.Logger + logger zerolog.Logger + consoleLogger zerolog.Logger ) // GetLogger get the configured logger instance @@ -41,6 +45,13 @@ func InitLogger(logFilePath string, level zerolog.Level) { MaxAge: logMaxAge, Compress: false, }).With().Timestamp().Logger().Level(level) + + consoleOutput := zerolog.ConsoleWriter{ + Out: os.Stdout, + TimeFormat: dateFormat, + NoColor: true, + } + consoleLogger = zerolog.New(consoleOutput).With().Timestamp().Logger() } // Debug logs at debug level for the specified sender @@ -63,6 +74,26 @@ func Error(sender string, format string, v ...interface{}) { logger.Error().Str("sender", sender).Msg(fmt.Sprintf(format, v...)) } +// DebugToConsole logs at debug level to stdout +func DebugToConsole(format string, v ...interface{}) { + consoleLogger.Debug().Msg(fmt.Sprintf(format, v...)) +} + +// InfoToConsole logs at info level to stdout +func InfoToConsole(format string, v ...interface{}) { + consoleLogger.Info().Msg(fmt.Sprintf(format, v...)) +} + +// WarnToConsole logs at info level to stdout +func WarnToConsole(format string, v ...interface{}) { + consoleLogger.Warn().Msg(fmt.Sprintf(format, v...)) +} + +// ErrorToConsole logs at error level to stdout +func ErrorToConsole(format string, v ...interface{}) { + consoleLogger.Error().Msg(fmt.Sprintf(format, v...)) +} + // TransferLog logs an SFTP upload or download func TransferLog(operation string, path string, elapsed int64, size int64, user string, connectionID string) { logger.Info(). diff --git a/main.go b/main.go index e8efc457..949fc93f 100644 --- a/main.go +++ b/main.go @@ -45,7 +45,8 @@ func main() { err := dataprovider.Initialize(providerConf, configDir) if err != nil { - logger.Warn(logSender, "error initializing data provider: %v", err) + logger.Error(logSender, "error initializing data provider: %v", err) + logger.ErrorToConsole("error initializing data provider: %v", err) os.Exit(1) } @@ -61,6 +62,7 @@ func main() { logger.Debug(logSender, "initializing SFTP server with config %+v", sftpdConf) if err := sftpdConf.Initialize(configDir); err != nil { logger.Error(logSender, "could not start SFTP server: %v", err) + logger.ErrorToConsole("could not start SFTP server: %v", err) } shutdown <- true }() @@ -80,11 +82,13 @@ func main() { } if err := s.ListenAndServe(); err != nil { logger.Error(logSender, "could not start HTTP server: %v", err) + logger.ErrorToConsole("could not start HTTP server: %v", err) } shutdown <- true }() } else { logger.Debug(logSender, "HTTP server not started, disabled in config file") + logger.DebugToConsole("HTTP server not started, disabled in config file") } <-shutdown diff --git a/sftpd/server.go b/sftpd/server.go index f6329584..a72a4d0e 100644 --- a/sftpd/server.go +++ b/sftpd/server.go @@ -52,6 +52,7 @@ func (c Configuration) Initialize(configDir string) error { utils.SetUmask(int(umask), c.Umask) } else { logger.Warn(logSender, "error reading umask, please fix your config file: %v", err) + logger.WarnToConsole("error reading umask, please fix your config file: %v", err) } actions = c.Actions serverConfig := &ssh.ServerConfig{ @@ -78,6 +79,7 @@ func (c Configuration) Initialize(configDir string) error { if _, err := os.Stat(filepath.Join(configDir, "id_rsa")); os.IsNotExist(err) { logger.Info(logSender, "creating new private key for server") + logger.InfoToConsole("id_rsa does not exist, creating new private key for server") if err := c.generatePrivateKey(configDir); err != nil { return err }