logger: add a flag to use UTC time for logging

This commit is contained in:
Nicola Murino 2021-11-06 15:18:16 +01:00
parent 3bc58f5988
commit 094ee1522e
No known key found for this signature in database
GPG key ID: 2F1FB59433D5A8CB
13 changed files with 86 additions and 29 deletions

View file

@ -28,6 +28,8 @@ const (
logCompressKey = "log_compress" logCompressKey = "log_compress"
logVerboseFlag = "log-verbose" logVerboseFlag = "log-verbose"
logVerboseKey = "log_verbose" logVerboseKey = "log_verbose"
logUTCTimeFlag = "log-utc-time"
logUTCTimeKey = "log_utc_time"
loadDataFromFlag = "loaddata-from" loadDataFromFlag = "loaddata-from"
loadDataFromKey = "loaddata_from" loadDataFromKey = "loaddata_from"
loadDataModeFlag = "loaddata-mode" loadDataModeFlag = "loaddata-mode"
@ -44,6 +46,7 @@ const (
defaultLogMaxAge = 28 defaultLogMaxAge = 28
defaultLogCompress = false defaultLogCompress = false
defaultLogVerbose = true defaultLogVerbose = true
defaultLogUTCTime = false
defaultLoadDataFrom = "" defaultLoadDataFrom = ""
defaultLoadDataMode = 1 defaultLoadDataMode = 1
defaultLoadDataQuotaScan = 0 defaultLoadDataQuotaScan = 0
@ -59,6 +62,7 @@ var (
logMaxAge int logMaxAge int
logCompress bool logCompress bool
logVerbose bool logVerbose bool
logUTCTime bool
loadDataFrom string loadDataFrom string
loadDataMode int loadDataMode int
loadDataQuotaScan int loadDataQuotaScan int
@ -180,6 +184,14 @@ using SFTPGO_LOG_VERBOSE env var too.
`) `)
viper.BindPFlag(logVerboseKey, cmd.Flags().Lookup(logVerboseFlag)) //nolint:errcheck viper.BindPFlag(logVerboseKey, cmd.Flags().Lookup(logVerboseFlag)) //nolint:errcheck
viper.SetDefault(logUTCTimeKey, defaultLogUTCTime)
viper.BindEnv(logUTCTimeKey, "SFTPGO_LOG_UTC_TIME") //nolint:errcheck
cmd.Flags().BoolVar(&logUTCTime, logUTCTimeFlag, viper.GetBool(logUTCTimeKey),
`Use UTC time for logging. This flag can be set
using SFTPGO_LOG_UTC_TIME env var too.
`)
viper.BindPFlag(logUTCTimeKey, cmd.Flags().Lookup(logUTCTimeFlag)) //nolint:errcheck
viper.SetDefault(loadDataFromKey, defaultLoadDataFrom) viper.SetDefault(loadDataFromKey, defaultLoadDataFrom)
viper.BindEnv(loadDataFromKey, "SFTPGO_LOADDATA_FROM") //nolint:errcheck viper.BindEnv(loadDataFromKey, "SFTPGO_LOADDATA_FROM") //nolint:errcheck
cmd.Flags().StringVar(&loadDataFrom, loadDataFromFlag, viper.GetString(loadDataFromKey), cmd.Flags().StringVar(&loadDataFrom, loadDataFromFlag, viper.GetString(loadDataFromKey),

View file

@ -29,6 +29,7 @@ Please take a look at the usage below to customize the startup options`,
LogMaxAge: logMaxAge, LogMaxAge: logMaxAge,
LogCompress: logCompress, LogCompress: logCompress,
LogVerbose: logVerbose, LogVerbose: logVerbose,
LogUTCTime: logUTCTime,
LoadDataFrom: loadDataFrom, LoadDataFrom: loadDataFrom,
LoadDataMode: loadDataMode, LoadDataMode: loadDataMode,
LoadDataQuotaScan: loadDataQuotaScan, LoadDataQuotaScan: loadDataQuotaScan,

View file

@ -44,6 +44,7 @@ Command-line flags should be specified in the Subsystem declaration.
if !logVerbose { if !logVerbose {
logLevel = zerolog.InfoLevel logLevel = zerolog.InfoLevel
} }
logger.SetLogTime(logUTCTime)
if logJournalD { if logJournalD {
logger.InitJournalDLogger(logLevel) logger.InitJournalDLogger(logLevel)
} else { } else {
@ -180,5 +181,13 @@ using SFTPGO_LOG_VERBOSE env var too.
`) `)
viper.BindPFlag(logVerboseKey, subsystemCmd.Flags().Lookup(logVerboseFlag)) //nolint:errcheck viper.BindPFlag(logVerboseKey, subsystemCmd.Flags().Lookup(logVerboseFlag)) //nolint:errcheck
viper.SetDefault(logUTCTimeKey, defaultLogUTCTime)
viper.BindEnv(logUTCTimeKey, "SFTPGO_LOG_UTC_TIME") //nolint:errcheck
subsystemCmd.Flags().BoolVar(&logUTCTime, logUTCTimeFlag, viper.GetBool(logUTCTimeKey),
`Use UTC time for logging. This flag can be set
using SFTPGO_LOG_UTC_TIME env var too.
`)
viper.BindPFlag(logUTCTimeKey, subsystemCmd.Flags().Lookup(logUTCTimeFlag)) //nolint:errcheck
rootCmd.AddCommand(subsystemCmd) rootCmd.AddCommand(subsystemCmd)
} }

View file

@ -63,7 +63,7 @@ var (
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
homeBasePath = os.TempDir() homeBasePath = os.TempDir()
logFilePath := filepath.Join(configDir, "common_test.log") logFilePath := filepath.Join(configDir, "common_test.log")
logger.InitLogger(logFilePath, 5, 1, 28, false, zerolog.DebugLevel) logger.InitLogger(logFilePath, 5, 1, 28, false, false, zerolog.DebugLevel)
os.Setenv("SFTPGO_DATA_PROVIDER__CREATE_DEFAULT_ADMIN", "1") os.Setenv("SFTPGO_DATA_PROVIDER__CREATE_DEFAULT_ADMIN", "1")
os.Setenv("SFTPGO_DEFAULT_ADMIN_USERNAME", "admin") os.Setenv("SFTPGO_DEFAULT_ADMIN_USERNAME", "admin")

View file

@ -1185,15 +1185,18 @@ func (p *BoltProvider) updateShare(share *Share) error {
if err != nil { if err != nil {
return err return err
} }
var a []byte var s []byte
if a = bucket.Get([]byte(share.ShareID)); a == nil { if s = bucket.Get([]byte(share.ShareID)); s == nil {
return util.NewRecordNotFoundError(fmt.Sprintf("Share %v does not exist", share.ShareID)) return util.NewRecordNotFoundError(fmt.Sprintf("Share %v does not exist", share.ShareID))
} }
var oldObject Share var oldObject Share
if err = json.Unmarshal(a, &oldObject); err != nil { if err = json.Unmarshal(s, &oldObject); err != nil {
return err return err
} }
if oldObject.Username != share.Username {
return util.NewRecordNotFoundError(fmt.Sprintf("Share %v does not exist", share.ShareID))
}
share.ID = oldObject.ID share.ID = oldObject.ID
share.ShareID = oldObject.ShareID share.ShareID = oldObject.ShareID
@ -1219,7 +1222,16 @@ func (p *BoltProvider) deleteShare(share *Share) error {
return err return err
} }
if bucket.Get([]byte(share.ShareID)) == nil { var s []byte
if s = bucket.Get([]byte(share.ShareID)); s == nil {
return util.NewRecordNotFoundError(fmt.Sprintf("Share %v does not exist", share.ShareID))
}
var oldObject Share
if err = json.Unmarshal(s, &oldObject); err != nil {
return err
}
if oldObject.Username != share.Username {
return util.NewRecordNotFoundError(fmt.Sprintf("Share %v does not exist", share.ShareID)) return util.NewRecordNotFoundError(fmt.Sprintf("Share %v does not exist", share.ShareID))
} }

View file

@ -39,7 +39,7 @@ The `serve` command supports the following flags:
- `--log-max-backups` int. Maximum number of old log files to retain. Default 5 or the value of `SFTPGO_LOG_MAX_BACKUPS` environment variable. It is unused if `log-file-path` is empty. - `--log-max-backups` int. Maximum number of old log files to retain. Default 5 or the value of `SFTPGO_LOG_MAX_BACKUPS` environment variable. It is unused if `log-file-path` is empty.
- `--log-max-size` int. Maximum size in megabytes of the log file before it gets rotated. Default 10 or the value of `SFTPGO_LOG_MAX_SIZE` environment variable. It is unused if `log-file-path` is empty. - `--log-max-size` int. Maximum size in megabytes of the log file before it gets rotated. Default 10 or the value of `SFTPGO_LOG_MAX_SIZE` environment variable. It is unused if `log-file-path` is empty.
- `--log-verbose` boolean. Enable verbose logs. Default `true` or the value of `SFTPGO_LOG_VERBOSE` environment variable (1 or `true`, 0 or `false`). - `--log-verbose` boolean. Enable verbose logs. Default `true` or the value of `SFTPGO_LOG_VERBOSE` environment variable (1 or `true`, 0 or `false`).
- `--profiler` boolean. Enable the built-in profiler. The profiler will be accessible via HTTP/HTTPS using the base URL "/debug/pprof/". Default `false` or the value of `SFTPGO_PROFILER` environment variable (1 or `true`, 0 or `false`). - `--log-utc-time` boolean. Enable UTC time for logging. Default `false` or the value of `SFTPGO_LOG_UTC_TIME` environment variable (1 or `true`, 0 or `false`)
Log file can be rotated on demand sending a `SIGUSR1` signal on Unix based systems and using the command `sftpgo service rotatelogs` on Windows. Log file can be rotated on demand sending a `SIGUSR1` signal on Unix based systems and using the command `sftpgo service rotatelogs` on Windows.

View file

@ -20,27 +20,32 @@ Flags:
starting directory. The home directory for a new starting directory. The home directory for a new
user will be: user will be:
<base-home-dir>/<username> [base-home-dir]/[username]
base-home-dir must be an absolute path. base-home-dir must be an absolute path.
-c, --config-dir string Location for SFTPGo config dir. This directory -c, --config-dir string Location for the config dir. This directory
should contain the "sftpgo" configuration file is used as the base for files with a relative
or the configured config-file and it is used as path, eg. the private keys for the SFTP
the base for files with a relative path (eg. the server or the SQLite database if you use
private keys for the SFTP server, the SQLite SQLite as data provider.
database if you use SQLite as data provider). The configuration file, if not explicitly set,
is looked for in this dir. We support reading
from JSON, TOML, YAML, HCL, envfile and Java
properties config files. The default config
file name is "sftpgo" and therefore
"sftpgo.json", "sftpgo.yaml" and so on are
searched.
This flag can be set using SFTPGO_CONFIG_DIR This flag can be set using SFTPGO_CONFIG_DIR
env var too. (default ".") env var too. (default ".")
-f, --config-file string Name for SFTPGo configuration file. It must be --config-file string Path to SFTPGo configuration file.
the name of a file stored in config-dir not the This flag explicitly defines the path, name
absolute path to the configuration file. The and extension of the config file. If must be
specified file name must have no extension we an absolute path or a path relative to the
automatically load JSON, YAML, TOML, HCL and configuration directory. The specified file
Java properties. Therefore if you set "sftpgo" name must have a supported extension (JSON,
then "sftpgo.json", "sftpgo.yaml" and so on YAML, TOML, HCL or Java properties).
are searched.
This flag can be set using SFTPGO_CONFIG_FILE This flag can be set using SFTPGO_CONFIG_FILE
env var too. (default "sftpgo") env var too.
-h, --help help for startsubsys -h, --help help for startsubsys
-j, --log-to-journald Send logs to journald. Only available on Linux. -j, --log-to-journald Send logs to journald. Only available on Linux.
Use: Use:
@ -50,6 +55,9 @@ Flags:
To see full logs. To see full logs.
If not set, the logs will be sent to the standard If not set, the logs will be sent to the standard
error error
--log-utc-time Use UTC time for logging. This flag can be set
using SFTPGO_LOG_UTC_TIME env var too.
(default true)
-v, --log-verbose Enable verbose logs. This flag can be set -v, --log-verbose Enable verbose logs. This flag can be set
using SFTPGO_LOG_VERBOSE env var too. using SFTPGO_LOG_VERBOSE env var too.
(default true) (default true)

View file

@ -247,7 +247,7 @@ func TestMain(m *testing.M) {
logFilePath = filepath.Join(configDir, "sftpgo_ftpd_test.log") logFilePath = filepath.Join(configDir, "sftpgo_ftpd_test.log")
bannerFileName := "banner_file" bannerFileName := "banner_file"
bannerFile := filepath.Join(configDir, bannerFileName) bannerFile := filepath.Join(configDir, bannerFileName)
logger.InitLogger(logFilePath, 5, 1, 28, false, zerolog.DebugLevel) logger.InitLogger(logFilePath, 5, 1, 28, false, false, zerolog.DebugLevel)
err := os.WriteFile(bannerFile, []byte("SFTPGo test ready\nsimple banner line\n"), os.ModePerm) err := os.WriteFile(bannerFile, []byte("SFTPGo test ready\nsimple banner line\n"), os.ModePerm)
if err != nil { if err != nil {
logger.ErrorToConsole("error creating banner file: %v", err) logger.ErrorToConsole("error creating banner file: %v", err)

View file

@ -245,7 +245,7 @@ type recoveryCode struct {
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
homeBasePath = os.TempDir() homeBasePath = os.TempDir()
logfilePath := filepath.Join(configDir, "sftpgo_api_test.log") logfilePath := filepath.Join(configDir, "sftpgo_api_test.log")
logger.InitLogger(logfilePath, 5, 1, 28, false, zerolog.DebugLevel) logger.InitLogger(logfilePath, 5, 1, 28, false, false, zerolog.DebugLevel)
os.Setenv("SFTPGO_COMMON__UPLOAD_MODE", "2") os.Setenv("SFTPGO_COMMON__UPLOAD_MODE", "2")
os.Setenv("SFTPGO_DATA_PROVIDER__CREATE_DEFAULT_ADMIN", "1") os.Setenv("SFTPGO_DATA_PROVIDER__CREATE_DEFAULT_ADMIN", "1")
os.Setenv("SFTPGO_DEFAULT_ADMIN_USERNAME", "admin") os.Setenv("SFTPGO_DEFAULT_ADMIN_USERNAME", "admin")

View file

@ -14,6 +14,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"runtime" "runtime"
"time"
ftpserverlog "github.com/fclairamb/go-log" ftpserverlog "github.com/fclairamb/go-log"
"github.com/rs/zerolog" "github.com/rs/zerolog"
@ -136,9 +137,21 @@ func GetLogger() *zerolog.Logger {
return &logger return &logger
} }
// InitLogger configures the logger using the given parameters // SetLogTime sets logging time related setting
func InitLogger(logFilePath string, logMaxSize int, logMaxBackups int, logMaxAge int, logCompress bool, level zerolog.Level) { func SetLogTime(utc bool) {
zerolog.TimeFieldFormat = dateFormat zerolog.TimeFieldFormat = dateFormat
if utc {
zerolog.TimestampFunc = time.Now().UTC
} else {
zerolog.TimestampFunc = time.Now
}
}
// InitLogger configures the logger using the given parameters
func InitLogger(logFilePath string, logMaxSize int, logMaxBackups int, logMaxAge int, logCompress, logUTCTime bool,
level zerolog.Level,
) {
SetLogTime(logUTCTime)
if isLogFilePathValid(logFilePath) { if isLogFilePathValid(logFilePath) {
logDir := filepath.Dir(logFilePath) logDir := filepath.Dir(logFilePath)
if _, err := os.Stat(logDir); os.IsNotExist(err) { if _, err := os.Stat(logDir); os.IsNotExist(err) {
@ -153,6 +166,7 @@ func InitLogger(logFilePath string, logMaxSize int, logMaxBackups int, logMaxAge
MaxBackups: logMaxBackups, MaxBackups: logMaxBackups,
MaxAge: logMaxAge, MaxAge: logMaxAge,
Compress: logCompress, Compress: logCompress,
LocalTime: !logUTCTime,
} }
logger = zerolog.New(rollingLogger) logger = zerolog.New(rollingLogger)
EnableConsoleLogger(level) EnableConsoleLogger(level)

View file

@ -39,6 +39,7 @@ type Service struct {
PortableUser dataprovider.User PortableUser dataprovider.User
LogCompress bool LogCompress bool
LogVerbose bool LogVerbose bool
LogUTCTime bool
LoadDataClean bool LoadDataClean bool
LoadDataFrom string LoadDataFrom string
LoadDataMode int LoadDataMode int
@ -55,7 +56,7 @@ func (s *Service) initLogger() {
if !filepath.IsAbs(s.LogFilePath) && util.IsFileInputValid(s.LogFilePath) { if !filepath.IsAbs(s.LogFilePath) && util.IsFileInputValid(s.LogFilePath) {
s.LogFilePath = filepath.Join(s.ConfigDir, s.LogFilePath) s.LogFilePath = filepath.Join(s.ConfigDir, s.LogFilePath)
} }
logger.InitLogger(s.LogFilePath, s.LogMaxSize, s.LogMaxBackups, s.LogMaxAge, s.LogCompress, logLevel) logger.InitLogger(s.LogFilePath, s.LogMaxSize, s.LogMaxBackups, s.LogMaxAge, s.LogCompress, s.LogUTCTime, logLevel)
if s.PortableMode == 1 { if s.PortableMode == 1 {
logger.EnableConsoleLogger(logLevel) logger.EnableConsoleLogger(logLevel)
if s.LogFilePath == "" { if s.LogFilePath == "" {

View file

@ -144,7 +144,7 @@ func TestMain(m *testing.M) {
logFilePath = filepath.Join(configDir, "sftpgo_sftpd_test.log") logFilePath = filepath.Join(configDir, "sftpgo_sftpd_test.log")
loginBannerFileName := "login_banner" loginBannerFileName := "login_banner"
loginBannerFile := filepath.Join(configDir, loginBannerFileName) loginBannerFile := filepath.Join(configDir, loginBannerFileName)
logger.InitLogger(logFilePath, 5, 1, 28, false, zerolog.DebugLevel) logger.InitLogger(logFilePath, 5, 1, 28, false, false, zerolog.DebugLevel)
err := os.WriteFile(loginBannerFile, []byte("simple login banner\n"), os.ModePerm) err := os.WriteFile(loginBannerFile, []byte("simple login banner\n"), os.ModePerm)
if err != nil { if err != nil {
logger.ErrorToConsole("error creating login banner: %v", err) logger.ErrorToConsole("error creating login banner: %v", err)

View file

@ -248,7 +248,7 @@ var (
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
logFilePath = filepath.Join(configDir, "sftpgo_webdavd_test.log") logFilePath = filepath.Join(configDir, "sftpgo_webdavd_test.log")
logger.InitLogger(logFilePath, 5, 1, 28, false, zerolog.DebugLevel) logger.InitLogger(logFilePath, 5, 1, 28, false, false, zerolog.DebugLevel)
os.Setenv("SFTPGO_DATA_PROVIDER__CREATE_DEFAULT_ADMIN", "1") os.Setenv("SFTPGO_DATA_PROVIDER__CREATE_DEFAULT_ADMIN", "1")
os.Setenv("SFTPGO_DEFAULT_ADMIN_USERNAME", "admin") os.Setenv("SFTPGO_DEFAULT_ADMIN_USERNAME", "admin")
os.Setenv("SFTPGO_DEFAULT_ADMIN_PASSWORD", "password") os.Setenv("SFTPGO_DEFAULT_ADMIN_PASSWORD", "password")