From 9908cbe73a2f30980f81adeaa5accaca8b26a7cd Mon Sep 17 00:00:00 2001 From: Yuki Sawa Date: Wed, 21 Oct 2020 15:54:18 -0700 Subject: [PATCH 01/19] Add example prom statsd exporter conf Signed-off-by: Yuki Sawa --- examples/prom-statsd-exporter/conf.yaml | 67 +++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 examples/prom-statsd-exporter/conf.yaml diff --git a/examples/prom-statsd-exporter/conf.yaml b/examples/prom-statsd-exporter/conf.yaml new file mode 100644 index 00000000..0706548d --- /dev/null +++ b/examples/prom-statsd-exporter/conf.yaml @@ -0,0 +1,67 @@ +mappings: # Requires statsd exporter >= v0.6.0 since it uses the "drop" action. + - match: + "ratelimit.service.rate_limit.*.*.near_limit" + name: "ratelimit_service_rate_limit_near_limit" + timer_type: "histogram" + labels: + domain: "$1" + key1: "$2" + - match: + "ratelimit.service.rate_limit.*.*.over_limit" + name: "ratelimit_service_rate_limit_over_limit" + timer_type: "histogram" + labels: + domain: "$1" + key1: "$2" + - match: + "ratelimit.service.rate_limit.*.*.total_hits" + name: "ratelimit_service_rate_limit_total_hits" + timer_type: "histogram" + labels: + domain: "$1" + key1: "$2" + + - match: + "ratelimit.service.rate_limit.*.*.*.near_limit" + name: "ratelimit_service_rate_limit_near_limit" + timer_type: "histogram" + labels: + domain: "$1" + key1: "$2" + key2: "$3" + - match: + "ratelimit.service.rate_limit.*.*.*.over_limit" + name: "ratelimit_service_rate_limit_over_limit" + timer_type: "histogram" + labels: + domain: "$1" + key1: "$2" + key2: "$3" + - match: + "ratelimit.service.rate_limit.*.*.*.total_hits" + name: "ratelimit_service_rate_limit_total_hits" + timer_type: "histogram" + labels: + domain: "$1" + key1: "$2" + key2: "$3" + + - match: "ratelimit.service.call.should_rate_limit.*" + name: "ratelimit_service_should_rate_limit_error" + match_metric_type: counter + labels: + err_type: "$1" + + - match: "ratelimit.service.config_load_success" + name: "ratelimit_service_config_load_success" + match_metric_type: counter + - match: "ratelimit.service.config_load_error" + name: "ratelimit_service_config_load_error" + match_metric_type: counter + - match: "ratelimit.service.config_load_error" + name: "ratelimit_service_config_load_error" + match_metric_type: counter + - match: "." + match_type: "regex" + action: "drop" + name: "dropped" From c90a8294a2a523de55a24bec6fda9d70278b3c4b Mon Sep 17 00:00:00 2001 From: Yuki Sawa Date: Wed, 21 Oct 2020 15:54:33 -0700 Subject: [PATCH 02/19] Add example prom statsd exporter conf Signed-off-by: Yuki Sawa --- docker-compose-example.yml | 7 +++++++ examples/envoy/proxy.yaml | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/docker-compose-example.yml b/docker-compose-example.yml index f96879ee..9739feaa 100644 --- a/docker-compose-example.yml +++ b/docker-compose-example.yml @@ -11,12 +11,19 @@ services: statsd: image: prom/statsd-exporter:v0.18.0 + entrypoint: /bin/statsd_exporter + command: + - "--statsd.mapping-config=/etc/statsd-exporter/conf.yaml" expose: - 9125 + - 9102 ports: - 9125:9125 + - 9102:9102 # Visit http://localhost:9102/metrics to see metrics in Prometheus format networks: - ratelimit-network + volumes: + - ./examples/prom-statsd-exporter/conf.yaml:/etc/statsd-exporter/conf.yaml ratelimit: image: envoyproxy/ratelimit:master diff --git a/examples/envoy/proxy.yaml b/examples/envoy/proxy.yaml index bb45503f..74a58cef 100644 --- a/examples/envoy/proxy.yaml +++ b/examples/envoy/proxy.yaml @@ -72,8 +72,8 @@ static_resources: cluster: mock rate_limits: - actions: - - source_cluster: {} - - destination_cluster: {} + - source_cluster: {} # This action's value is populated by the "service-cluster" arg passed in when starting Envoy. In this example, it's "proxy" (see docker-compose-example.yml) + - destination_cluster: {} # This action's value is populated by the value set in the above "cluster" field -- "mock". - match: prefix: /header route: From d920809af658a5791cf5cab67a09e5e2d268d323 Mon Sep 17 00:00:00 2001 From: Yuki Sawa Date: Tue, 3 Nov 2020 14:09:31 -0800 Subject: [PATCH 03/19] Convert example envoy conf to v3 Signed-off-by: Yuki Sawa --- examples/envoy/mock.yaml | 53 ++++++++++++++++++++------------------- examples/envoy/proxy.yaml | 11 ++++---- 2 files changed, 33 insertions(+), 31 deletions(-) diff --git a/examples/envoy/mock.yaml b/examples/envoy/mock.yaml index bd85fc3d..87574494 100644 --- a/examples/envoy/mock.yaml +++ b/examples/envoy/mock.yaml @@ -1,31 +1,32 @@ static_resources: listeners: - - address: - socket_address: - address: 0.0.0.0 - port_value: 9999 - filter_chains: - - filters: - - name: envoy.http_connection_manager - config: - codec_type: auto - stat_prefix: ingress - route_config: - name: ingress - virtual_hosts: - - name: backend - domains: - - "*" - routes: - - match: - prefix: "/" - direct_response: - status: "200" - body: - inline_string: "Hello World" - http_filters: - - name: envoy.router - config: {} + - address: + socket_address: + address: 0.0.0.0 + port_value: 9999 + filter_chains: + - filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + codec_type: AUTO + stat_prefix: ingress + route_config: + name: ingress + virtual_hosts: + - name: backend + domains: + - "*" + routes: + - match: + prefix: "/" + direct_response: + status: "200" + body: + inline_string: "Hello World" + http_filters: + - name: envoy.filters.http.router + typed_config: {} admin: access_log_path: "/dev/null" address: diff --git a/examples/envoy/proxy.yaml b/examples/envoy/proxy.yaml index 74a58cef..4b01d5a5 100644 --- a/examples/envoy/proxy.yaml +++ b/examples/envoy/proxy.yaml @@ -41,9 +41,10 @@ static_resources: port_value: 8888 filter_chains: - filters: - - name: envoy.http_connection_manager - config: - codec_type: auto + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + codec_type: AUTO stat_prefix: ingress http_filters: - name: envoy.rate_limit @@ -57,8 +58,8 @@ static_resources: grpc_service: envoy_grpc: cluster_name: ratelimit - - name: envoy.router - config: {} + - name: envoy.filters.http.router + typed_config: {} route_config: name: route virtual_hosts: From 559c9757e244fea76baee0f790486fa63fc2bab2 Mon Sep 17 00:00:00 2001 From: Yuki Sawa Date: Mon, 16 Nov 2020 12:51:23 -0800 Subject: [PATCH 04/19] CI Signed-off-by: Yuki Sawa --- examples/envoy/proxy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/envoy/proxy.yaml b/examples/envoy/proxy.yaml index 4b01d5a5..4c5605d1 100644 --- a/examples/envoy/proxy.yaml +++ b/examples/envoy/proxy.yaml @@ -74,7 +74,7 @@ static_resources: rate_limits: - actions: - source_cluster: {} # This action's value is populated by the "service-cluster" arg passed in when starting Envoy. In this example, it's "proxy" (see docker-compose-example.yml) - - destination_cluster: {} # This action's value is populated by the value set in the above "cluster" field -- "mock". + - destination_cluster: {} # This action's value is populated by the value set in the above "cluster" field -- "mock" - match: prefix: /header route: From 87ea936f58d1a7f2733df41f3c99912f25095fa6 Mon Sep 17 00:00:00 2001 From: Yuki Sawa Date: Mon, 16 Nov 2020 22:13:57 -0800 Subject: [PATCH 05/19] Ensure DurationUntilReset is always the same in integration test Signed-off-by: Yuki Sawa --- test/integration/integration_test.go | 33 ++++++++++++++++------------ 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/test/integration/integration_test.go b/test/integration/integration_test.go index 91b56012..8f9cb1f4 100644 --- a/test/integration/integration_test.go +++ b/test/integration/integration_test.go @@ -14,7 +14,6 @@ import ( pb_legacy "github.com/envoyproxy/go-control-plane/envoy/service/ratelimit/v2" pb "github.com/envoyproxy/go-control-plane/envoy/service/ratelimit/v3" "github.com/envoyproxy/ratelimit/src/service_cmd/runner" - "github.com/envoyproxy/ratelimit/src/utils" "github.com/envoyproxy/ratelimit/test/common" "github.com/golang/protobuf/ptypes/duration" "github.com/stretchr/testify/assert" @@ -22,18 +21,15 @@ import ( "google.golang.org/grpc" ) -func newDescriptorStatus( - status pb.RateLimitResponse_Code, requestsPerUnit uint32, - unit pb.RateLimitResponse_RateLimit_Unit, limitRemaining uint32) *pb.RateLimitResponse_DescriptorStatus { +func newDescriptorStatus(status pb.RateLimitResponse_Code, requestsPerUnit uint32, unit pb.RateLimitResponse_RateLimit_Unit, limitRemaining uint32, durRemain *duration.Duration) *pb.RateLimitResponse_DescriptorStatus { limit := &pb.RateLimitResponse_RateLimit{RequestsPerUnit: requestsPerUnit, Unit: unit} - sec := utils.UnitToDivider(unit) - now := time.Now().Unix() + return &pb.RateLimitResponse_DescriptorStatus{ Code: status, CurrentLimit: limit, LimitRemaining: limitRemaining, - DurationUntilReset: &duration.Duration{Seconds: sec - now%sec}, + DurationUntilReset: &duration.Duration{Seconds: durRemain.GetSeconds()}, } } @@ -294,6 +290,7 @@ func testBasicBaseConfig(grpcPort, perSecond string, local_cache_size string) fu localCacheMissCounter := runner.GetStatsStore().NewGauge("ratelimit.localcache.missCount") assert.Equal(0, int(localCacheMissCounter.Value())) + durRemain := response.GetStatuses()[0].DurationUntilReset response, err = c.ShouldRateLimit( context.Background(), @@ -303,7 +300,7 @@ func testBasicBaseConfig(grpcPort, perSecond string, local_cache_size string) fu &pb.RateLimitResponse{ OverallCode: pb.RateLimitResponse_OK, Statuses: []*pb.RateLimitResponse_DescriptorStatus{ - newDescriptorStatus(pb.RateLimitResponse_OK, 50, pb.RateLimitResponse_RateLimit_SECOND, 49)}}, + newDescriptorStatus(pb.RateLimitResponse_OK, 50, pb.RateLimitResponse_RateLimit_SECOND, 49, durRemain)}}, response) assert.NoError(err) @@ -331,6 +328,7 @@ func testBasicBaseConfig(grpcPort, perSecond string, local_cache_size string) fu context.Background(), common.NewRateLimitRequest( "another", [][][2]string{{{getCacheKey("key2", enable_local_cache), strconv.Itoa(randomInt)}}}, 1)) + assert.NotNil(err) status := pb.RateLimitResponse_OK limitRemaining := uint32(20 - (i + 1)) @@ -338,13 +336,15 @@ func testBasicBaseConfig(grpcPort, perSecond string, local_cache_size string) fu status = pb.RateLimitResponse_OVER_LIMIT limitRemaining = 0 } + fmt.Println("DurationUntilReset: ", response.GetStatuses()[0].DurationUntilReset) + durRemain = response.GetStatuses()[0].DurationUntilReset common.AssertProtoEqual( assert, &pb.RateLimitResponse{ OverallCode: status, Statuses: []*pb.RateLimitResponse_DescriptorStatus{ - newDescriptorStatus(status, 20, pb.RateLimitResponse_RateLimit_MINUTE, limitRemaining)}}, + newDescriptorStatus(status, 20, pb.RateLimitResponse_RateLimit_MINUTE, limitRemaining, durRemain)}}, response) assert.NoError(err) key2HitCounter := runner.GetStatsStore().NewCounter(fmt.Sprintf("ratelimit.service.rate_limit.another.%s.total_hits", getCacheKey("key2", enable_local_cache))) @@ -355,7 +355,7 @@ func testBasicBaseConfig(grpcPort, perSecond string, local_cache_size string) fu } else { assert.Equal(0, int(key2OverlimitCounter.Value())) } - + assert.NotNil(nil) key2LocalCacheOverLimitCounter := runner.GetStatsStore().NewCounter(fmt.Sprintf("ratelimit.service.rate_limit.another.%s.over_limit_with_local_cache", getCacheKey("key2", enable_local_cache))) if enable_local_cache && i >= 20 { assert.Equal(i-20, int(key2LocalCacheOverLimitCounter.Value())) @@ -394,6 +394,7 @@ func testBasicBaseConfig(grpcPort, perSecond string, local_cache_size string) fu [][][2]string{ {{getCacheKey("key2", enable_local_cache), strconv.Itoa(randomInt)}}, {{getCacheKey("key3", enable_local_cache), strconv.Itoa(randomInt)}}}, 1)) + assert.NotNil(err) status := pb.RateLimitResponse_OK limitRemaining1 := uint32(20 - (i + 1)) @@ -402,14 +403,15 @@ func testBasicBaseConfig(grpcPort, perSecond string, local_cache_size string) fu status = pb.RateLimitResponse_OVER_LIMIT limitRemaining2 = 0 } - + durRemain1 = response.GetStatuses()[0].DurationUntilReset + durRemain2 = response.GetStatuses()[1].DurationUntilReset common.AssertProtoEqual( assert, &pb.RateLimitResponse{ OverallCode: status, Statuses: []*pb.RateLimitResponse_DescriptorStatus{ - newDescriptorStatus(pb.RateLimitResponse_OK, 20, pb.RateLimitResponse_RateLimit_MINUTE, limitRemaining1), - newDescriptorStatus(status, 10, pb.RateLimitResponse_RateLimit_HOUR, limitRemaining2)}}, + newDescriptorStatus(pb.RateLimitResponse_OK, 20, pb.RateLimitResponse_RateLimit_MINUTE, limitRemaining1, durRemain2), + newDescriptorStatus(status, 10, pb.RateLimitResponse_RateLimit_HOUR, limitRemaining2, durRemain1)}}, response) assert.NoError(err) @@ -669,12 +671,15 @@ func testConfigReload(grpcPort, perSecond string, local_cache_size string) func( response, err = c.ShouldRateLimit( context.Background(), common.NewRateLimitRequest("reload", [][][2]string{{{getCacheKey("key1", enable_local_cache), "foo"}}}, 1)) + assert.NotNil(err) + + durRemain := response.GetStatuses()[0].DurationUntilReset common.AssertProtoEqual( assert, &pb.RateLimitResponse{ OverallCode: pb.RateLimitResponse_OK, Statuses: []*pb.RateLimitResponse_DescriptorStatus{ - newDescriptorStatus(pb.RateLimitResponse_OK, 50, pb.RateLimitResponse_RateLimit_SECOND, 49)}}, + newDescriptorStatus(pb.RateLimitResponse_OK, 50, pb.RateLimitResponse_RateLimit_SECOND, 49, durRemain)}}, response) assert.NoError(err) From 49f08695f0849e03458ff78533ee2cf2b387c188 Mon Sep 17 00:00:00 2001 From: Yuki Sawa Date: Mon, 16 Nov 2020 22:22:41 -0800 Subject: [PATCH 06/19] Remove notNils Signed-off-by: Yuki Sawa --- test/integration/integration_test.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/test/integration/integration_test.go b/test/integration/integration_test.go index 8f9cb1f4..cf9d4e1c 100644 --- a/test/integration/integration_test.go +++ b/test/integration/integration_test.go @@ -328,7 +328,6 @@ func testBasicBaseConfig(grpcPort, perSecond string, local_cache_size string) fu context.Background(), common.NewRateLimitRequest( "another", [][][2]string{{{getCacheKey("key2", enable_local_cache), strconv.Itoa(randomInt)}}}, 1)) - assert.NotNil(err) status := pb.RateLimitResponse_OK limitRemaining := uint32(20 - (i + 1)) @@ -355,7 +354,6 @@ func testBasicBaseConfig(grpcPort, perSecond string, local_cache_size string) fu } else { assert.Equal(0, int(key2OverlimitCounter.Value())) } - assert.NotNil(nil) key2LocalCacheOverLimitCounter := runner.GetStatsStore().NewCounter(fmt.Sprintf("ratelimit.service.rate_limit.another.%s.over_limit_with_local_cache", getCacheKey("key2", enable_local_cache))) if enable_local_cache && i >= 20 { assert.Equal(i-20, int(key2LocalCacheOverLimitCounter.Value())) @@ -394,7 +392,6 @@ func testBasicBaseConfig(grpcPort, perSecond string, local_cache_size string) fu [][][2]string{ {{getCacheKey("key2", enable_local_cache), strconv.Itoa(randomInt)}}, {{getCacheKey("key3", enable_local_cache), strconv.Itoa(randomInt)}}}, 1)) - assert.NotNil(err) status := pb.RateLimitResponse_OK limitRemaining1 := uint32(20 - (i + 1)) @@ -403,8 +400,8 @@ func testBasicBaseConfig(grpcPort, perSecond string, local_cache_size string) fu status = pb.RateLimitResponse_OVER_LIMIT limitRemaining2 = 0 } - durRemain1 = response.GetStatuses()[0].DurationUntilReset - durRemain2 = response.GetStatuses()[1].DurationUntilReset + durRemain1 := response.GetStatuses()[0].DurationUntilReset + durRemain2 := response.GetStatuses()[1].DurationUntilReset common.AssertProtoEqual( assert, &pb.RateLimitResponse{ @@ -671,7 +668,6 @@ func testConfigReload(grpcPort, perSecond string, local_cache_size string) func( response, err = c.ShouldRateLimit( context.Background(), common.NewRateLimitRequest("reload", [][][2]string{{{getCacheKey("key1", enable_local_cache), "foo"}}}, 1)) - assert.NotNil(err) durRemain := response.GetStatuses()[0].DurationUntilReset common.AssertProtoEqual( From cf43c06803b3e915cf2d277a6d0303a718365553 Mon Sep 17 00:00:00 2001 From: Yuki Sawa Date: Mon, 16 Nov 2020 22:31:26 -0800 Subject: [PATCH 07/19] fix dur remain Signed-off-by: Yuki Sawa --- test/integration/integration_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/integration/integration_test.go b/test/integration/integration_test.go index cf9d4e1c..9753fc02 100644 --- a/test/integration/integration_test.go +++ b/test/integration/integration_test.go @@ -335,7 +335,7 @@ func testBasicBaseConfig(grpcPort, perSecond string, local_cache_size string) fu status = pb.RateLimitResponse_OVER_LIMIT limitRemaining = 0 } - fmt.Println("DurationUntilReset: ", response.GetStatuses()[0].DurationUntilReset) + //fmt.Println("DurationUntilReset: ", response.GetStatuses()[0].DurationUntilReset) durRemain = response.GetStatuses()[0].DurationUntilReset common.AssertProtoEqual( @@ -407,8 +407,8 @@ func testBasicBaseConfig(grpcPort, perSecond string, local_cache_size string) fu &pb.RateLimitResponse{ OverallCode: status, Statuses: []*pb.RateLimitResponse_DescriptorStatus{ - newDescriptorStatus(pb.RateLimitResponse_OK, 20, pb.RateLimitResponse_RateLimit_MINUTE, limitRemaining1, durRemain2), - newDescriptorStatus(status, 10, pb.RateLimitResponse_RateLimit_HOUR, limitRemaining2, durRemain1)}}, + newDescriptorStatus(pb.RateLimitResponse_OK, 20, pb.RateLimitResponse_RateLimit_MINUTE, limitRemaining1, durRemain1), + newDescriptorStatus(status, 10, pb.RateLimitResponse_RateLimit_HOUR, limitRemaining2, durRemain2)}}, response) assert.NoError(err) From db30fb8fe3a4868428f8ddd2fe77f76e34cd315b Mon Sep 17 00:00:00 2001 From: Yuki Sawa Date: Mon, 16 Nov 2020 22:32:45 -0800 Subject: [PATCH 08/19] fix dur remain Signed-off-by: Yuki Sawa --- test/integration/integration_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/integration/integration_test.go b/test/integration/integration_test.go index 9753fc02..7cb44e26 100644 --- a/test/integration/integration_test.go +++ b/test/integration/integration_test.go @@ -290,11 +290,12 @@ func testBasicBaseConfig(grpcPort, perSecond string, local_cache_size string) fu localCacheMissCounter := runner.GetStatsStore().NewGauge("ratelimit.localcache.missCount") assert.Equal(0, int(localCacheMissCounter.Value())) - durRemain := response.GetStatuses()[0].DurationUntilReset response, err = c.ShouldRateLimit( context.Background(), common.NewRateLimitRequest("basic", [][][2]string{{{getCacheKey("key1", enable_local_cache), "foo"}}}, 1)) + durRemain := response.GetStatuses()[0].DurationUntilReset + common.AssertProtoEqual( assert, &pb.RateLimitResponse{ From 6f6349aa2536fef33b3b15dfb0297d48cb3b6eeb Mon Sep 17 00:00:00 2001 From: Yuki Sawa Date: Mon, 16 Nov 2020 22:54:42 -0800 Subject: [PATCH 09/19] Add test for DurationUntilReset Signed-off-by: Yuki Sawa --- test/integration/integration_test.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/integration/integration_test.go b/test/integration/integration_test.go index 7cb44e26..cb65e001 100644 --- a/test/integration/integration_test.go +++ b/test/integration/integration_test.go @@ -305,6 +305,15 @@ func testBasicBaseConfig(grpcPort, perSecond string, local_cache_size string) fu response) assert.NoError(err) + // Test DurationUntilReset by hitting same key after waiting 1 sec + time.Sleep(1 * time.Second) + + response, err = c.ShouldRateLimit( + context.Background(), + common.NewRateLimitRequest("basic", [][][2]string{{{getCacheKey("key1", enable_local_cache), "foo"}}}, 1)) + + assert.Less(response.GetStatuses()[0].DurationUntilReset, durRemain) + // store.NewCounter returns the existing counter. key1HitCounter := runner.GetStatsStore().NewCounter(fmt.Sprintf("ratelimit.service.rate_limit.basic.%s.total_hits", getCacheKey("key1", enable_local_cache))) assert.Equal(1, int(key1HitCounter.Value())) From 2dc36601968b7f52b292d63b6ab50c936c9aa909 Mon Sep 17 00:00:00 2001 From: Yuki Sawa Date: Mon, 16 Nov 2020 23:21:01 -0800 Subject: [PATCH 10/19] durRemain to durRemaining Signed-off-by: Yuki Sawa --- test/integration/integration_test.go | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/test/integration/integration_test.go b/test/integration/integration_test.go index cb65e001..18627bc2 100644 --- a/test/integration/integration_test.go +++ b/test/integration/integration_test.go @@ -21,7 +21,7 @@ import ( "google.golang.org/grpc" ) -func newDescriptorStatus(status pb.RateLimitResponse_Code, requestsPerUnit uint32, unit pb.RateLimitResponse_RateLimit_Unit, limitRemaining uint32, durRemain *duration.Duration) *pb.RateLimitResponse_DescriptorStatus { +func newDescriptorStatus(status pb.RateLimitResponse_Code, requestsPerUnit uint32, unit pb.RateLimitResponse_RateLimit_Unit, limitRemaining uint32, durRemaining *duration.Duration) *pb.RateLimitResponse_DescriptorStatus { limit := &pb.RateLimitResponse_RateLimit{RequestsPerUnit: requestsPerUnit, Unit: unit} @@ -29,7 +29,7 @@ func newDescriptorStatus(status pb.RateLimitResponse_Code, requestsPerUnit uint3 Code: status, CurrentLimit: limit, LimitRemaining: limitRemaining, - DurationUntilReset: &duration.Duration{Seconds: durRemain.GetSeconds()}, + DurationUntilReset: &duration.Duration{Seconds: durRemaining.GetSeconds()}, } } @@ -294,14 +294,14 @@ func testBasicBaseConfig(grpcPort, perSecond string, local_cache_size string) fu response, err = c.ShouldRateLimit( context.Background(), common.NewRateLimitRequest("basic", [][][2]string{{{getCacheKey("key1", enable_local_cache), "foo"}}}, 1)) - durRemain := response.GetStatuses()[0].DurationUntilReset + durRemaining := response.GetStatuses()[0].DurationUntilReset common.AssertProtoEqual( assert, &pb.RateLimitResponse{ OverallCode: pb.RateLimitResponse_OK, Statuses: []*pb.RateLimitResponse_DescriptorStatus{ - newDescriptorStatus(pb.RateLimitResponse_OK, 50, pb.RateLimitResponse_RateLimit_SECOND, 49, durRemain)}}, + newDescriptorStatus(pb.RateLimitResponse_OK, 50, pb.RateLimitResponse_RateLimit_SECOND, 49, durRemaining)}}, response) assert.NoError(err) @@ -312,7 +312,7 @@ func testBasicBaseConfig(grpcPort, perSecond string, local_cache_size string) fu context.Background(), common.NewRateLimitRequest("basic", [][][2]string{{{getCacheKey("key1", enable_local_cache), "foo"}}}, 1)) - assert.Less(response.GetStatuses()[0].DurationUntilReset, durRemain) + assert.Less(response.GetStatuses()[0].DurationUntilReset, durRemaining) // store.NewCounter returns the existing counter. key1HitCounter := runner.GetStatsStore().NewCounter(fmt.Sprintf("ratelimit.service.rate_limit.basic.%s.total_hits", getCacheKey("key1", enable_local_cache))) @@ -346,14 +346,14 @@ func testBasicBaseConfig(grpcPort, perSecond string, local_cache_size string) fu limitRemaining = 0 } //fmt.Println("DurationUntilReset: ", response.GetStatuses()[0].DurationUntilReset) - durRemain = response.GetStatuses()[0].DurationUntilReset + durRemaining = response.GetStatuses()[0].DurationUntilReset common.AssertProtoEqual( assert, &pb.RateLimitResponse{ OverallCode: status, Statuses: []*pb.RateLimitResponse_DescriptorStatus{ - newDescriptorStatus(status, 20, pb.RateLimitResponse_RateLimit_MINUTE, limitRemaining, durRemain)}}, + newDescriptorStatus(status, 20, pb.RateLimitResponse_RateLimit_MINUTE, limitRemaining, durRemaining)}}, response) assert.NoError(err) key2HitCounter := runner.GetStatsStore().NewCounter(fmt.Sprintf("ratelimit.service.rate_limit.another.%s.total_hits", getCacheKey("key2", enable_local_cache))) @@ -410,15 +410,15 @@ func testBasicBaseConfig(grpcPort, perSecond string, local_cache_size string) fu status = pb.RateLimitResponse_OVER_LIMIT limitRemaining2 = 0 } - durRemain1 := response.GetStatuses()[0].DurationUntilReset - durRemain2 := response.GetStatuses()[1].DurationUntilReset + durRemaining1 := response.GetStatuses()[0].DurationUntilReset + durRemaining2 := response.GetStatuses()[1].DurationUntilReset common.AssertProtoEqual( assert, &pb.RateLimitResponse{ OverallCode: status, Statuses: []*pb.RateLimitResponse_DescriptorStatus{ - newDescriptorStatus(pb.RateLimitResponse_OK, 20, pb.RateLimitResponse_RateLimit_MINUTE, limitRemaining1, durRemain1), - newDescriptorStatus(status, 10, pb.RateLimitResponse_RateLimit_HOUR, limitRemaining2, durRemain2)}}, + newDescriptorStatus(pb.RateLimitResponse_OK, 20, pb.RateLimitResponse_RateLimit_MINUTE, limitRemaining1, durRemaining1), + newDescriptorStatus(status, 10, pb.RateLimitResponse_RateLimit_HOUR, limitRemaining2, durRemaining2)}}, response) assert.NoError(err) @@ -679,13 +679,13 @@ func testConfigReload(grpcPort, perSecond string, local_cache_size string) func( context.Background(), common.NewRateLimitRequest("reload", [][][2]string{{{getCacheKey("key1", enable_local_cache), "foo"}}}, 1)) - durRemain := response.GetStatuses()[0].DurationUntilReset + durRemaining := response.GetStatuses()[0].DurationUntilReset common.AssertProtoEqual( assert, &pb.RateLimitResponse{ OverallCode: pb.RateLimitResponse_OK, Statuses: []*pb.RateLimitResponse_DescriptorStatus{ - newDescriptorStatus(pb.RateLimitResponse_OK, 50, pb.RateLimitResponse_RateLimit_SECOND, 49, durRemain)}}, + newDescriptorStatus(pb.RateLimitResponse_OK, 50, pb.RateLimitResponse_RateLimit_SECOND, 49, durRemaining)}}, response) assert.NoError(err) From d5ec5a8ee910f0f96e65d90e7b7b69170d4126e3 Mon Sep 17 00:00:00 2001 From: Yuki Sawa Date: Mon, 16 Nov 2020 23:35:57 -0800 Subject: [PATCH 11/19] Add test for duration until reset Signed-off-by: Yuki Sawa --- test/integration/integration_test.go | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/test/integration/integration_test.go b/test/integration/integration_test.go index 18627bc2..afb99f80 100644 --- a/test/integration/integration_test.go +++ b/test/integration/integration_test.go @@ -26,9 +26,9 @@ func newDescriptorStatus(status pb.RateLimitResponse_Code, requestsPerUnit uint3 limit := &pb.RateLimitResponse_RateLimit{RequestsPerUnit: requestsPerUnit, Unit: unit} return &pb.RateLimitResponse_DescriptorStatus{ - Code: status, - CurrentLimit: limit, - LimitRemaining: limitRemaining, + Code: status, + CurrentLimit: limit, + LimitRemaining: limitRemaining, DurationUntilReset: &duration.Duration{Seconds: durRemaining.GetSeconds()}, } } @@ -305,15 +305,6 @@ func testBasicBaseConfig(grpcPort, perSecond string, local_cache_size string) fu response) assert.NoError(err) - // Test DurationUntilReset by hitting same key after waiting 1 sec - time.Sleep(1 * time.Second) - - response, err = c.ShouldRateLimit( - context.Background(), - common.NewRateLimitRequest("basic", [][][2]string{{{getCacheKey("key1", enable_local_cache), "foo"}}}, 1)) - - assert.Less(response.GetStatuses()[0].DurationUntilReset, durRemaining) - // store.NewCounter returns the existing counter. key1HitCounter := runner.GetStatsStore().NewCounter(fmt.Sprintf("ratelimit.service.rate_limit.basic.%s.total_hits", getCacheKey("key1", enable_local_cache))) assert.Equal(1, int(key1HitCounter.Value())) @@ -476,6 +467,19 @@ func testBasicBaseConfig(grpcPort, perSecond string, local_cache_size string) fu } } + + // Test DurationUntilReset by hitting same key twice + resp1, err = c.ShouldRateLimit( + context.Background(), + common.NewRateLimitRequest("basic", [][][2]string{{{getCacheKey("key1", enable_local_cache), "durTest"}}}, 1)) + + time.Sleep(1 * time.Second) // Wait 1 sec to allow duration to tick down + + resp2, err = c.ShouldRateLimit( + context.Background(), + common.NewRateLimitRequest("basic", [][][2]string{{{getCacheKey("key1", enable_local_cache), "durTest"}}}, 1)) + + assert.Less(resp2.GetStatuses()[0].DurationUntilReset, resp1.GetStatuses()[0].DurationUntilReset) } } From daab215b07004d313ed34090a753f6be49d0b344 Mon Sep 17 00:00:00 2001 From: Yuki Sawa Date: Mon, 16 Nov 2020 23:37:09 -0800 Subject: [PATCH 12/19] Add test for duration until reset Signed-off-by: Yuki Sawa --- test/integration/integration_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/integration/integration_test.go b/test/integration/integration_test.go index afb99f80..27fb502c 100644 --- a/test/integration/integration_test.go +++ b/test/integration/integration_test.go @@ -469,17 +469,17 @@ func testBasicBaseConfig(grpcPort, perSecond string, local_cache_size string) fu } // Test DurationUntilReset by hitting same key twice - resp1, err = c.ShouldRateLimit( + resp1, err := c.ShouldRateLimit( context.Background(), common.NewRateLimitRequest("basic", [][][2]string{{{getCacheKey("key1", enable_local_cache), "durTest"}}}, 1)) time.Sleep(1 * time.Second) // Wait 1 sec to allow duration to tick down - resp2, err = c.ShouldRateLimit( + resp2, err := c.ShouldRateLimit( context.Background(), common.NewRateLimitRequest("basic", [][][2]string{{{getCacheKey("key1", enable_local_cache), "durTest"}}}, 1)) - assert.Less(resp2.GetStatuses()[0].DurationUntilReset, resp1.GetStatuses()[0].DurationUntilReset) + assert.Less(resp2.GetStatuses()[0].DurationUntilReset.GetSeconds(), resp1.GetStatuses()[0].DurationUntilReset.GetSeconds()) } } From 747db9743d75efa3b9cbcb1d76467d41e1e9c71f Mon Sep 17 00:00:00 2001 From: Yuki Sawa Date: Mon, 16 Nov 2020 23:42:55 -0800 Subject: [PATCH 13/19] Add test for duration until reset Signed-off-by: Yuki Sawa --- test/integration/integration_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/integration_test.go b/test/integration/integration_test.go index 27fb502c..0d2427e4 100644 --- a/test/integration/integration_test.go +++ b/test/integration/integration_test.go @@ -479,7 +479,7 @@ func testBasicBaseConfig(grpcPort, perSecond string, local_cache_size string) fu context.Background(), common.NewRateLimitRequest("basic", [][][2]string{{{getCacheKey("key1", enable_local_cache), "durTest"}}}, 1)) - assert.Less(resp2.GetStatuses()[0].DurationUntilReset.GetSeconds(), resp1.GetStatuses()[0].DurationUntilReset.GetSeconds()) + assert.Less(resp2.GetStatuses()[0].DurationUntilReset.GetNanos(), resp1.GetStatuses()[0].DurationUntilReset.GetNanos()) } } From 24cb29fd4bfb6d71716b624d0de350bbae273986 Mon Sep 17 00:00:00 2001 From: Yuki Sawa Date: Tue, 17 Nov 2020 00:11:13 -0800 Subject: [PATCH 14/19] Add test for duration until reset Signed-off-by: Yuki Sawa --- test/integration/integration_test.go | 8 ++++---- .../runtime/current/ratelimit/config/basic.yaml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/integration/integration_test.go b/test/integration/integration_test.go index 0d2427e4..5e4f54c8 100644 --- a/test/integration/integration_test.go +++ b/test/integration/integration_test.go @@ -471,15 +471,15 @@ func testBasicBaseConfig(grpcPort, perSecond string, local_cache_size string) fu // Test DurationUntilReset by hitting same key twice resp1, err := c.ShouldRateLimit( context.Background(), - common.NewRateLimitRequest("basic", [][][2]string{{{getCacheKey("key1", enable_local_cache), "durTest"}}}, 1)) + common.NewRateLimitRequest("another", [][][2]string{{{getCacheKey("key2", enable_local_cache), "durTest"}}}, 1)) - time.Sleep(1 * time.Second) // Wait 1 sec to allow duration to tick down + time.Sleep(5 * time.Second) // Wait 1 sec to allow duration to tick down resp2, err := c.ShouldRateLimit( context.Background(), - common.NewRateLimitRequest("basic", [][][2]string{{{getCacheKey("key1", enable_local_cache), "durTest"}}}, 1)) + common.NewRateLimitRequest("another", [][][2]string{{{getCacheKey("key2", enable_local_cache), "durTest"}}}, 1)) - assert.Less(resp2.GetStatuses()[0].DurationUntilReset.GetNanos(), resp1.GetStatuses()[0].DurationUntilReset.GetNanos()) + assert.Less(resp2.GetStatuses()[0].DurationUntilReset.GetSeconds(), resp1.GetStatuses()[0].DurationUntilReset.GetSeconds()) } } diff --git a/test/integration/runtime/current/ratelimit/config/basic.yaml b/test/integration/runtime/current/ratelimit/config/basic.yaml index 843b9887..a941ce58 100644 --- a/test/integration/runtime/current/ratelimit/config/basic.yaml +++ b/test/integration/runtime/current/ratelimit/config/basic.yaml @@ -13,4 +13,4 @@ descriptors: - key: one_per_minute rate_limit: unit: minute - requests_per_unit: 1 \ No newline at end of file + requests_per_unit: 1 From bf0a2cd4dda2af62f631d3453f625d6d5030637b Mon Sep 17 00:00:00 2001 From: Yuki Sawa Date: Tue, 17 Nov 2020 00:19:25 -0800 Subject: [PATCH 15/19] Add test for duration until reset Signed-off-by: Yuki Sawa --- test/integration/integration_test.go | 7 +++---- .../runtime/current/ratelimit/config/another.yaml | 5 +++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/test/integration/integration_test.go b/test/integration/integration_test.go index 5e4f54c8..54a4bfc8 100644 --- a/test/integration/integration_test.go +++ b/test/integration/integration_test.go @@ -336,7 +336,6 @@ func testBasicBaseConfig(grpcPort, perSecond string, local_cache_size string) fu status = pb.RateLimitResponse_OVER_LIMIT limitRemaining = 0 } - //fmt.Println("DurationUntilReset: ", response.GetStatuses()[0].DurationUntilReset) durRemaining = response.GetStatuses()[0].DurationUntilReset common.AssertProtoEqual( @@ -471,13 +470,13 @@ func testBasicBaseConfig(grpcPort, perSecond string, local_cache_size string) fu // Test DurationUntilReset by hitting same key twice resp1, err := c.ShouldRateLimit( context.Background(), - common.NewRateLimitRequest("another", [][][2]string{{{getCacheKey("key2", enable_local_cache), "durTest"}}}, 1)) + common.NewRateLimitRequest("another", [][][2]string{{{getCacheKey("key4", enable_local_cache), "durTest"}}}, 1)) - time.Sleep(5 * time.Second) // Wait 1 sec to allow duration to tick down + time.Sleep(2 * time.Second) // Wait 1 sec to allow duration to tick down resp2, err := c.ShouldRateLimit( context.Background(), - common.NewRateLimitRequest("another", [][][2]string{{{getCacheKey("key2", enable_local_cache), "durTest"}}}, 1)) + common.NewRateLimitRequest("another", [][][2]string{{{getCacheKey("key4", enable_local_cache), "durTest"}}}, 1)) assert.Less(resp2.GetStatuses()[0].DurationUntilReset.GetSeconds(), resp1.GetStatuses()[0].DurationUntilReset.GetSeconds()) } diff --git a/test/integration/runtime/current/ratelimit/config/another.yaml b/test/integration/runtime/current/ratelimit/config/another.yaml index 94f8dd96..a291e4a0 100644 --- a/test/integration/runtime/current/ratelimit/config/another.yaml +++ b/test/integration/runtime/current/ratelimit/config/another.yaml @@ -19,3 +19,8 @@ descriptors: rate_limit: unit: hour requests_per_unit: 10 + + - key: key4 + rate_limit: + unit: minute + requests_per_unit: 20 From f89e9d782ad6a1a1b5bbb6c0204e947d62761afb Mon Sep 17 00:00:00 2001 From: Yuki Sawa Date: Tue, 17 Nov 2020 00:30:43 -0800 Subject: [PATCH 16/19] Add test for duration until reset Signed-off-by: Yuki Sawa --- test/integration/runtime/current/ratelimit/config/another.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/runtime/current/ratelimit/config/another.yaml b/test/integration/runtime/current/ratelimit/config/another.yaml index a291e4a0..c96d89ab 100644 --- a/test/integration/runtime/current/ratelimit/config/another.yaml +++ b/test/integration/runtime/current/ratelimit/config/another.yaml @@ -22,5 +22,5 @@ descriptors: - key: key4 rate_limit: - unit: minute + unit: day requests_per_unit: 20 From 0e82602fd99e75ed5b9292dceefcf14543e9dafc Mon Sep 17 00:00:00 2001 From: Yuki Sawa Date: Tue, 17 Nov 2020 01:00:51 -0800 Subject: [PATCH 17/19] Check resp not nil Signed-off-by: Yuki Sawa --- test/integration/integration_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/integration/integration_test.go b/test/integration/integration_test.go index 54a4bfc8..b215da2c 100644 --- a/test/integration/integration_test.go +++ b/test/integration/integration_test.go @@ -478,7 +478,9 @@ func testBasicBaseConfig(grpcPort, perSecond string, local_cache_size string) fu context.Background(), common.NewRateLimitRequest("another", [][][2]string{{{getCacheKey("key4", enable_local_cache), "durTest"}}}, 1)) - assert.Less(resp2.GetStatuses()[0].DurationUntilReset.GetSeconds(), resp1.GetStatuses()[0].DurationUntilReset.GetSeconds()) + if resp2.GetStatuses()[0].DurationUntilReset != nil { + assert.Less(resp2.GetStatuses()[0].DurationUntilReset.GetSeconds(), resp1.GetStatuses()[0].DurationUntilReset.GetSeconds()) + } } } From eb559d8bf1607c465194d7fa7a223ce97537c84d Mon Sep 17 00:00:00 2001 From: Yuki Sawa Date: Tue, 17 Nov 2020 09:54:14 -0800 Subject: [PATCH 18/19] Verbiage Signed-off-by: Yuki Sawa --- test/integration/integration_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/integration_test.go b/test/integration/integration_test.go index b215da2c..f021a5c2 100644 --- a/test/integration/integration_test.go +++ b/test/integration/integration_test.go @@ -472,7 +472,7 @@ func testBasicBaseConfig(grpcPort, perSecond string, local_cache_size string) fu context.Background(), common.NewRateLimitRequest("another", [][][2]string{{{getCacheKey("key4", enable_local_cache), "durTest"}}}, 1)) - time.Sleep(2 * time.Second) // Wait 1 sec to allow duration to tick down + time.Sleep(2 * time.Second) // Wait to allow duration to tick down resp2, err := c.ShouldRateLimit( context.Background(), From 5e50ab86470447c5d0e5aff60a0c775020b38099 Mon Sep 17 00:00:00 2001 From: Yuki Sawa Date: Wed, 18 Nov 2020 20:47:04 -0800 Subject: [PATCH 19/19] Fix tests for localcache Signed-off-by: Yuki Sawa --- test/integration/integration_test.go | 5 +---- .../runtime/current/ratelimit/config/another.yaml | 5 +++++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/test/integration/integration_test.go b/test/integration/integration_test.go index f021a5c2..b76c8ada 100644 --- a/test/integration/integration_test.go +++ b/test/integration/integration_test.go @@ -464,7 +464,6 @@ func testBasicBaseConfig(grpcPort, perSecond string, local_cache_size string) fu } else { assert.Equal(0, int(localCacheMissCounter.Value())) } - } // Test DurationUntilReset by hitting same key twice @@ -478,9 +477,7 @@ func testBasicBaseConfig(grpcPort, perSecond string, local_cache_size string) fu context.Background(), common.NewRateLimitRequest("another", [][][2]string{{{getCacheKey("key4", enable_local_cache), "durTest"}}}, 1)) - if resp2.GetStatuses()[0].DurationUntilReset != nil { - assert.Less(resp2.GetStatuses()[0].DurationUntilReset.GetSeconds(), resp1.GetStatuses()[0].DurationUntilReset.GetSeconds()) - } + assert.Less(resp2.GetStatuses()[0].DurationUntilReset.GetSeconds(), resp1.GetStatuses()[0].DurationUntilReset.GetSeconds()) } } diff --git a/test/integration/runtime/current/ratelimit/config/another.yaml b/test/integration/runtime/current/ratelimit/config/another.yaml index c96d89ab..0281bb68 100644 --- a/test/integration/runtime/current/ratelimit/config/another.yaml +++ b/test/integration/runtime/current/ratelimit/config/another.yaml @@ -24,3 +24,8 @@ descriptors: rate_limit: unit: day requests_per_unit: 20 + + - key: key4_local + rate_limit: + unit: day + requests_per_unit: 20