Record object ACKs into MOQT traces.

PiperOrigin-RevId: 824650956
diff --git a/quiche/quic/moqt/moqt_integration_test.cc b/quiche/quic/moqt/moqt_integration_test.cc
index fcf84df..8831652 100644
--- a/quiche/quic/moqt/moqt_integration_test.cc
+++ b/quiche/quic/moqt/moqt_integration_test.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include <cstddef>
+#include <cstdint>
 #include <memory>
 #include <optional>
 #include <string>
@@ -44,6 +45,7 @@
 using ::quiche::QuicheMemSlice;
 using ::testing::_;
 using ::testing::Assign;
+using ::testing::ElementsAre;
 using ::testing::Return;
 
 class MoqtIntegrationTest : public quiche::test::QuicheTest {
@@ -754,6 +756,15 @@
       .WillOnce([&] { done = true; });
   bool success = test_harness_.RunUntilWithDefaultTimeout([&] { return done; });
   EXPECT_TRUE(success);
+
+  const quic_trace::Trace& trace = *server_->trace_visitor()->trace();
+  std::vector<int64_t> ack_deltas;
+  for (const quic_trace::Event& event : trace.events()) {
+    if (event.event_type() == quic_trace::EventType::MOQT_OBJECT_ACKNOWLEDGED) {
+      ack_deltas.push_back(event.moq_object_ack_time_delta_us());
+    }
+  }
+  EXPECT_THAT(ack_deltas, ElementsAre(-123, 456));
 }
 
 TEST_F(MoqtIntegrationTest, DeliveryTimeout) {
diff --git a/quiche/quic/moqt/moqt_session.cc b/quiche/quic/moqt/moqt_session.cc
index 01b64be..6518125 100644
--- a/quiche/quic/moqt/moqt_session.cc
+++ b/quiche/quic/moqt/moqt_session.cc
@@ -2656,4 +2656,17 @@
       stream->GetStreamId());
 }
 
+void MoqtSession::PublishedSubscription::ProcessObjectAck(
+    const MoqtObjectAck& message) {
+  session_->trace_recorder_.RecordObjectAck(
+      track_alias_, Location(message.group_id, message.object_id),
+      message.delta_from_deadline);
+
+  if (monitoring_interface_ == nullptr) {
+    return;
+  }
+  monitoring_interface_->OnObjectAckReceived(
+      message.group_id, message.object_id, message.delta_from_deadline);
+}
+
 }  // namespace moqt
diff --git a/quiche/quic/moqt/moqt_session.h b/quiche/quic/moqt/moqt_session.h
index db35e5e..8b719ba 100644
--- a/quiche/quic/moqt/moqt_session.h
+++ b/quiche/quic/moqt/moqt_session.h
@@ -381,13 +381,7 @@
     void OnSubgroupAbandoned(uint64_t group, uint64_t subgroup,
                              webtransport::StreamErrorCode error_code) override;
     void OnGroupAbandoned(uint64_t group_id) override;
-    void ProcessObjectAck(const MoqtObjectAck& message) {
-      if (monitoring_interface_ == nullptr) {
-        return;
-      }
-      monitoring_interface_->OnObjectAckReceived(
-          message.group_id, message.object_id, message.delta_from_deadline);
-    }
+    void ProcessObjectAck(const MoqtObjectAck& message);
 
     // Updates the window and other properties of the subscription in question.
     void Update(Location start, std::optional<uint64_t> end,
diff --git a/quiche/quic/moqt/moqt_trace_recorder.cc b/quiche/quic/moqt/moqt_trace_recorder.cc
index 0a503ef..0f8eb6e 100644
--- a/quiche/quic/moqt/moqt_trace_recorder.cc
+++ b/quiche/quic/moqt/moqt_trace_recorder.cc
@@ -7,6 +7,7 @@
 #include <cstdint>
 #include <optional>
 
+#include "quiche/quic/core/quic_time.h"
 #include "quiche/quic/moqt/moqt_messages.h"
 #include "quiche/quic/moqt/moqt_object.h"
 #include "quiche/quic/moqt/moqt_priority.h"
@@ -101,4 +102,18 @@
   }
 }
 
+void MoqtTraceRecorder::RecordObjectAck(uint64_t track_alias, Location location,
+                                        quic::QuicTimeDelta ack_delta) {
+  if (parent_ == nullptr) {
+    return;
+  }
+  quic_trace::Event* event = AddEvent();
+  event->set_event_type(EventType::MOQT_OBJECT_ACKNOWLEDGED);
+  event->set_moq_object_ack_time_delta_us(ack_delta.ToMicroseconds());
+  event->mutable_moqt_object()->set_track_alias(track_alias);
+  event->mutable_moqt_object()->set_group_id(location.group);
+  event->mutable_moqt_object()->set_object_id(location.object);
+  parent_->PopulateTransportState(event->mutable_transport_state());
+}
+
 }  // namespace moqt
diff --git a/quiche/quic/moqt/moqt_trace_recorder.h b/quiche/quic/moqt/moqt_trace_recorder.h
index a40693a..81b5531 100644
--- a/quiche/quic/moqt/moqt_trace_recorder.h
+++ b/quiche/quic/moqt/moqt_trace_recorder.h
@@ -9,6 +9,7 @@
 #include <memory>
 
 #include "absl/base/nullability.h"
+#include "quiche/quic/core/quic_time.h"
 #include "quiche/quic/core/quic_trace_visitor.h"
 #include "quiche/quic/moqt/moqt_messages.h"
 #include "quiche/quic/moqt/moqt_priority.h"
@@ -55,6 +56,10 @@
                                 Location location, uint64_t subgroup,
                                 MoqtPriority publisher_priority);
 
+  // Records an incoming MOQT Object ACK message.
+  void RecordObjectAck(uint64_t track_alias, Location location,
+                       quic::QuicTimeDelta ack_delta);
+
  private:
   // Adds a new event to the trace, and populates the timestamp.
   quic_trace::Event* AddEvent();