diff --git a/lib/model/folder.go b/lib/model/folder.go index 550271f8e..b62281562 100644 --- a/lib/model/folder.go +++ b/lib/model/folder.go @@ -462,11 +462,10 @@ func (f *folder) scanSubdirs(subDirs []string) error { } defer f.ioLimiter.Give(1) - t0 := time.Now() - defer func() { - metricFolderScans.WithLabelValues(f.ID).Inc() - metricFolderScanSeconds.WithLabelValues(f.ID).Add(time.Since(t0).Seconds()) - }() + metricFolderScans.WithLabelValues(f.ID).Inc() + ctx, cancel := context.WithCancel(f.ctx) + defer cancel() + go addTimeUntilCancelled(ctx, metricFolderScanSeconds.WithLabelValues(f.ID)) for i := range subDirs { sub := osutil.NativeFilename(subDirs[i]) diff --git a/lib/model/folder_sendrecv.go b/lib/model/folder_sendrecv.go index 4ab2f90ba..693b455ac 100644 --- a/lib/model/folder_sendrecv.go +++ b/lib/model/folder_sendrecv.go @@ -8,6 +8,7 @@ package model import ( "bytes" + "context" "errors" "fmt" "io" @@ -163,13 +164,10 @@ func (f *sendReceiveFolder) pull() (bool, error) { scanChan := make(chan string) go f.pullScannerRoutine(scanChan) - t0 := time.Now() - defer func() { - close(scanChan) - f.setState(FolderIdle) - metricFolderPulls.WithLabelValues(f.ID).Inc() - metricFolderPullSeconds.WithLabelValues(f.ID).Add(time.Since(t0).Seconds()) - }() + metricFolderPulls.WithLabelValues(f.ID).Inc() + ctx, cancel := context.WithCancel(f.ctx) + defer cancel() + go addTimeUntilCancelled(ctx, metricFolderPullSeconds.WithLabelValues(f.ID)) changed := 0 diff --git a/lib/model/util.go b/lib/model/util.go index 77b542226..3bc9079b6 100644 --- a/lib/model/util.go +++ b/lib/model/util.go @@ -7,6 +7,7 @@ package model import ( + "context" "errors" "fmt" "path/filepath" @@ -14,6 +15,7 @@ import ( "sync" "time" + "github.com/prometheus/client_golang/prometheus" "github.com/syncthing/syncthing/lib/events" "github.com/syncthing/syncthing/lib/fs" "github.com/syncthing/syncthing/lib/ur" @@ -117,11 +119,11 @@ func inWritableDir(fn func(string) error, targetFs fs.Filesystem, path string, i const permBits = fs.ModePerm | fs.ModeSetuid | fs.ModeSetgid | fs.ModeSticky var parentErr error - if mode := info.Mode() & permBits; mode&0200 == 0 { + if mode := info.Mode() & permBits; mode&0o200 == 0 { // A non-writeable directory (for this user; we assume that's the // relevant part). Temporarily change the mode so we can delete the // file or directory inside it. - parentErr = targetFs.Chmod(dir, mode|0700) + parentErr = targetFs.Chmod(dir, mode|0o700) if parentErr != nil { l.Debugf("Failed to make parent directory writable: %v", parentErr) } else { @@ -148,3 +150,23 @@ func inWritableDir(fn func(string) error, targetFs fs.Filesystem, path string, i } return err } + +// addTimeUntilCancelled adds time to the counter for the duration of the +// Context. We do this piecemeal so that polling the counter during a long +// operation shows a relevant value, instead of the counter just increasing +// by a large amount at the end of the operation. +func addTimeUntilCancelled(ctx context.Context, counter prometheus.Counter) { + t0 := time.Now() + ticker := time.NewTicker(time.Second) + defer ticker.Stop() + for { + select { + case <-ticker.C: + t1 := time.Now() + counter.Add(t1.Sub(t0).Seconds()) + t0 = t1 + case <-ctx.Done(): + counter.Add(time.Since(t0).Seconds()) + } + } +}