Skip to content

Commit bf549b3

Browse files
author
Petr Pchelko
committed
Add support for rate limit overrides.
Fixes #154 Signed-off-by: Petr Pchelko <ppchelko@wikimedia.org>
1 parent 60af777 commit bf549b3

File tree

6 files changed

+161
-11
lines changed

6 files changed

+161
-11
lines changed

go.mod

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@ go 1.14
55
require (
66
github.com/alicebob/miniredis/v2 v2.11.4
77
github.com/cespare/xxhash v1.1.0 // indirect
8+
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354 // indirect
89
github.com/coocood/freecache v1.1.0
9-
github.com/envoyproxy/go-control-plane v0.9.5
10+
github.com/envoyproxy/go-control-plane v0.9.6
1011
github.com/gogo/protobuf v1.3.1 // indirect
1112
github.com/golang/mock v1.4.1
12-
github.com/golang/protobuf v1.3.2
13+
github.com/golang/protobuf v1.4.2
1314
github.com/gorilla/mux v1.7.4-0.20191121170500-49c01487a141
1415
github.com/kavu/go_reuseport v1.2.0
1516
github.com/kelseyhightower/envconfig v1.1.0
@@ -26,8 +27,8 @@ require (
2627
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553
2728
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a // indirect
2829
golang.org/x/text v0.3.3-0.20191122225017-cbf43d21aaeb // indirect
29-
google.golang.org/genproto v0.0.0-20191216205247-b31c10ee225f // indirect
30-
google.golang.org/grpc v1.25.1
30+
google.golang.org/grpc v1.27.0
31+
google.golang.org/protobuf v1.25.0 // indirect
3132
gopkg.in/airbrake/gobrake.v2 v2.0.9 // indirect
3233
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 // indirect
3334
gopkg.in/yaml.v2 v2.3.0

go.sum

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,11 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR
1414
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
1515
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
1616
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
17+
github.com/cncf/udpa v0.0.0-20200629203442-efcf912fb354 h1:JBAT2dkeyeqzQOaAA8tB21Zfyv/nHfaqjZvWIllABnw=
1718
github.com/cncf/udpa/go v0.0.0-20200313221541-5f7e5dd04533 h1:8wZizuKuZVu5COB7EsBYxBQz8nRcXXn5d4Gt91eJLvU=
1819
github.com/cncf/udpa/go v0.0.0-20200313221541-5f7e5dd04533/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
20+
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354 h1:9kRtNpqLHbZVO/NNxhHp2ymxFxsHOe3x2efJGn//Tas=
21+
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
1922
github.com/coocood/freecache v1.1.0 h1:ENiHOsWdj1BrrlPwblhbn4GdAsMymK3pZORJ+bJGAjA=
2023
github.com/coocood/freecache v1.1.0/go.mod h1:ePwxCDzOYvARfHdr1pByNct1at3CoKnsipOHwKlNbzI=
2124
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -24,8 +27,13 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
2427
github.com/envoyproxy/go-control-plane v0.6.9 h1:deEH9W8ZAUGNbCdX+9iNzBOGrAOrnpJGoy0PcTqk/tE=
2528
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
2629
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
30+
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
2731
github.com/envoyproxy/go-control-plane v0.9.5 h1:lRJIqDD8yjV1YyPRqecMdytjDLs2fTXq363aCib5xPU=
2832
github.com/envoyproxy/go-control-plane v0.9.5/go.mod h1:OXl5to++W0ctG+EHWTFUjiypVxC/Y4VLc/KFU+al13s=
33+
github.com/envoyproxy/go-control-plane v0.9.6-0.20200630214754-219d0fe20d5e h1:C4C1u9L0TNuvG9Se3g5DdqplIjf4qy7EqzUrOr8RCVI=
34+
github.com/envoyproxy/go-control-plane v0.9.6-0.20200630214754-219d0fe20d5e/go.mod h1:JvuSsUgXzeWfLVfAe9OeW40eBtd+E8yMydqNm0iuBxs=
35+
github.com/envoyproxy/go-control-plane v0.9.6 h1:GgblEiDzxf5ajlAZY4aC8xp7DwkrGfauFNMGdB2bBv0=
36+
github.com/envoyproxy/go-control-plane v0.9.6/go.mod h1:GFqM7v0B62MraO4PWRedIbhThr/Rf7ev6aHOOPXeaDA=
2937
github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A=
3038
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
3139
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
@@ -40,8 +48,21 @@ github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
4048
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
4149
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
4250
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
51+
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
52+
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
53+
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
54+
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
55+
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
56+
github.com/golang/protobuf v1.4.1 h1:ZFgWrT+bLgsYPirOnRfKLYJLvssAegOj/hgyMFdJZe0=
57+
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
58+
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
59+
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
4360
github.com/gomodule/redigo v1.7.1-0.20190322064113-39e2c31b7ca3/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
4461
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
62+
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
63+
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
64+
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
65+
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
4566
github.com/gorilla/mux v1.7.4-0.20191121170500-49c01487a141 h1:VQjjMh+uElTfioy6GnUrVrTMAiLTNF3xsrAlSwC+g8o=
4667
github.com/gorilla/mux v1.7.4-0.20191121170500-49c01487a141/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
4768
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
@@ -136,17 +157,33 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+y
136157
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
137158
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA=
138159
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
160+
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
161+
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
139162
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
140163
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
141164
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
142165
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
143166
google.golang.org/genproto v0.0.0-20191216205247-b31c10ee225f h1:0RYv5T9ZdroAqqfM2taEB0nJrArv0X1JpIdgUmY4xg8=
144167
google.golang.org/genproto v0.0.0-20191216205247-b31c10ee225f/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
168+
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=
169+
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
145170
google.golang.org/grpc v1.19.0 h1:cfg4PD8YEdSFnm7qLV4++93WcmhH2nIUhMjhdCvl3j8=
146171
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
147172
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
148173
google.golang.org/grpc v1.25.1 h1:wdKvqQk7IttEw92GoRyKG2IDrUIpgpj6H6m81yfeMW0=
149174
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
175+
google.golang.org/grpc v1.27.0 h1:rRYRFMVgRv6E0D70Skyfsr28tDXIuuPZyWGMPdMcnXg=
176+
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
177+
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
178+
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
179+
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
180+
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
181+
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
182+
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
183+
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
184+
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
185+
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
186+
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
150187
gopkg.in/airbrake/gobrake.v2 v2.0.9 h1:7z2uVWwn7oVeeugY1DtlPAy5H+KYgB1KeKTnqjNatLo=
151188
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
152189
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=

src/config/config_impl.go

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,12 @@ type rateLimitDescriptor struct {
3636

3737
type rateLimitDomain struct {
3838
rateLimitDescriptor
39+
overrides map[string]*RateLimit
3940
}
4041

4142
type rateLimitConfigImpl struct {
42-
domains map[string]*rateLimitDomain
43+
domains map[string]*rateLimitDomain
44+
statsScope stats.Scope
4345
}
4446

4547
var validKeys = map[string]bool{
@@ -197,8 +199,7 @@ func validateYamlKeys(config RateLimitConfigToLoad, config_map map[interface{}]i
197199

198200
// Load a single YAML config file into the global config.
199201
// @param config specifies the file contents to load.
200-
// @param statsScope supplies the owning scope.
201-
func (this *rateLimitConfigImpl) loadConfig(config RateLimitConfigToLoad, statsScope stats.Scope) {
202+
func (this *rateLimitConfigImpl) loadConfig(config RateLimitConfigToLoad) {
202203
// validate keys in config with generic map
203204
any := map[interface{}]interface{}{}
204205
err := yaml.Unmarshal([]byte(config.FileBytes), &any)
@@ -227,11 +228,25 @@ func (this *rateLimitConfigImpl) loadConfig(config RateLimitConfigToLoad, statsS
227228
}
228229

229230
logger.Debugf("loading domain: %s", root.Domain)
230-
newDomain := &rateLimitDomain{rateLimitDescriptor{map[string]*rateLimitDescriptor{}, nil}}
231-
newDomain.loadDescriptors(config, root.Domain+".", root.Descriptors, statsScope)
231+
newDomain := &rateLimitDomain{rateLimitDescriptor{map[string]*rateLimitDescriptor{}, nil}, map[string]*RateLimit{}}
232+
newDomain.loadDescriptors(config, root.Domain+".", root.Descriptors, this.statsScope)
232233
this.domains[root.Domain] = newDomain
233234
}
234235

236+
func (this *rateLimitConfigImpl) descriptorToKey(descriptor *pb_struct.RateLimitDescriptor) string {
237+
rateLimitKey := ""
238+
for _, entry := range descriptor.Entries {
239+
if rateLimitKey != "" {
240+
rateLimitKey += "."
241+
}
242+
rateLimitKey += entry.Key
243+
if entry.Value != "" {
244+
rateLimitKey += "_" + entry.Value
245+
}
246+
}
247+
return rateLimitKey
248+
}
249+
235250
func (this *rateLimitConfigImpl) Dump() string {
236251
ret := ""
237252
for _, domain := range this.domains {
@@ -252,6 +267,28 @@ func (this *rateLimitConfigImpl) GetLimit(
252267
return rateLimit
253268
}
254269

270+
if descriptor.GetLimit() != nil {
271+
rateLimitKey := domain + "." + this.descriptorToKey(descriptor)
272+
rateLimit := value.overrides[rateLimitKey]
273+
rateLimitOverrideUnit := pb.RateLimitResponse_RateLimit_Unit(descriptor.GetLimit().GetUnit())
274+
if rateLimit != nil {
275+
if rateLimit.Limit.RequestsPerUnit != descriptor.GetLimit().GetRequestsPerUnit() ||
276+
rateLimit.Limit.Unit != rateLimitOverrideUnit {
277+
278+
rateLimit.Limit.RequestsPerUnit = descriptor.GetLimit().GetRequestsPerUnit()
279+
rateLimit.Limit.Unit = rateLimitOverrideUnit
280+
}
281+
return rateLimit
282+
}
283+
rateLimit = NewRateLimit(
284+
descriptor.GetLimit().GetRequestsPerUnit(),
285+
rateLimitOverrideUnit,
286+
rateLimitKey,
287+
this.statsScope)
288+
value.overrides[rateLimitKey] = rateLimit
289+
return rateLimit
290+
}
291+
255292
descriptorsMap := value.descriptors
256293
for i, entry := range descriptor.Entries {
257294
// First see if key_value is in the map. If that isn't in the map we look for just key
@@ -292,9 +329,9 @@ func (this *rateLimitConfigImpl) GetLimit(
292329
func NewRateLimitConfigImpl(
293330
configs []RateLimitConfigToLoad, statsScope stats.Scope) RateLimitConfig {
294331

295-
ret := &rateLimitConfigImpl{map[string]*rateLimitDomain{}}
332+
ret := &rateLimitConfigImpl{map[string]*rateLimitDomain{}, statsScope}
296333
for _, config := range configs {
297-
ret.loadConfig(config, statsScope)
334+
ret.loadConfig(config)
298335
}
299336

300337
return ret

src/service/ratelimit_legacy.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ func ConvertResponse(response *pb.RateLimitResponse) (*pb_legacy.RateLimitRespon
110110
}
111111
if status.GetCurrentLimit() != nil {
112112
statuses[i].CurrentLimit = &pb_legacy.RateLimitResponse_RateLimit{
113+
Name: status.GetCurrentLimit().GetName(),
113114
RequestsPerUnit: status.GetCurrentLimit().GetRequestsPerUnit(),
114115
Unit: pb_legacy.RateLimitResponse_RateLimit_Unit(status.GetCurrentLimit().GetUnit()),
115116
}

test/config/config_test.go

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package config_test
22

33
import (
4+
"github.com/envoyproxy/ratelimit/test/common"
45
"io/ioutil"
56
"testing"
67

78
pb_struct "github.com/envoyproxy/go-control-plane/envoy/extensions/common/ratelimit/v3"
89
pb "github.com/envoyproxy/go-control-plane/envoy/service/ratelimit/v3"
10+
pb_type "github.com/envoyproxy/go-control-plane/envoy/type/v3"
911
"github.com/envoyproxy/ratelimit/src/config"
1012
"github.com/lyft/gostats"
1113
"github.com/stretchr/testify/assert"
@@ -150,6 +152,77 @@ func TestBasicConfig(t *testing.T) {
150152
assert.EqualValues(1, stats.NewCounter("test-domain.key4.near_limit").Value())
151153
}
152154

155+
func TestConfigLimitOverride(t *testing.T) {
156+
assert := assert.New(t)
157+
stats := stats.NewStore(stats.NewNullSink(), false)
158+
rlConfig := config.NewRateLimitConfigImpl(loadFile("basic_config.yaml"), stats)
159+
rlConfig.Dump()
160+
// No matching domain
161+
assert.Nil(rlConfig.GetLimit(nil, "foo_domain", &pb_struct.RateLimitDescriptor{
162+
Limit: &pb_struct.RateLimitDescriptor_RateLimitOverride{
163+
RequestsPerUnit: 10, Unit: pb_type.RateLimitUnit_DAY,
164+
},
165+
}))
166+
rl := rlConfig.GetLimit(
167+
nil, "test-domain",
168+
&pb_struct.RateLimitDescriptor{
169+
Entries: []*pb_struct.RateLimitDescriptor_Entry{{Key: "key1", Value: "value1"}, {Key: "subkey1", Value: "something"}},
170+
Limit: &pb_struct.RateLimitDescriptor_RateLimitOverride{
171+
RequestsPerUnit: 10, Unit: pb_type.RateLimitUnit_DAY,
172+
},
173+
})
174+
assert.Equal("test-domain.key1_value1.subkey1_something", rl.FullKey)
175+
common.AssertProtoEqual(assert, &pb.RateLimitResponse_RateLimit{
176+
RequestsPerUnit: 10,
177+
Unit: pb.RateLimitResponse_RateLimit_DAY,
178+
}, rl.Limit)
179+
rl.Stats.TotalHits.Inc()
180+
rl.Stats.OverLimit.Inc()
181+
rl.Stats.NearLimit.Inc()
182+
assert.EqualValues(1, stats.NewCounter("test-domain.key1_value1.subkey1_something.total_hits").Value())
183+
assert.EqualValues(1, stats.NewCounter("test-domain.key1_value1.subkey1_something.over_limit").Value())
184+
assert.EqualValues(1, stats.NewCounter("test-domain.key1_value1.subkey1_something.near_limit").Value())
185+
186+
// Change in override value doesn't erase stats
187+
rl = rlConfig.GetLimit(
188+
nil, "test-domain",
189+
&pb_struct.RateLimitDescriptor{
190+
Entries: []*pb_struct.RateLimitDescriptor_Entry{{Key: "key1", Value: "value1"}, {Key: "subkey1", Value: "something"}},
191+
Limit: &pb_struct.RateLimitDescriptor_RateLimitOverride{
192+
RequestsPerUnit: 42, Unit: pb_type.RateLimitUnit_HOUR,
193+
},
194+
})
195+
assert.Equal("test-domain.key1_value1.subkey1_something", rl.FullKey)
196+
common.AssertProtoEqual(assert, &pb.RateLimitResponse_RateLimit{
197+
RequestsPerUnit: 42,
198+
Unit: pb.RateLimitResponse_RateLimit_HOUR,
199+
}, rl.Limit)
200+
assert.EqualValues(1, stats.NewCounter("test-domain.key1_value1.subkey1_something.total_hits").Value())
201+
assert.EqualValues(1, stats.NewCounter("test-domain.key1_value1.subkey1_something.over_limit").Value())
202+
assert.EqualValues(1, stats.NewCounter("test-domain.key1_value1.subkey1_something.near_limit").Value())
203+
204+
// Different value creates a different counter
205+
rl = rlConfig.GetLimit(
206+
nil, "test-domain",
207+
&pb_struct.RateLimitDescriptor{
208+
Entries: []*pb_struct.RateLimitDescriptor_Entry{{Key: "key1", Value: "value1"}, {Key: "subkey1", Value: "something_else"}},
209+
Limit: &pb_struct.RateLimitDescriptor_RateLimitOverride{
210+
RequestsPerUnit: 42, Unit: pb_type.RateLimitUnit_HOUR,
211+
},
212+
})
213+
assert.Equal("test-domain.key1_value1.subkey1_something_else", rl.FullKey)
214+
common.AssertProtoEqual(assert, &pb.RateLimitResponse_RateLimit{
215+
RequestsPerUnit: 42,
216+
Unit: pb.RateLimitResponse_RateLimit_HOUR,
217+
}, rl.Limit)
218+
rl.Stats.TotalHits.Inc()
219+
rl.Stats.OverLimit.Inc()
220+
rl.Stats.NearLimit.Inc()
221+
assert.EqualValues(1, stats.NewCounter("test-domain.key1_value1.subkey1_something_else.total_hits").Value())
222+
assert.EqualValues(1, stats.NewCounter("test-domain.key1_value1.subkey1_something_else.over_limit").Value())
223+
assert.EqualValues(1, stats.NewCounter("test-domain.key1_value1.subkey1_something_else.near_limit").Value())
224+
}
225+
153226
func expectConfigPanic(t *testing.T, call func(), expectedError string) {
154227
assert := assert.New(t)
155228
defer func() {

test/service/ratelimit_legacy_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ func convertRatelimit(ratelimit *pb.RateLimitResponse_RateLimit) (*pb_legacy.Rat
2525
}
2626

2727
return &pb_legacy.RateLimitResponse_RateLimit{
28+
Name: ratelimit.GetName(),
2829
RequestsPerUnit: ratelimit.GetRequestsPerUnit(),
2930
Unit: pb_legacy.RateLimitResponse_RateLimit_Unit(ratelimit.GetUnit()),
3031
}, nil

0 commit comments

Comments
 (0)