github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/clients/pkg/logentry/metric/counters_test.go (about) 1 package metric 2 3 import ( 4 "testing" 5 "time" 6 7 "github.com/pkg/errors" 8 "github.com/prometheus/client_golang/prometheus" 9 "github.com/prometheus/common/model" 10 "github.com/stretchr/testify/assert" 11 ) 12 13 var ( 14 counterTestTrue = true 15 counterTestFalse = false 16 counterTestVal = "some val" 17 ) 18 19 func Test_validateCounterConfig(t *testing.T) { 20 t.Parallel() 21 tests := []struct { 22 name string 23 config CounterConfig 24 err error 25 }{ 26 {"invalid action", 27 CounterConfig{ 28 Action: "del", 29 }, 30 errors.Errorf(ErrCounterInvalidAction, "del"), 31 }, 32 {"invalid counter match all", 33 CounterConfig{ 34 MatchAll: &counterTestTrue, 35 Value: &counterTestVal, 36 Action: "inc", 37 }, 38 errors.New(ErrCounterInvalidMatchAll), 39 }, 40 {"invalid counter match bytes", 41 CounterConfig{ 42 MatchAll: nil, 43 CountBytes: &counterTestTrue, 44 Action: "add", 45 }, 46 errors.New(ErrCounterInvalidCountBytes), 47 }, 48 {"invalid counter match bytes action", 49 CounterConfig{ 50 MatchAll: &counterTestTrue, 51 CountBytes: &counterTestTrue, 52 Action: "inc", 53 }, 54 errors.New(ErrCounterInvalidCountBytesAction), 55 }, 56 {"valid counter match bytes", 57 CounterConfig{ 58 MatchAll: &counterTestTrue, 59 CountBytes: &counterTestTrue, 60 Action: "add", 61 }, 62 nil, 63 }, 64 {"valid", 65 CounterConfig{ 66 Value: &counterTestVal, 67 Action: "inc", 68 }, 69 nil, 70 }, 71 {"valid match all is false", 72 CounterConfig{ 73 MatchAll: &counterTestFalse, 74 Value: &counterTestVal, 75 Action: "inc", 76 }, 77 nil, 78 }, 79 } 80 for _, tt := range tests { 81 tt := tt 82 t.Run(tt.name, func(t *testing.T) { 83 t.Parallel() 84 err := validateCounterConfig(&tt.config) 85 if ((err != nil) && (err.Error() != tt.err.Error())) || (err == nil && tt.err != nil) { 86 t.Errorf("Metrics stage validation error, expected error = %v, actual error = %v", tt.err, err) 87 return 88 } 89 }) 90 } 91 } 92 93 func TestCounterExpiration(t *testing.T) { 94 t.Parallel() 95 cfg := CounterConfig{ 96 Action: "inc", 97 } 98 99 cnt, err := NewCounters("test1", "HELP ME!!!!!", cfg, 1) 100 assert.Nil(t, err) 101 102 // Create a label and increment the counter 103 lbl1 := model.LabelSet{} 104 lbl1["test"] = "i don't wanna make this a constant" 105 cnt.With(lbl1).Inc() 106 107 // Collect the metrics, should still find the metric in the map 108 collect(cnt) 109 assert.Contains(t, cnt.metrics, lbl1.Fingerprint()) 110 111 time.Sleep(1100 * time.Millisecond) // Wait just past our max idle of 1 sec 112 113 //Add another counter with new label val 114 lbl2 := model.LabelSet{} 115 lbl2["test"] = "eat this linter" 116 cnt.With(lbl2).Inc() 117 118 // Collect the metrics, first counter should have expired and removed, second should still be present 119 collect(cnt) 120 assert.NotContains(t, cnt.metrics, lbl1.Fingerprint()) 121 assert.Contains(t, cnt.metrics, lbl2.Fingerprint()) 122 } 123 124 func collect(c prometheus.Collector) { 125 done := make(chan struct{}) 126 collector := make(chan prometheus.Metric) 127 128 go func() { 129 defer close(done) 130 c.Collect(collector) 131 }() 132 133 for { 134 select { 135 case <-collector: 136 case <-done: 137 return 138 } 139 } 140 }