|
1 | 1 | package queue |
2 | 2 |
|
3 | | -// import ( |
4 | | -// "sync" |
5 | | -// "testing" |
6 | | - |
7 | | -// "github.com/stretchr/testify/require" |
8 | | - |
9 | | -// "github.com/flant/shell-operator/pkg/hook/task_metadata" |
10 | | -// "github.com/flant/shell-operator/pkg/metric" |
11 | | -// "github.com/flant/shell-operator/pkg/metrics" |
12 | | -// "github.com/flant/shell-operator/pkg/task" |
13 | | -// ) |
14 | | - |
15 | | -// func TestTaskCounterRemoveUsesQueueName(t *testing.T) { |
16 | | -// metricStorage := metric.NewStorageMock(t) |
17 | | - |
18 | | -// type gaugeCall struct { |
19 | | -// metric string |
20 | | -// value float64 |
21 | | -// labels map[string]string |
22 | | -// } |
23 | | - |
24 | | -// var ( |
25 | | -// mu sync.Mutex |
26 | | -// calls []gaugeCall |
27 | | -// ) |
28 | | - |
29 | | -// metricStorage.GaugeSetMock.Set(func(metric string, value float64, labels map[string]string) { |
30 | | -// cloned := make(map[string]string, len(labels)) |
31 | | -// for k, v := range labels { |
32 | | -// cloned[k] = v |
33 | | -// } |
34 | | - |
35 | | -// mu.Lock() |
36 | | -// calls = append(calls, gaugeCall{ |
37 | | -// metric: metric, |
38 | | -// value: value, |
39 | | -// labels: cloned, |
40 | | -// }) |
41 | | -// mu.Unlock() |
42 | | -// }) |
43 | | - |
44 | | -// tc := NewTaskCounter("main", nil, metricStorage) |
45 | | - |
46 | | -// testTask := task.NewTask(task_metadata.HookRun). |
47 | | -// WithCompactionID("test-hook") |
48 | | - |
49 | | -// tc.Add(testTask) |
50 | | -// tc.Remove(testTask) |
51 | | - |
52 | | -// mu.Lock() |
53 | | -// require.NotEmpty(t, calls) |
54 | | -// lastCall := calls[len(calls)-1] |
55 | | -// mu.Unlock() |
56 | | - |
57 | | -// require.Equal(t, metrics.TasksQueueCompactionInQueueTasks, lastCall.metric) |
58 | | -// require.Equal(t, float64(0), lastCall.value) |
59 | | -// require.Equal(t, "main", lastCall.labels["queue_name"]) |
60 | | -// require.Equal(t, "test-hook", lastCall.labels["task_id"]) |
61 | | -// } |
62 | | - |
63 | | -// func TestTaskCounterRemoveClearsReachedCap(t *testing.T) { |
64 | | -// metricStorage := metric.NewStorageMock(t) |
65 | | - |
66 | | -// var ( |
67 | | -// mu sync.Mutex |
68 | | -// reachedValues []float64 |
69 | | -// ) |
70 | | - |
71 | | -// metricStorage.GaugeSetMock.Set(func(metric string, value float64, labels map[string]string) { |
72 | | -// if metric == metrics.TasksQueueCompactionReached { |
73 | | -// mu.Lock() |
74 | | -// reachedValues = append(reachedValues, value) |
75 | | -// mu.Unlock() |
76 | | -// } |
77 | | -// }) |
78 | | - |
79 | | -// tc := NewTaskCounter("main", nil, metricStorage) |
80 | | - |
81 | | -// testTask := task.NewTask(task_metadata.HookRun). |
82 | | -// WithCompactionID("test-hook") |
83 | | - |
84 | | -// for i := 0; i < taskCap; i++ { |
85 | | -// tc.Add(testTask) |
86 | | -// } |
87 | | - |
88 | | -// require.True(t, tc.IsAnyCapReached()) |
89 | | - |
90 | | -// tc.Remove(testTask) |
91 | | - |
92 | | -// require.False(t, tc.IsAnyCapReached()) |
93 | | - |
94 | | -// mu.Lock() |
95 | | -// require.NotEmpty(t, reachedValues) |
96 | | -// require.Equal(t, float64(0), reachedValues[len(reachedValues)-1]) |
97 | | -// mu.Unlock() |
98 | | -// } |
| 3 | +import ( |
| 4 | + "sync" |
| 5 | + "testing" |
| 6 | + |
| 7 | + "github.com/stretchr/testify/require" |
| 8 | + |
| 9 | + "github.com/flant/shell-operator/pkg/metric" |
| 10 | + "github.com/flant/shell-operator/pkg/metrics" |
| 11 | +) |
| 12 | + |
| 13 | +func TestTaskCounterUpdateHookMetricsFromSnapshot(t *testing.T) { |
| 14 | + metricStorage := metric.NewStorageMock(t) |
| 15 | + |
| 16 | + type gaugeCall struct { |
| 17 | + metric string |
| 18 | + value float64 |
| 19 | + labels map[string]string |
| 20 | + } |
| 21 | + |
| 22 | + var ( |
| 23 | + mu sync.Mutex |
| 24 | + calls []gaugeCall |
| 25 | + ) |
| 26 | + |
| 27 | + metricStorage.GaugeSetMock.Set(func(metric string, value float64, labels map[string]string) { |
| 28 | + cloned := make(map[string]string, len(labels)) |
| 29 | + for k, v := range labels { |
| 30 | + cloned[k] = v |
| 31 | + } |
| 32 | + |
| 33 | + mu.Lock() |
| 34 | + calls = append(calls, gaugeCall{ |
| 35 | + metric: metric, |
| 36 | + value: value, |
| 37 | + labels: cloned, |
| 38 | + }) |
| 39 | + mu.Unlock() |
| 40 | + }) |
| 41 | + |
| 42 | + tc := NewTaskCounter("main", nil, metricStorage) |
| 43 | + |
| 44 | + // Simulate initial state with hooks above threshold by setting up a snapshot |
| 45 | + initialSnapshot := map[string]uint{ |
| 46 | + "hook1": 26, |
| 47 | + "hook2": 31, |
| 48 | + "hook3": 51, |
| 49 | + } |
| 50 | + tc.UpdateHookMetricsFromSnapshot(initialSnapshot) |
| 51 | + |
| 52 | + mu.Lock() |
| 53 | + calls = nil // Clear previous calls |
| 54 | + mu.Unlock() |
| 55 | + |
| 56 | + // Update with new snapshot where: |
| 57 | + // - hook1 still has high count (25 tasks) |
| 58 | + // - hook2 dropped below threshold (15 tasks) - should not be published |
| 59 | + // - hook3 is completely gone (0 tasks in new snapshot) - should not be published |
| 60 | + // - hook4 is new (30 tasks) |
| 61 | + newSnapshot := map[string]uint{ |
| 62 | + "hook1": 25, |
| 63 | + "hook2": 15, |
| 64 | + "hook4": 30, |
| 65 | + } |
| 66 | + |
| 67 | + tc.UpdateHookMetricsFromSnapshot(newSnapshot) |
| 68 | + |
| 69 | + mu.Lock() |
| 70 | + defer mu.Unlock() |
| 71 | + |
| 72 | + // Verify that metrics were set correctly |
| 73 | + require.NotEmpty(t, calls) |
| 74 | + |
| 75 | + // Build a map of last call for each hook |
| 76 | + lastCallByHook := make(map[string]gaugeCall) |
| 77 | + for _, call := range calls { |
| 78 | + if call.metric == metrics.TasksQueueCompactionTasksByHook { |
| 79 | + hook := call.labels["hook"] |
| 80 | + lastCallByHook[hook] = call |
| 81 | + } |
| 82 | + } |
| 83 | + |
| 84 | + // hook1: should have value 25 |
| 85 | + require.Contains(t, lastCallByHook, "hook1") |
| 86 | + require.Equal(t, float64(25), lastCallByHook["hook1"].value) |
| 87 | + require.Equal(t, "main", lastCallByHook["hook1"].labels["queue_name"]) |
| 88 | + |
| 89 | + // hook2: should NOT be published (below threshold) |
| 90 | + require.NotContains(t, lastCallByHook, "hook2") |
| 91 | + |
| 92 | + // hook3: should NOT be published (removed from snapshot and was above threshold before) |
| 93 | + require.NotContains(t, lastCallByHook, "hook3") |
| 94 | + |
| 95 | + // hook4: should have value 30 |
| 96 | + require.Contains(t, lastCallByHook, "hook4") |
| 97 | + require.Equal(t, float64(30), lastCallByHook["hook4"].value) |
| 98 | + require.Equal(t, "main", lastCallByHook["hook4"].labels["queue_name"]) |
| 99 | +} |
0 commit comments