in source/extensions/access_loggers/http_grpc/grpc_access_log_impl.cc [160:354]
void HttpGrpcAccessLog::log(const Http::HeaderMap* request_headers,
const Http::HeaderMap* response_headers,
const Http::HeaderMap* response_trailers,
const StreamInfo::StreamInfo& stream_info) {
static Http::HeaderMapImpl empty_headers;
if (!request_headers) {
request_headers = &empty_headers;
}
if (!response_headers) {
response_headers = &empty_headers;
}
if (!response_trailers) {
response_trailers = &empty_headers;
}
if (filter_) {
if (!filter_->evaluate(stream_info, *request_headers)) {
return;
}
}
envoy::service::accesslog::v2::StreamAccessLogsMessage message;
auto* log_entry = message.mutable_http_logs()->add_log_entry();
// Common log properties.
// TODO(mattklein123): Populate sample_rate field.
// TODO(mattklein123): Populate tls_properties field.
auto* common_properties = log_entry->mutable_common_properties();
if (stream_info.downstreamRemoteAddress() != nullptr) {
Network::Utility::addressToProtobufAddress(
*stream_info.downstreamRemoteAddress(),
*common_properties->mutable_downstream_remote_address());
}
if (stream_info.downstreamLocalAddress() != nullptr) {
Network::Utility::addressToProtobufAddress(
*stream_info.downstreamLocalAddress(),
*common_properties->mutable_downstream_local_address());
}
common_properties->mutable_start_time()->MergeFrom(
Protobuf::util::TimeUtil::NanosecondsToTimestamp(
std::chrono::duration_cast<std::chrono::nanoseconds>(
stream_info.startTime().time_since_epoch())
.count()));
absl::optional<std::chrono::nanoseconds> dur = stream_info.lastDownstreamRxByteReceived();
if (dur) {
common_properties->mutable_time_to_last_rx_byte()->MergeFrom(
Protobuf::util::TimeUtil::NanosecondsToDuration(dur.value().count()));
}
dur = stream_info.firstUpstreamTxByteSent();
if (dur) {
common_properties->mutable_time_to_first_upstream_tx_byte()->MergeFrom(
Protobuf::util::TimeUtil::NanosecondsToDuration(dur.value().count()));
}
dur = stream_info.lastUpstreamTxByteSent();
if (dur) {
common_properties->mutable_time_to_last_upstream_tx_byte()->MergeFrom(
Protobuf::util::TimeUtil::NanosecondsToDuration(dur.value().count()));
}
dur = stream_info.firstUpstreamRxByteReceived();
if (dur) {
common_properties->mutable_time_to_first_upstream_rx_byte()->MergeFrom(
Protobuf::util::TimeUtil::NanosecondsToDuration(dur.value().count()));
}
dur = stream_info.lastUpstreamRxByteReceived();
if (dur) {
common_properties->mutable_time_to_last_upstream_rx_byte()->MergeFrom(
Protobuf::util::TimeUtil::NanosecondsToDuration(dur.value().count()));
}
dur = stream_info.firstDownstreamTxByteSent();
if (dur) {
common_properties->mutable_time_to_first_downstream_tx_byte()->MergeFrom(
Protobuf::util::TimeUtil::NanosecondsToDuration(dur.value().count()));
}
dur = stream_info.lastDownstreamTxByteSent();
if (dur) {
common_properties->mutable_time_to_last_downstream_tx_byte()->MergeFrom(
Protobuf::util::TimeUtil::NanosecondsToDuration(dur.value().count()));
}
if (stream_info.upstreamHost() != nullptr) {
Network::Utility::addressToProtobufAddress(
*stream_info.upstreamHost()->address(),
*common_properties->mutable_upstream_remote_address());
common_properties->set_upstream_cluster(stream_info.upstreamHost()->cluster().name());
}
if (stream_info.upstreamLocalAddress() != nullptr) {
Network::Utility::addressToProtobufAddress(
*stream_info.upstreamLocalAddress(), *common_properties->mutable_upstream_local_address());
}
responseFlagsToAccessLogResponseFlags(*common_properties, stream_info);
if (stream_info.dynamicMetadata().filter_metadata_size() > 0) {
common_properties->mutable_metadata()->MergeFrom(stream_info.dynamicMetadata());
}
if (stream_info.protocol()) {
switch (stream_info.protocol().value()) {
case Http::Protocol::Http10:
log_entry->set_protocol_version(envoy::data::accesslog::v2::HTTPAccessLogEntry::HTTP10);
break;
case Http::Protocol::Http11:
log_entry->set_protocol_version(envoy::data::accesslog::v2::HTTPAccessLogEntry::HTTP11);
break;
case Http::Protocol::Http2:
log_entry->set_protocol_version(envoy::data::accesslog::v2::HTTPAccessLogEntry::HTTP2);
break;
}
}
// HTTP request properties.
// TODO(mattklein123): Populate port field.
auto* request_properties = log_entry->mutable_request();
if (request_headers->Scheme() != nullptr) {
request_properties->set_scheme(request_headers->Scheme()->value().c_str());
}
if (request_headers->Host() != nullptr) {
request_properties->set_authority(request_headers->Host()->value().c_str());
}
if (request_headers->Path() != nullptr) {
request_properties->set_path(request_headers->Path()->value().c_str());
}
if (request_headers->UserAgent() != nullptr) {
request_properties->set_user_agent(request_headers->UserAgent()->value().c_str());
}
if (request_headers->Referer() != nullptr) {
request_properties->set_referer(request_headers->Referer()->value().c_str());
}
if (request_headers->ForwardedFor() != nullptr) {
request_properties->set_forwarded_for(request_headers->ForwardedFor()->value().c_str());
}
if (request_headers->RequestId() != nullptr) {
request_properties->set_request_id(request_headers->RequestId()->value().c_str());
}
if (request_headers->EnvoyOriginalPath() != nullptr) {
request_properties->set_original_path(request_headers->EnvoyOriginalPath()->value().c_str());
}
request_properties->set_request_headers_bytes(request_headers->byteSize());
request_properties->set_request_body_bytes(stream_info.bytesReceived());
if (request_headers->Method() != nullptr) {
envoy::api::v2::core::RequestMethod method =
envoy::api::v2::core::RequestMethod::METHOD_UNSPECIFIED;
envoy::api::v2::core::RequestMethod_Parse(
std::string(request_headers->Method()->value().c_str()), &method);
request_properties->set_request_method(method);
}
if (!request_headers_to_log_.empty()) {
auto* logged_headers = request_properties->mutable_request_headers();
for (const auto& header : request_headers_to_log_) {
const Http::HeaderEntry* entry = request_headers->get(header);
if (entry != nullptr) {
logged_headers->insert({header.get(), ProtobufTypes::String(entry->value().c_str())});
}
}
}
// HTTP response properties.
auto* response_properties = log_entry->mutable_response();
if (stream_info.responseCode()) {
response_properties->mutable_response_code()->set_value(stream_info.responseCode().value());
}
response_properties->set_response_headers_bytes(response_headers->byteSize());
response_properties->set_response_body_bytes(stream_info.bytesSent());
if (!response_headers_to_log_.empty()) {
auto* logged_headers = response_properties->mutable_response_headers();
for (const auto& header : response_headers_to_log_) {
const Http::HeaderEntry* entry = response_headers->get(header);
if (entry != nullptr) {
logged_headers->insert({header.get(), ProtobufTypes::String(entry->value().c_str())});
}
}
}
if (!response_trailers_to_log_.empty()) {
auto* logged_headers = response_properties->mutable_response_trailers();
for (const auto& header : response_trailers_to_log_) {
const Http::HeaderEntry* entry = response_trailers->get(header);
if (entry != nullptr) {
logged_headers->insert({header.get(), ProtobufTypes::String(entry->value().c_str())});
}
}
}
// TODO(mattklein123): Consider batching multiple logs and flushing.
grpc_access_log_streamer_->send(message, config_.common_config().log_name());
}