diff --git a/cmd/cmd.go b/cmd/cmd.go index dc02c1f57..f1d516ee9 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -253,7 +253,7 @@ func Run(Retry bool, showStats bool, cmd *cobra.Command, f func() error) { log.Fatalf("Failed to %s: %v", cmd.Name(), err) } if showStats && (fs.Stats.Errored() || *statsInterval > 0) { - fs.Infof(nil, "%s", fs.Stats) + fs.Stats.Log() } fs.Debugf(nil, "Go routines at exit %d\n", runtime.NumGoroutine()) if fs.Stats.Errored() { diff --git a/docs/content/docs.md b/docs/content/docs.md index 2fde75ee7..36ff902c0 100644 --- a/docs/content/docs.md +++ b/docs/content/docs.md @@ -396,8 +396,8 @@ using `--checksum`). Log all of rclone's output to FILE. This is not active by default. This can be useful for tracking down problems with syncs in -combination with the `-v` flag. See the Logging section for more -info. +combination with the `-v` flag. See the [Logging section](#logging) +for more info. ### --log-level LEVEL ### @@ -514,10 +514,23 @@ This sets the interval. The default is `1m`. Use 0 to disable. -If you set the stats interval then all command can show stats. This +If you set the stats interval then all commands can show stats. This can be useful when running other commands, `check` or `mount` for example. +Stats are logged at `INFO` level by default which means they won't +show at default log level `NOTICE`. Use `--stats-log-level NOTICE` or +`-v` to make them show. See the [Logging section](#logging) for more +info on log levels. + +### --stats-log-level string ### + +Log level to show `--stats` output at. This can be `DEBUG`, `INFO`, +`NOTICE`, or `ERROR`. The default is `INFO`. This means at the +default level of logging which is `NOTICE` the stats won't show - if +you want them to then use `-stats-log-level NOTICE`. See the [Logging +section](#logging) for more info on log levels. + ### --stats-unit=bits|bytes ### By default, data transfer rates will be printed in bytes/second. diff --git a/fs/accounting.go b/fs/accounting.go index 26a437319..0e7f7c38e 100644 --- a/fs/accounting.go +++ b/fs/accounting.go @@ -203,7 +203,7 @@ Elapsed time: %10v // Log outputs the StatsInfo to the log func (s *StatsInfo) Log() { - Infof(nil, "%v\n", s) + LogLevelPrintf(Config.StatsLogLevel, nil, "%v\n", s) } // Bytes updates the stats for bytes bytes diff --git a/fs/config.go b/fs/config.go index 8c5d2ac5d..89704cede 100644 --- a/fs/config.go +++ b/fs/config.go @@ -65,7 +65,6 @@ var ( // Flags verbose = CountP("verbose", "v", "Print lots more stuff (repeat for more)") quiet = BoolP("quiet", "q", false, "Print as little stuff as possible") - logLevel = StringP("log-level", "", "INFO", "Log level DEBUG|INFO|NOTICE|ERROR") modifyWindow = DurationP("modify-window", "", time.Nanosecond, "Max time diff to be considered the same") checkers = IntP("checkers", "", 8, "Number of checkers to run in parallel.") transfers = IntP("transfers", "", 4, "Number of file transfers to run in parallel.") @@ -97,6 +96,8 @@ var ( backupDir = StringP("backup-dir", "", "", "Make backups into hierarchy based in DIR.") suffix = StringP("suffix", "", "", "Suffix for use with --backup-dir.") useListR = BoolP("fast-list", "", false, "Use recursive list if available. Uses more memory but fewer transactions.") + logLevel = LogLevelNotice + statsLogLevel = LogLevelInfo bwLimit BwTimetable bufferSize SizeSuffix = 16 << 20 @@ -106,6 +107,8 @@ var ( ) func init() { + VarP(&logLevel, "log-level", "", "Log level DEBUG|INFO|NOTICE|ERROR") + VarP(&statsLogLevel, "stats-log-level", "", "Log level to show --stats output DEBUG|INFO|NOTICE|ERROR") VarP(&bwLimit, "bwlimit", "", "Bandwidth limit in kBytes/s, or use suffix b|k|M|G or a full timetable.") VarP(&bufferSize, "buffer-size", "", "Buffer size when copying files.") } @@ -194,6 +197,7 @@ func MustReveal(x string) string { // ConfigInfo is filesystem config options type ConfigInfo struct { LogLevel LogLevel + StatsLogLevel LogLevel DryRun bool CheckSum bool SizeOnly bool @@ -332,19 +336,9 @@ func LoadConfig() { if *quiet { log.Fatalf("Can't set -q and --log-level") } - switch strings.ToUpper(*logLevel) { - case "ERROR": - Config.LogLevel = LogLevelError - case "NOTICE": - Config.LogLevel = LogLevelNotice - case "INFO": - Config.LogLevel = LogLevelInfo - case "DEBUG": - Config.LogLevel = LogLevelDebug - default: - log.Fatalf("Unknown --log-level %q", *logLevel) - } + Config.LogLevel = logLevel } + Config.StatsLogLevel = statsLogLevel Config.ModifyWindow = *modifyWindow Config.Checkers = *checkers Config.Transfers = *transfers diff --git a/fs/log.go b/fs/log.go index b2b60d355..3c6573ecf 100644 --- a/fs/log.go +++ b/fs/log.go @@ -9,6 +9,9 @@ import ( "reflect" "runtime" "strings" + + "github.com/pkg/errors" + "github.com/spf13/pflag" ) // LogLevel describes rclone's logs. These are a subset of the syslog log levels. @@ -55,6 +58,25 @@ func (l LogLevel) String() string { return logLevelToString[l] } +// Set a LogLevel +func (l *LogLevel) Set(s string) error { + for n, name := range logLevelToString { + if s != "" && name == s { + *l = LogLevel(n) + return nil + } + } + return errors.Errorf("Unknown log level %q", s) +} + +// Type of the value +func (l *LogLevel) Type() string { + return "string" +} + +// Check it satisfies the interface +var _ pflag.Value = (*LogLevel)(nil) + // Flags var ( logFile = StringP("log-file", "", "", "Log everything to this file") @@ -77,6 +99,13 @@ func logPrintf(level LogLevel, o interface{}, text string, args ...interface{}) logPrint(level, out) } +// LogLevelPrintf writes logs at the given level +func LogLevelPrintf(level LogLevel, o interface{}, text string, args ...interface{}) { + if Config.LogLevel >= level { + logPrintf(level, o, text, args...) + } +} + // Errorf writes error log output for this Object or Fs. It // should always be seen by the user. func Errorf(o interface{}, text string, args ...interface{}) {