Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
c0e451b
access_log: Added new command operator %VIRTUAL_CLUSTER_NAME% to retr…
agrawroh Nov 9, 2021
338e117
Fixed Tests
agrawroh Nov 9, 2021
2afee97
Merge branch 'main' into add-vc-name-to-access-logs
agrawroh Nov 10, 2021
6aa15e8
Fixed Formatter Test
agrawroh Nov 10, 2021
ef45a22
Merge branch 'main' of github.com:envoyproxy/envoy into add-vc-name-t…
agrawroh Nov 15, 2021
2037455
Addressed Comments From @lambdai
agrawroh Nov 15, 2021
70e6cdf
Merge branch 'main' into add-vc-name-to-access-logs
agrawroh Nov 16, 2021
6735c98
Resolved Merge Conflicts
agrawroh Nov 16, 2021
258a0ff
Merge branch 'main' of github.com:envoyproxy/envoy into add-vc-name-t…
agrawroh Nov 17, 2021
d7d782c
Addressed Comments From @jmarantz
agrawroh Nov 17, 2021
18b19f0
Remove Unwanted Fields
agrawroh Nov 17, 2021
1d01999
Merge branch 'main' of github.com:envoyproxy/envoy into add-vc-name-t…
agrawroh Nov 17, 2021
67e84df
Merge branch 'main' of github.com:envoyproxy/envoy into add-vc-name-t…
agrawroh Nov 18, 2021
6a47aff
Merge branch 'main' of github.com:envoyproxy/envoy into add-vc-name-t…
agrawroh Nov 18, 2021
73bb998
Addressed Comments From @jmarantz
agrawroh Nov 18, 2021
341aaf7
Merge branch 'main' of github.com:envoyproxy/envoy into add-vc-name-t…
agrawroh Nov 18, 2021
fb141c1
Merge branch 'main' of github.com:envoyproxy/envoy into add-vc-name-t…
agrawroh Nov 19, 2021
073fdb6
Addressed Comments From @jmarantz
agrawroh Nov 19, 2021
a3342e7
Merge branch 'main' of github.com:envoyproxy/envoy into add-vc-name-t…
agrawroh Nov 20, 2021
d4eb829
Fix Syntax
agrawroh Nov 20, 2021
0dee63c
Addressed Comments From @jmarantz
agrawroh Nov 21, 2021
ad17748
Merge branch 'main' of github.com:envoyproxy/envoy into add-vc-name-t…
agrawroh Nov 29, 2021
325cf76
Addressed Comments From @zuercher
agrawroh Nov 29, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions docs/root/configuration/observability/access_log/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,13 @@ The following command operators are supported:
%ROUTE_NAME%
Name of the route.

%VIRTUAL_CLUSTER_NAME%
HTTP*/gRPC
Name of the matched Virtual Cluster (if any).

TCP/UDP
Not implemented ("-")

%UPSTREAM_HOST%
Upstream host URL (e.g., tcp://ip:port for TCP connections).

Expand Down
1 change: 1 addition & 0 deletions docs/root/version_history/current.rst
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ Removed Config or Runtime
New Features
------------
* access log: added :ref:`grpc_stream_retry_policy <envoy_v3_api_field_extensions.access_loggers.grpc.v3.CommonGrpcAccessLogConfig.grpc_stream_retry_policy>` to the gRPC logger to reconnect when a connection fails to be established.
* access_log: added new access_log command operator ``%VIRTUAL_CLUSTER_NAME%`` to retrieve the matched Virtual Cluster name.
* api: added support for *xds.type.v3.TypedStruct* in addition to the now-deprecated *udpa.type.v1.TypedStruct* proto message, which is a wrapper proto used to encode typed JSON data in a *google.protobuf.Any* field.
* aws_request_signing_filter: added :ref:`match_excluded_headers <envoy_v3_api_field_extensions.filters.http.aws_request_signing.v3.AwsRequestSigning.match_excluded_headers>` to the signing filter to optionally exclude request headers from signing.
* bootstrap: added :ref:`typed_dns_resolver_config <envoy_v3_api_field_config.bootstrap.v3.Bootstrap.typed_dns_resolver_config>` in the bootstrap to support DNS resolver as an extension.
Expand Down
5 changes: 5 additions & 0 deletions envoy/router/router.h
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,11 @@ class VirtualCluster {
public:
virtual ~VirtualCluster() = default;

/**
* @return the string name of the virtual cluster.
*/
virtual const absl::optional<std::string>& name() const PURE;

/**
* @return the stat-name of the virtual cluster.
*/
Expand Down
10 changes: 10 additions & 0 deletions envoy/stream_info/stream_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,16 @@ class StreamInfo {
*/
virtual const std::string& getRouteName() const PURE;

/**
* @param std::string name denotes the name of the virtual cluster.
*/
virtual void setVirtualClusterName(const absl::optional<std::string>& name) PURE;

/**
* @return std::string& the name of the virtual cluster which got matched.
*/
virtual const absl::optional<std::string>& virtualClusterName() const PURE;

/**
* @param bytes_received denotes number of bytes to add to total received bytes.
*/
Expand Down
6 changes: 6 additions & 0 deletions source/common/formatter/substitution_formatter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,7 @@ class StreamInfoSslConnectionInfoFieldExtractor : public StreamInfoFormatter::Fi
};

StreamInfoFormatter::StreamInfoFormatter(const std::string& field_name) {
// TODO: Change this huge if-else ladder to use a switch case instead.
if (field_name == "REQUEST_DURATION") {
field_extractor_ = std::make_unique<StreamInfoDurationFieldExtractor>(
[](const StreamInfo::StreamInfo& stream_info) {
Expand Down Expand Up @@ -953,6 +954,11 @@ StreamInfoFormatter::StreamInfoFormatter(const std::string& field_name) {
}
return absl::nullopt;
});
} else if (field_name == "VIRTUAL_CLUSTER_NAME") {
field_extractor_ = std::make_unique<StreamInfoStringFieldExtractor>(
[](const StreamInfo::StreamInfo& stream_info) -> absl::optional<std::string> {
return stream_info.virtualClusterName();
});
} else if (field_name == "TLS_JA3_FINGERPRINT") {
field_extractor_ = std::make_unique<StreamInfoStringFieldExtractor>(
[](const StreamInfo::StreamInfo& stream_info) {
Expand Down
2 changes: 1 addition & 1 deletion source/common/router/config_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1430,7 +1430,7 @@ VirtualHostImpl::VirtualClusterEntry::VirtualClusterEntry(
const envoy::config::route::v3::VirtualCluster& virtual_cluster, Stats::Scope& scope,
const VirtualClusterStatNames& stat_names)
: StatNameProvider(virtual_cluster.name(), scope.symbolTable()),
VirtualClusterBase(stat_name_storage_.statName(),
VirtualClusterBase(virtual_cluster.name(), stat_name_storage_.statName(),
scope.scopeFromStatName(stat_name_storage_.statName()), stat_names) {
if (virtual_cluster.headers().empty()) {
throw EnvoyException("virtual clusters must define 'headers'");
Expand Down
14 changes: 9 additions & 5 deletions source/common/router/config_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -236,16 +236,20 @@ class VirtualHostImpl : public VirtualHost, Logger::Loggable<Logger::Id::router>

struct VirtualClusterBase : public VirtualCluster {
public:
VirtualClusterBase(Stats::StatName stat_name, Stats::ScopePtr&& scope,
const VirtualClusterStatNames& stat_names)
: stat_name_(stat_name), scope_(std::move(scope)),
VirtualClusterBase(const absl::optional<std::string>& name, Stats::StatName stat_name,
Stats::ScopePtr&& scope, const VirtualClusterStatNames& stat_names)
: name_(name), stat_name_(stat_name), scope_(std::move(scope)),
stats_(generateStats(*scope_, stat_names)) {}

// Router::VirtualCluster
// name_ and stat_name_ are two different representations for the same string, retained in
// memory to avoid symbol-table locks that would be needed when converting on-the-fly.
const absl::optional<std::string>& name() const override { return name_; }
Stats::StatName statName() const override { return stat_name_; }
VirtualClusterStats& stats() const override { return stats_; }

private:
const absl::optional<std::string> name_;
const Stats::StatName stat_name_;
Stats::ScopePtr scope_;
mutable VirtualClusterStats stats_;
Expand All @@ -259,8 +263,8 @@ class VirtualHostImpl : public VirtualHost, Logger::Loggable<Logger::Id::router>

struct CatchAllVirtualCluster : public VirtualClusterBase {
CatchAllVirtualCluster(Stats::Scope& scope, const VirtualClusterStatNames& stat_names)
: VirtualClusterBase(stat_names.other_, scope.scopeFromStatName(stat_names.other_),
stat_names) {}
: VirtualClusterBase(absl::nullopt, stat_names.other_,
scope.scopeFromStatName(stat_names.other_), stat_names) {}
};

static const std::shared_ptr<const SslRedirectRoute> SSL_REDIRECT_ROUTE;
Expand Down
3 changes: 3 additions & 0 deletions source/common/router/router.cc
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,9 @@ Http::FilterHeadersStatus Filter::decodeHeaders(Http::RequestHeaderMap& headers,

// Set up stat prefixes, etc.
request_vcluster_ = route_entry_->virtualCluster(headers);
if (request_vcluster_ != nullptr) {
callbacks_->streamInfo().setVirtualClusterName(request_vcluster_->name());
}
ENVOY_STREAM_LOG(debug, "cluster '{}' match for URL '{}'", *callbacks_,
route_entry_->clusterName(), headers.getPathValue());

Expand Down
11 changes: 11 additions & 0 deletions source/common/stream_info/stream_info_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,14 @@ struct StreamInfoImpl : public StreamInfo {

const std::string& getRouteName() const override { return route_name_; }

void setVirtualClusterName(const absl::optional<std::string>& virtual_cluster_name) override {
virtual_cluster_name_ = virtual_cluster_name;
}

const absl::optional<std::string>& virtualClusterName() const override {
return virtual_cluster_name_;
}

void setUpstreamLocalAddress(
const Network::Address::InstanceConstSharedPtr& upstream_local_address) override {
maybeCreateUpstreamInfo();
Expand Down Expand Up @@ -443,6 +451,9 @@ struct StreamInfoImpl : public StreamInfo {
FilterStateSharedPtr legacy_upstream_filter_state_;
std::string route_name_;
absl::optional<uint32_t> attempt_count_;
// TODO(agrawroh): Check if the owner of this storage outlives the StreamInfo. We should only copy
// the string if it could outlive the StreamInfo.
absl::optional<std::string> virtual_cluster_name_;

private:
static Network::ConnectionInfoProviderSharedPtr emptyDownstreamAddressProvider() {
Expand Down
16 changes: 16 additions & 0 deletions test/common/formatter/substitution_formatter_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -752,6 +752,22 @@ TEST(SubstitutionFormatterTest, streamInfoFormatterWithSsl) {
Http::TestResponseTrailerMapImpl response_trailers;
std::string body;

{
NiceMock<StreamInfo::MockStreamInfo> stream_info;
StreamInfoFormatter upstream_format("VIRTUAL_CLUSTER_NAME");
std::string virtual_cluster_name = "authN";
stream_info.setVirtualClusterName(virtual_cluster_name);
EXPECT_EQ("authN", upstream_format.format(request_headers, response_headers, response_trailers,
stream_info, body));
}

{
NiceMock<StreamInfo::MockStreamInfo> stream_info;
StreamInfoFormatter upstream_format("VIRTUAL_CLUSTER_NAME");
EXPECT_EQ(absl::nullopt, upstream_format.format(request_headers, response_headers,
response_trailers, stream_info, body));
}

{
// Use a local stream info for these tests as as setSslConnection can only be called once.
NiceMock<StreamInfo::MockStreamInfo> stream_info;
Expand Down
6 changes: 6 additions & 0 deletions test/common/router/router_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5912,6 +5912,9 @@ TEST_F(RouterTest, CanaryStatusTrue) {
Http::TestRequestHeaderMapImpl headers{{"x-envoy-upstream-alt-stat-name", "alt_stat"},
{"x-envoy-internal", "true"}};
HttpTestUtility::addDefaultHeaders(headers);
const absl::optional<std::string> virtual_cluster_name =
absl::optional<std::string>("fake_virtual_cluster");
EXPECT_CALL(callbacks_.stream_info_, setVirtualClusterName(virtual_cluster_name));
router_.decodeHeaders(headers, true);
EXPECT_EQ(1U,
callbacks_.route_->route_entry_.virtual_cluster_.stats().upstream_rq_total_.value());
Expand Down Expand Up @@ -5949,6 +5952,9 @@ TEST_F(RouterTest, CanaryStatusFalse) {
Http::TestRequestHeaderMapImpl headers{{"x-envoy-upstream-alt-stat-name", "alt_stat"},
{"x-envoy-internal", "true"}};
HttpTestUtility::addDefaultHeaders(headers);
const absl::optional<std::string> virtual_cluster_name =
absl::optional<std::string>("fake_virtual_cluster");
EXPECT_CALL(callbacks_.stream_info_, setVirtualClusterName(virtual_cluster_name));
router_.decodeHeaders(headers, true);
EXPECT_EQ(1U,
callbacks_.route_->route_entry_.virtual_cluster_.stats().upstream_rq_total_.value());
Expand Down
5 changes: 5 additions & 0 deletions test/common/stream_info/test_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ class TestStreamInfo : public StreamInfo::StreamInfoImpl {
return *downstream_connection_info_provider_;
}

const absl::optional<std::string>& virtualClusterName() const override {
return virtual_cluster_name_;
}

void onRequestComplete() override { end_time_ = timeSystem().monotonicTime(); }

absl::optional<std::chrono::nanoseconds> requestComplete() const override {
Expand All @@ -54,6 +58,7 @@ class TestStreamInfo : public StreamInfo::StreamInfoImpl {
SystemTime start_time_;
MonotonicTime start_time_monotonic_;
absl::optional<MonotonicTime> end_time_;
absl::optional<std::string> virtual_cluster_name_;
Network::ConnectionInfoSetterSharedPtr downstream_connection_info_provider_{
std::make_shared<Network::ConnectionInfoSetterImpl>(nullptr, nullptr)};
Envoy::Event::SimulatedTimeSystem test_time_;
Expand Down
2 changes: 2 additions & 0 deletions test/mocks/router/mocks.h
Original file line number Diff line number Diff line change
Expand Up @@ -263,9 +263,11 @@ class MockShadowWriter : public ShadowWriter {
class TestVirtualCluster : public VirtualCluster {
public:
// Router::VirtualCluster
const absl::optional<std::string>& name() const override { return name_; }
Stats::StatName statName() const override { return stat_name_.statName(); }
VirtualClusterStats& stats() const override { return stats_; }

const absl::optional<std::string> name_ = "fake_virtual_cluster";
Stats::TestUtil::TestSymbolTable symbol_table_;
Stats::StatNameManagedStorage stat_name_{"fake_virtual_cluster", *symbol_table_};
Stats::IsolatedStoreImpl stats_store_;
Expand Down
5 changes: 5 additions & 0 deletions test/mocks/stream_info/mocks.cc
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,12 @@ MockStreamInfo::MockStreamInfo()
ON_CALL(*this, setRouteName(_)).WillByDefault(Invoke([this](const absl::string_view route_name) {
route_name_ = std::string(route_name);
}));
ON_CALL(*this, setVirtualClusterName(_))
.WillByDefault(Invoke([this](const absl::optional<std::string>& virtual_cluster_name) {
virtual_cluster_name_ = virtual_cluster_name;
}));
ON_CALL(*this, getRouteName()).WillByDefault(ReturnRef(route_name_));
ON_CALL(*this, virtualClusterName()).WillByDefault(ReturnRef(virtual_cluster_name_));
ON_CALL(*this, upstreamTransportFailureReason())
.WillByDefault(ReturnRef(upstream_transport_failure_reason_));
ON_CALL(*this, setConnectionID(_)).WillByDefault(Invoke([this](uint64_t id) {
Expand Down
4 changes: 4 additions & 0 deletions test/mocks/stream_info/mocks.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,10 @@ class MockStreamInfo : public StreamInfo {
MOCK_METHOD(void, addWireBytesReceived, (uint64_t));
MOCK_METHOD(uint64_t, wireBytesReceived, (), (const));
MOCK_METHOD(void, setRouteName, (absl::string_view route_name));
MOCK_METHOD(void, setVirtualClusterName,
(const absl::optional<std::string>& virtual_cluster_name));
MOCK_METHOD(const std::string&, getRouteName, (), (const));
MOCK_METHOD(const absl::optional<std::string>&, virtualClusterName, (), (const));
MOCK_METHOD(absl::optional<Http::Protocol>, protocol, (), (const));
MOCK_METHOD(void, protocol, (Http::Protocol protocol));
MOCK_METHOD(absl::optional<uint32_t>, responseCode, (), (const));
Expand Down Expand Up @@ -145,6 +148,7 @@ class MockStreamInfo : public StreamInfo {
std::string filter_chain_name_;
absl::optional<uint64_t> upstream_connection_id_;
absl::optional<uint32_t> attempt_count_;
absl::optional<std::string> virtual_cluster_name_;
DownstreamTiming downstream_timing_;
};

Expand Down