Skip to content

Commit e667a8f

Browse files
committedJan 10, 2025·
🐛 Fix a bug in the priorityqueue metrics
The priorityqueue needs to call `metrics.add` but only once an item was ready. When an item was initially added with `After`, so not ready, then without which makes it ready, we didn't do that, resulting in potentially negative values for the queue depth metric.
1 parent 1de5a3e commit e667a8f

File tree

3 files changed

+29
-9
lines changed

3 files changed

+29
-9
lines changed
 

‎pkg/controller/priorityqueue/metrics.go

+2-8
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"sync"
55
"time"
66

7-
"k8s.io/apimachinery/pkg/util/sets"
87
"k8s.io/client-go/util/workqueue"
98
"k8s.io/utils/clock"
109
)
@@ -34,7 +33,6 @@ func newQueueMetrics[T comparable](mp workqueue.MetricsProvider, name string, cl
3433
workDuration: mp.NewWorkDurationMetric(name),
3534
unfinishedWorkSeconds: mp.NewUnfinishedWorkSecondsMetric(name),
3635
longestRunningProcessor: mp.NewLongestRunningProcessorSecondsMetric(name),
37-
added: sets.Set[T]{},
3836
addTimes: map[T]time.Time{},
3937
processingStartTimes: map[T]time.Time{},
4038
retries: mp.NewRetriesMetric(name),
@@ -55,7 +53,6 @@ type defaultQueueMetrics[T comparable] struct {
5553
workDuration workqueue.HistogramMetric
5654

5755
mapLock sync.RWMutex
58-
added sets.Set[T]
5956
addTimes map[T]time.Time
6057
processingStartTimes map[T]time.Time
6158

@@ -73,13 +70,11 @@ func (m *defaultQueueMetrics[T]) add(item T) {
7370
}
7471

7572
m.adds.Inc()
73+
m.depth.Inc()
7674

7775
m.mapLock.Lock()
7876
defer m.mapLock.Unlock()
79-
if !m.added.Has(item) {
80-
m.added.Insert(item)
81-
m.depth.Inc()
82-
}
77+
8378
if _, exists := m.addTimes[item]; !exists {
8479
m.addTimes[item] = m.clock.Now()
8580
}
@@ -94,7 +89,6 @@ func (m *defaultQueueMetrics[T]) get(item T) {
9489
defer m.mapLock.Unlock()
9590

9691
m.depth.Dec()
97-
m.added.Delete(item)
9892

9993
m.processingStartTimes[item] = m.clock.Now()
10094
if startTime, exists := m.addTimes[item]; exists {

‎pkg/controller/priorityqueue/priorityqueue.go

+3
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,9 @@ func (w *priorityqueue[T]) AddWithOpts(o AddOpts, items ...T) {
163163
}
164164

165165
if item.readyAt != nil && (readyAt == nil || readyAt.Before(*item.readyAt)) {
166+
if readyAt == nil {
167+
w.metrics.add(key)
168+
}
166169
item.readyAt = readyAt
167170
}
168171

‎pkg/controller/priorityqueue/priorityqueue_test.go

+24-1
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,23 @@ var _ = Describe("Controllerworkqueue", func() {
379379
wg.Wait()
380380
}
381381
})
382+
383+
It("updates metrics correctly for an item that gets initially added with after and then without", func() {
384+
q, metrics := newQueue()
385+
defer q.ShutDown()
386+
387+
q.AddWithOpts(AddOpts{After: time.Hour}, "foo")
388+
Expect(q.Len()).To(Equal(0))
389+
metrics.mu.Lock()
390+
Expect(metrics.depth["test"]).To(Equal(0))
391+
metrics.mu.Unlock()
392+
393+
q.AddWithOpts(AddOpts{}, "foo")
394+
395+
Expect(q.Len()).To(Equal(1))
396+
metrics.mu.Lock()
397+
Expect(metrics.depth["test"]).To(Equal(1))
398+
})
382399
})
383400

384401
func BenchmarkAddGetDone(b *testing.B) {
@@ -454,7 +471,7 @@ func TestFuzzPrioriorityQueue(t *testing.T) {
454471
handedOutLock := sync.Mutex{}
455472

456473
wg := sync.WaitGroup{}
457-
q, _ := newQueue()
474+
q, metrics := newQueue()
458475

459476
for range 10 {
460477
wg.Add(1)
@@ -519,6 +536,12 @@ func TestFuzzPrioriorityQueue(t *testing.T) {
519536
if handedOut.Has(item) {
520537
t.Errorf("item %s got handed out more than once", item)
521538
}
539+
540+
metrics.mu.Lock()
541+
if metrics.depth["test"] < 0 {
542+
t.Errorf("negative depth of %d", metrics.depth["test"])
543+
}
544+
metrics.mu.Unlock()
522545
handedOut.Insert(item)
523546
}()
524547

0 commit comments

Comments
 (0)
Please sign in to comment.