diff --git a/src/config/config_impl.go b/src/config/config_impl.go index df0e473d..7ada07e1 100644 --- a/src/config/config_impl.go +++ b/src/config/config_impl.go @@ -285,6 +285,8 @@ func (this *rateLimitConfigImpl) GetLimit( value := this.domains[domain] if value == nil { logger.Debugf("unknown domain '%s'", domain) + domainStats := this.statsManager.NewDomainStats(domain) + domainStats.NotFound.Inc() return rateLimit } diff --git a/src/stats/manager.go b/src/stats/manager.go index ba83fd51..43d72d59 100644 --- a/src/stats/manager.go +++ b/src/stats/manager.go @@ -9,6 +9,9 @@ type Manager interface { // NewStats provides a RateLimitStats structure associated with a given descriptorKey. // Multiple calls with the same descriptorKey argument are guaranteed to be equivalent. NewStats(descriptorKey string) RateLimitStats + // Gets stats for a domain (when no descriptors are found) + // Multiple calls with the same domain argument are guaranteed to be equivalent. + NewDomainStats(domain string) DomainStats // Initializes a ShouldRateLimitStats structure. // Multiple calls to this method are idempotent. NewShouldRateLimitStats() ShouldRateLimitStats @@ -52,3 +55,9 @@ type RateLimitStats struct { WithinLimit gostats.Counter ShadowMode gostats.Counter } + +// Stats for a domain entry +type DomainStats struct { + Key string + NotFound gostats.Counter +} diff --git a/src/stats/manager_impl.go b/src/stats/manager_impl.go index efe8aa07..ee0cf013 100644 --- a/src/stats/manager_impl.go +++ b/src/stats/manager_impl.go @@ -39,6 +39,13 @@ func (this *ManagerImpl) NewStats(key string) RateLimitStats { return ret } +func (this *ManagerImpl) NewDomainStats(domain string) DomainStats { + ret := DomainStats{} + domain = utils.SanitizeStatName(domain) + ret.NotFound = this.rlStatsScope.NewCounter(domain + ".domain_not_found") + return ret +} + func (this *ManagerImpl) NewShouldRateLimitStats() ShouldRateLimitStats { ret := ShouldRateLimitStats{} ret.RedisError = this.shouldRateLimitScope.NewCounter("redis_error") diff --git a/test/config/config_test.go b/test/config/config_test.go index eb52974f..3c06b088 100644 --- a/test/config/config_test.go +++ b/test/config/config_test.go @@ -33,8 +33,11 @@ func TestBasicConfig(t *testing.T) { rlConfig := config.NewRateLimitConfigImpl(loadFile("basic_config.yaml"), mockstats.NewMockStatManager(stats), false) rlConfig.Dump() assert.Equal(rlConfig.IsEmptyDomains(), false) + assert.EqualValues(0, stats.NewCounter("foo_domain.domain_not_found").Value()) assert.Nil(rlConfig.GetLimit(context.TODO(), "foo_domain", &pb_struct.RateLimitDescriptor{})) + assert.EqualValues(1, stats.NewCounter("foo_domain.domain_not_found").Value()) assert.Nil(rlConfig.GetLimit(context.TODO(), "test-domain", &pb_struct.RateLimitDescriptor{})) + assert.EqualValues(0, stats.NewCounter("test-domain.domain_not_found").Value()) rl := rlConfig.GetLimit( context.TODO(), "test-domain", diff --git a/test/mocks/stats/manager.go b/test/mocks/stats/manager.go index dd9db246..522f8486 100644 --- a/test/mocks/stats/manager.go +++ b/test/mocks/stats/manager.go @@ -48,6 +48,15 @@ func (m *MockStatManager) NewStats(key string) stats.RateLimitStats { return ret } +func (m *MockStatManager) NewDomainStats(key string) stats.DomainStats { + ret := stats.DomainStats{} + logger.Debugf("outputing test domain stats %s", key) + ret.Key = key + ret.NotFound = m.store.NewCounter(key + ".domain_not_found") + + return ret +} + func NewMockStatManager(store gostats.Store) stats.Manager { return &MockStatManager{store: store} }