LCOV - code coverage report
Current view: top level - source/server/admin - stats_request.h (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 0 1 0.0 %
Date: 2024-01-05 06:35:25 Functions: 0 1 0.0 %

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include "envoy/server/admin.h"
       4             : 
       5             : #include "source/server/admin/stats_params.h"
       6             : #include "source/server/admin/stats_render.h"
       7             : #include "source/server/admin/utils.h"
       8             : 
       9             : #include "absl/container/btree_map.h"
      10             : #include "absl/types/variant.h"
      11             : 
      12             : namespace Envoy {
      13             : namespace Server {
      14             : 
      15             : // Captures context for a streaming request, implementing the AdminHandler interface.
      16             : class StatsRequest : public Admin::Request {
      17             :   using ScopeVec = std::vector<Stats::ConstScopeSharedPtr>;
      18             :   using StatOrScopes = absl::variant<ScopeVec, Stats::TextReadoutSharedPtr, Stats::CounterSharedPtr,
      19             :                                      Stats::GaugeSharedPtr, Stats::HistogramSharedPtr>;
      20             : 
      21             :   // Ordered to match the StatsOrScopes variant.
      22             :   enum class StatOrScopesIndex { Scopes, TextReadout, Counter, Gauge, Histogram };
      23             : 
      24             :   // In order to keep the output consistent with the fully buffered behavior
      25             :   // prior to the chunked implementation that buffered each type, we iterate
      26             :   // over all scopes for each type. This enables the complex chunking
      27             :   // implementation to pass the tests that capture the buffered behavior. There
      28             :   // is not a significant cost to this, but in a future PR we may choose to
      29             :   // co-mingle the types. Note that histograms are groups together in the data
      30             :   // JSON data model, so we won't be able to fully co-mingle.
      31             :   enum class Phase {
      32             :     TextReadouts,
      33             :     CountersAndGauges,
      34             :     Histograms,
      35             :   };
      36             : 
      37             : public:
      38             :   using UrlHandlerFn = std::function<Admin::UrlHandler()>;
      39             : 
      40             :   static constexpr uint64_t DefaultChunkSize = 2 * 1000 * 1000;
      41             : 
      42             :   StatsRequest(Stats::Store& stats, const StatsParams& params,
      43             :                const Upstream::ClusterManager& cluster_manager,
      44             :                UrlHandlerFn url_handler_fn = nullptr);
      45             : 
      46             :   // Admin::Request
      47             :   Http::Code start(Http::ResponseHeaderMap& response_headers) override;
      48             : 
      49             :   // Streams out the next chunk of stats to the client, visiting only the scopes
      50             :   // that can plausibly contribute the next set of named stats. This enables us
      51             :   // to linearly traverse the entire set of stats without buffering all of them
      52             :   // and sorting.
      53             :   //
      54             :   // Instead we keep the a set of candidate stats to emit in stat_map_ an
      55             :   // alphabetically ordered btree, which heterogeneously stores stats of all
      56             :   // types and scopes. Note that there can be multiple scopes with the same
      57             :   // name, so we keep same-named scopes in a vector. However leaf metrics cannot
      58             :   // have duplicates. It would also be feasible to use a multi-map for this.
      59             :   //
      60             :   // So in start() above, we initially populate all the scopes, as well as the
      61             :   // metrics contained in all scopes with an empty name. So in nextChunk we can
      62             :   // emit and remove the first element of stat_map_. When we encounter a vector
      63             :   // of scopes then we add the contained metrics to the map and continue
      64             :   // iterating.
      65             :   //
      66             :   // Whenever the desired chunk size is reached we end the current chunk so that
      67             :   // the current buffer can be flushed to the network. In #19898 we will
      68             :   // introduce flow-control so that we don't buffer the all the serialized stats
      69             :   // while waiting for a slow client.
      70             :   //
      71             :   // Note that we do 3 passes through all the scopes_, so that we can emit
      72             :   // text-readouts first, then the intermingled counters and gauges, and finally
      73             :   // the histograms.
      74             :   bool nextChunk(Buffer::Instance& response) override;
      75             : 
      76             :   // To duplicate prior behavior for this class, we do three passes over all the stats:
      77             :   //   1. text readouts across all scopes
      78             :   //   2. counters and gauges, co-mingled, across all scopes
      79             :   //   3. histograms across all scopes.
      80             :   // It would be little more efficient to co-mingle all the stats, but three
      81             :   // passes over the scopes is OK. In the future we may decide to organize the
      82             :   // result data differently, but in the process of changing from buffering
      83             :   // the entire /stats response to streaming the data out in chunks, it's easier
      84             :   // to reason about if the tests don't change their expectations.
      85             :   void startPhase();
      86             : 
      87             :   // Iterates over scope_vec and populates the metric types associated with the
      88             :   // current phase.
      89             :   void populateStatsForCurrentPhase(const ScopeVec& scope_vec);
      90             : 
      91             :   // Populates all the metrics of the templatized type from scope_vec. Here we
      92             :   // exploit that Scope::iterate is a generic templatized function to avoid code
      93             :   // duplication.
      94             :   template <class StatType> void populateStatsFromScopes(const ScopeVec& scope_vec);
      95             : 
      96             :   void renderPerHostMetrics(Buffer::Instance& response);
      97             : 
      98             :   // Renders the templatized type, exploiting the fact that Render::generate is
      99             :   // generic to avoid code duplication.
     100             :   template <class SharedStatType>
     101             :   void renderStat(const std::string& name, Buffer::Instance& response, StatOrScopes& variant);
     102             : 
     103             :   // Sets the chunk size.
     104           0 :   void setChunkSize(uint64_t chunk_size) { chunk_size_ = chunk_size; }
     105             : 
     106             : private:
     107             :   StatsParams params_;
     108             :   std::unique_ptr<StatsRender> render_;
     109             :   Stats::Store& stats_;
     110             :   ScopeVec scopes_;
     111             :   absl::btree_map<std::string, StatOrScopes> stat_map_;
     112             :   Phase phase_{Phase::TextReadouts};
     113             :   uint64_t phase_stat_count_{0};
     114             :   absl::string_view phase_string_{"text readouts"};
     115             :   Buffer::OwnedImpl response_;
     116             :   const Upstream::ClusterManager& cluster_manager_;
     117             :   UrlHandlerFn url_handler_fn_;
     118             :   uint64_t chunk_size_{DefaultChunkSize};
     119             : };
     120             : 
     121             : } // namespace Server
     122             : } // namespace Envoy

Generated by: LCOV version 1.15