1
#pragma once
2

            
3
#include <cstdint>
4

            
5
#include "envoy/access_log/access_log.h"
6
#include "envoy/http/codec.h"
7
#include "envoy/http/header_map.h"
8
#include "envoy/stream_info/stream_info.h"
9

            
10
#include "source/common/runtime/runtime_features.h"
11

            
12
#include "quiche/quic/core/quic_ack_listener_interface.h"
13
#include "quiche/quic/platform/api/quic_flags.h"
14

            
15
namespace Envoy {
16
namespace Quic {
17

            
18
// Ack listener that stores access logging information and performs
19
// logging after the final ack.
20
class QuicStatsGatherer : public quic::QuicAckListenerInterface {
21
public:
22
12033
  explicit QuicStatsGatherer(Envoy::TimeSource* time_source) : time_source_(time_source) {}
23
4011
  ~QuicStatsGatherer() override {
24
4011
    if (!logging_done_) {
25
2504
      if (notify_ack_listener_before_soon_to_be_destroyed_) {
26
2504
        ENVOY_BUG(stream_info_ == nullptr,
27
2504
                  "Stream destroyed without logging metrics available in stream info.");
28
2504
      } else {
29
        maybeDoDeferredLog(false);
30
      }
31
2504
    }
32
4011
  }
33

            
34
  // QuicAckListenerInterface
35
  void OnPacketAcked(int acked_bytes, quic::QuicTime::Delta delta_largest_observed) override;
36
  void OnPacketRetransmitted(int retransmitted_bytes) override;
37

            
38
  // Add bytes sent for this stream, for internal tracking of bytes acked.
39
8163
  void addBytesSent(uint64_t bytes_sent, bool end_stream) {
40
8163
    bytes_outstanding_ += bytes_sent;
41
8163
    fin_sent_ = end_stream;
42
8163
  }
43
  // Log this stream using available stream info and access loggers.
44
  void maybeDoDeferredLog(bool record_ack_timing = true);
45
  // Set list of pointers to access loggers.
46
4036
  void setAccessLogHandlers(AccessLog::InstanceSharedPtrVector handlers) {
47
4036
    access_log_handlers_ = std::move(handlers);
48
4036
  }
49
  // Set headers, trailers, and stream info used for deferred logging.
50
  void
51
  setDeferredLoggingHeadersAndTrailers(Http::RequestHeaderMapConstSharedPtr request_header_map,
52
                                       Http::ResponseHeaderMapConstSharedPtr response_header_map,
53
                                       Http::ResponseTrailerMapConstSharedPtr response_trailer_map,
54
1507
                                       std::unique_ptr<StreamInfo::StreamInfo> stream_info) {
55
1507
    request_header_map_ = request_header_map;
56
1507
    response_header_map_ = response_header_map;
57
1507
    response_trailer_map_ = response_trailer_map;
58
1507
    stream_info_ = std::move(stream_info);
59
1507
  }
60
4011
  bool loggingDone() { return logging_done_; }
61
1
  uint64_t bytesOutstanding() { return bytes_outstanding_; }
62
5687
  bool notify_ack_listener_before_soon_to_be_destroyed() const {
63
5687
    return notify_ack_listener_before_soon_to_be_destroyed_;
64
5687
  }
65

            
66
private:
67
  uint64_t bytes_outstanding_ = 0;
68
  bool fin_sent_ = false;
69
  AccessLog::InstanceSharedPtrVector access_log_handlers_{};
70
  Http::RequestHeaderMapConstSharedPtr request_header_map_;
71
  Http::ResponseHeaderMapConstSharedPtr response_header_map_;
72
  Http::ResponseTrailerMapConstSharedPtr response_trailer_map_;
73
  // nullptr indicates that deferred logging should be skipped.
74
  std::unique_ptr<StreamInfo::StreamInfo> stream_info_;
75
  Envoy::TimeSource* time_source_ = nullptr;
76
  bool logging_done_ = false;
77
  uint64_t retransmitted_packets_ = 0;
78
  uint64_t retransmitted_bytes_ = 0;
79
  absl::optional<MonotonicTime> last_downstream_ack_timestamp_;
80

            
81
  const bool notify_ack_listener_before_soon_to_be_destroyed_{
82
      GetQuicReloadableFlag(quic_notify_ack_listener_earlier) &&
83
      GetQuicReloadableFlag(quic_notify_stream_soon_to_destroy)};
84
  const bool fix_defer_logging_miss_for_half_closed_stream_{Runtime::runtimeFeatureEnabled(
85
      "envoy.reloadable_features.quic_fix_defer_logging_miss_for_half_closed_stream")};
86
};
87

            
88
} // namespace Quic
89
} // namespace Envoy