#pragma once #include #include #include "envoy/common/time.h" #include "envoy/config/core/v3/base.pb.h" #include "envoy/http/header_map.h" #include "envoy/http/request_id_extension.h" #include "envoy/stream_info/stream_info.h" #include "common/common/assert.h" #include "common/common/dump_state_utils.h" #include "common/http/request_id_extension_impl.h" #include "common/stream_info/filter_state_impl.h" #include "absl/strings/str_replace.h" namespace Envoy { namespace StreamInfo { namespace { using ReplacementMap = absl::flat_hash_map; const ReplacementMap& emptySpaceReplacement() { CONSTRUCT_ON_FIRST_USE( ReplacementMap, ReplacementMap{{" ", "_"}, {"\t", "_"}, {"\f", "_"}, {"\v", "_"}, {"\n", "_"}, {"\r", "_"}}); } } // namespace struct StreamInfoImpl : public StreamInfo { StreamInfoImpl(TimeSource& time_source, FilterState::LifeSpan life_span = FilterState::LifeSpan::FilterChain) : StreamInfoImpl(absl::nullopt, time_source, std::make_shared(life_span)) {} StreamInfoImpl(Http::Protocol protocol, TimeSource& time_source) : StreamInfoImpl(protocol, time_source, std::make_shared(FilterState::LifeSpan::FilterChain)) {} StreamInfoImpl(Http::Protocol protocol, TimeSource& time_source, FilterStateSharedPtr parent_filter_state, FilterState::LifeSpan life_span) : StreamInfoImpl( protocol, time_source, std::make_shared( FilterStateImpl::LazyCreateAncestor(std::move(parent_filter_state), life_span), FilterState::LifeSpan::FilterChain)) {} SystemTime startTime() const override { return start_time_; } MonotonicTime startTimeMonotonic() const override { return start_time_monotonic_; } absl::optional duration(absl::optional time) const { if (!time) { return {}; } return std::chrono::duration_cast(time.value() - start_time_monotonic_); } absl::optional lastDownstreamRxByteReceived() const override { return duration(last_downstream_rx_byte_received); } void onLastDownstreamRxByteReceived() override { ASSERT(!last_downstream_rx_byte_received); last_downstream_rx_byte_received = time_source_.monotonicTime(); } void setUpstreamTiming(const UpstreamTiming& upstream_timing) override { upstream_timing_ = upstream_timing; } absl::optional firstUpstreamTxByteSent() const override { return duration(upstream_timing_.first_upstream_tx_byte_sent_); } absl::optional lastUpstreamTxByteSent() const override { return duration(upstream_timing_.last_upstream_tx_byte_sent_); } absl::optional firstUpstreamRxByteReceived() const override { return duration(upstream_timing_.first_upstream_rx_byte_received_); } absl::optional lastUpstreamRxByteReceived() const override { return duration(upstream_timing_.last_upstream_rx_byte_received_); } absl::optional firstDownstreamTxByteSent() const override { return duration(first_downstream_tx_byte_sent_); } void onFirstDownstreamTxByteSent() override { ASSERT(!first_downstream_tx_byte_sent_); first_downstream_tx_byte_sent_ = time_source_.monotonicTime(); } absl::optional lastDownstreamTxByteSent() const override { return duration(last_downstream_tx_byte_sent_); } void onLastDownstreamTxByteSent() override { ASSERT(!last_downstream_tx_byte_sent_); last_downstream_tx_byte_sent_ = time_source_.monotonicTime(); } absl::optional requestComplete() const override { return duration(final_time_); } void onRequestComplete() override { ASSERT(!final_time_); final_time_ = time_source_.monotonicTime(); } void addBytesReceived(uint64_t bytes_received) override { bytes_received_ += bytes_received; } uint64_t bytesReceived() const override { return bytes_received_; } absl::optional protocol() const override { return protocol_; } void protocol(Http::Protocol protocol) override { protocol_ = protocol; } absl::optional responseCode() const override { return response_code_; } const absl::optional& responseCodeDetails() const override { return response_code_details_; } void setResponseCodeDetails(absl::string_view rc_details) override { response_code_details_.emplace(absl::StrReplaceAll(rc_details, emptySpaceReplacement())); } const absl::optional& connectionTerminationDetails() const override { return connection_termination_details_; } void setConnectionTerminationDetails(absl::string_view connection_termination_details) override { connection_termination_details_.emplace(connection_termination_details); } void addBytesSent(uint64_t bytes_sent) override { bytes_sent_ += bytes_sent; } uint64_t bytesSent() const override { return bytes_sent_; } void setResponseFlag(ResponseFlag response_flag) override { response_flags_ |= response_flag; } bool intersectResponseFlags(uint64_t response_flags) const override { return (response_flags_ & response_flags) != 0; } bool hasResponseFlag(ResponseFlag flag) const override { return response_flags_ & flag; } bool hasAnyResponseFlag() const override { return response_flags_ != 0; } uint64_t responseFlags() const override { return response_flags_; } void onUpstreamHostSelected(Upstream::HostDescriptionConstSharedPtr host) override { upstream_host_ = host; } Upstream::HostDescriptionConstSharedPtr upstreamHost() const override { return upstream_host_; } void setRouteName(absl::string_view route_name) override { route_name_ = std::string(route_name); } const std::string& getRouteName() const override { return route_name_; } void setUpstreamLocalAddress( const Network::Address::InstanceConstSharedPtr& upstream_local_address) override { upstream_local_address_ = upstream_local_address; } const Network::Address::InstanceConstSharedPtr& upstreamLocalAddress() const override { return upstream_local_address_; } bool healthCheck() const override { return health_check_request_; } void healthCheck(bool is_health_check) override { health_check_request_ = is_health_check; } void setDownstreamLocalAddress( const Network::Address::InstanceConstSharedPtr& downstream_local_address) override { downstream_local_address_ = downstream_local_address; } const Network::Address::InstanceConstSharedPtr& downstreamLocalAddress() const override { return downstream_local_address_; } void setDownstreamDirectRemoteAddress( const Network::Address::InstanceConstSharedPtr& downstream_direct_remote_address) override { downstream_direct_remote_address_ = downstream_direct_remote_address; } const Network::Address::InstanceConstSharedPtr& downstreamDirectRemoteAddress() const override { return downstream_direct_remote_address_; } void setDownstreamRemoteAddress( const Network::Address::InstanceConstSharedPtr& downstream_remote_address) override { downstream_remote_address_ = downstream_remote_address; } const Network::Address::InstanceConstSharedPtr& downstreamRemoteAddress() const override { return downstream_remote_address_; } void setDownstreamSslConnection(const Ssl::ConnectionInfoConstSharedPtr& connection_info) override { downstream_ssl_info_ = connection_info; } Ssl::ConnectionInfoConstSharedPtr downstreamSslConnection() const override { return downstream_ssl_info_; } void setUpstreamSslConnection(const Ssl::ConnectionInfoConstSharedPtr& connection_info) override { upstream_ssl_info_ = connection_info; } Ssl::ConnectionInfoConstSharedPtr upstreamSslConnection() const override { return upstream_ssl_info_; } const Router::RouteEntry* routeEntry() const override { return route_entry_; } envoy::config::core::v3::Metadata& dynamicMetadata() override { return metadata_; }; const envoy::config::core::v3::Metadata& dynamicMetadata() const override { return metadata_; }; void setDynamicMetadata(const std::string& name, const ProtobufWkt::Struct& value) override { (*metadata_.mutable_filter_metadata())[name].MergeFrom(value); }; const FilterStateSharedPtr& filterState() override { return filter_state_; } const FilterState& filterState() const override { return *filter_state_; } const FilterStateSharedPtr& upstreamFilterState() const override { return upstream_filter_state_; } void setUpstreamFilterState(const FilterStateSharedPtr& filter_state) override { upstream_filter_state_ = filter_state; } void setRequestedServerName(absl::string_view requested_server_name) override { requested_server_name_ = std::string(requested_server_name); } const std::string& requestedServerName() const override { return requested_server_name_; } void setUpstreamTransportFailureReason(absl::string_view failure_reason) override { upstream_transport_failure_reason_ = std::string(failure_reason); } const std::string& upstreamTransportFailureReason() const override { return upstream_transport_failure_reason_; } void setRequestHeaders(const Http::RequestHeaderMap& headers) override { request_headers_ = &headers; } const Http::RequestHeaderMap* getRequestHeaders() const override { return request_headers_; } void setRequestIDExtension(Http::RequestIDExtensionSharedPtr utils) override { request_id_extension_ = utils; } Http::RequestIDExtensionSharedPtr getRequestIDExtension() const override { return request_id_extension_; } void dumpState(std::ostream& os, int indent_level = 0) const { const char* spaces = spacesForLevel(indent_level); os << spaces << "StreamInfoImpl " << this << DUMP_OPTIONAL_MEMBER(protocol_) << DUMP_OPTIONAL_MEMBER(response_code_) << DUMP_OPTIONAL_MEMBER(response_code_details_) << DUMP_MEMBER(health_check_request_) << DUMP_MEMBER(route_name_) << "\n"; } void setUpstreamClusterInfo( const Upstream::ClusterInfoConstSharedPtr& upstream_cluster_info) override { upstream_cluster_info_ = upstream_cluster_info; } absl::optional upstreamClusterInfo() const override { return upstream_cluster_info_; } void setConnectionID(uint64_t id) override { connection_id_ = id; } absl::optional connectionID() const override { return connection_id_; } TimeSource& time_source_; const SystemTime start_time_; const MonotonicTime start_time_monotonic_; absl::optional last_downstream_rx_byte_received; absl::optional first_downstream_tx_byte_sent_; absl::optional last_downstream_tx_byte_sent_; absl::optional final_time_; absl::optional protocol_; absl::optional response_code_; absl::optional response_code_details_; absl::optional connection_termination_details_; uint64_t response_flags_{}; Upstream::HostDescriptionConstSharedPtr upstream_host_{}; bool health_check_request_{}; const Router::RouteEntry* route_entry_{}; envoy::config::core::v3::Metadata metadata_{}; FilterStateSharedPtr filter_state_; FilterStateSharedPtr upstream_filter_state_; std::string route_name_; private: StreamInfoImpl(absl::optional protocol, TimeSource& time_source, FilterStateSharedPtr filter_state) : time_source_(time_source), start_time_(time_source.systemTime()), start_time_monotonic_(time_source.monotonicTime()), protocol_(protocol), filter_state_(std::move(filter_state)), request_id_extension_(Http::RequestIDExtensionFactory::noopInstance()) {} uint64_t bytes_received_{}; uint64_t bytes_sent_{}; Network::Address::InstanceConstSharedPtr upstream_local_address_; Network::Address::InstanceConstSharedPtr downstream_local_address_; Network::Address::InstanceConstSharedPtr downstream_direct_remote_address_; Network::Address::InstanceConstSharedPtr downstream_remote_address_; Ssl::ConnectionInfoConstSharedPtr downstream_ssl_info_; Ssl::ConnectionInfoConstSharedPtr upstream_ssl_info_; std::string requested_server_name_; const Http::RequestHeaderMap* request_headers_{}; Http::RequestIDExtensionSharedPtr request_id_extension_; UpstreamTiming upstream_timing_; std::string upstream_transport_failure_reason_; absl::optional upstream_cluster_info_; absl::optional connection_id_; }; } // namespace StreamInfo } // namespace Envoy