Line data Source code
1 : #include "source/extensions/access_loggers/grpc/http_grpc_access_log_impl.h" 2 : 3 : #include "envoy/config/core/v3/base.pb.h" 4 : #include "envoy/data/accesslog/v3/accesslog.pb.h" 5 : #include "envoy/extensions/access_loggers/grpc/v3/als.pb.h" 6 : 7 : #include "source/common/common/assert.h" 8 : #include "source/common/config/utility.h" 9 : #include "source/common/http/header_utility.h" 10 : #include "source/common/http/headers.h" 11 : #include "source/common/network/utility.h" 12 : #include "source/common/stream_info/utility.h" 13 : #include "source/extensions/access_loggers/grpc/grpc_access_log_utils.h" 14 : 15 : namespace Envoy { 16 : namespace Extensions { 17 : namespace AccessLoggers { 18 : namespace HttpGrpc { 19 : 20 : Http::RegisterCustomInlineHeader<Http::CustomInlineHeaderRegistry::Type::RequestHeaders> 21 : referer_handle(Http::CustomHeaders::get().Referer); 22 : 23 : HttpGrpcAccessLog::ThreadLocalLogger::ThreadLocalLogger( 24 : GrpcCommon::GrpcAccessLoggerSharedPtr logger) 25 0 : : logger_(std::move(logger)) {} 26 : 27 : HttpGrpcAccessLog::HttpGrpcAccessLog(AccessLog::FilterPtr&& filter, 28 : const HttpGrpcAccessLogConfig config, 29 : ThreadLocal::SlotAllocator& tls, 30 : GrpcCommon::GrpcAccessLoggerCacheSharedPtr access_logger_cache) 31 : : Common::ImplBase(std::move(filter)), 32 : config_(std::make_shared<const HttpGrpcAccessLogConfig>(std::move(config))), 33 0 : tls_slot_(tls.allocateSlot()), access_logger_cache_(std::move(access_logger_cache)) { 34 0 : for (const auto& header : config_->additional_request_headers_to_log()) { 35 0 : request_headers_to_log_.emplace_back(header); 36 0 : } 37 : 38 0 : for (const auto& header : config_->additional_response_headers_to_log()) { 39 0 : response_headers_to_log_.emplace_back(header); 40 0 : } 41 : 42 0 : for (const auto& header : config_->additional_response_trailers_to_log()) { 43 0 : response_trailers_to_log_.emplace_back(header); 44 0 : } 45 0 : THROW_IF_NOT_OK(Envoy::Config::Utility::checkTransportVersion(config_->common_config())); 46 0 : tls_slot_->set( 47 0 : [config = config_, access_logger_cache = access_logger_cache_](Event::Dispatcher&) { 48 0 : return std::make_shared<ThreadLocalLogger>(access_logger_cache->getOrCreateLogger( 49 0 : config->common_config(), Common::GrpcAccessLoggerType::HTTP)); 50 0 : }); 51 0 : } 52 : 53 : void HttpGrpcAccessLog::emitLog(const Formatter::HttpFormatterContext& context, 54 0 : const StreamInfo::StreamInfo& stream_info) { 55 : // Common log properties. 56 : // TODO(mattklein123): Populate sample_rate field. 57 0 : envoy::data::accesslog::v3::HTTPAccessLogEntry log_entry; 58 : 59 0 : const auto& request_headers = context.requestHeaders(); 60 : 61 0 : GrpcCommon::Utility::extractCommonAccessLogProperties( 62 0 : *log_entry.mutable_common_properties(), request_headers, stream_info, 63 0 : config_->common_config(), context.accessLogType()); 64 : 65 0 : if (stream_info.protocol()) { 66 0 : switch (stream_info.protocol().value()) { 67 0 : case Http::Protocol::Http10: 68 0 : log_entry.set_protocol_version(envoy::data::accesslog::v3::HTTPAccessLogEntry::HTTP10); 69 0 : break; 70 0 : case Http::Protocol::Http11: 71 0 : log_entry.set_protocol_version(envoy::data::accesslog::v3::HTTPAccessLogEntry::HTTP11); 72 0 : break; 73 0 : case Http::Protocol::Http2: 74 0 : log_entry.set_protocol_version(envoy::data::accesslog::v3::HTTPAccessLogEntry::HTTP2); 75 0 : break; 76 0 : case Http::Protocol::Http3: 77 0 : log_entry.set_protocol_version(envoy::data::accesslog::v3::HTTPAccessLogEntry::HTTP3); 78 0 : break; 79 0 : } 80 0 : } 81 : 82 : // HTTP request properties. 83 : // TODO(mattklein123): Populate port field. 84 0 : auto* request_properties = log_entry.mutable_request(); 85 0 : if (request_headers.Scheme() != nullptr) { 86 0 : request_properties->set_scheme( 87 0 : MessageUtil::sanitizeUtf8String(request_headers.getSchemeValue())); 88 0 : } 89 0 : if (request_headers.Host() != nullptr) { 90 0 : request_properties->set_authority( 91 0 : MessageUtil::sanitizeUtf8String(request_headers.getHostValue())); 92 0 : } 93 0 : if (request_headers.Path() != nullptr) { 94 0 : request_properties->set_path(MessageUtil::sanitizeUtf8String(request_headers.getPathValue())); 95 0 : } 96 0 : if (request_headers.UserAgent() != nullptr) { 97 0 : request_properties->set_user_agent( 98 0 : MessageUtil::sanitizeUtf8String(request_headers.getUserAgentValue())); 99 0 : } 100 0 : if (request_headers.getInline(referer_handle.handle()) != nullptr) { 101 0 : request_properties->set_referer( 102 0 : MessageUtil::sanitizeUtf8String(request_headers.getInlineValue(referer_handle.handle()))); 103 0 : } 104 0 : if (request_headers.ForwardedFor() != nullptr) { 105 0 : request_properties->set_forwarded_for( 106 0 : MessageUtil::sanitizeUtf8String(request_headers.getForwardedForValue())); 107 0 : } 108 0 : if (request_headers.RequestId() != nullptr) { 109 0 : request_properties->set_request_id( 110 0 : MessageUtil::sanitizeUtf8String(request_headers.getRequestIdValue())); 111 0 : } 112 0 : if (request_headers.EnvoyOriginalPath() != nullptr) { 113 0 : request_properties->set_original_path( 114 0 : MessageUtil::sanitizeUtf8String(request_headers.getEnvoyOriginalPathValue())); 115 0 : } 116 0 : request_properties->set_request_headers_bytes(request_headers.byteSize()); 117 0 : request_properties->set_request_body_bytes(stream_info.bytesReceived()); 118 : 119 0 : if (request_headers.Method() != nullptr) { 120 0 : envoy::config::core::v3::RequestMethod method = envoy::config::core::v3::METHOD_UNSPECIFIED; 121 0 : envoy::config::core::v3::RequestMethod_Parse( 122 0 : MessageUtil::sanitizeUtf8String(request_headers.getMethodValue()), &method); 123 0 : request_properties->set_request_method(method); 124 0 : } 125 0 : if (!request_headers_to_log_.empty()) { 126 0 : auto* logged_headers = request_properties->mutable_request_headers(); 127 : 128 0 : for (const auto& header : request_headers_to_log_) { 129 0 : const auto all_values = Http::HeaderUtility::getAllOfHeaderAsString(request_headers, header); 130 0 : if (all_values.result().has_value()) { 131 0 : logged_headers->insert( 132 0 : {header.get(), MessageUtil::sanitizeUtf8String(all_values.result().value())}); 133 0 : } 134 0 : } 135 0 : } 136 : 137 : // HTTP response properties. 138 0 : const auto& response_headers = context.responseHeaders(); 139 0 : const auto& response_trailers = context.responseTrailers(); 140 : 141 0 : auto* response_properties = log_entry.mutable_response(); 142 0 : if (stream_info.responseCode()) { 143 0 : response_properties->mutable_response_code()->set_value(stream_info.responseCode().value()); 144 0 : } 145 0 : if (stream_info.responseCodeDetails()) { 146 0 : response_properties->set_response_code_details(stream_info.responseCodeDetails().value()); 147 0 : } 148 0 : response_properties->set_response_headers_bytes(response_headers.byteSize()); 149 0 : response_properties->set_response_body_bytes(stream_info.bytesSent()); 150 0 : if (!response_headers_to_log_.empty()) { 151 0 : auto* logged_headers = response_properties->mutable_response_headers(); 152 : 153 0 : for (const auto& header : response_headers_to_log_) { 154 0 : const auto all_values = Http::HeaderUtility::getAllOfHeaderAsString(response_headers, header); 155 0 : if (all_values.result().has_value()) { 156 0 : logged_headers->insert( 157 0 : {header.get(), MessageUtil::sanitizeUtf8String(all_values.result().value())}); 158 0 : } 159 0 : } 160 0 : } 161 : 162 0 : if (!response_trailers_to_log_.empty()) { 163 0 : auto* logged_headers = response_properties->mutable_response_trailers(); 164 : 165 0 : for (const auto& header : response_trailers_to_log_) { 166 0 : const auto all_values = 167 0 : Http::HeaderUtility::getAllOfHeaderAsString(response_trailers, header); 168 0 : if (all_values.result().has_value()) { 169 0 : logged_headers->insert( 170 0 : {header.get(), MessageUtil::sanitizeUtf8String(all_values.result().value())}); 171 0 : } 172 0 : } 173 0 : } 174 : 175 0 : if (const auto& bytes_meter = stream_info.getDownstreamBytesMeter(); bytes_meter != nullptr) { 176 0 : request_properties->set_downstream_header_bytes_received(bytes_meter->headerBytesReceived()); 177 0 : response_properties->set_downstream_header_bytes_sent(bytes_meter->headerBytesSent()); 178 0 : } 179 0 : if (const auto& bytes_meter = stream_info.getUpstreamBytesMeter(); bytes_meter != nullptr) { 180 0 : request_properties->set_upstream_header_bytes_sent(bytes_meter->headerBytesSent()); 181 0 : response_properties->set_upstream_header_bytes_received(bytes_meter->headerBytesReceived()); 182 0 : } 183 : 184 0 : tls_slot_->getTyped<ThreadLocalLogger>().logger_->log(std::move(log_entry)); 185 0 : } 186 : 187 : } // namespace HttpGrpc 188 : } // namespace AccessLoggers 189 : } // namespace Extensions 190 : } // namespace Envoy