Browse Source

logger: add a flag to use UTC time for logging

Nicola Murino 4 năm trước cách đây
mục cha
commit
094ee1522e

+ 12 - 0
cmd/root.go

@@ -28,6 +28,8 @@ const (
 	logCompressKey           = "log_compress"
 	logVerboseFlag           = "log-verbose"
 	logVerboseKey            = "log_verbose"
+	logUTCTimeFlag           = "log-utc-time"
+	logUTCTimeKey            = "log_utc_time"
 	loadDataFromFlag         = "loaddata-from"
 	loadDataFromKey          = "loaddata_from"
 	loadDataModeFlag         = "loaddata-mode"
@@ -44,6 +46,7 @@ const (
 	defaultLogMaxAge         = 28
 	defaultLogCompress       = false
 	defaultLogVerbose        = true
+	defaultLogUTCTime        = false
 	defaultLoadDataFrom      = ""
 	defaultLoadDataMode      = 1
 	defaultLoadDataQuotaScan = 0
@@ -59,6 +62,7 @@ var (
 	logMaxAge         int
 	logCompress       bool
 	logVerbose        bool
+	logUTCTime        bool
 	loadDataFrom      string
 	loadDataMode      int
 	loadDataQuotaScan int
@@ -180,6 +184,14 @@ using SFTPGO_LOG_VERBOSE env var too.
 `)
 	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.BindEnv(loadDataFromKey, "SFTPGO_LOADDATA_FROM") //nolint:errcheck
 	cmd.Flags().StringVar(&loadDataFrom, loadDataFromFlag, viper.GetString(loadDataFromKey),

+ 1 - 0
cmd/serve.go

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

+ 9 - 0
cmd/startsubsys.go

@@ -44,6 +44,7 @@ Command-line flags should be specified in the Subsystem declaration.
 			if !logVerbose {
 				logLevel = zerolog.InfoLevel
 			}
+			logger.SetLogTime(logUTCTime)
 			if logJournalD {
 				logger.InitJournalDLogger(logLevel)
 			} else {
@@ -180,5 +181,13 @@ using SFTPGO_LOG_VERBOSE env var too.
 `)
 	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)
 }

+ 1 - 1
common/protocol_test.go

@@ -63,7 +63,7 @@ var (
 func TestMain(m *testing.M) {
 	homeBasePath = os.TempDir()
 	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_DEFAULT_ADMIN_USERNAME", "admin")

+ 16 - 4
dataprovider/bolt.go

@@ -1185,15 +1185,18 @@ func (p *BoltProvider) updateShare(share *Share) error {
 		if err != nil {
 			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))
 		}
 		var oldObject Share
-		if err = json.Unmarshal(a, &oldObject); err != nil {
+		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))
+		}
 
 		share.ID = oldObject.ID
 		share.ShareID = oldObject.ShareID
@@ -1219,7 +1222,16 @@ func (p *BoltProvider) deleteShare(share *Share) error {
 			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))
 		}
 

+ 1 - 1
docs/full-configuration.md

@@ -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-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`).
-- `--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.
 

+ 24 - 16
docs/sftp-subsystem.md

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

+ 1 - 1
ftpd/ftpd_test.go

@@ -247,7 +247,7 @@ func TestMain(m *testing.M) {
 	logFilePath = filepath.Join(configDir, "sftpgo_ftpd_test.log")
 	bannerFileName := "banner_file"
 	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)
 	if err != nil {
 		logger.ErrorToConsole("error creating banner file: %v", err)

+ 1 - 1
httpd/httpd_test.go

@@ -245,7 +245,7 @@ type recoveryCode struct {
 func TestMain(m *testing.M) {
 	homeBasePath = os.TempDir()
 	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_DATA_PROVIDER__CREATE_DEFAULT_ADMIN", "1")
 	os.Setenv("SFTPGO_DEFAULT_ADMIN_USERNAME", "admin")

+ 16 - 2
logger/logger.go

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

+ 2 - 1
service/service.go

@@ -39,6 +39,7 @@ type Service struct {
 	PortableUser      dataprovider.User
 	LogCompress       bool
 	LogVerbose        bool
+	LogUTCTime        bool
 	LoadDataClean     bool
 	LoadDataFrom      string
 	LoadDataMode      int
@@ -55,7 +56,7 @@ func (s *Service) initLogger() {
 	if !filepath.IsAbs(s.LogFilePath) && util.IsFileInputValid(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 {
 		logger.EnableConsoleLogger(logLevel)
 		if s.LogFilePath == "" {

+ 1 - 1
sftpd/sftpd_test.go

@@ -144,7 +144,7 @@ func TestMain(m *testing.M) {
 	logFilePath = filepath.Join(configDir, "sftpgo_sftpd_test.log")
 	loginBannerFileName := "login_banner"
 	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)
 	if err != nil {
 		logger.ErrorToConsole("error creating login banner: %v", err)

+ 1 - 1
webdavd/webdavd_test.go

@@ -248,7 +248,7 @@ var (
 
 func TestMain(m *testing.M) {
 	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_DEFAULT_ADMIN_USERNAME", "admin")
 	os.Setenv("SFTPGO_DEFAULT_ADMIN_PASSWORD", "password")