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

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include <vector>
       4             : 
       5             : #include "envoy/server/admin.h"
       6             : #include "envoy/singleton/manager.h"
       7             : 
       8             : #include "source/extensions/common/tap/tap.h"
       9             : 
      10             : #include "absl/container/node_hash_set.h"
      11             : #include "absl/types/optional.h"
      12             : 
      13             : namespace envoy {
      14             : namespace admin {
      15             : namespace v3 {
      16             : class TapRequest;
      17             : }
      18             : } // namespace admin
      19             : } // namespace envoy
      20             : 
      21             : namespace Envoy {
      22             : namespace Extensions {
      23             : namespace Common {
      24             : namespace Tap {
      25             : 
      26             : class AdminHandler;
      27             : using AdminHandlerSharedPtr = std::shared_ptr<AdminHandler>;
      28             : 
      29             : /**
      30             :  * Singleton /tap admin handler for admin management of tap configurations and output. This
      31             :  * handler is not installed and active unless the tap configuration specifically configures it.
      32             :  * TODO(mattklein123): We should allow the admin handler to always be installed in read only mode
      33             :  *                     so it's easier to debug the active tap configuration.
      34             :  */
      35             : class AdminHandler : public Singleton::Instance,
      36             :                      public Extensions::Common::Tap::Sink,
      37             :                      Logger::Loggable<Logger::Id::tap> {
      38             : public:
      39             :   AdminHandler(OptRef<Server::Admin> admin, Event::Dispatcher& main_thread_dispatcher);
      40             :   ~AdminHandler() override;
      41             : 
      42             :   /**
      43             :    * Get the singleton admin handler. The handler will be created if it doesn't already exist,
      44             :    * otherwise the existing handler will be returned.
      45             :    */
      46             :   static AdminHandlerSharedPtr getSingleton(OptRef<Server::Admin> admin,
      47             :                                             Singleton::Manager& singleton_manager,
      48             :                                             Event::Dispatcher& main_thread_dispatcher);
      49             : 
      50             :   /**
      51             :    * Register a new extension config to the handler so that it can be admin managed.
      52             :    * @param config supplies the config to register.
      53             :    * @param config_id supplies the ID to use for managing the configuration. Multiple extensions
      54             :    *        can use the same ID so they can be managed in aggregate (e.g., an HTTP filter on
      55             :    *        many listeners).
      56             :    */
      57             :   void registerConfig(ExtensionConfig& config, const std::string& config_id);
      58             : 
      59             :   /**
      60             :    * Unregister an extension config from the handler.
      61             :    * @param config supplies the previously registered config.
      62             :    */
      63             :   void unregisterConfig(ExtensionConfig& config);
      64             : 
      65             :   // Extensions::Common::Tap::Sink
      66             :   PerTapSinkHandlePtr
      67             :   createPerTapSinkHandle(uint64_t trace_id,
      68             :                          envoy::config::tap::v3::OutputSink::OutputSinkTypeCase type) override;
      69             : 
      70             : private:
      71             :   /**
      72             :    * TraceBuffer internally buffers TraceWrappers in a vector. The size of the
      73             :    * internal buffer is determined on construction by max_buf_size. TraceBuffer will continue to
      74             :    * buffer traces via calls to bufferTrace until there is no remaining room in the buffer, or
      75             :    * traceList is called, transfering ownership of the buffered data.
      76             :    * Note that TraceBuffer is not threadsafe by itself - accesses to TraceBuffer need to be
      77             :    * serialized. Serialization is currently done by the main thread dispatcher.
      78             :    */
      79             :   class TraceBuffer {
      80             :     using TraceWrapper = envoy::data::tap::v3::TraceWrapper;
      81             : 
      82             :   public:
      83             :     TraceBuffer(uint64_t max_buf_size)
      84           0 :         : max_buf_size_(max_buf_size), buffer_(std::vector<TraceWrapper>()) {
      85           0 :       buffer_->reserve(max_buf_size);
      86           0 :     }
      87             : 
      88             :     // Buffers trace internally if there is space available
      89             :     // This function takes exclusive ownership of trace and may destroy the content of trace.
      90             :     // A unique_ptr is semantically more correct here, but a shared pointer is
      91             :     // needed for traces to be captured in lambda function (submitTrace).
      92             :     void bufferTrace(const std::shared_ptr<envoy::data::tap::v3::TraceWrapper>& trace);
      93             : 
      94             :     // Returns true if the trace buffer is full (reached max_buf_size_) false otherwise
      95           0 :     bool full() const {
      96           0 :       if (!buffer_) {
      97           0 :         return false;
      98           0 :       }
      99           0 :       return (buffer_->size() == max_buf_size_);
     100           0 :     }
     101             : 
     102             :     // Return true if the buffer has already been flushed, false otherwise.
     103           0 :     bool flushed() const { return !buffer_; }
     104             : 
     105             :     // Take ownership of the internally managed trace list
     106           0 :     std::vector<TraceWrapper> flush() {
     107           0 :       std::vector<TraceWrapper> buffer = std::move(*buffer_);
     108           0 :       buffer_.reset(); // set optional to empty
     109           0 :       return buffer;
     110           0 :     }
     111             : 
     112             :   private:
     113             :     const size_t max_buf_size_; // Number of traces to buffer
     114             :     absl::optional<std::vector<TraceWrapper>> buffer_;
     115             :   };
     116             : 
     117             :   /**
     118             :    * This object's lifetime is tied to the lifetime of the admin_stream, and is responsible for
     119             :    * managing all data that has lifetime tied to the admin_stream.
     120             :    */
     121             :   class AttachedRequest {
     122             :   public:
     123             :     AttachedRequest(AdminHandler* admin_handler, const envoy::admin::v3::TapRequest& tap_request,
     124             :                     Server::AdminStream* admin_stream);
     125           0 :     virtual ~AttachedRequest() = default;
     126             :     // Stream the protobuf message to the admin_stream using the configured format
     127             :     // Requires the admin_stream to be open
     128             :     virtual void streamMsg(const Protobuf::Message& message, bool end_stream = false);
     129             : 
     130             :     // Explicitly close the admin_stream. Stream must be open.
     131             :     virtual void endStream();
     132             : 
     133             :     // Factory method for AttachedRequests - uses protobuf input to determine the subtype of
     134             :     // AttachedRequest to create
     135             :     static std::shared_ptr<AttachedRequest>
     136             :     createAttachedRequest(AdminHandler* admin_handler,
     137             :                           const envoy::admin::v3::TapRequest& tap_request,
     138             :                           Server::AdminStream* admin_stream);
     139             : 
     140             :     // --------- Accessors ---------
     141             :     // Get a pointer to the internal trace buffer. This method only applies for
     142             :     // the Buffered sink type, but exists in the generic API to avoid
     143             :     // dynamic casting of the AttachedRequest type elsewhere
     144           0 :     virtual TraceBuffer* traceBuffer() const { return nullptr; }
     145           0 :     const std::string& id() const { return config_id_; }
     146           0 :     const envoy::config::tap::v3::TapConfig& config() const { return config_; }
     147           0 :     envoy::config::tap::v3::OutputSink::Format format() const {
     148           0 :       return config_.output_config().sinks()[0].format();
     149           0 :     }
     150             : 
     151             :   protected:
     152           0 :     Event::Dispatcher& dispatcher() { return main_thread_dispatcher_; }
     153           0 :     const Server::AdminStream* stream() const { return admin_stream_; }
     154             : 
     155             :   private:
     156             :     const std::string config_id_;
     157             :     const envoy::config::tap::v3::TapConfig config_;
     158             :     const Server::AdminStream* admin_stream_;
     159             :     Event::Dispatcher& main_thread_dispatcher_;
     160             :     friend class BaseAdminHandlerTest;
     161             :   };
     162             : 
     163             :   /**
     164             :    * AttachedRequest with additional data specific to the Buffered Sink type
     165             :    */
     166             :   class AttachedRequestBuffered : public AttachedRequest {
     167             :     // Callback fired on timer expiry
     168             :     void onTimeout(const std::weak_ptr<AttachedRequest>& attached_request);
     169             : 
     170             :   public:
     171           0 :     TraceBuffer* traceBuffer() const override { return trace_buffer_.get(); }
     172             : 
     173             :     AttachedRequestBuffered(AdminHandler* admin_handler,
     174             :                             const envoy::admin::v3::TapRequest& tap_request,
     175             :                             Server::AdminStream* admin_stream);
     176             : 
     177             :   private:
     178             :     Event::TimerPtr timer_;
     179             :     // Pointer to buffered traces, only exists if the sink type requires buffering multiple traces
     180             :     std::unique_ptr<TraceBuffer> trace_buffer_;
     181             :     friend class BufferedAdminHandlerTest; // For testing Purposes
     182             :   };
     183             : 
     184             :   struct AdminPerTapSinkHandle : public PerTapSinkHandle {
     185           0 :     AdminPerTapSinkHandle(AdminHandler& parent) : parent_(parent) {}
     186             : 
     187             :     // Extensions::Common::Tap::PerTapSinkHandle
     188             :     void submitTrace(TraceWrapperPtr&& trace,
     189             :                      envoy::config::tap::v3::OutputSink::Format format) override;
     190             : 
     191             :     AdminHandler& parent_;
     192             :   };
     193             : 
     194             :   /**
     195             :    * Sink for buffering a variable number of traces in a TraceBuffer
     196             :    */
     197             :   struct BufferedPerTapSinkHandle : public PerTapSinkHandle {
     198           0 :     BufferedPerTapSinkHandle(AdminHandler& parent) : parent_(parent) {}
     199             : 
     200             :     // Extensions::Common::Tap::PerTapSinkHandle
     201             :     void submitTrace(TraceWrapperPtr&& trace,
     202             :                      envoy::config::tap::v3::OutputSink::Format format) override;
     203             : 
     204             :     AdminHandler& parent_;
     205             :   };
     206             : 
     207             :   Http::Code handler(Http::HeaderMap& response_headers, Buffer::Instance& response,
     208             :                      Server::AdminStream& admin_stream);
     209             :   Http::Code badRequest(Buffer::Instance& response, absl::string_view error);
     210             : 
     211             :   Server::Admin& admin_;
     212             :   Event::Dispatcher& main_thread_dispatcher_;
     213             :   absl::node_hash_map<std::string, absl::node_hash_set<ExtensionConfig*>> config_id_map_;
     214             :   std::shared_ptr<AttachedRequest> attached_request_;
     215             :   friend class BaseAdminHandlerTest;     // For testing purposes
     216             :   friend class BufferedAdminHandlerTest; // For testing Purposes
     217             : };
     218             : 
     219             : } // namespace Tap
     220             : } // namespace Common
     221             : } // namespace Extensions
     222             : } // namespace Envoy

Generated by: LCOV version 1.15