1
#pragma once
2

            
3
#include <memory>
4
#include <string>
5

            
6
#include "envoy/extensions/quic/connection_debug_visitor/quic_stats/v3/quic_stats.pb.h"
7
#include "envoy/registry/registry.h"
8

            
9
#include "source/common/protobuf/protobuf.h"
10
#include "source/common/quic/envoy_quic_connection_debug_visitor_factory_interface.h"
11

            
12
#include "quiche/quic/core/frames/quic_connection_close_frame.h"
13
#include "quiche/quic/core/quic_connection.h"
14
#include "quiche/quic/core/quic_session.h"
15
#include "quiche/quic/core/quic_types.h"
16

            
17
namespace Envoy {
18
namespace Extensions {
19
namespace Quic {
20
namespace ConnectionDebugVisitors {
21
namespace QuicStats {
22

            
23
#define ALL_QUIC_STATS(COUNTER, GAUGE, HISTOGRAM)                                                  \
24
5
  COUNTER(cx_tx_packets_total)                                                                     \
25
5
  COUNTER(cx_tx_packets_retransmitted_total)                                                       \
26
5
  COUNTER(cx_tx_amplification_throttling_total)                                                    \
27
5
  COUNTER(cx_rx_packets_total)                                                                     \
28
5
  COUNTER(cx_path_degrading_total)                                                                 \
29
5
  COUNTER(cx_forward_progress_after_path_degrading_total)                                          \
30
5
  HISTOGRAM(cx_rtt_us, Microseconds)                                                               \
31
5
  HISTOGRAM(cx_tx_estimated_bandwidth, Bytes)                                                      \
32
5
  HISTOGRAM(cx_tx_percent_retransmitted_packets, Percent)                                          \
33
5
  HISTOGRAM(cx_tx_mtu, Bytes)                                                                      \
34
5
  HISTOGRAM(cx_rx_mtu, Bytes)
35

            
36
struct QuicStats {
37
  ALL_QUIC_STATS(GENERATE_COUNTER_STRUCT, GENERATE_GAUGE_STRUCT, GENERATE_HISTOGRAM_STRUCT)
38
};
39

            
40
class Config;
41

            
42
// Visitor class that publishes various QUICHE connection stats as Envoy stats.
43
class QuicStatsVisitor : public quic::QuicConnectionDebugVisitor {
44
public:
45
  QuicStatsVisitor(Config& config, Event::Dispatcher& dispatcher);
46

            
47
  // quic::QuicConnectionDebugVisitor
48
  void OnConnectionClosed(const quic::QuicConnectionCloseFrame& frame,
49
                          quic::ConnectionCloseSource source) override;
50

            
51
  // This is virtual so that tests can override it.
52
  virtual const quic::QuicConnectionStats& getQuicStats() PURE;
53

            
54
private:
55
  void recordStats();
56

            
57
  Config& config_;
58
  Event::TimerPtr timer_;
59

            
60
  quic::QuicPacketCount last_packets_sent_{};
61
  quic::QuicPacketCount last_packets_retransmitted_{};
62
  quic::QuicPacketCount last_packets_received_{};
63
  size_t last_num_amplification_throttling_{};
64
  size_t last_num_path_degrading_{};
65
  size_t last_num_forward_progress_after_path_degrading_{};
66
};
67

            
68
class QuicStatsVisitorProd final : public QuicStatsVisitor {
69
public:
70
  QuicStatsVisitorProd(Config& config, Event::Dispatcher& dispatcher, quic::QuicSession& session)
71
2
      : QuicStatsVisitor(config, dispatcher), session_(session) {}
72

            
73
  const quic::QuicConnectionStats& getQuicStats() override;
74

            
75
private:
76
  quic::QuicSession& session_;
77
};
78

            
79
class Config : public Envoy::Quic::EnvoyQuicConnectionDebugVisitorFactoryInterface {
80
public:
81
  Config(const envoy::extensions::quic::connection_debug_visitor::quic_stats::v3::Config& config,
82
         Stats::Scope& scope);
83

            
84
  std::unique_ptr<quic::QuicConnectionDebugVisitor>
85
  createQuicConnectionDebugVisitor(Event::Dispatcher& dispatcher, quic::QuicSession& session,
86
                                   const StreamInfo::StreamInfo& stream_info) override;
87

            
88
  const absl::optional<std::chrono::milliseconds> update_period_;
89
  QuicStats stats_;
90

            
91
private:
92
  static QuicStats generateStats(Stats::Scope& scope);
93
};
94

            
95
class QuicStatsFactoryFactory
96
    : public Envoy::Quic::EnvoyQuicConnectionDebugVisitorFactoryFactoryInterface {
97
public:
98
8
  std::string name() const override { return "envoy.quic.connection_debug_visitor.quic_stats"; }
99

            
100
4
  Envoy::ProtobufTypes::MessagePtr createEmptyConfigProto() override {
101
4
    return std::make_unique<
102
4
        envoy::extensions::quic::connection_debug_visitor::quic_stats::v3::Config>();
103
4
  }
104

            
105
  Envoy::Quic::EnvoyQuicConnectionDebugVisitorFactoryInterfacePtr
106
  createFactory(const Protobuf::Message& config,
107
                Server::Configuration::ListenerFactoryContext& listener_context) override;
108
};
109

            
110
DECLARE_FACTORY(QuicStatsFactoryFactory);
111

            
112
} // namespace QuicStats
113
} // namespace ConnectionDebugVisitors
114
} // namespace Quic
115
} // namespace Extensions
116
} // namespace Envoy