LCOV - code coverage report
Current view: top level - source/common/stats - metric_impl.h (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 19 23 82.6 %
Date: 2024-01-05 06:35:25 Functions: 37 54 68.5 %

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include <string>
       4             : #include <vector>
       5             : 
       6             : #include "envoy/stats/allocator.h"
       7             : #include "envoy/stats/stats.h"
       8             : #include "envoy/stats/tag.h"
       9             : 
      10             : #include "source/common/common/assert.h"
      11             : #include "source/common/stats/symbol_table.h"
      12             : 
      13             : namespace Envoy {
      14             : namespace Stats {
      15             : 
      16             : /**
      17             :  * Helper class for implementing Metrics. This does not participate in any
      18             :  * inheritance chains, but can be instantiated by classes that do. It just
      19             :  * implements the mechanics of representing the name, tag-extracted-name,
      20             :  * and all tags as a StatNameList.
      21             :  */
      22             : class MetricHelper {
      23             : public:
      24             :   MetricHelper(StatName name, StatName tag_extracted_name, const StatNameTagVector& stat_name_tags,
      25             :                SymbolTable& symbol_table);
      26             :   ~MetricHelper();
      27             : 
      28             :   StatName statName() const;
      29             :   std::string name(const SymbolTable& symbol_table) const;
      30             :   TagVector tags(const SymbolTable& symbol_table) const;
      31             :   StatName tagExtractedStatName() const;
      32             :   void iterateTagStatNames(const Metric::TagStatNameIterFn& fn) const;
      33      392190 :   void clear(SymbolTable& symbol_table) { stat_names_.clear(symbol_table); }
      34             : 
      35             :   // Hasher for metrics.
      36             :   struct Hash {
      37             :     using is_transparent = void; // NOLINT(readability-identifier-naming)
      38      750139 :     size_t operator()(const Metric* a) const { return a->statName().hash(); }
      39      661506 :     size_t operator()(StatName a) const { return a.hash(); }
      40             :   };
      41             : 
      42             :   // Comparator for metrics.
      43             :   struct Compare {
      44             :     using is_transparent = void; // NOLINT(readability-identifier-naming)
      45       22684 :     bool operator()(const Metric* a, const Metric* b) const {
      46       22684 :       return a->statName() == b->statName();
      47       22684 :     }
      48      355938 :     bool operator()(const Metric* a, StatName b) const { return a->statName() == b; }
      49             :   };
      50             : 
      51             : private:
      52             :   StatNameList stat_names_;
      53             : };
      54             : 
      55             : // An unordered set of stat pointers. which keys off Metric::statName().
      56             : // This necessitates a custom comparator and hasher, using the StatNamePtr's
      57             : // own StatNamePtrHash and StatNamePtrCompare operators.
      58             : //
      59             : // This is used by AllocatorImpl for counters, gauges, and text-readouts, and
      60             : // is also used by thread_local_store.h for histograms.
      61             : template <class StatType>
      62             : using StatSet = absl::flat_hash_set<StatType*, MetricHelper::Hash, MetricHelper::Compare>;
      63             : 
      64             : /**
      65             :  * Partial implementation of the Metric interface on behalf of Counters, Gauges,
      66             :  * and Histograms. It leaves symbolTable() unimplemented so that implementations
      67             :  * of stats managed by an allocator, specifically Counters and Gauges, can keep
      68             :  * a reference to the allocator instead, and derive the symbolTable() from that.
      69             :  *
      70             :  * We templatize on the base class (Counter, Gauge, or Histogram), rather than
      71             :  * using multiple virtual inheritance, as this avoids the overhead of an extra
      72             :  * vptr per instance. This is important for stats because there can be many
      73             :  * stats in systems with large numbers of clusters and hosts, and a few 8-byte
      74             :  * pointers per-stat here and there can add up to significant amounts of memory.
      75             :  *
      76             :  * Note the delegation of the implementation to a helper class, which is neither
      77             :  * templatized nor virtual. This avoids having the compiler elaborate complete
      78             :  * copies of the underlying implementation for each base class during template
      79             :  * expansion.
      80             :  */
      81             : template <class BaseClass> class MetricImpl : public BaseClass {
      82             : public:
      83             :   MetricImpl(StatName name, StatName tag_extracted_name, const StatNameTagVector& stat_name_tags,
      84             :              SymbolTable& symbol_table)
      85      392190 :       : helper_(name, tag_extracted_name, stat_name_tags, symbol_table) {}
      86             : 
      87             :   // Empty construction of a MetricImpl; used for null stats.
      88             :   explicit MetricImpl(SymbolTable& symbol_table)
      89       43042 :       : MetricImpl(StatName(), StatName(), StatNameTagVector(), symbol_table) {}
      90             : 
      91           0 :   TagVector tags() const override { return helper_.tags(constSymbolTable()); }
      92     2412579 :   StatName statName() const override { return helper_.statName(); }
      93       38576 :   StatName tagExtractedStatName() const override { return helper_.tagExtractedStatName(); }
      94           0 :   void iterateTagStatNames(const Metric::TagStatNameIterFn& fn) const override {
      95           0 :     helper_.iterateTagStatNames(fn);
      96           0 :   }
      97             : 
      98      575706 :   const SymbolTable& constSymbolTable() const override {
      99             :     // Cast our 'this', which is of type `const MetricImpl*` to a non-const
     100             :     // pointer, so we can use it to call the subclass implementation of
     101             :     // symbolTable(). That will be returned as a non-const SymbolTable&,
     102             :     // which will become const on return.
     103             :     //
     104             :     // This pattern is used to share a single non-trivial implementation to
     105             :     // provide const and non-const variants of a method.
     106      575706 :     return const_cast<MetricImpl*>(this)->symbolTable();
     107      575706 :   }
     108      537129 :   std::string name() const override { return constSymbolTable().toString(this->statName()); }
     109       38576 :   std::string tagExtractedName() const override {
     110       38576 :     return constSymbolTable().toString(this->tagExtractedStatName());
     111       38576 :   }
     112             : 
     113             : protected:
     114      392190 :   void clear(SymbolTable& symbol_table) { helper_.clear(symbol_table); }
     115             : 
     116             : private:
     117             :   MetricHelper helper_;
     118             : };
     119             : 
     120             : } // namespace Stats
     121             : } // namespace Envoy

Generated by: LCOV version 1.15