mirror of
https://github.com/kubernetes/client-go.git
synced 2025-09-02 07:35:21 +00:00
Test workqueue metrics
Kubernetes-commit: 5a8444ceec9e28e8a7dbf36bfd7cb55554c5b865
This commit is contained in:
committed by
Kubernetes Publisher
parent
75d4dad922
commit
26f9385b8e
@@ -19,6 +19,8 @@ package workqueue
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/clock"
|
||||
)
|
||||
|
||||
type testMetrics struct {
|
||||
@@ -32,18 +34,211 @@ func (m *testMetrics) get(item t) { m.gotten++ }
|
||||
func (m *testMetrics) done(item t) { m.finished++ }
|
||||
func (m *testMetrics) updateUnfinishedWork() { m.updateCalled <- struct{}{} }
|
||||
|
||||
func TestMetrics(t *testing.T) {
|
||||
func TestMetricShutdown(t *testing.T) {
|
||||
ch := make(chan struct{})
|
||||
m := &testMetrics{
|
||||
updateCalled: ch,
|
||||
}
|
||||
q := newQueue("test", m, time.Millisecond)
|
||||
c := clock.NewFakeClock(time.Now())
|
||||
q := newQueue(c, m, time.Millisecond)
|
||||
for !c.HasWaiters() {
|
||||
// Wait for the go routine to call NewTicker()
|
||||
time.Sleep(time.Millisecond)
|
||||
}
|
||||
|
||||
c.Step(time.Millisecond)
|
||||
<-ch
|
||||
q.ShutDown()
|
||||
|
||||
c.Step(time.Hour)
|
||||
select {
|
||||
case <-time.After(time.Second):
|
||||
default:
|
||||
return
|
||||
case <-ch:
|
||||
t.Errorf("Unexpected update after shutdown was called.")
|
||||
}
|
||||
}
|
||||
|
||||
type testMetric struct {
|
||||
inc int64
|
||||
dec int64
|
||||
set float64
|
||||
|
||||
observedValue float64
|
||||
observedCount int
|
||||
|
||||
notifyCh chan<- struct{}
|
||||
}
|
||||
|
||||
func (m *testMetric) Inc() { m.inc++; m.notify() }
|
||||
func (m *testMetric) Dec() { m.dec++; m.notify() }
|
||||
func (m *testMetric) Set(f float64) { m.set = f; m.notify() }
|
||||
func (m *testMetric) Observe(f float64) { m.observedValue = f; m.observedCount++; m.notify() }
|
||||
|
||||
func (m *testMetric) gaugeValue() float64 {
|
||||
if m.set != 0 {
|
||||
return m.set
|
||||
}
|
||||
return float64(m.inc - m.dec)
|
||||
}
|
||||
|
||||
func (m *testMetric) notify() {
|
||||
if m.notifyCh != nil {
|
||||
m.notifyCh <- struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
type testMetricsProvider struct {
|
||||
depth testMetric
|
||||
adds testMetric
|
||||
latency testMetric
|
||||
duration testMetric
|
||||
unfinished testMetric
|
||||
retries testMetric
|
||||
}
|
||||
|
||||
func (m *testMetricsProvider) NewDepthMetric(name string) GaugeMetric {
|
||||
return &m.depth
|
||||
}
|
||||
|
||||
func (m *testMetricsProvider) NewAddsMetric(name string) CounterMetric {
|
||||
return &m.adds
|
||||
}
|
||||
|
||||
func (m *testMetricsProvider) NewLatencyMetric(name string) SummaryMetric {
|
||||
return &m.latency
|
||||
}
|
||||
|
||||
func (m *testMetricsProvider) NewWorkDurationMetric(name string) SummaryMetric {
|
||||
return &m.duration
|
||||
}
|
||||
|
||||
func (m *testMetricsProvider) NewUnfinishedWorkMicrosecondsMetric(name string) SettableGaugeMetric {
|
||||
return &m.unfinished
|
||||
}
|
||||
|
||||
func (m *testMetricsProvider) NewRetriesMetric(name string) CounterMetric {
|
||||
return &m.retries
|
||||
}
|
||||
|
||||
func TestSinceInMicroseconds(t *testing.T) {
|
||||
mp := testMetricsProvider{}
|
||||
c := clock.NewFakeClock(time.Now())
|
||||
mf := metricsFactory{metricsProvider: &mp}
|
||||
m := mf.newQueueMetrics("test", c)
|
||||
dqm := m.(*defaultQueueMetrics)
|
||||
|
||||
for _, i := range []int{1, 50, 100, 500, 1000, 10000, 100000, 1000000} {
|
||||
n := c.Now()
|
||||
c.Step(time.Duration(i) * time.Microsecond)
|
||||
if e, a := float64(i), dqm.sinceInMicroseconds(n); e != a {
|
||||
t.Errorf("Expected %v, got %v", e, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMetrics(t *testing.T) {
|
||||
mp := testMetricsProvider{}
|
||||
t0 := time.Unix(0, 0)
|
||||
c := clock.NewFakeClock(t0)
|
||||
mf := metricsFactory{metricsProvider: &mp}
|
||||
m := mf.newQueueMetrics("test", c)
|
||||
q := newQueue(c, m, time.Millisecond)
|
||||
defer q.ShutDown()
|
||||
for !c.HasWaiters() {
|
||||
// Wait for the go routine to call NewTicker()
|
||||
time.Sleep(time.Millisecond)
|
||||
}
|
||||
|
||||
q.Add("foo")
|
||||
if e, a := 1.0, mp.adds.gaugeValue(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
|
||||
if e, a := 1.0, mp.depth.gaugeValue(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
|
||||
c.Step(50 * time.Microsecond)
|
||||
|
||||
// Start processing
|
||||
i, _ := q.Get()
|
||||
if i != "foo" {
|
||||
t.Errorf("Expected %v, got %v", "foo", i)
|
||||
}
|
||||
|
||||
if e, a := 50.0, mp.latency.observedValue; e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
if e, a := 1, mp.latency.observedCount; e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
if e, a := 0.0, mp.depth.gaugeValue(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
|
||||
// Add it back while processing; multiple adds of the same item are
|
||||
// de-duped.
|
||||
q.Add(i)
|
||||
q.Add(i)
|
||||
q.Add(i)
|
||||
q.Add(i)
|
||||
q.Add(i)
|
||||
if e, a := 2.0, mp.adds.gaugeValue(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
// One thing remains in the queue
|
||||
if e, a := 1.0, mp.depth.gaugeValue(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
|
||||
c.Step(25 * time.Microsecond)
|
||||
|
||||
// Finish it up
|
||||
q.Done(i)
|
||||
|
||||
if e, a := 25.0, mp.duration.observedValue; e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
if e, a := 1, mp.duration.observedCount; e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
|
||||
// One thing remains in the queue
|
||||
if e, a := 1.0, mp.depth.gaugeValue(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
|
||||
// It should be back on the queue
|
||||
i, _ = q.Get()
|
||||
if i != "foo" {
|
||||
t.Errorf("Expected %v, got %v", "foo", i)
|
||||
}
|
||||
|
||||
if e, a := 25.0, mp.latency.observedValue; e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
if e, a := 2, mp.latency.observedCount; e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
|
||||
// use a channel to ensure we don't look at the metric before it's
|
||||
// been set.
|
||||
ch := make(chan struct{}, 1)
|
||||
mp.unfinished.notifyCh = ch
|
||||
c.Step(time.Millisecond)
|
||||
<-ch
|
||||
mp.unfinished.notifyCh = nil
|
||||
if e, a := 1000.0, mp.unfinished.gaugeValue(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
|
||||
// Finish that one up
|
||||
q.Done(i)
|
||||
if e, a := 1000.0, mp.duration.observedValue; e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
if e, a := 2, mp.duration.observedCount; e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user