diff --git a/fs/accounting/prometheus.go b/fs/accounting/prometheus.go index 535f99e6a..47e9c7594 100644 --- a/fs/accounting/prometheus.go +++ b/fs/accounting/prometheus.go @@ -14,6 +14,7 @@ type RcloneCollector struct { numOfCheckFiles *prometheus.Desc transferredFiles *prometheus.Desc deletes *prometheus.Desc + renames *prometheus.Desc fatalError *prometheus.Desc retryError *prometheus.Desc } @@ -45,6 +46,10 @@ func NewRcloneCollector() *RcloneCollector { "Total number of files deleted", nil, nil, ), + renames: prometheus.NewDesc(namespace+"files_renamed_total", + "Total number of files renamed", + nil, nil, + ), fatalError: prometheus.NewDesc(namespace+"fatal_error", "Whether a fatal error has occurred", nil, nil, @@ -64,6 +69,7 @@ func (c *RcloneCollector) Describe(ch chan<- *prometheus.Desc) { ch <- c.numOfCheckFiles ch <- c.transferredFiles ch <- c.deletes + ch <- c.renames ch <- c.fatalError ch <- c.retryError } @@ -79,6 +85,7 @@ func (c *RcloneCollector) Collect(ch chan<- prometheus.Metric) { ch <- prometheus.MustNewConstMetric(c.numOfCheckFiles, prometheus.CounterValue, float64(s.checks)) ch <- prometheus.MustNewConstMetric(c.transferredFiles, prometheus.CounterValue, float64(s.transfers)) ch <- prometheus.MustNewConstMetric(c.deletes, prometheus.CounterValue, float64(s.deletes)) + ch <- prometheus.MustNewConstMetric(c.renames, prometheus.CounterValue, float64(s.renames)) ch <- prometheus.MustNewConstMetric(c.fatalError, prometheus.GaugeValue, bool2Float(s.fatalError)) ch <- prometheus.MustNewConstMetric(c.retryError, prometheus.GaugeValue, bool2Float(s.retryError)) diff --git a/fs/accounting/stats.go b/fs/accounting/stats.go index 39831edf0..00423a46c 100644 --- a/fs/accounting/stats.go +++ b/fs/accounting/stats.go @@ -33,6 +33,7 @@ type StatsInfo struct { transferring *stringSet transferQueue int transferQueueSize int64 + renames int64 renameQueue int renameQueueSize int64 deletes int64 @@ -64,6 +65,7 @@ func (s *StatsInfo) RemoteStats() (out rc.Params, err error) { out["checks"] = s.checks out["transfers"] = s.transfers out["deletes"] = s.deletes + out["renames"] = s.renames out["elapsedTime"] = s.totalDuration().Seconds() s.mu.RUnlock() if !s.checking.empty() { @@ -330,6 +332,9 @@ func (s *StatsInfo) String() string { if s.deletes != 0 { _, _ = fmt.Fprintf(buf, "Deleted: %10d\n", s.deletes) } + if s.renames != 0 { + _, _ = fmt.Fprintf(buf, "Renamed: %10d\n", s.renames) + } if s.transfers != 0 || totalTransfer != 0 { _, _ = fmt.Fprintf(buf, "Transferred: %10d / %d, %s\n", s.transfers, totalTransfer, percent(s.transfers, totalTransfer)) @@ -467,7 +472,15 @@ func (s *StatsInfo) Deletes(deletes int64) int64 { return s.deletes } -// ResetCounters sets the counters (bytes, checks, errors, transfers, deletes) to 0 and resets lastError, fatalError and retryError +// Renames updates the stats for renames +func (s *StatsInfo) Renames(renames int64) int64 { + s.mu.Lock() + defer s.mu.Unlock() + s.renames += renames + return s.renames +} + +// ResetCounters sets the counters (bytes, checks, errors, transfers, deletes, renames) to 0 and resets lastError, fatalError and retryError func (s *StatsInfo) ResetCounters() { s.mu.Lock() defer s.mu.Unlock() @@ -480,6 +493,7 @@ func (s *StatsInfo) ResetCounters() { s.checks = 0 s.transfers = 0 s.deletes = 0 + s.renames = 0 s.startedTransfers = nil s.oldDuration = 0 } diff --git a/fs/accounting/stats_groups.go b/fs/accounting/stats_groups.go index 269821a0b..02ce96afa 100644 --- a/fs/accounting/stats_groups.go +++ b/fs/accounting/stats_groups.go @@ -94,6 +94,7 @@ Returns the following values: "checks": number of checked files, "transfers": number of transferred files, "deletes" : number of deleted files, + "renames" : number of renamed files, "elapsedTime": time in seconds since the start of the process, "lastError": last occurred error, "transferring": an array of currently active file transfers: @@ -356,6 +357,7 @@ func (sg *statsGroups) sum() *StatsInfo { sum.checks += stats.checks sum.transfers += stats.transfers sum.deletes += stats.deletes + sum.renames += stats.renames sum.checking.merge(stats.checking) sum.transferring.merge(stats.transferring) sum.inProgress.merge(stats.inProgress) diff --git a/fs/operations/operations.go b/fs/operations/operations.go index 1cd86a9e1..51d4f6b38 100644 --- a/fs/operations/operations.go +++ b/fs/operations/operations.go @@ -513,6 +513,9 @@ func SameObject(src, dst fs.Object) bool { func Move(ctx context.Context, fdst fs.Fs, dst fs.Object, remote string, src fs.Object) (newDst fs.Object, err error) { tr := accounting.Stats(ctx).NewCheckingTransfer(src) defer func() { + if err == nil { + accounting.Stats(ctx).Renames(1) + } tr.Done(err) }() newDst = dst @@ -2058,7 +2061,11 @@ func (l *ListFormat) Format(entry *ListJSONItem) (result string) { func DirMove(ctx context.Context, f fs.Fs, srcRemote, dstRemote string) (err error) { // Use DirMove if possible if doDirMove := f.Features().DirMove; doDirMove != nil { - return doDirMove(ctx, f, srcRemote, dstRemote) + err = doDirMove(ctx, f, srcRemote, dstRemote) + if err == nil { + accounting.Stats(ctx).Renames(1) + } + return err } // Load the directory tree into memory