Repository: kopia/kopia
Pull request #2588 (2022-11-19 05:05:52)

feat(repository): added Snapshot(bool) option to reset metrics

codecov[bot]: # [Codecov](https://codecov.io/gh/kopia/kopia/pull/2588?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kopia) Report
Base: **74.83**% // Head: **74.80**% // Decreases project coverage by **`-0.02%`** :warning:
> Coverage data is based on head [(`6ce8789`)](https://codecov.io/gh/kopia/kopia/pull/2588?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kopia) compared to base [(`78edd92`)](https://codecov.io/gh/kopia/kopia/commit/78edd926925f2aa048c54900057fe434e3be2f49?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kopia).
> Patch coverage: 100.00% of modified lines in pull request are covered.

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master    #2588      +/-   ##
==========================================
- Coverage   74.83%   74.80%   -0.03%     
==========================================
  Files         450      450              
  Lines       35476    35486      +10     
==========================================
- Hits        26549    26547       -2     
- Misses       7039     7044       +5     
- Partials     1888     1895       +7     
```


| [Impacted Files](https://codecov.io/gh/kopia/kopia/pull/2588?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kopia) | Coverage Δ | |
|---|---|---|
| [internal/metrics/metrics\_counter.go](https://codecov.io/gh/kopia/kopia/pull/2588/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kopia#diff-aW50ZXJuYWwvbWV0cmljcy9tZXRyaWNzX2NvdW50ZXIuZ28=) | `100.00% <100.00%> (ø)` | |
| [internal/metrics/metrics\_distribution.go](https://codecov.io/gh/kopia/kopia/pull/2588/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kopia#diff-aW50ZXJuYWwvbWV0cmljcy9tZXRyaWNzX2Rpc3RyaWJ1dGlvbi5nbw==) | `100.00% <100.00%> (ø)` | |
| [internal/metrics/metrics\_gauge.go](https://codecov.io/gh/kopia/kopia/pull/2588/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kopia#diff-aW50ZXJuYWwvbWV0cmljcy9tZXRyaWNzX2dhdWdlLmdv) | `100.00% <100.00%> (ø)` | |
| [internal/metrics/metrics\_registry.go](https://codecov.io/gh/kopia/kopia/pull/2588/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kopia#diff-aW50ZXJuYWwvbWV0cmljcy9tZXRyaWNzX3JlZ2lzdHJ5Lmdv) | `100.00% <100.00%> (ø)` | |
| [internal/dirutil/mksubdirall.go](https://codecov.io/gh/kopia/kopia/pull/2588/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kopia#diff-aW50ZXJuYWwvZGlydXRpbC9ta3N1YmRpcmFsbC5nbw==) | `92.10% <0.00%> (-7.90%)` | :arrow_down: |
| [cli/command\_content\_verify.go](https://codecov.io/gh/kopia/kopia/pull/2588/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kopia#diff-Y2xpL2NvbW1hbmRfY29udGVudF92ZXJpZnkuZ28=) | `75.00% <0.00%> (-6.04%)` | :arrow_down: |
| [internal/server/source\_manager.go](https://codecov.io/gh/kopia/kopia/pull/2588/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kopia#diff-aW50ZXJuYWwvc2VydmVyL3NvdXJjZV9tYW5hZ2VyLmdv) | `81.28% <0.00%> (-1.54%)` | :arrow_down: |
| [snapshot/snapshotfs/repofs.go](https://codecov.io/gh/kopia/kopia/pull/2588/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kopia#diff-c25hcHNob3Qvc25hcHNob3Rmcy9yZXBvZnMuZ28=) | `79.29% <0.00%> (-1.52%)` | :arrow_down: |
| [repo/content/index/index\_v1.go](https://codecov.io/gh/kopia/kopia/pull/2588/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kopia#diff-cmVwby9jb250ZW50L2luZGV4L2luZGV4X3YxLmdv) | `75.00% <0.00%> (-1.18%)` | :arrow_down: |
| [snapshot/snapshotfs/upload.go](https://codecov.io/gh/kopia/kopia/pull/2588/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kopia#diff-c25hcHNob3Qvc25hcHNob3Rmcy91cGxvYWQuZ28=) | `85.37% <0.00%> (+0.11%)` | :arrow_up: |
| ... and [3 more](https://codecov.io/gh/kopia/kopia/pull/2588/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kopia) | |

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kopia). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kopia)

</details>

[:umbrella: View full report at Codecov](https://codecov.io/gh/kopia/kopia/pull/2588?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kopia).   
:loudspeaker: Do you have feedback about the report comment? [Let us know in this issue](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kopia).


Patch:
diff --git a/internal/metrics/metrics_counter.go b/internal/metrics/metrics_counter.go
index b6a19a64..d7eccb48 100644
--- a/internal/metrics/metrics_counter.go
+++ b/internal/metrics/metrics_counter.go
@@ -29,11 +29,15 @@ func (c *Counter) newState() int64 {
 }
 
 // Snapshot captures the momentary state of a counter.
-func (c *Counter) Snapshot() int64 {
+func (c *Counter) Snapshot(reset bool) int64 {
 	if c == nil {
 		return 0
 	}
 
+	if reset {
+		return c.newState()
+	}
+
 	return c.state.Load()
 }
 
diff --git a/internal/metrics/metrics_distribution.go b/internal/metrics/metrics_distribution.go
index dff44b39..a6cec80a 100644
--- a/internal/metrics/metrics_distribution.go
+++ b/internal/metrics/metrics_distribution.go
@@ -11,12 +11,12 @@
 
 // DistributionState captures momentary state of a Distribution.
 type DistributionState[T constraints.Float | constraints.Integer] struct {
-	Min              T
-	Max              T
-	Sum              T
-	Count            int64
-	BucketCounters   []int64
-	BucketThresholds []T
+	Min              T       `json:"min"`
+	Max              T       `json:"max"`
+	Sum              T       `json:"sum"`
+	Count            int64   `json:"count"`
+	BucketCounters   []int64 `json:"buckets"`
+	BucketThresholds []T     `json:"-"`
 }
 
 // Mean returns arithmetic mean value captured in the distribution.
@@ -72,11 +72,15 @@ func (d *Distribution[T]) Observe(value T) {
 }
 
 // Snapshot returns a snapshot of the distribution state.
-func (d *Distribution[T]) Snapshot() DistributionState[T] {
+func (d *Distribution[T]) Snapshot(reset bool) DistributionState[T] {
 	if d == nil {
 		return DistributionState[T]{}
 	}
 
+	if reset {
+		return *(d.newState())
+	}
+
 	d.mu.Lock()
 	defer d.mu.Unlock()
 
diff --git a/internal/metrics/metrics_gauge.go b/internal/metrics/metrics_gauge.go
index dcccee76..753fac65 100644
--- a/internal/metrics/metrics_gauge.go
+++ b/internal/metrics/metrics_gauge.go
@@ -32,11 +32,15 @@ func (c *Gauge) newState() int64 {
 }
 
 // Snapshot captures a momentary state of the gauge.
-func (c *Gauge) Snapshot() int64 {
+func (c *Gauge) Snapshot(reset bool) int64 {
 	if c == nil {
 		return 0
 	}
 
+	if reset {
+		return c.newState()
+	}
+
 	return c.state.Load()
 }
 
diff --git a/internal/metrics/metrics_registry.go b/internal/metrics/metrics_registry.go
index 1a61c39b..61901c21 100644
--- a/internal/metrics/metrics_registry.go
+++ b/internal/metrics/metrics_registry.go
@@ -24,14 +24,14 @@ type Registry struct {
 
 // Snapshot captures the state of all metrics.
 type Snapshot struct {
-	Counters              map[string]int64
-	Gauges                map[string]int64
-	DurationDistributions map[string]DistributionState[time.Duration]
-	SizeDistributions     map[string]DistributionState[int64]
+	Counters              map[string]int64                            `json:"counters"`
+	Gauges                map[string]int64                            `json:"gauges"`
+	DurationDistributions map[string]DistributionState[time.Duration] `json:"durationDistributions"`
+	SizeDistributions     map[string]DistributionState[int64]         `json:"sizeDistributions"`
 }
 
 // Snapshot captures the snapshot of all metrics.
-func (r *Registry) Snapshot() Snapshot {
+func (r *Registry) Snapshot(reset bool) Snapshot {
 	s := Snapshot{
 		Counters:              map[string]int64{},
 		Gauges:                map[string]int64{},
@@ -40,19 +40,19 @@ func (r *Registry) Snapshot() Snapshot {
 	}
 
 	for k, c := range r.allCounters {
-		s.Counters[k] = c.Snapshot()
+		s.Counters[k] = c.Snapshot(reset)
 	}
 
 	for k, c := range r.allGauges {
-		s.Gauges[k] = c.Snapshot()
+		s.Gauges[k] = c.Snapshot(reset)
 	}
 
 	for k, c := range r.allDurationDistributions {
-		s.DurationDistributions[k] = c.Snapshot()
+		s.DurationDistributions[k] = c.Snapshot(reset)
 	}
 
 	for k, c := range r.allSizeDistributions {
-		s.SizeDistributions[k] = c.Snapshot()
+		s.SizeDistributions[k] = c.Snapshot(reset)
 	}
 
 	return s
@@ -60,6 +60,10 @@ func (r *Registry) Snapshot() Snapshot {
 
 // Close closes the metrics registry.
 func (r *Registry) Close(ctx context.Context) error {
+	if r == nil {
+		return nil
+	}
+
 	return nil
 }
 
@@ -69,7 +73,7 @@ func (r *Registry) Log(ctx context.Context) error {
 		return nil
 	}
 
-	s := r.Snapshot()
+	s := r.Snapshot(false)
 
 	for n, val := range s.Counters {
 		log(ctx).Debugw("COUNTER", "name", n, "value", val)
@@ -94,15 +98,13 @@ func (r *Registry) Log(ctx context.Context) error {
 
 // NewRegistry returns new metrics registry.
 func NewRegistry() *Registry {
-	e := &Registry{
+	return &Registry{
 		allCounters:              map[string]*Counter{},
 		allGauges:                map[string]*Gauge{},
 		allDurationDistributions: map[string]*Distribution[time.Duration]{},
 		allSizeDistributions:     map[string]*Distribution[int64]{},
 		allThroughput:            map[string]*Throughput{},
 	}
-
-	return e
 }
 
 func labelsSuffix(l map[string]string) string {


Test patch:
diff --git a/internal/metrics/metrics_counter_test.go b/internal/metrics/metrics_counter_test.go
index 6ac56d5c..3f1b2f55 100644
--- a/internal/metrics/metrics_counter_test.go
+++ b/internal/metrics/metrics_counter_test.go
@@ -14,7 +14,7 @@ func TestCounter_Nil(t *testing.T) {
 	cnt := e.CounterInt64("aaa", "bbb", nil)
 	require.Nil(t, cnt)
 	cnt.Add(33)
-	require.Equal(t, int64(0), cnt.Snapshot())
+	require.Equal(t, int64(0), cnt.Snapshot(false))
 }
 
 func TestCounter_NoLabels(t *testing.T) {
@@ -33,7 +33,10 @@ func TestCounter_NoLabels(t *testing.T) {
 		mustFindMetric(t, "kopia_some_gauge_total", prommodel.MetricType_COUNTER, nil).
 			GetCounter().GetValue())
 
-	require.Equal(t, int64(133), cnt.Snapshot())
+	require.Equal(t, int64(133), cnt.Snapshot(false))
+
+	require.Equal(t, int64(133), cnt.Snapshot(true)) // reset
+	require.Equal(t, int64(0), cnt.Snapshot(false))
 }
 
 func TestCounter_WithLabels(t *testing.T) {
diff --git a/internal/metrics/metrics_duration_distribution_test.go b/internal/metrics/metrics_duration_distribution_test.go
index 0bba97e5..085eaafa 100644
--- a/internal/metrics/metrics_duration_distribution_test.go
+++ b/internal/metrics/metrics_duration_distribution_test.go
@@ -15,7 +15,7 @@ func TestDurationDistribution_Nil(t *testing.T) {
 	dist := e.DurationDistribution("aaa", "bbb", metrics.IOLatencyThresholds, nil)
 	require.Nil(t, dist)
 	dist.Observe(time.Second)
-	require.Equal(t, metrics.DistributionState[time.Duration]{}, dist.Snapshot())
+	require.Equal(t, metrics.DistributionState[time.Duration]{}, dist.Snapshot(false))
 }
 
 func TestSizeDistribution_Nil(t *testing.T) {
@@ -46,7 +46,7 @@ func TestDurationDistribution_WithLabels(t *testing.T) {
 	cnt1 := e.DurationDistribution("some_dur_dist2", "some-help", metrics.IOLatencyThresholds, map[string]string{"key1": "label1"})
 	cnt2 := e.DurationDistribution("some_dur_dist2", "some-help", metrics.IOLatencyThresholds, map[string]string{"key1": "label2"})
 
-	snap0 := cnt1.Snapshot()
+	snap0 := cnt1.Snapshot(false)
 
 	require.Equal(t, int64(0), snap0.Count)
 	require.Equal(t, 0*time.Second, snap0.Min)
@@ -74,7 +74,7 @@ func TestDurationDistribution_WithLabels(t *testing.T) {
 	require.Equal(t, uint64(2), h2.GetHistogram().GetSampleCount())
 	require.Equal(t, 3650000.0, h2.GetHistogram().GetSampleSum())
 
-	snap1 := cnt1.Snapshot()
+	snap1 := cnt1.Snapshot(false)
 
 	require.Equal(t, int64(2), snap1.Count)
 	require.Equal(t, time.Second, snap1.Min)
@@ -82,7 +82,7 @@ func TestDurationDistribution_WithLabels(t *testing.T) {
 	require.Equal(t, 31*time.Second, snap1.Sum)
 	require.Equal(t, 15500*time.Millisecond, snap1.Mean())
 
-	snap2 := cnt2.Snapshot()
+	snap2 := cnt2.Snapshot(false)
 
 	require.Equal(t, int64(2), snap2.Count)
 	require.Equal(t, 50*time.Second, snap2.Min)
@@ -96,7 +96,7 @@ func TestSizeDistribution_WithLabels(t *testing.T) {
 	cnt1 := e.SizeDistribution("some_size_dist", "some-help", metrics.ISOBytesThresholds, map[string]string{"key1": "label1"})
 	cnt2 := e.SizeDistribution("some_size_dist", "some-help", metrics.ISOBytesThresholds, map[string]string{"key1": "label2"})
 
-	snap0 := cnt1.Snapshot()
+	snap0 := cnt1.Snapshot(false)
 
 	require.Equal(t, int64(0), snap0.Count)
 	require.Equal(t, int64(0), snap0.Min)
@@ -124,7 +124,7 @@ func TestSizeDistribution_WithLabels(t *testing.T) {
 	require.Equal(t, uint64(2), h2.GetHistogram().GetSampleCount())
 	require.Equal(t, 51.0e6, h2.GetHistogram().GetSampleSum())
 
-	snap1 := cnt1.Snapshot()
+	snap1 := cnt1.Snapshot(false)
 
 	require.Equal(t, int64(2), snap1.Count)
 	require.Equal(t, int64(300), snap1.Min)
@@ -132,11 +132,27 @@ func TestSizeDistribution_WithLabels(t *testing.T) {
 	require.Equal(t, int64(1300), snap1.Sum)
 	require.Equal(t, int64(650), snap1.Mean())
 
-	snap2 := cnt2.Snapshot()
+	snap2 := cnt2.Snapshot(false)
 
 	require.Equal(t, int64(2), snap2.Count)
 	require.Equal(t, int64(1000000), snap2.Min)
 	require.Equal(t, int64(50000000), snap2.Max)
 	require.Equal(t, int64(51000000), snap2.Sum)
 	require.Equal(t, int64(25500000), snap2.Mean())
+
+	snap3 := cnt2.Snapshot(true) // reset
+
+	require.Equal(t, int64(2), snap3.Count)
+	require.Equal(t, int64(1000000), snap3.Min)
+	require.Equal(t, int64(50000000), snap3.Max)
+	require.Equal(t, int64(51000000), snap3.Sum)
+	require.Equal(t, int64(25500000), snap3.Mean())
+
+	snap4 := cnt2.Snapshot(false)
+
+	require.Equal(t, int64(0), snap4.Count)
+	require.Equal(t, int64(0), snap4.Min)
+	require.Equal(t, int64(0), snap4.Max)
+	require.Equal(t, int64(0), snap4.Sum)
+	require.Equal(t, int64(0), snap4.Mean())
 }
diff --git a/internal/metrics/metrics_gauge_test.go b/internal/metrics/metrics_gauge_test.go
index 4be217be..b0bdf4f3 100644
--- a/internal/metrics/metrics_gauge_test.go
+++ b/internal/metrics/metrics_gauge_test.go
@@ -14,7 +14,7 @@ func TestGauge_Nil(t *testing.T) {
 	g := mr.Gauge("aaa", "bbb", nil)
 	require.Nil(t, g)
 	g.Set(33)
-	require.Equal(t, int64(0), g.Snapshot())
+	require.Equal(t, int64(0), g.Snapshot(false))
 }
 
 func TestGauge_NoLabels(t *testing.T) {
@@ -33,7 +33,9 @@ func TestGauge_NoLabels(t *testing.T) {
 		mustFindMetric(t, "kopia_some_gauge", prommodel.MetricType_GAUGE, nil).
 			GetGauge().GetValue())
 
-	require.Equal(t, int64(133), g.Snapshot())
+	require.Equal(t, int64(133), g.Snapshot(false))
+	require.Equal(t, int64(133), g.Snapshot(true)) // reset
+	require.Equal(t, int64(0), g.Snapshot(false))
 }
 
 func TestGauge_WithLabels(t *testing.T) {
diff --git a/repo/blob/storagemetrics/storage_metrics_test.go b/repo/blob/storagemetrics/storage_metrics_test.go
index 14bf0c52..91c46788 100644
--- a/repo/blob/storagemetrics/storage_metrics_test.go
+++ b/repo/blob/storagemetrics/storage_metrics_test.go
@@ -24,7 +24,7 @@ func TestStorageMetrics_PutBlob(t *testing.T) {
 
 	mr := metrics.NewRegistry()
 	ms := storagemetrics.NewWrapper(fs, mr)
-	snap := mr.Snapshot()
+	snap := mr.Snapshot(false)
 
 	requireCounterValue(t, snap, "blob_upload_bytes", 0)
 	requireCounterValue(t, snap, "blob_errors[method:PutBlob]", 0)
@@ -32,7 +32,7 @@ func TestStorageMetrics_PutBlob(t *testing.T) {
 	require.ErrorIs(t, ms.PutBlob(ctx, "someBlob1", gather.FromSlice([]byte{1, 2, 3, 4}), blob.PutOptions{}), someError)
 	require.NoError(t, ms.PutBlob(ctx, "someBlob", gather.FromSlice([]byte{1, 2, 3}), blob.PutOptions{}))
 
-	snap = mr.Snapshot()
+	snap = mr.Snapshot(false)
 	requireCounterValue(t, snap, "blob_errors[method:PutBlob]", 1)
 	requireCounterValue(t, snap, "blob_upload_bytes", 3)
 
@@ -52,7 +52,7 @@ func TestStorageMetrics_GetBlob(t *testing.T) {
 
 	mr := metrics.NewRegistry()
 	ms := storagemetrics.NewWrapper(fs, mr)
-	snap := mr.Snapshot()
+	snap := mr.Snapshot(false)
 
 	requireCounterValue(t, snap, "blob_download_full_blob_bytes", 0)
 	requireCounterValue(t, snap, "blob_download_partial_blob_bytes", 0)
@@ -64,7 +64,7 @@ func TestStorageMetrics_GetBlob(t *testing.T) {
 	require.ErrorIs(t, ms.GetBlob(ctx, "someBlob", 0, -1, &tmp), someError)
 	require.NoError(t, ms.GetBlob(ctx, "someBlob", 0, -1, &tmp))
 
-	snap = mr.Snapshot()
+	snap = mr.Snapshot(false)
 	requireCounterValue(t, snap, "blob_errors[method:GetBlob]", 1)
 	requireCounterValue(t, snap, "blob_download_full_blob_bytes", 5)
 
@@ -73,7 +73,7 @@ func TestStorageMetrics_GetBlob(t *testing.T) {
 
 	require.NoError(t, ms.GetBlob(ctx, "someBlob", 2, 2, &tmp))
 
-	snap = mr.Snapshot()
+	snap = mr.Snapshot(false)
 	requireCounterValue(t, snap, "blob_errors[method:GetBlob]", 1)
 	requireCounterValue(t, snap, "blob_download_full_blob_bytes", 5)
 	require.Equal(t, 2, tmp.Length())
@@ -94,7 +94,7 @@ func TestStorageMetrics_GetMetadata(t *testing.T) {
 
 	mr := metrics.NewRegistry()
 	ms := storagemetrics.NewWrapper(fs, mr)
-	snap := mr.Snapshot()
+	snap := mr.Snapshot(false)
 
 	requireCounterValue(t, snap, "blob_errors[method:GetMetadata]", 0)
 
@@ -107,7 +107,7 @@ func TestStorageMetrics_GetMetadata(t *testing.T) {
 	_, err = ms.GetMetadata(ctx, "someBlob")
 	require.NoError(t, err)
 
-	snap = mr.Snapshot()
+	snap = mr.Snapshot(false)
 	requireCounterValue(t, snap, "blob_errors[method:GetMetadata]", 1)
 
 	d := snap.DurationDistributions["blob_storage_latency[method:GetMetadata]"]
@@ -124,7 +124,7 @@ func TestStorageMetrics_GetCapacity(t *testing.T) {
 
 	mr := metrics.NewRegistry()
 	ms := storagemetrics.NewWrapper(fs, mr)
-	snap := mr.Snapshot()
+	snap := mr.Snapshot(false)
 
 	requireCounterValue(t, snap, "blob_errors[method:GetCapacity]", 0)
 
@@ -137,7 +137,7 @@ func TestStorageMetrics_GetCapacity(t *testing.T) {
 	_, err = ms.GetCapacity(ctx)
 	require.ErrorIs(t, err, blob.ErrNotAVolume)
 
-	snap = mr.Snapshot()
+	snap = mr.Snapshot(false)
 	requireCounterValue(t, snap, "blob_errors[method:GetCapacity]", 2)
 
 	d := snap.DurationDistributions["blob_storage_latency[method:GetCapacity]"]
@@ -156,7 +156,7 @@ func TestStorageMetrics_DeleteBlob(t *testing.T) {
 
 	mr := metrics.NewRegistry()
 	ms := storagemetrics.NewWrapper(fs, mr)
-	snap := mr.Snapshot()
+	snap := mr.Snapshot(false)
 
 	requireCounterValue(t, snap, "blob_errors[method:DeleteBlob]", 0)
 
@@ -169,7 +169,7 @@ func TestStorageMetrics_DeleteBlob(t *testing.T) {
 	err = ms.DeleteBlob(ctx, "someBlob")
 	require.NoError(t, err)
 
-	snap = mr.Snapshot()
+	snap = mr.Snapshot(false)
 	requireCounterValue(t, snap, "blob_errors[method:DeleteBlob]", 1)
 
 	d := snap.DurationDistributions["blob_storage_latency[method:DeleteBlob]"]
@@ -186,7 +186,7 @@ func TestStorageMetrics_Close(t *testing.T) {
 
 	mr := metrics.NewRegistry()
 	ms := storagemetrics.NewWrapper(fs, mr)
-	snap := mr.Snapshot()
+	snap := mr.Snapshot(false)
 
 	requireCounterValue(t, snap, "blob_errors[method:Close]", 0)
 
@@ -199,7 +199,7 @@ func TestStorageMetrics_Close(t *testing.T) {
 	err = ms.Close(ctx)
 	require.NoError(t, err)
 
-	snap = mr.Snapshot()
+	snap = mr.Snapshot(false)
 	requireCounterValue(t, snap, "blob_errors[method:Close]", 1)
 
 	d := snap.DurationDistributions["blob_storage_latency[method:Close]"]
@@ -216,7 +216,7 @@ func TestStorageMetrics_FlushCaches(t *testing.T) {
 
 	mr := metrics.NewRegistry()
 	ms := storagemetrics.NewWrapper(fs, mr)
-	snap := mr.Snapshot()
+	snap := mr.Snapshot(false)
 
 	requireCounterValue(t, snap, "blob_errors[method:FlushCaches]", 0)
 
@@ -229,7 +229,7 @@ func TestStorageMetrics_FlushCaches(t *testing.T) {
 	err = ms.FlushCaches(ctx)
 	require.NoError(t, err)
 
-	snap = mr.Snapshot()
+	snap = mr.Snapshot(false)
 	requireCounterValue(t, snap, "blob_errors[method:FlushCaches]", 1)
 
 	d := snap.DurationDistributions["blob_storage_latency[method:FlushCaches]"]
@@ -249,7 +249,7 @@ func TestStorageMetrics_ListBlobs(t *testing.T) {
 
 	mr := metrics.NewRegistry()
 	ms := storagemetrics.NewWrapper(fs, mr)
-	snap := mr.Snapshot()
+	snap := mr.Snapshot(false)
 
 	requireCounterValue(t, snap, "blob_errors[method:ListBlobs]", 0)
 	requireCounterValue(t, snap, "blob_list_items", 0)
@@ -263,7 +263,7 @@ func TestStorageMetrics_ListBlobs(t *testing.T) {
 	err = ms.ListBlobs(ctx, "", func(bm blob.Metadata) error { return nil })
 	require.NoError(t, err)
 
-	snap = mr.Snapshot()
+	snap = mr.Snapshot(false)
 	requireCounterValue(t, snap, "blob_errors[method:ListBlobs]", 1)
 
 	d := snap.DurationDistributions["blob_storage_latency[method:ListBlobs]"]
diff --git a/repo/repository_test.go b/repo/repository_test.go
index 22d04284..40ca7f11 100644
--- a/repo/repository_test.go
+++ b/repo/repository_test.go
@@ -650,7 +650,7 @@ func (s *formatSpecificTestSuite) TestChangePassword(t *testing.T) {
 func TestMetrics_CompressibleData(t *testing.T) {
 	ctx, env := repotesting.NewEnvironment(t, repotesting.FormatNotImportant)
 	_ = ctx
-	ms := env.Repository.Metrics().Snapshot()
+	ms := env.Repository.Metrics().Snapshot(false)
 
 	require.EqualValues(t, 0, ensureMapEntry(t, ms.Counters, "content_write_bytes"))
 
@@ -660,7 +660,7 @@ func TestMetrics_CompressibleData(t *testing.T) {
 		oid       object.ID
 	)
 
-	for ensureMapEntry(t, env.Repository.Metrics().Snapshot().Counters, "content_write_duration_nanos") < 5e6 {
+	for ensureMapEntry(t, env.Repository.Metrics().Snapshot(false).Counters, "content_write_duration_nanos") < 5e6 {
 		w := env.RepositoryWriter.NewObjectWriter(ctx, object.WriterOptions{
 			Compressor: "gzip",
 		})
@@ -674,7 +674,7 @@ func TestMetrics_CompressibleData(t *testing.T) {
 		count++
 	}
 
-	ms = env.Repository.Metrics().Snapshot()
+	ms = env.Repository.Metrics().Snapshot(false)
 	require.EqualValues(t, count*len(inputData), ensureMapEntry(t, ms.Counters, "content_write_bytes"))
 	require.EqualValues(t, count*len(inputData), ensureMapEntry(t, ms.Counters, "content_hashed_bytes"))
 	require.EqualValues(t, len(inputData), ensureMapEntry(t, ms.Counters, "content_compression_attempted_bytes"))
@@ -698,7 +698,7 @@ func TestMetrics_CompressibleData(t *testing.T) {
 	require.NoError(t, err)
 	require.Equal(t, inputData, data)
 
-	ms = env.Repository.Metrics().Snapshot()
+	ms = env.Repository.Metrics().Snapshot(false)
 	require.EqualValues(t, len(inputData), ensureMapEntry(t, ms.Counters, "content_read_bytes"))
 	require.EqualValues(t, compressedByteCount, ensureMapEntry(t, ms.Counters, "content_decompressed_bytes"))
 	require.EqualValues(t, compressedByteCount+encryptionOverhead, ensureMapEntry(t, ms.Counters, "content_decrypted_bytes"))