Skip to content

Commit

Permalink
Merge pull request kubernetes#123190 from padlar/add-apiserver-wait-c…
Browse files Browse the repository at this point in the history
…ache-metric

Add apiserver_watch_cache_read_wait metric to cache refresh time
  • Loading branch information
k8s-ci-robot committed Mar 4, 2024
2 parents 89cbd94 + e6ed0f3 commit 599d92f
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 0 deletions.
11 changes: 11 additions & 0 deletions staging/src/k8s.io/apiserver/pkg/storage/cacher/metrics/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,16 @@ var (
},
[]string{"resource"},
)

WatchCacheReadWait = compbasemetrics.NewHistogramVec(
&compbasemetrics.HistogramOpts{
Namespace: namespace,
Subsystem: subsystem,
Name: "read_wait_seconds",
Help: "Histogram of time spent waiting for a watch cache to become fresh.",
StabilityLevel: compbasemetrics.ALPHA,
Buckets: []float64{0.005, 0.025, 0.05, 0.1, 0.2, 0.4, 0.6, 0.8, 1.0, 1.25, 1.5, 2, 3},
}, []string{"resource"})
)

var registerMetrics sync.Once
Expand All @@ -165,6 +175,7 @@ func Register() {
legacyregistry.MustRegister(watchCacheCapacityDecreaseTotal)
legacyregistry.MustRegister(WatchCacheCapacity)
legacyregistry.MustRegister(WatchCacheInitializations)
legacyregistry.MustRegister(WatchCacheReadWait)
})
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,11 @@ func (w *watchCache) List() []interface{} {
// You HAVE TO explicitly call w.RUnlock() after this function.
func (w *watchCache) waitUntilFreshAndBlock(ctx context.Context, resourceVersion uint64) error {
startTime := w.clock.Now()
defer func() {
if resourceVersion > 0 {
metrics.WatchCacheReadWait.WithContext(ctx).WithLabelValues(w.groupResource.String()).Observe(w.clock.Since(startTime).Seconds())
}
}()

// In case resourceVersion is 0, we accept arbitrarily stale result.
// As a result, the condition in the below for loop will never be
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,12 @@ import (
"k8s.io/apimachinery/pkg/watch"
"k8s.io/apiserver/pkg/features"
"k8s.io/apiserver/pkg/storage"
"k8s.io/apiserver/pkg/storage/cacher/metrics"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/tools/cache"
featuregatetesting "k8s.io/component-base/featuregate/testing"
k8smetrics "k8s.io/component-base/metrics"
"k8s.io/component-base/metrics/testutil"
"k8s.io/utils/clock"
testingclock "k8s.io/utils/clock/testing"
)
Expand Down Expand Up @@ -1123,3 +1126,72 @@ func BenchmarkWatchCache_updateCache(b *testing.B) {
store.updateCache(add)
}
}

func TestHistogramCacheReadWait(t *testing.T) {
registry := k8smetrics.NewKubeRegistry()
if err := registry.Register(metrics.WatchCacheReadWait); err != nil {
t.Errorf("unexpected error: %v", err)
}
ctx := context.Background()
testedMetrics := "apiserver_watch_cache_read_wait_seconds"
store := newTestWatchCache(2, &cache.Indexers{})
defer store.Stop()

// In background, update the store.
go func() {
if err := store.Add(makeTestPod("foo", 2)); err != nil {
t.Errorf("unexpected error: %v", err)
}
if err := store.Add(makeTestPod("bar", 5)); err != nil {
t.Errorf("unexpected error: %v", err)
}
}()

testCases := []struct {
desc string
resourceVersion uint64
want string
}{
{
desc: "resourceVersion is non-zero",
resourceVersion: 5,
want: `
# HELP apiserver_watch_cache_read_wait_seconds [ALPHA] Histogram of time spent waiting for a watch cache to become fresh.
# TYPE apiserver_watch_cache_read_wait_seconds histogram
apiserver_watch_cache_read_wait_seconds_bucket{resource="pods",le="0.005"} 1
apiserver_watch_cache_read_wait_seconds_bucket{resource="pods",le="0.025"} 1
apiserver_watch_cache_read_wait_seconds_bucket{resource="pods",le="0.05"} 1
apiserver_watch_cache_read_wait_seconds_bucket{resource="pods",le="0.1"} 1
apiserver_watch_cache_read_wait_seconds_bucket{resource="pods",le="0.2"} 1
apiserver_watch_cache_read_wait_seconds_bucket{resource="pods",le="0.4"} 1
apiserver_watch_cache_read_wait_seconds_bucket{resource="pods",le="0.6"} 1
apiserver_watch_cache_read_wait_seconds_bucket{resource="pods",le="0.8"} 1
apiserver_watch_cache_read_wait_seconds_bucket{resource="pods",le="1"} 1
apiserver_watch_cache_read_wait_seconds_bucket{resource="pods",le="1.25"} 1
apiserver_watch_cache_read_wait_seconds_bucket{resource="pods",le="1.5"} 1
apiserver_watch_cache_read_wait_seconds_bucket{resource="pods",le="2"} 1
apiserver_watch_cache_read_wait_seconds_bucket{resource="pods",le="3"} 1
apiserver_watch_cache_read_wait_seconds_bucket{resource="pods",le="+Inf"} 1
apiserver_watch_cache_read_wait_seconds_sum{resource="pods"} 0
apiserver_watch_cache_read_wait_seconds_count{resource="pods"} 1
`,
},
{
desc: "resourceVersion is 0",
resourceVersion: 0,
want: ``,
},
}

for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
defer registry.Reset()
if _, _, _, err := store.WaitUntilFreshAndGet(ctx, test.resourceVersion, "prefix/ns/bar"); err != nil {
t.Errorf("unexpected error: %v", err)
}
if err := testutil.GatherAndCompare(registry, strings.NewReader(test.want), testedMetrics); err != nil {
t.Errorf("unexpected error: %v", err)
}
})
}
}

0 comments on commit 599d92f

Please sign in to comment.