|
| 1 | +/* |
| 2 | +Copyright 2024 Adobe. All rights reserved. |
| 3 | +This file is licensed to you under the Apache License, Version 2.0 (the "License"); |
| 4 | +you may not use this file except in compliance with the License. You may obtain a copy |
| 5 | +of the License at http://www.apache.org/licenses/LICENSE-2.0 |
| 6 | +
|
| 7 | +Unless required by applicable law or agreed to in writing, software distributed under |
| 8 | +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS |
| 9 | +OF ANY KIND, either express or implied. See the License for the specific language |
| 10 | +governing permissions and limitations under the License. |
| 11 | +*/ |
| 12 | + |
| 13 | +package monitoring |
| 14 | + |
| 15 | +import ( |
| 16 | + "fmt" |
| 17 | + "github.com/prometheus/client_golang/prometheus/testutil" |
| 18 | + "github.com/stretchr/testify/assert" |
| 19 | + "math/rand" |
| 20 | + "strings" |
| 21 | + "testing" |
| 22 | +) |
| 23 | + |
| 24 | +const ( |
| 25 | + clusterSyncTarget = "orgnumber-env-region-cluster-sync" |
| 26 | + subsystem = "cluster_registry_sync_manager" |
| 27 | + minRand = 1 |
| 28 | + maxRand = 2.5 |
| 29 | +) |
| 30 | + |
| 31 | +// Generate a random float number between min and max |
| 32 | +func generateFloatRand(min, max float64) float64 { |
| 33 | + return min + rand.Float64()*(max-min) |
| 34 | +} |
| 35 | + |
| 36 | +// Generate what we expect a histogram of some random number to look like. metricTopic is what the metric is about, e.g. |
| 37 | +// reconciliation or enqueue. helpString is the literal help string from metrics.go. I'd grab this myself, but it's not |
| 38 | +// exposed in the HistogramVec object AFAICT :( |
| 39 | +func generateExpectedHistogram(randomFloat float64, metricTopic string, helpString string) string { |
| 40 | + expected := fmt.Sprintf(` |
| 41 | + # HELP %[1]s_%[5]s_duration_seconds %[4]s |
| 42 | + # TYPE %[1]s_%[5]s_duration_seconds histogram |
| 43 | + %[1]s_%[5]s_duration_seconds_bucket{target="%[2]s",le="0.005"} 0 |
| 44 | + %[1]s_%[5]s_duration_seconds_bucket{target="%[2]s",le="0.01"} 0 |
| 45 | + %[1]s_%[5]s_duration_seconds_bucket{target="%[2]s",le="0.025"} 0 |
| 46 | + %[1]s_%[5]s_duration_seconds_bucket{target="%[2]s",le="0.05"} 0 |
| 47 | + %[1]s_%[5]s_duration_seconds_bucket{target="%[2]s",le="0.1"} 0 |
| 48 | + %[1]s_%[5]s_duration_seconds_bucket{target="%[2]s",le="0.25"} 0 |
| 49 | + %[1]s_%[5]s_duration_seconds_bucket{target="%[2]s",le="0.5"} 0 |
| 50 | + %[1]s_%[5]s_duration_seconds_bucket{target="%[2]s",le="1"} 0 |
| 51 | + %[1]s_%[5]s_duration_seconds_bucket{target="%[2]s",le="2.5"} 1 |
| 52 | + %[1]s_%[5]s_duration_seconds_bucket{target="%[2]s",le="5"} 1 |
| 53 | + %[1]s_%[5]s_duration_seconds_bucket{target="%[2]s",le="10"} 1 |
| 54 | + %[1]s_%[5]s_duration_seconds_bucket{target="%[2]s",le="+Inf"} 1 |
| 55 | + %[1]s_%[5]s_duration_seconds_sum{target="%[2]s"} %[3]s |
| 56 | + %[1]s_%[5]s_duration_seconds_count{target="%[2]s"} 1 |
| 57 | + `, subsystem, clusterSyncTarget, fmt.Sprintf("%.16f", randomFloat), helpString, metricTopic) |
| 58 | + return expected |
| 59 | +} |
| 60 | + |
| 61 | +func TestNewMetrics(t *testing.T) { |
| 62 | + test := assert.New(t) |
| 63 | + m := NewMetrics() |
| 64 | + test.NotNil(m) |
| 65 | +} |
| 66 | + |
| 67 | +func TestInit(t *testing.T) { |
| 68 | + test := assert.New(t) |
| 69 | + m := NewMetrics() |
| 70 | + m.Init(true) |
| 71 | + test.NotNil(m.RequeueCnt) |
| 72 | + test.NotNil(m.ReconciliationCnt) |
| 73 | + test.NotNil(m.ReconciliationDur) |
| 74 | + test.NotNil(m.EnqueueCnt) |
| 75 | + test.NotNil(m.EnqueueDur) |
| 76 | + test.NotNil(m.ErrCnt) |
| 77 | +} |
| 78 | + |
| 79 | +func TestRecordRequeueCnt(t *testing.T) { |
| 80 | + test := assert.New(t) |
| 81 | + m := NewMetrics() |
| 82 | + m.Init(true) |
| 83 | + m.RecordRequeueCnt(clusterSyncTarget) |
| 84 | + test.Equal(1, testutil.CollectAndCount(*m.RequeueCnt)) |
| 85 | + test.Equal(float64(1), testutil.ToFloat64((*m.RequeueCnt).WithLabelValues(clusterSyncTarget))) |
| 86 | +} |
| 87 | + |
| 88 | +func TestRecordReconciliationCnt(t *testing.T) { |
| 89 | + test := assert.New(t) |
| 90 | + m := NewMetrics() |
| 91 | + m.Init(true) |
| 92 | + m.RecordReconciliationCnt(clusterSyncTarget) |
| 93 | + test.Equal(1, testutil.CollectAndCount(*m.ReconciliationCnt)) |
| 94 | + test.Equal(float64(1), testutil.ToFloat64((*m.ReconciliationCnt).WithLabelValues(clusterSyncTarget))) |
| 95 | +} |
| 96 | + |
| 97 | +func TestRecordReconciliationDur(t *testing.T) { |
| 98 | + m := NewMetrics() |
| 99 | + m.Init(true) |
| 100 | + randomFloat := generateFloatRand(minRand, maxRand) |
| 101 | + m.RecordReconciliationDur(clusterSyncTarget, randomFloat) |
| 102 | + expected := generateExpectedHistogram(randomFloat, "reconciliation", "The time taken to reconcile resources in seconds partitioned by target.") |
| 103 | + if err := testutil.CollectAndCompare( |
| 104 | + *m.ReconciliationDur, |
| 105 | + strings.NewReader(expected), |
| 106 | + fmt.Sprintf("%s_%s_duration_seconds", subsystem, "reconciliation")); err != nil { |
| 107 | + t.Errorf("unexpected collecting result:\n%s", err) |
| 108 | + } |
| 109 | + |
| 110 | +} |
| 111 | + |
| 112 | +func TestRecordEnqueueCnt(t *testing.T) { |
| 113 | + test := assert.New(t) |
| 114 | + m := NewMetrics() |
| 115 | + m.Init(true) |
| 116 | + m.RecordEnqueueCnt(clusterSyncTarget) |
| 117 | + test.Equal(1, testutil.CollectAndCount(*m.EnqueueCnt)) |
| 118 | + test.Equal(float64(1), testutil.ToFloat64((*m.EnqueueCnt).WithLabelValues(clusterSyncTarget))) |
| 119 | + |
| 120 | +} |
| 121 | + |
| 122 | +func TestRecordEnqueueDur(t *testing.T) { |
| 123 | + m := NewMetrics() |
| 124 | + m.Init(true) |
| 125 | + randomFloat := generateFloatRand(minRand, maxRand) |
| 126 | + m.RecordEnqueueDur(clusterSyncTarget, randomFloat) |
| 127 | + expected := generateExpectedHistogram(randomFloat, "enqueue", "The time taken to enqueue a reconciliation in seconds partitioned by target.") |
| 128 | + if err := testutil.CollectAndCompare( |
| 129 | + *m.EnqueueDur, |
| 130 | + strings.NewReader(expected), |
| 131 | + fmt.Sprintf("%s_%s_duration_seconds", subsystem, "enqueue")); err != nil { |
| 132 | + t.Errorf("unexpected collecting result:\n%s", err) |
| 133 | + } |
| 134 | + |
| 135 | +} |
| 136 | + |
| 137 | +func TestRecordErrCnt(t *testing.T) { |
| 138 | + test := assert.New(t) |
| 139 | + m := NewMetrics() |
| 140 | + m.Init(true) |
| 141 | + m.RecordErrorCnt(clusterSyncTarget) |
| 142 | + test.Equal(1, testutil.CollectAndCount(*m.ErrCnt)) |
| 143 | + test.Equal(float64(1), testutil.ToFloat64((*m.ErrCnt).WithLabelValues(clusterSyncTarget))) |
| 144 | + |
| 145 | +} |
0 commit comments