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  }