From e643dfffedc6e79305b4eaf175b9ce67c42e0551 Mon Sep 17 00:00:00 2001 From: Mikhail Scherba <41360396+miklezzzz@users.noreply.github.com> Date: Fri, 1 Nov 2024 17:55:26 +0400 Subject: [PATCH] [metric_storage] Metric storage group expire (#676) Signed-off-by: Mikhail Scherba --- pkg/metric/grouped_storage_mock.go | 326 +++++++++++++++++++++++++ pkg/metric/storage.go | 1 + pkg/metric_storage/metric_storage.go | 2 +- pkg/metric_storage/vault/vault.go | 41 +++- pkg/metric_storage/vault/vault_test.go | 39 ++- 5 files changed, 394 insertions(+), 15 deletions(-) diff --git a/pkg/metric/grouped_storage_mock.go b/pkg/metric/grouped_storage_mock.go index 86df32c4..babe2e96 100644 --- a/pkg/metric/grouped_storage_mock.go +++ b/pkg/metric/grouped_storage_mock.go @@ -25,6 +25,13 @@ type GroupedStorageMock struct { beforeCounterAddCounter uint64 CounterAddMock mGroupedStorageMockCounterAdd + funcExpireGroupMetricByName func(group string, name string) + funcExpireGroupMetricByNameOrigin string + inspectFuncExpireGroupMetricByName func(group string, name string) + afterExpireGroupMetricByNameCounter uint64 + beforeExpireGroupMetricByNameCounter uint64 + ExpireGroupMetricByNameMock mGroupedStorageMockExpireGroupMetricByName + funcExpireGroupMetrics func(group string) funcExpireGroupMetricsOrigin string inspectFuncExpireGroupMetrics func(group string) @@ -72,6 +79,9 @@ func NewGroupedStorageMock(t minimock.Tester) *GroupedStorageMock { m.CounterAddMock = mGroupedStorageMockCounterAdd{mock: m} m.CounterAddMock.callArgs = []*GroupedStorageMockCounterAddParams{} + m.ExpireGroupMetricByNameMock = mGroupedStorageMockExpireGroupMetricByName{mock: m} + m.ExpireGroupMetricByNameMock.callArgs = []*GroupedStorageMockExpireGroupMetricByNameParams{} + m.ExpireGroupMetricsMock = mGroupedStorageMockExpireGroupMetrics{mock: m} m.ExpireGroupMetricsMock.callArgs = []*GroupedStorageMockExpireGroupMetricsParams{} @@ -466,6 +476,319 @@ func (m *GroupedStorageMock) MinimockCounterAddInspect() { } } +type mGroupedStorageMockExpireGroupMetricByName struct { + optional bool + mock *GroupedStorageMock + defaultExpectation *GroupedStorageMockExpireGroupMetricByNameExpectation + expectations []*GroupedStorageMockExpireGroupMetricByNameExpectation + + callArgs []*GroupedStorageMockExpireGroupMetricByNameParams + mutex sync.RWMutex + + expectedInvocations uint64 + expectedInvocationsOrigin string +} + +// GroupedStorageMockExpireGroupMetricByNameExpectation specifies expectation struct of the GroupedStorage.ExpireGroupMetricByName +type GroupedStorageMockExpireGroupMetricByNameExpectation struct { + mock *GroupedStorageMock + params *GroupedStorageMockExpireGroupMetricByNameParams + paramPtrs *GroupedStorageMockExpireGroupMetricByNameParamPtrs + expectationOrigins GroupedStorageMockExpireGroupMetricByNameExpectationOrigins + + returnOrigin string + Counter uint64 +} + +// GroupedStorageMockExpireGroupMetricByNameParams contains parameters of the GroupedStorage.ExpireGroupMetricByName +type GroupedStorageMockExpireGroupMetricByNameParams struct { + group string + name string +} + +// GroupedStorageMockExpireGroupMetricByNameParamPtrs contains pointers to parameters of the GroupedStorage.ExpireGroupMetricByName +type GroupedStorageMockExpireGroupMetricByNameParamPtrs struct { + group *string + name *string +} + +// GroupedStorageMockExpireGroupMetricByNameOrigins contains origins of expectations of the GroupedStorage.ExpireGroupMetricByName +type GroupedStorageMockExpireGroupMetricByNameExpectationOrigins struct { + origin string + originGroup string + originName string +} + +// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning +// the test will fail minimock's automatic final call check if the mocked method was not called at least once. +// Optional() makes method check to work in '0 or more' mode. +// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to +// catch the problems when the expected method call is totally skipped during test run. +func (mmExpireGroupMetricByName *mGroupedStorageMockExpireGroupMetricByName) Optional() *mGroupedStorageMockExpireGroupMetricByName { + mmExpireGroupMetricByName.optional = true + return mmExpireGroupMetricByName +} + +// Expect sets up expected params for GroupedStorage.ExpireGroupMetricByName +func (mmExpireGroupMetricByName *mGroupedStorageMockExpireGroupMetricByName) Expect(group string, name string) *mGroupedStorageMockExpireGroupMetricByName { + if mmExpireGroupMetricByName.mock.funcExpireGroupMetricByName != nil { + mmExpireGroupMetricByName.mock.t.Fatalf("GroupedStorageMock.ExpireGroupMetricByName mock is already set by Set") + } + + if mmExpireGroupMetricByName.defaultExpectation == nil { + mmExpireGroupMetricByName.defaultExpectation = &GroupedStorageMockExpireGroupMetricByNameExpectation{} + } + + if mmExpireGroupMetricByName.defaultExpectation.paramPtrs != nil { + mmExpireGroupMetricByName.mock.t.Fatalf("GroupedStorageMock.ExpireGroupMetricByName mock is already set by ExpectParams functions") + } + + mmExpireGroupMetricByName.defaultExpectation.params = &GroupedStorageMockExpireGroupMetricByNameParams{group, name} + mmExpireGroupMetricByName.defaultExpectation.expectationOrigins.origin = minimock.CallerInfo(1) + for _, e := range mmExpireGroupMetricByName.expectations { + if minimock.Equal(e.params, mmExpireGroupMetricByName.defaultExpectation.params) { + mmExpireGroupMetricByName.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmExpireGroupMetricByName.defaultExpectation.params) + } + } + + return mmExpireGroupMetricByName +} + +// ExpectGroupParam1 sets up expected param group for GroupedStorage.ExpireGroupMetricByName +func (mmExpireGroupMetricByName *mGroupedStorageMockExpireGroupMetricByName) ExpectGroupParam1(group string) *mGroupedStorageMockExpireGroupMetricByName { + if mmExpireGroupMetricByName.mock.funcExpireGroupMetricByName != nil { + mmExpireGroupMetricByName.mock.t.Fatalf("GroupedStorageMock.ExpireGroupMetricByName mock is already set by Set") + } + + if mmExpireGroupMetricByName.defaultExpectation == nil { + mmExpireGroupMetricByName.defaultExpectation = &GroupedStorageMockExpireGroupMetricByNameExpectation{} + } + + if mmExpireGroupMetricByName.defaultExpectation.params != nil { + mmExpireGroupMetricByName.mock.t.Fatalf("GroupedStorageMock.ExpireGroupMetricByName mock is already set by Expect") + } + + if mmExpireGroupMetricByName.defaultExpectation.paramPtrs == nil { + mmExpireGroupMetricByName.defaultExpectation.paramPtrs = &GroupedStorageMockExpireGroupMetricByNameParamPtrs{} + } + mmExpireGroupMetricByName.defaultExpectation.paramPtrs.group = &group + mmExpireGroupMetricByName.defaultExpectation.expectationOrigins.originGroup = minimock.CallerInfo(1) + + return mmExpireGroupMetricByName +} + +// ExpectNameParam2 sets up expected param name for GroupedStorage.ExpireGroupMetricByName +func (mmExpireGroupMetricByName *mGroupedStorageMockExpireGroupMetricByName) ExpectNameParam2(name string) *mGroupedStorageMockExpireGroupMetricByName { + if mmExpireGroupMetricByName.mock.funcExpireGroupMetricByName != nil { + mmExpireGroupMetricByName.mock.t.Fatalf("GroupedStorageMock.ExpireGroupMetricByName mock is already set by Set") + } + + if mmExpireGroupMetricByName.defaultExpectation == nil { + mmExpireGroupMetricByName.defaultExpectation = &GroupedStorageMockExpireGroupMetricByNameExpectation{} + } + + if mmExpireGroupMetricByName.defaultExpectation.params != nil { + mmExpireGroupMetricByName.mock.t.Fatalf("GroupedStorageMock.ExpireGroupMetricByName mock is already set by Expect") + } + + if mmExpireGroupMetricByName.defaultExpectation.paramPtrs == nil { + mmExpireGroupMetricByName.defaultExpectation.paramPtrs = &GroupedStorageMockExpireGroupMetricByNameParamPtrs{} + } + mmExpireGroupMetricByName.defaultExpectation.paramPtrs.name = &name + mmExpireGroupMetricByName.defaultExpectation.expectationOrigins.originName = minimock.CallerInfo(1) + + return mmExpireGroupMetricByName +} + +// Inspect accepts an inspector function that has same arguments as the GroupedStorage.ExpireGroupMetricByName +func (mmExpireGroupMetricByName *mGroupedStorageMockExpireGroupMetricByName) Inspect(f func(group string, name string)) *mGroupedStorageMockExpireGroupMetricByName { + if mmExpireGroupMetricByName.mock.inspectFuncExpireGroupMetricByName != nil { + mmExpireGroupMetricByName.mock.t.Fatalf("Inspect function is already set for GroupedStorageMock.ExpireGroupMetricByName") + } + + mmExpireGroupMetricByName.mock.inspectFuncExpireGroupMetricByName = f + + return mmExpireGroupMetricByName +} + +// Return sets up results that will be returned by GroupedStorage.ExpireGroupMetricByName +func (mmExpireGroupMetricByName *mGroupedStorageMockExpireGroupMetricByName) Return() *GroupedStorageMock { + if mmExpireGroupMetricByName.mock.funcExpireGroupMetricByName != nil { + mmExpireGroupMetricByName.mock.t.Fatalf("GroupedStorageMock.ExpireGroupMetricByName mock is already set by Set") + } + + if mmExpireGroupMetricByName.defaultExpectation == nil { + mmExpireGroupMetricByName.defaultExpectation = &GroupedStorageMockExpireGroupMetricByNameExpectation{mock: mmExpireGroupMetricByName.mock} + } + + mmExpireGroupMetricByName.defaultExpectation.returnOrigin = minimock.CallerInfo(1) + return mmExpireGroupMetricByName.mock +} + +// Set uses given function f to mock the GroupedStorage.ExpireGroupMetricByName method +func (mmExpireGroupMetricByName *mGroupedStorageMockExpireGroupMetricByName) Set(f func(group string, name string)) *GroupedStorageMock { + if mmExpireGroupMetricByName.defaultExpectation != nil { + mmExpireGroupMetricByName.mock.t.Fatalf("Default expectation is already set for the GroupedStorage.ExpireGroupMetricByName method") + } + + if len(mmExpireGroupMetricByName.expectations) > 0 { + mmExpireGroupMetricByName.mock.t.Fatalf("Some expectations are already set for the GroupedStorage.ExpireGroupMetricByName method") + } + + mmExpireGroupMetricByName.mock.funcExpireGroupMetricByName = f + mmExpireGroupMetricByName.mock.funcExpireGroupMetricByNameOrigin = minimock.CallerInfo(1) + return mmExpireGroupMetricByName.mock +} + +// Times sets number of times GroupedStorage.ExpireGroupMetricByName should be invoked +func (mmExpireGroupMetricByName *mGroupedStorageMockExpireGroupMetricByName) Times(n uint64) *mGroupedStorageMockExpireGroupMetricByName { + if n == 0 { + mmExpireGroupMetricByName.mock.t.Fatalf("Times of GroupedStorageMock.ExpireGroupMetricByName mock can not be zero") + } + mm_atomic.StoreUint64(&mmExpireGroupMetricByName.expectedInvocations, n) + mmExpireGroupMetricByName.expectedInvocationsOrigin = minimock.CallerInfo(1) + return mmExpireGroupMetricByName +} + +func (mmExpireGroupMetricByName *mGroupedStorageMockExpireGroupMetricByName) invocationsDone() bool { + if len(mmExpireGroupMetricByName.expectations) == 0 && mmExpireGroupMetricByName.defaultExpectation == nil && mmExpireGroupMetricByName.mock.funcExpireGroupMetricByName == nil { + return true + } + + totalInvocations := mm_atomic.LoadUint64(&mmExpireGroupMetricByName.mock.afterExpireGroupMetricByNameCounter) + expectedInvocations := mm_atomic.LoadUint64(&mmExpireGroupMetricByName.expectedInvocations) + + return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations) +} + +// ExpireGroupMetricByName implements GroupedStorage +func (mmExpireGroupMetricByName *GroupedStorageMock) ExpireGroupMetricByName(group string, name string) { + mm_atomic.AddUint64(&mmExpireGroupMetricByName.beforeExpireGroupMetricByNameCounter, 1) + defer mm_atomic.AddUint64(&mmExpireGroupMetricByName.afterExpireGroupMetricByNameCounter, 1) + + mmExpireGroupMetricByName.t.Helper() + + if mmExpireGroupMetricByName.inspectFuncExpireGroupMetricByName != nil { + mmExpireGroupMetricByName.inspectFuncExpireGroupMetricByName(group, name) + } + + mm_params := GroupedStorageMockExpireGroupMetricByNameParams{group, name} + + // Record call args + mmExpireGroupMetricByName.ExpireGroupMetricByNameMock.mutex.Lock() + mmExpireGroupMetricByName.ExpireGroupMetricByNameMock.callArgs = append(mmExpireGroupMetricByName.ExpireGroupMetricByNameMock.callArgs, &mm_params) + mmExpireGroupMetricByName.ExpireGroupMetricByNameMock.mutex.Unlock() + + for _, e := range mmExpireGroupMetricByName.ExpireGroupMetricByNameMock.expectations { + if minimock.Equal(*e.params, mm_params) { + mm_atomic.AddUint64(&e.Counter, 1) + return + } + } + + if mmExpireGroupMetricByName.ExpireGroupMetricByNameMock.defaultExpectation != nil { + mm_atomic.AddUint64(&mmExpireGroupMetricByName.ExpireGroupMetricByNameMock.defaultExpectation.Counter, 1) + mm_want := mmExpireGroupMetricByName.ExpireGroupMetricByNameMock.defaultExpectation.params + mm_want_ptrs := mmExpireGroupMetricByName.ExpireGroupMetricByNameMock.defaultExpectation.paramPtrs + + mm_got := GroupedStorageMockExpireGroupMetricByNameParams{group, name} + + if mm_want_ptrs != nil { + + if mm_want_ptrs.group != nil && !minimock.Equal(*mm_want_ptrs.group, mm_got.group) { + mmExpireGroupMetricByName.t.Errorf("GroupedStorageMock.ExpireGroupMetricByName got unexpected parameter group, expected at\n%s:\nwant: %#v\n got: %#v%s\n", + mmExpireGroupMetricByName.ExpireGroupMetricByNameMock.defaultExpectation.expectationOrigins.originGroup, *mm_want_ptrs.group, mm_got.group, minimock.Diff(*mm_want_ptrs.group, mm_got.group)) + } + + if mm_want_ptrs.name != nil && !minimock.Equal(*mm_want_ptrs.name, mm_got.name) { + mmExpireGroupMetricByName.t.Errorf("GroupedStorageMock.ExpireGroupMetricByName got unexpected parameter name, expected at\n%s:\nwant: %#v\n got: %#v%s\n", + mmExpireGroupMetricByName.ExpireGroupMetricByNameMock.defaultExpectation.expectationOrigins.originName, *mm_want_ptrs.name, mm_got.name, minimock.Diff(*mm_want_ptrs.name, mm_got.name)) + } + + } else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) { + mmExpireGroupMetricByName.t.Errorf("GroupedStorageMock.ExpireGroupMetricByName got unexpected parameters, expected at\n%s:\nwant: %#v\n got: %#v%s\n", + mmExpireGroupMetricByName.ExpireGroupMetricByNameMock.defaultExpectation.expectationOrigins.origin, *mm_want, mm_got, minimock.Diff(*mm_want, mm_got)) + } + + return + + } + if mmExpireGroupMetricByName.funcExpireGroupMetricByName != nil { + mmExpireGroupMetricByName.funcExpireGroupMetricByName(group, name) + return + } + mmExpireGroupMetricByName.t.Fatalf("Unexpected call to GroupedStorageMock.ExpireGroupMetricByName. %v %v", group, name) + +} + +// ExpireGroupMetricByNameAfterCounter returns a count of finished GroupedStorageMock.ExpireGroupMetricByName invocations +func (mmExpireGroupMetricByName *GroupedStorageMock) ExpireGroupMetricByNameAfterCounter() uint64 { + return mm_atomic.LoadUint64(&mmExpireGroupMetricByName.afterExpireGroupMetricByNameCounter) +} + +// ExpireGroupMetricByNameBeforeCounter returns a count of GroupedStorageMock.ExpireGroupMetricByName invocations +func (mmExpireGroupMetricByName *GroupedStorageMock) ExpireGroupMetricByNameBeforeCounter() uint64 { + return mm_atomic.LoadUint64(&mmExpireGroupMetricByName.beforeExpireGroupMetricByNameCounter) +} + +// Calls returns a list of arguments used in each call to GroupedStorageMock.ExpireGroupMetricByName. +// The list is in the same order as the calls were made (i.e. recent calls have a higher index) +func (mmExpireGroupMetricByName *mGroupedStorageMockExpireGroupMetricByName) Calls() []*GroupedStorageMockExpireGroupMetricByNameParams { + mmExpireGroupMetricByName.mutex.RLock() + + argCopy := make([]*GroupedStorageMockExpireGroupMetricByNameParams, len(mmExpireGroupMetricByName.callArgs)) + copy(argCopy, mmExpireGroupMetricByName.callArgs) + + mmExpireGroupMetricByName.mutex.RUnlock() + + return argCopy +} + +// MinimockExpireGroupMetricByNameDone returns true if the count of the ExpireGroupMetricByName invocations corresponds +// the number of defined expectations +func (m *GroupedStorageMock) MinimockExpireGroupMetricByNameDone() bool { + if m.ExpireGroupMetricByNameMock.optional { + // Optional methods provide '0 or more' call count restriction. + return true + } + + for _, e := range m.ExpireGroupMetricByNameMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + return false + } + } + + return m.ExpireGroupMetricByNameMock.invocationsDone() +} + +// MinimockExpireGroupMetricByNameInspect logs each unmet expectation +func (m *GroupedStorageMock) MinimockExpireGroupMetricByNameInspect() { + for _, e := range m.ExpireGroupMetricByNameMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + m.t.Errorf("Expected call to GroupedStorageMock.ExpireGroupMetricByName at\n%s with params: %#v", e.expectationOrigins.origin, *e.params) + } + } + + afterExpireGroupMetricByNameCounter := mm_atomic.LoadUint64(&m.afterExpireGroupMetricByNameCounter) + // if default expectation was set then invocations count should be greater than zero + if m.ExpireGroupMetricByNameMock.defaultExpectation != nil && afterExpireGroupMetricByNameCounter < 1 { + if m.ExpireGroupMetricByNameMock.defaultExpectation.params == nil { + m.t.Errorf("Expected call to GroupedStorageMock.ExpireGroupMetricByName at\n%s", m.ExpireGroupMetricByNameMock.defaultExpectation.returnOrigin) + } else { + m.t.Errorf("Expected call to GroupedStorageMock.ExpireGroupMetricByName at\n%s with params: %#v", m.ExpireGroupMetricByNameMock.defaultExpectation.expectationOrigins.origin, *m.ExpireGroupMetricByNameMock.defaultExpectation.params) + } + } + // if func was set then invocations count should be greater than zero + if m.funcExpireGroupMetricByName != nil && afterExpireGroupMetricByNameCounter < 1 { + m.t.Errorf("Expected call to GroupedStorageMock.ExpireGroupMetricByName at\n%s", m.funcExpireGroupMetricByNameOrigin) + } + + if !m.ExpireGroupMetricByNameMock.invocationsDone() && afterExpireGroupMetricByNameCounter > 0 { + m.t.Errorf("Expected %d calls to GroupedStorageMock.ExpireGroupMetricByName at\n%s but found %d calls", + mm_atomic.LoadUint64(&m.ExpireGroupMetricByNameMock.expectedInvocations), m.ExpireGroupMetricByNameMock.expectedInvocationsOrigin, afterExpireGroupMetricByNameCounter) + } +} + type mGroupedStorageMockExpireGroupMetrics struct { optional bool mock *GroupedStorageMock @@ -2001,6 +2324,8 @@ func (m *GroupedStorageMock) MinimockFinish() { if !m.minimockDone() { m.MinimockCounterAddInspect() + m.MinimockExpireGroupMetricByNameInspect() + m.MinimockExpireGroupMetricsInspect() m.MinimockGaugeSetInspect() @@ -2034,6 +2359,7 @@ func (m *GroupedStorageMock) minimockDone() bool { done := true return done && m.MinimockCounterAddDone() && + m.MinimockExpireGroupMetricByNameDone() && m.MinimockExpireGroupMetricsDone() && m.MinimockGaugeSetDone() && m.MinimockGetOrCreateCounterCollectorDone() && diff --git a/pkg/metric/storage.go b/pkg/metric/storage.go index c460ecb2..4cdca8b1 100644 --- a/pkg/metric/storage.go +++ b/pkg/metric/storage.go @@ -28,6 +28,7 @@ type Storage interface { type GroupedStorage interface { Registerer() prometheus.Registerer ExpireGroupMetrics(group string) + ExpireGroupMetricByName(group, name string) GetOrCreateCounterCollector(name string, labelNames []string) (*ConstCounterCollector, error) GetOrCreateGaugeCollector(name string, labelNames []string) (*ConstGaugeCollector, error) CounterAdd(group string, name string, value float64, labels map[string]string) diff --git a/pkg/metric_storage/metric_storage.go b/pkg/metric_storage/metric_storage.go index 3ed7db55..6adf62c8 100644 --- a/pkg/metric_storage/metric_storage.go +++ b/pkg/metric_storage/metric_storage.go @@ -55,10 +55,10 @@ func NewMetricStorage(ctx context.Context, prefix string, newRegistry bool) *Met Counters: make(map[string]*prometheus.CounterVec), Histograms: make(map[string]*prometheus.HistogramVec), HistogramBuckets: make(map[string][]float64), - groupedVault: vault.NewGroupedVault(), Gatherer: prometheus.DefaultGatherer, Registerer: prometheus.DefaultRegisterer, } + m.groupedVault = vault.NewGroupedVault(m.resolveMetricName) m.groupedVault.SetRegisterer(m.Registerer) if newRegistry { diff --git a/pkg/metric_storage/vault/vault.go b/pkg/metric_storage/vault/vault.go index 8ebbcfe6..6827306c 100644 --- a/pkg/metric_storage/vault/vault.go +++ b/pkg/metric_storage/vault/vault.go @@ -15,11 +15,13 @@ type GroupedVault struct { collectors map[string]metric.ConstCollector mtx sync.Mutex registerer prometheus.Registerer + resolveMetricNameFunc func(name string) string } -func NewGroupedVault() *GroupedVault { +func NewGroupedVault(resolveMetricNameFunc func(name string) string) *GroupedVault { return &GroupedVault{ collectors: make(map[string]metric.ConstCollector), + resolveMetricNameFunc : resolveMetricNameFunc, } } @@ -34,22 +36,34 @@ func (v *GroupedVault) SetRegisterer(r prometheus.Registerer) { // ClearAllMetrics takes each collector in collectors and clear all metrics by group. func (v *GroupedVault) ExpireGroupMetrics(group string) { v.mtx.Lock() - defer v.mtx.Unlock() for _, collector := range v.collectors { collector.ExpireGroupMetrics(group) } + v.mtx.Unlock() +} + +// ExpireGroupMetricByName gets a collector by its name and clears all metrics inside the collector by the group. +func (v *GroupedVault) ExpireGroupMetricByName(group, name string) { + metricName := v.resolveMetricNameFunc(name) + v.mtx.Lock() + collector, ok := v.collectors[metricName] + if ok { + collector.ExpireGroupMetrics(group) + } + v.mtx.Unlock() } func (v *GroupedVault) GetOrCreateCounterCollector(name string, labelNames []string) (*metric.ConstCounterCollector, error) { + metricName := v.resolveMetricNameFunc(name) v.mtx.Lock() defer v.mtx.Unlock() - collector, ok := v.collectors[name] + collector, ok := v.collectors[metricName] if !ok { - collector = metric.NewConstCounterCollector(name, labelNames) + collector = metric.NewConstCounterCollector(metricName, labelNames) if err := v.registerer.Register(collector); err != nil { - return nil, fmt.Errorf("counter '%s' %v registration: %v", name, labelNames, err) + return nil, fmt.Errorf("counter '%s' %v registration: %v", metricName, labelNames, err) } - v.collectors[name] = collector + v.collectors[metricName] = collector } else if !IsSubset(collector.LabelNames(), labelNames) { collector.UpdateLabels(labelNames) } @@ -60,15 +74,16 @@ func (v *GroupedVault) GetOrCreateCounterCollector(name string, labelNames []str } func (v *GroupedVault) GetOrCreateGaugeCollector(name string, labelNames []string) (*metric.ConstGaugeCollector, error) { + metricName := v.resolveMetricNameFunc(name) v.mtx.Lock() defer v.mtx.Unlock() - collector, ok := v.collectors[name] + collector, ok := v.collectors[metricName] if !ok { - collector = metric.NewConstGaugeCollector(name, labelNames) + collector = metric.NewConstGaugeCollector(metricName, labelNames) if err := v.registerer.Register(collector); err != nil { - return nil, fmt.Errorf("gauge '%s' %v registration: %v", name, labelNames, err) + return nil, fmt.Errorf("gauge '%s' %v registration: %v", metricName, labelNames, err) } - v.collectors[name] = collector + v.collectors[metricName] = collector } else if !IsSubset(collector.LabelNames(), labelNames) { collector.UpdateLabels(labelNames) } @@ -80,7 +95,8 @@ func (v *GroupedVault) GetOrCreateGaugeCollector(name string, labelNames []strin } func (v *GroupedVault) CounterAdd(group string, name string, value float64, labels map[string]string) { - c, err := v.GetOrCreateCounterCollector(name, LabelNames(labels)) + metricName := v.resolveMetricNameFunc(name) + c, err := v.GetOrCreateCounterCollector(metricName, LabelNames(labels)) if err != nil { log.Errorf("CounterAdd: %v", err) return @@ -89,7 +105,8 @@ func (v *GroupedVault) CounterAdd(group string, name string, value float64, labe } func (v *GroupedVault) GaugeSet(group string, name string, value float64, labels map[string]string) { - c, err := v.GetOrCreateGaugeCollector(name, LabelNames(labels)) + metricName := v.resolveMetricNameFunc(name) + c, err := v.GetOrCreateGaugeCollector(metricName, LabelNames(labels)) if err != nil { log.Errorf("GaugeSet: %v", err) return diff --git a/pkg/metric_storage/vault/vault_test.go b/pkg/metric_storage/vault/vault_test.go index 473f974f..d24714e6 100644 --- a/pkg/metric_storage/vault/vault_test.go +++ b/pkg/metric_storage/vault/vault_test.go @@ -17,7 +17,7 @@ func Test_CounterAdd(t *testing.T) { buf := &bytes.Buffer{} log.SetOutput(buf) - v := NewGroupedVault() + v := NewGroupedVault(func (name string) string { return name }) v.registerer = prometheus.DefaultRegisterer v.CounterAdd("group1", "metric_total", 1.0, map[string]string{"lbl": "val"}) @@ -125,6 +125,8 @@ metric2_total{lbl="val222"} 2 v.CounterAdd("group3", "metric_total4", 39.0, map[string]string{"j": "j1"}) v.CounterAdd("group3", "metric_total4", 1.0, map[string]string{"j": "j1"}) v.CounterAdd("group3", "metric_total4", 1.0, map[string]string{"a": "", "b": "", "c": "", "d": "", "j": "j1"}) + v.CounterAdd("group3", "metric_total5", 7.0, map[string]string{"g": "g1"}) + v.CounterAdd("group3", "metric_total5", 11.0, map[string]string{"foo": "bar"}) g.Expect(buf.String()).ShouldNot(ContainSubstring("error"), "error occurred in log: %s", buf.String()) @@ -151,8 +153,41 @@ metric_total4{a="a1", b="b1", c="c1", d="d1", j=""} 99 metric_total4{a="", b="", c="c2", d="", j=""} 19 metric_total4{a="", b="", c="", d="", j=""} 29 metric_total4{a="", b="", c="", d="", j="j1"} 41 +# HELP metric_total5 metric_total5 +# TYPE metric_total5 counter +metric_total5{foo="", g="g1"} 7 +metric_total5{foo="bar", g=""} 11 ` - err = promtest.GatherAndCompare(prometheus.DefaultGatherer, strings.NewReader(expect), "metric_total1", "metric_total2", "metric_total3", "metric_total4") + err = promtest.GatherAndCompare(prometheus.DefaultGatherer, strings.NewReader(expect), "metric_total1", "metric_total2", "metric_total3", "metric_total4", "metric_total5") + g.Expect(err).ShouldNot(HaveOccurred()) + + expect = ` +# HELP metric_total1 metric_total1 +# TYPE metric_total1 gauge +metric_total1{a="A", b="", c=""} 5 +metric_total1{a="", b="", c="C"} 2 +metric_total1{a="A", b="B", c=""} 3 +# HELP metric_total2 metric_total2 +# TYPE metric_total2 gauge +metric_total2{a="A1", b="", c=""} 1 +metric_total2{a="", b="", c="C2"} 2 +metric_total2{a="A3", b="B3", c=""} 3 +# HELP metric_total3 metric_total3 +# TYPE metric_total3 counter +metric_total3{lbl="val222", ord=""} 5 +metric_total3{lbl="", ord="ord222"} 10 +metric_total3{lbl="val222", ord="ord222"} 108 +# HELP metric_total4 metric_total4 +# TYPE metric_total4 counter +metric_total4{a="", b="", c="", d="d1", j=""} 9 +metric_total4{a="a1", b="b1", c="c1", d="d1", j=""} 99 +metric_total4{a="", b="", c="c2", d="", j=""} 19 +metric_total4{a="", b="", c="", d="", j=""} 29 +metric_total4{a="", b="", c="", d="", j="j1"} 41 +` + + v.ExpireGroupMetricByName("group3", "metric_total5") + err = promtest.GatherAndCompare(prometheus.DefaultGatherer, strings.NewReader(expect), "metric_total1", "metric_total2", "metric_totalr3", "metric_total4", "metric_total5") g.Expect(err).ShouldNot(HaveOccurred()) }