From 87b029762153c330c47a4cc86fb9743d4b38e30c Mon Sep 17 00:00:00 2001 From: Pengyuan Bian Date: Tue, 5 Nov 2019 17:06:22 -0800 Subject: [PATCH 1/5] add response flag --- extensions/common/BUILD | 13 +++ extensions/common/context.cc | 5 + extensions/common/util.cc | 162 +++++++++++++++++++++++++++++++++ extensions/common/util.h | 27 ++++++ extensions/common/util_test.cc | 50 ++++++++++ 5 files changed, 257 insertions(+) create mode 100644 extensions/common/util.cc create mode 100644 extensions/common/util.h create mode 100644 extensions/common/util_test.cc diff --git a/extensions/common/BUILD b/extensions/common/BUILD index d7f01ffaf16..31539cfff3c 100644 --- a/extensions/common/BUILD +++ b/extensions/common/BUILD @@ -31,9 +31,11 @@ envoy_cc_library( name = "context", srcs = [ "context.cc", + "util.cc", ], hdrs = [ "context.h", + "util.h", ], repository = "@envoy", visibility = ["//visibility:public"], @@ -83,6 +85,17 @@ envoy_cc_test( ], ) +envoy_cc_test( + name = "util_test", + size = "small", + srcs = ["util_test.cc"], + repository = "@envoy", + deps = [ + ":context", + "@envoy//source/extensions/common/wasm:wasm_lib", + ], +) + envoy_cc_binary( name = "context_speed_test", srcs = ["context_speed_test.cc"], diff --git a/extensions/common/context.cc b/extensions/common/context.cc index a283a6ed93c..6f2757b4b65 100644 --- a/extensions/common/context.cc +++ b/extensions/common/context.cc @@ -17,6 +17,7 @@ #include "absl/strings/str_cat.h" #include "absl/strings/str_split.h" +#include "extensions/common/util.h" #include "google/protobuf/util/json_util.h" // WASM_PROLOG @@ -225,6 +226,10 @@ void populateHTTPRequestInfo(bool outbound, RequestInfo* request_info) { &request_info->source_principal); } request_info->destination_port = destination_port; + + uint64_t response_flags; + getValue({"response", "flags"}, &response_flags); + request_info->response_flag = parseResponseFlag(response_flags); } google::protobuf::util::Status extractNodeMetadataValue( diff --git a/extensions/common/util.cc b/extensions/common/util.cc new file mode 100644 index 00000000000..8c3454bdd72 --- /dev/null +++ b/extensions/common/util.cc @@ -0,0 +1,162 @@ +/* Copyright 2019 Istio Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +namespace Wasm { +namespace Common { + +namespace { + +const std::string NONE = "-"; +const std::string DOWNSTREAM_CONNECTION_TERMINATION = "DC"; +const std::string FAILED_LOCAL_HEALTH_CHECK = "LH"; +const std::string NO_HEALTHY_UPSTREAM = "UH"; +const std::string UPSTREAM_REQUEST_TIMEOUT = "UT"; +const std::string LOCAL_RESET = "LR"; +const std::string UPSTREAM_REMOTE_RESET = "UR"; +const std::string UPSTREAM_CONNECTION_FAILURE = "UF"; +const std::string UPSTREAM_CONNECTION_TERMINATION = "UC"; +const std::string UPSTREAM_OVERFLOW = "UO"; +const std::string UPSTREAM_RETRY_LIMIT_EXCEEDED = "URX"; +const std::string NO_ROUTE_FOUND = "NR"; +const std::string DELAY_INJECTED = "DI"; +const std::string FAULT_INJECTED = "FI"; +const std::string RATE_LIMITED = "RL"; +const std::string UNAUTHORIZED_EXTERNAL_SERVICE = "UAEX"; +const std::string RATELIMIT_SERVICE_ERROR = "RLSE"; +const std::string STREAM_IDLE_TIMEOUT = "SI"; +const std::string INVALID_ENVOY_REQUEST_HEADERS = "IH"; +const std::string DOWNSTREAM_PROTOCOL_ERROR = "DPE"; + + +enum ResponseFlag { + FailedLocalHealthCheck = 0x1, + NoHealthyUpstream = 0x2, + UpstreamRequestTimeout = 0x4, + LocalReset = 0x8, + UpstreamRemoteReset = 0x10, + UpstreamConnectionFailure = 0x20, + UpstreamConnectionTermination = 0x40, + UpstreamOverflow = 0x80, + NoRouteFound = 0x100, + DelayInjected = 0x200, + FaultInjected = 0x400, + RateLimited = 0x800, + UnauthorizedExternalService = 0x1000, + RateLimitServiceError = 0x2000, + DownstreamConnectionTermination = 0x4000, + UpstreamRetryLimitExceeded = 0x8000, + StreamIdleTimeout = 0x10000, + InvalidEnvoyRequestHeaders = 0x20000, + DownstreamProtocolError = 0x40000, + LastFlag = DownstreamProtocolError +}; + + +void appendString(std::string& result, const std::string& append) { + if (result.empty()) { + result = append; + } else { + result += "," + append; + } +} + +} // namespace + +const std::string parseResponseFlag(uint64_t response_flag) { + std::string result; + + if (response_flag & FailedLocalHealthCheck) { + appendString(result, FAILED_LOCAL_HEALTH_CHECK); + } + + if (response_flag & NoHealthyUpstream) { + appendString(result, NO_HEALTHY_UPSTREAM); + } + + if (response_flag & UpstreamRequestTimeout) { + appendString(result, UPSTREAM_REQUEST_TIMEOUT); + } + + if (response_flag & LocalReset) { + appendString(result, LOCAL_RESET); + } + + if (response_flag & UpstreamRemoteReset) { + appendString(result, UPSTREAM_REMOTE_RESET); + } + + if (response_flag & UpstreamConnectionFailure) { + appendString(result, UPSTREAM_CONNECTION_FAILURE); + } + + if (response_flag & UpstreamConnectionTermination) { + appendString(result, UPSTREAM_CONNECTION_TERMINATION); + } + + if (response_flag & UpstreamOverflow) { + appendString(result, UPSTREAM_OVERFLOW); + } + + if (response_flag & NoRouteFound) { + appendString(result, NO_ROUTE_FOUND); + } + + if (response_flag & DelayInjected) { + appendString(result, DELAY_INJECTED); + } + + if (response_flag & FaultInjected) { + appendString(result, FAULT_INJECTED); + } + + if (response_flag & RateLimited) { + appendString(result, RATE_LIMITED); + } + + if (response_flag & UnauthorizedExternalService) { + appendString(result, UNAUTHORIZED_EXTERNAL_SERVICE); + } + + if (response_flag & RateLimitServiceError) { + appendString(result, RATELIMIT_SERVICE_ERROR); + } + + if (response_flag & DownstreamConnectionTermination) { + appendString(result, DOWNSTREAM_CONNECTION_TERMINATION); + } + + if (response_flag & UpstreamRetryLimitExceeded) { + appendString(result, UPSTREAM_RETRY_LIMIT_EXCEEDED); + } + + if (response_flag & StreamIdleTimeout) { + appendString(result, STREAM_IDLE_TIMEOUT); + } + + if (response_flag & InvalidEnvoyRequestHeaders) { + appendString(result, INVALID_ENVOY_REQUEST_HEADERS); + } + + if (response_flag & DownstreamProtocolError) { + appendString(result, DOWNSTREAM_PROTOCOL_ERROR); + } + + return result.empty() ? NONE : result; +} + +} // namespace Common +} // namespace Wasm diff --git a/extensions/common/util.h b/extensions/common/util.h new file mode 100644 index 00000000000..fd2773a6116 --- /dev/null +++ b/extensions/common/util.h @@ -0,0 +1,27 @@ +/* Copyright 2019 Istio Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +namespace Wasm { +namespace Common { + +// Parses an integer response flag into a readable short string. +const std::string parseResponseFlag(uint64_t response_flag); + +} // namespace Common +} // namespace Wasm diff --git a/extensions/common/util_test.cc b/extensions/common/util_test.cc new file mode 100644 index 00000000000..7caa40e68c9 --- /dev/null +++ b/extensions/common/util_test.cc @@ -0,0 +1,50 @@ +#include "extensions/common/util.h" + +#include "gtest/gtest.h" + +namespace Wasm { +namespace Common { +namespace { + +TEST(WasmCommonUtilsTest, ParseResponseFlag) { + std::vector> expected = { + std::make_pair(0x1, "LH"), + std::make_pair(0x2, "UH"), + std::make_pair(0x4, "UT"), + std::make_pair(0x8, "LR"), + std::make_pair(0x10, "UR"), + std::make_pair(0x20, "UF"), + std::make_pair(0x40, "UC"), + std::make_pair(0x80, "UO"), + std::make_pair(0x100, "NR"), + std::make_pair(0x200, "DI"), + std::make_pair(0x400, "FI"), + std::make_pair(0x800, "RL"), + std::make_pair(0x1000, "UAEX"), + std::make_pair(0x2000, "RLSE"), + std::make_pair(0x4000, "DC"), + std::make_pair(0x8000, "URX"), + std::make_pair(0x10000, "SI"), + std::make_pair(0x20000, "IH"), + std::make_pair(0x40000, "DPE"), + }; + + for (const auto& test_case : expected) { + EXPECT_EQ(test_case.second, parseResponseFlag(test_case.first)); + } + + // No flag is set. + { + EXPECT_EQ("-", parseResponseFlag(0x0)); + } + + // Test combinations. + // These are not real use cases, but are used to cover multiple response flags case. + { + EXPECT_EQ("UT,DI,FI", parseResponseFlag(0x604)); + } +} + +} // namespace +} // namespace Common +} // namespace Wasm From 15cd0e5b264534770de329826b11ad3f5a0ea3c9 Mon Sep 17 00:00:00 2001 From: Pengyuan Bian Date: Tue, 5 Nov 2019 17:24:58 -0800 Subject: [PATCH 2/5] update stats plugin --- extensions/stats/plugin.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/extensions/stats/plugin.h b/extensions/stats/plugin.h index e8b341995dd..4fcf4bcc52e 100644 --- a/extensions/stats/plugin.h +++ b/extensions/stats/plugin.h @@ -185,8 +185,7 @@ struct IstioDimensions { request_protocol = request.request_protocol; response_code = std::to_string(request.response_code); - response_flags = - request.response_flag.empty() ? vDash : request.response_flag; + response_flags = request.response_flag; connection_security_policy = std::string(::Wasm::Common::AuthenticationPolicyString( From 7e4f863a797804d61acd02375343b5915198c1ee Mon Sep 17 00:00:00 2001 From: Pengyuan Bian Date: Tue, 5 Nov 2019 17:41:30 -0800 Subject: [PATCH 3/5] comment and format --- extensions/common/util.cc | 6 ++++-- extensions/common/util_test.cc | 38 ++++++++++++---------------------- 2 files changed, 17 insertions(+), 27 deletions(-) diff --git a/extensions/common/util.cc b/extensions/common/util.cc index 8c3454bdd72..b1c03284f53 100644 --- a/extensions/common/util.cc +++ b/extensions/common/util.cc @@ -20,6 +20,10 @@ namespace Common { namespace { +// This replicates the flag lists in envoyproxy/envoy, because the property +// access API does not support returning response flags as a short string since +// it is not owned by any object and always generated on demand: +// https://github.com/envoyproxy/envoy/blob/v1.12.0/source/common/stream_info/utility.cc#L8 const std::string NONE = "-"; const std::string DOWNSTREAM_CONNECTION_TERMINATION = "DC"; const std::string FAILED_LOCAL_HEALTH_CHECK = "LH"; @@ -41,7 +45,6 @@ const std::string STREAM_IDLE_TIMEOUT = "SI"; const std::string INVALID_ENVOY_REQUEST_HEADERS = "IH"; const std::string DOWNSTREAM_PROTOCOL_ERROR = "DPE"; - enum ResponseFlag { FailedLocalHealthCheck = 0x1, NoHealthyUpstream = 0x2, @@ -65,7 +68,6 @@ enum ResponseFlag { LastFlag = DownstreamProtocolError }; - void appendString(std::string& result, const std::string& append) { if (result.empty()) { result = append; diff --git a/extensions/common/util_test.cc b/extensions/common/util_test.cc index 7caa40e68c9..3459dc129bc 100644 --- a/extensions/common/util_test.cc +++ b/extensions/common/util_test.cc @@ -8,24 +8,15 @@ namespace { TEST(WasmCommonUtilsTest, ParseResponseFlag) { std::vector> expected = { - std::make_pair(0x1, "LH"), - std::make_pair(0x2, "UH"), - std::make_pair(0x4, "UT"), - std::make_pair(0x8, "LR"), - std::make_pair(0x10, "UR"), - std::make_pair(0x20, "UF"), - std::make_pair(0x40, "UC"), - std::make_pair(0x80, "UO"), - std::make_pair(0x100, "NR"), - std::make_pair(0x200, "DI"), - std::make_pair(0x400, "FI"), - std::make_pair(0x800, "RL"), - std::make_pair(0x1000, "UAEX"), - std::make_pair(0x2000, "RLSE"), - std::make_pair(0x4000, "DC"), - std::make_pair(0x8000, "URX"), - std::make_pair(0x10000, "SI"), - std::make_pair(0x20000, "IH"), + std::make_pair(0x1, "LH"), std::make_pair(0x2, "UH"), + std::make_pair(0x4, "UT"), std::make_pair(0x8, "LR"), + std::make_pair(0x10, "UR"), std::make_pair(0x20, "UF"), + std::make_pair(0x40, "UC"), std::make_pair(0x80, "UO"), + std::make_pair(0x100, "NR"), std::make_pair(0x200, "DI"), + std::make_pair(0x400, "FI"), std::make_pair(0x800, "RL"), + std::make_pair(0x1000, "UAEX"), std::make_pair(0x2000, "RLSE"), + std::make_pair(0x4000, "DC"), std::make_pair(0x8000, "URX"), + std::make_pair(0x10000, "SI"), std::make_pair(0x20000, "IH"), std::make_pair(0x40000, "DPE"), }; @@ -34,15 +25,12 @@ TEST(WasmCommonUtilsTest, ParseResponseFlag) { } // No flag is set. - { - EXPECT_EQ("-", parseResponseFlag(0x0)); - } + { EXPECT_EQ("-", parseResponseFlag(0x0)); } // Test combinations. - // These are not real use cases, but are used to cover multiple response flags case. - { - EXPECT_EQ("UT,DI,FI", parseResponseFlag(0x604)); - } + // These are not real use cases, but are used to cover multiple response flags + // case. + { EXPECT_EQ("UT,DI,FI", parseResponseFlag(0x604)); } } } // namespace From ccdb405425636c854d677842a8d481964ec2b843 Mon Sep 17 00:00:00 2001 From: Pengyuan Bian Date: Wed, 6 Nov 2019 09:20:43 -0800 Subject: [PATCH 4/5] response flag --- extensions/common/context.cc | 2 +- extensions/common/util.cc | 6 ++++++ extensions/common/util_test.cc | 3 +++ .../stackdriver/server_access_log.yaml.tmpl | 20 +++++++++---------- 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/extensions/common/context.cc b/extensions/common/context.cc index 6f2757b4b65..1b1c338c50a 100644 --- a/extensions/common/context.cc +++ b/extensions/common/context.cc @@ -227,7 +227,7 @@ void populateHTTPRequestInfo(bool outbound, RequestInfo* request_info) { } request_info->destination_port = destination_port; - uint64_t response_flags; + uint64_t response_flags = 0; getValue({"response", "flags"}, &response_flags); request_info->response_flag = parseResponseFlag(response_flags); } diff --git a/extensions/common/util.cc b/extensions/common/util.cc index b1c03284f53..b5f7eaa5ace 100644 --- a/extensions/common/util.cc +++ b/extensions/common/util.cc @@ -157,6 +157,12 @@ const std::string parseResponseFlag(uint64_t response_flag) { appendString(result, DOWNSTREAM_PROTOCOL_ERROR); } + if (response_flag >= (LastFlag << 1)) { + // Response flag integer overflows. Append the integer to avoid information + // loss. + appendString(result, std::to_string(response_flag)); + } + return result.empty() ? NONE : result; } diff --git a/extensions/common/util_test.cc b/extensions/common/util_test.cc index 3459dc129bc..fd19a7406cc 100644 --- a/extensions/common/util_test.cc +++ b/extensions/common/util_test.cc @@ -31,6 +31,9 @@ TEST(WasmCommonUtilsTest, ParseResponseFlag) { // These are not real use cases, but are used to cover multiple response flags // case. { EXPECT_EQ("UT,DI,FI", parseResponseFlag(0x604)); } + + // Test overflow. + { EXPECT_EQ("DPE,786432", parseResponseFlag(0xC0000)); } } } // namespace diff --git a/testdata/stackdriver/server_access_log.yaml.tmpl b/testdata/stackdriver/server_access_log.yaml.tmpl index 158ef2dd613..6326ea7d33e 100644 --- a/testdata/stackdriver/server_access_log.yaml.tmpl +++ b/testdata/stackdriver/server_access_log.yaml.tmpl @@ -4,7 +4,7 @@ entries: destination_service_host: server.default.svc.cluster.local protocol: http request_operation: GET - response_flag: "" + response_flag: "-" service_authentication_policy: {{ .Vars.ServiceAuthenticationPolicy }} source_name: productpage-v1-84975bc778-pxz2w source_namespace: default @@ -16,7 +16,7 @@ entries: destination_service_host: server.default.svc.cluster.local protocol: http request_operation: GET - response_flag: "" + response_flag: "-" service_authentication_policy: {{ .Vars.ServiceAuthenticationPolicy }} source_name: productpage-v1-84975bc778-pxz2w source_namespace: default @@ -28,7 +28,7 @@ entries: destination_service_host: server.default.svc.cluster.local protocol: http request_operation: GET - response_flag: "" + response_flag: "-" service_authentication_policy: {{ .Vars.ServiceAuthenticationPolicy }} source_name: productpage-v1-84975bc778-pxz2w source_namespace: default @@ -40,7 +40,7 @@ entries: destination_service_host: server.default.svc.cluster.local protocol: http request_operation: GET - response_flag: "" + response_flag: "-" service_authentication_policy: {{ .Vars.ServiceAuthenticationPolicy }} source_name: productpage-v1-84975bc778-pxz2w source_namespace: default @@ -52,7 +52,7 @@ entries: destination_service_host: server.default.svc.cluster.local protocol: http request_operation: GET - response_flag: "" + response_flag: "-" service_authentication_policy: {{ .Vars.ServiceAuthenticationPolicy }} source_name: productpage-v1-84975bc778-pxz2w source_namespace: default @@ -64,7 +64,7 @@ entries: destination_service_host: server.default.svc.cluster.local protocol: http request_operation: GET - response_flag: "" + response_flag: "-" service_authentication_policy: {{ .Vars.ServiceAuthenticationPolicy }} source_name: productpage-v1-84975bc778-pxz2w source_namespace: default @@ -76,7 +76,7 @@ entries: destination_service_host: server.default.svc.cluster.local protocol: http request_operation: GET - response_flag: "" + response_flag: "-" service_authentication_policy: {{ .Vars.ServiceAuthenticationPolicy }} source_name: productpage-v1-84975bc778-pxz2w source_namespace: default @@ -88,7 +88,7 @@ entries: destination_service_host: server.default.svc.cluster.local protocol: http request_operation: GET - response_flag: "" + response_flag: "-" service_authentication_policy: {{ .Vars.ServiceAuthenticationPolicy }} source_name: productpage-v1-84975bc778-pxz2w source_namespace: default @@ -100,7 +100,7 @@ entries: destination_service_host: server.default.svc.cluster.local protocol: http request_operation: GET - response_flag: "" + response_flag: "-" service_authentication_policy: {{ .Vars.ServiceAuthenticationPolicy }} source_name: productpage-v1-84975bc778-pxz2w source_namespace: default @@ -112,7 +112,7 @@ entries: destination_service_host: server.default.svc.cluster.local protocol: http request_operation: GET - response_flag: "" + response_flag: "-" service_authentication_policy: {{ .Vars.ServiceAuthenticationPolicy }} source_name: productpage-v1-84975bc778-pxz2w source_namespace: default From fca27dc532dd1ac9b79cd1fbb606bc24bc526e13 Mon Sep 17 00:00:00 2001 From: Pengyuan Bian Date: Wed, 6 Nov 2019 09:30:16 -0800 Subject: [PATCH 5/5] license --- extensions/common/util_test.cc | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/extensions/common/util_test.cc b/extensions/common/util_test.cc index fd19a7406cc..bdf124c8a26 100644 --- a/extensions/common/util_test.cc +++ b/extensions/common/util_test.cc @@ -1,3 +1,18 @@ +/* Copyright 2019 Istio Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #include "extensions/common/util.h" #include "gtest/gtest.h"