Line data Source code
1 : #include "source/common/http/user_agent.h" 2 : 3 : #include <cstdint> 4 : #include <memory> 5 : #include <string> 6 : 7 : #include "envoy/network/connection.h" 8 : #include "envoy/stats/scope.h" 9 : #include "envoy/stats/timespan.h" 10 : 11 : #include "source/common/http/headers.h" 12 : #include "source/common/stats/symbol_table.h" 13 : #include "source/common/stats/utility.h" 14 : 15 : namespace Envoy { 16 : namespace Http { 17 : 18 : UserAgentContext::UserAgentContext(Stats::SymbolTable& symbol_table) 19 : : symbol_table_(symbol_table), pool_(symbol_table), 20 : downstream_cx_length_ms_(pool_.add("downstream_cx_length_ms")), 21 : ios_(pool_.add("user_agent.ios")), android_(pool_.add("user_agent.android")), 22 : downstream_cx_total_(pool_.add("downstream_cx_total")), 23 : downstream_cx_destroy_remote_active_rq_(pool_.add("downstream_cx_destroy_remote_active_rq")), 24 589 : downstream_rq_total_(pool_.add("downstream_rq_total")) {} 25 : 26 922 : void UserAgent::completeConnectionLength(Stats::Timespan& span) { 27 922 : if (stats_ != nullptr) { 28 0 : stats_->downstream_cx_length_ms_.recordValue(span.elapsed().count()); 29 0 : } 30 922 : } 31 : 32 : UserAgentStats::UserAgentStats(Stats::StatName prefix, Stats::StatName device, Stats::Scope& scope, 33 : const UserAgentContext& context) 34 : : downstream_cx_total_(Stats::Utility::counterFromElements( 35 : scope, {prefix, device, context.downstream_cx_total_})), 36 : downstream_cx_destroy_remote_active_rq_(Stats::Utility::counterFromElements( 37 : scope, {prefix, device, context.downstream_cx_destroy_remote_active_rq_})), 38 : downstream_rq_total_(Stats::Utility::counterFromElements( 39 : scope, {prefix, device, context.downstream_rq_total_})), 40 : downstream_cx_length_ms_(Stats::Utility::histogramFromElements( 41 : scope, {prefix, device, context.downstream_cx_length_ms_}, 42 0 : Stats::Histogram::Unit::Milliseconds)) { 43 0 : downstream_cx_total_.inc(); 44 0 : downstream_rq_total_.inc(); 45 0 : } 46 : 47 : void UserAgent::initializeFromHeaders(const RequestHeaderMap& headers, Stats::StatName prefix, 48 547 : Stats::Scope& scope) { 49 : // We assume that the user-agent is consistent based on the first request. 50 547 : if (stats_ == nullptr && !initialized_) { 51 518 : initialized_ = true; 52 : 53 518 : const absl::string_view user_agent = headers.getUserAgentValue(); 54 518 : if (!user_agent.empty()) { 55 0 : if (user_agent.find("iOS") != absl::string_view::npos) { 56 0 : stats_ = std::make_unique<UserAgentStats>(prefix, context_.ios_, scope, context_); 57 0 : } else if (user_agent.find("android") != absl::string_view::npos) { 58 0 : stats_ = std::make_unique<UserAgentStats>(prefix, context_.android_, scope, context_); 59 0 : } 60 0 : } 61 518 : } 62 547 : } 63 : 64 130 : void UserAgent::onConnectionDestroy(Network::ConnectionEvent event, bool active_streams) { 65 130 : if (stats_ != nullptr && active_streams && event == Network::ConnectionEvent::RemoteClose) { 66 0 : stats_->downstream_cx_destroy_remote_active_rq_.inc(); 67 0 : } 68 130 : } 69 : 70 : } // namespace Http 71 : } // namespace Envoy