Record detailed location of FAIL_TO_SERIALIZE_PACKET error in UMA histogram.

PiperOrigin-RevId: 332882395
Change-Id: If948bd43a46f2c0abf948bc4de4509e8a429a8b2
diff --git a/quic/core/quic_error_codes.cc b/quic/core/quic_error_codes.cc
index cf153e3..f37ac84 100644
--- a/quic/core/quic_error_codes.cc
+++ b/quic/core/quic_error_codes.cc
@@ -7,6 +7,7 @@
 
 #include "third_party/boringssl/src/include/openssl/ssl.h"
 #include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_client_stats.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
 #include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
 
@@ -763,6 +764,13 @@
   return QUIC_STREAM_UNKNOWN_APPLICATION_ERROR_CODE;
 }
 
+void RecordFailToSerializePacketLocation(
+    QuicFailToSerializePacketLocation location) {
+  QUIC_CLIENT_HISTOGRAM_ENUM("QuicSession.FailToSerializePacketLocation",
+                             location, QUIC_FAIL_LOCATION_MAX,
+                             "The reason why a packet fails to serialize");
+}
+
 #undef RETURN_STRING_LITERAL  // undef for jumbo builds
 
 }  // namespace quic
diff --git a/quic/core/quic_error_codes.h b/quic/core/quic_error_codes.h
index 78b5614..7bd4e14 100644
--- a/quic/core/quic_error_codes.h
+++ b/quic/core/quic_error_codes.h
@@ -598,6 +598,36 @@
   return "cause";
 }
 
+enum QuicFailToSerializePacketLocation {
+  kQuicFailToAppendPacketHeaderFastPath = 0,
+  kQuicFailToAppendTypeFastPath = 1,
+  kQuicFailToAppendStreamFrameFastPath = 2,
+  kQuicFailToAddPaddingFastPath = 3,
+  kQuicFailToWriteIetfLongHeaderLengthFastPath = 4,
+  kQuicFailToEncryptPacketFastPath = 5,
+  kQuicSerializePacketNonEmptyBuffer = 6,
+  kQuicMissingInitialKey = 7,
+  kQuicMissingHandshakeKey = 8,
+  kQuicMissingZeroRttKey = 9,
+  kQuicMissingOneRttKey = 10,
+  kQuicFailToBuildPacketWithPaddingInitial = 11,
+  kQuicFailToBuildPacketInitial = 12,
+  kQuicFailToBuildPacketWithPaddingHandshake = 13,
+  kQuicFailToBuildPacketHandshake = 14,
+  kQuicFailToBuildPacketWithPaddingZeroRtt = 15,
+  kQuicFailToBuildPacketZeroRtt = 16,
+  kQuicFailToBuildPacketWithPaddingOneRtt = 17,
+  kQuicFailToBuildPacketOneRtt = 18,
+  kQuicFailToEncryptInitial = 19,
+  kQuicFailToEncryptHandshake = 20,
+  kQuicFailToEncryptZeroRtt = 21,
+  kQuicFailToEncryptOneRtt = 22,
+  kMaxValue = kQuicFailToEncryptOneRtt
+};
+
+QUIC_EXPORT_PRIVATE void RecordFailToSerializePacketLocation(
+    QuicFailToSerializePacketLocation location);
+
 }  // namespace quic
 
 #endif  // QUICHE_QUIC_CORE_QUIC_ERROR_CODES_H_
diff --git a/quic/core/quic_packet_creator.cc b/quic/core/quic_packet_creator.cc
index a3e2bf9..3160b67 100644
--- a/quic/core/quic_packet_creator.cc
+++ b/quic/core/quic_packet_creator.cc
@@ -18,6 +18,7 @@
 #include "net/third_party/quiche/src/quic/core/quic_connection_id.h"
 #include "net/third_party/quiche/src/quic/core/quic_constants.h"
 #include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
+#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
 #include "net/third_party/quiche/src/quic/core/quic_types.h"
 #include "net/third_party/quiche/src/quic/core/quic_utils.h"
 #include "net/third_party/quiche/src/quic/core/quic_versions.h"
@@ -599,6 +600,7 @@
   size_t length_field_offset = 0;
   if (!framer_->AppendPacketHeader(header, &writer, &length_field_offset)) {
     QUIC_BUG << "AppendPacketHeader failed";
+    RecordFailToSerializePacketLocation(kQuicFailToAppendPacketHeaderFastPath);
     return;
   }
 
@@ -640,10 +642,12 @@
   bool omit_frame_length = !needs_padding;
   if (!framer_->AppendTypeByte(QuicFrame(frame), omit_frame_length, &writer)) {
     QUIC_BUG << "AppendTypeByte failed";
+    RecordFailToSerializePacketLocation(kQuicFailToAppendTypeFastPath);
     return;
   }
   if (!framer_->AppendStreamFrame(frame, omit_frame_length, &writer)) {
     QUIC_BUG << "AppendStreamFrame failed";
+    RecordFailToSerializePacketLocation(kQuicFailToAppendStreamFrameFastPath);
     return;
   }
   if (needs_padding &&
@@ -651,11 +655,14 @@
       !writer.WritePaddingBytes(MinPlaintextPacketSize(framer_->version()) -
                                 plaintext_bytes_written)) {
     QUIC_BUG << "Unable to add padding bytes";
+    RecordFailToSerializePacketLocation(kQuicFailToAddPaddingFastPath);
     return;
   }
 
   if (!framer_->WriteIetfLongHeaderLength(header, &writer, length_field_offset,
                                           packet_.encryption_level)) {
+    RecordFailToSerializePacketLocation(
+        kQuicFailToWriteIetfLongHeaderLengthFastPath);
     return;
   }
 
@@ -670,6 +677,7 @@
       writer.length(), kMaxOutgoingPacketSize, encrypted_buffer);
   if (encrypted_length == 0) {
     QUIC_BUG << "Failed to encrypt packet number " << header.packet_number;
+    RecordFailToSerializePacketLocation(kQuicFailToEncryptPacketFastPath);
     return;
   }
   // TODO(ianswett): Optimize the storage so RetransmitableFrames can be
@@ -754,6 +762,7 @@
                                         size_t encrypted_buffer_len) {
   if (close_connection_on_serialization_failure_ &&
       packet_.encrypted_buffer != nullptr) {
+    RecordFailToSerializePacketLocation(kQuicSerializePacketNonEmptyBuffer);
     const std::string error_details =
         "Packet's encrypted buffer is not empty before serialization";
     QUIC_BUG << error_details;
@@ -795,6 +804,22 @@
              << QuicFramesToString(queued_frames_)
              << " at missing encryption_level " << packet_.encryption_level
              << " using " << framer_->version();
+    switch (packet_.encryption_level) {
+      case ENCRYPTION_INITIAL:
+        RecordFailToSerializePacketLocation(kQuicMissingInitialKey);
+        break;
+      case ENCRYPTION_HANDSHAKE:
+        RecordFailToSerializePacketLocation(kQuicMissingHandshakeKey);
+        break;
+      case ENCRYPTION_ZERO_RTT:
+        RecordFailToSerializePacketLocation(kQuicMissingZeroRttKey);
+        break;
+      case ENCRYPTION_FORWARD_SECURE:
+        RecordFailToSerializePacketLocation(kQuicMissingOneRttKey);
+        break;
+      default:
+        break;
+    }
     return false;
   }
 
@@ -813,6 +838,42 @@
              << latched_hard_max_packet_length_
              << ", max_packet_length_: " << max_packet_length_
              << ", header: " << header;
+    switch (packet_.encryption_level) {
+      case ENCRYPTION_INITIAL:
+        if (QuicUtils::ContainsFrameType(queued_frames_, PADDING_FRAME)) {
+          RecordFailToSerializePacketLocation(
+              kQuicFailToBuildPacketWithPaddingInitial);
+        } else {
+          RecordFailToSerializePacketLocation(kQuicFailToBuildPacketInitial);
+        }
+        break;
+      case ENCRYPTION_HANDSHAKE:
+        if (QuicUtils::ContainsFrameType(queued_frames_, PADDING_FRAME)) {
+          RecordFailToSerializePacketLocation(
+              kQuicFailToBuildPacketWithPaddingHandshake);
+        } else {
+          RecordFailToSerializePacketLocation(kQuicFailToBuildPacketHandshake);
+        }
+        break;
+      case ENCRYPTION_ZERO_RTT:
+        if (QuicUtils::ContainsFrameType(queued_frames_, PADDING_FRAME)) {
+          RecordFailToSerializePacketLocation(
+              kQuicFailToBuildPacketWithPaddingZeroRtt);
+        } else {
+          RecordFailToSerializePacketLocation(kQuicFailToBuildPacketZeroRtt);
+        }
+        break;
+      case ENCRYPTION_FORWARD_SECURE:
+        if (QuicUtils::ContainsFrameType(queued_frames_, PADDING_FRAME)) {
+          RecordFailToSerializePacketLocation(
+              kQuicFailToBuildPacketWithPaddingOneRtt);
+        } else {
+          RecordFailToSerializePacketLocation(kQuicFailToBuildPacketOneRtt);
+        }
+        break;
+      default:
+        break;
+    }
     return false;
   }
 
@@ -834,6 +895,22 @@
       encrypted_buffer_len, encrypted_buffer.buffer);
   if (encrypted_length == 0) {
     QUIC_BUG << "Failed to encrypt packet number " << packet_.packet_number;
+    switch (packet_.encryption_level) {
+      case ENCRYPTION_INITIAL:
+        RecordFailToSerializePacketLocation(kQuicFailToEncryptInitial);
+        break;
+      case ENCRYPTION_HANDSHAKE:
+        RecordFailToSerializePacketLocation(kQuicFailToEncryptHandshake);
+        break;
+      case ENCRYPTION_ZERO_RTT:
+        RecordFailToSerializePacketLocation(kQuicFailToEncryptZeroRtt);
+        break;
+      case ENCRYPTION_FORWARD_SECURE:
+        RecordFailToSerializePacketLocation(kQuicFailToEncryptOneRtt);
+        break;
+      default:
+        break;
+    }
     return false;
   }