1
#pragma once
2

            
3
#include <vector>
4

            
5
#include "envoy/stats/sink.h"
6
#include "envoy/stats/stats.h"
7

            
8
#include "source/common/common/thread.h"
9
#include "source/common/common/thread_synchronizer.h"
10
#include "source/common/stats/metric_impl.h"
11

            
12
#include "absl/container/flat_hash_set.h"
13

            
14
namespace Envoy {
15
namespace Stats {
16

            
17
/**
18
 * Helper class for Store to manage memory for statistics.
19
 */
20
class Allocator {
21
public:
22
  static const char DecrementToZeroSyncPoint[];
23

            
24
1837628
  Allocator(SymbolTable& symbol_table) : symbol_table_(symbol_table) {}
25
  virtual ~Allocator();
26

            
27
  /**
28
   * @param name the full name of the stat.
29
   * @param tag_extracted_name the name of the stat with tag-values stripped out.
30
   * @param tags the tag values.
31
   * @return CounterSharedPtr a counter.
32
   */
33
  CounterSharedPtr makeCounter(StatName name, StatName tag_extracted_name,
34
                               const StatNameTagVector& stat_name_tags);
35

            
36
  /**
37
   * @param name the full name of the stat.
38
   * @param tag_extracted_name the name of the stat with tag-values stripped out.
39
   * @param stat_name_tags the tag values.
40
   * @return GaugeSharedPtr a gauge.
41
   */
42
  GaugeSharedPtr makeGauge(StatName name, StatName tag_extracted_name,
43
                           const StatNameTagVector& stat_name_tags, Gauge::ImportMode import_mode);
44

            
45
  /**
46
   * @param name the full name of the stat.
47
   * @param tag_extracted_name the name of the stat with tag-values stripped out.
48
   * @param tags the tag values.
49
   * @return TextReadoutSharedPtr a text readout.
50
   */
51
  TextReadoutSharedPtr makeTextReadout(StatName name, StatName tag_extracted_name,
52
                                       const StatNameTagVector& stat_name_tags);
53
259091004
  SymbolTable& symbolTable() { return symbol_table_; }
54
6
  const SymbolTable& constSymbolTable() const { return symbol_table_; }
55

            
56
  /**
57
   * Iterate over all stats. Note, that implementations can potentially hold on to a mutex that
58
   * will deadlock if the passed in functors try to create or delete a stat.
59
   * @param f_size functor that is provided the current number of all stats. Note that this is
60
   * called only once, prior to any calls to f_stat.
61
   * @param f_stat functor that is provided one stat at a time from the stats container.
62
   */
63
  void forEachCounter(SizeFn, StatFn<Counter>) const;
64
  void forEachGauge(SizeFn, StatFn<Gauge>) const;
65
  void forEachTextReadout(SizeFn, StatFn<TextReadout>) const;
66

            
67
  /**
68
   * Iterate over all stats that need to be flushed to sinks. Note, that implementations can
69
   * potentially hold on to a mutex that will deadlock if the passed in functors try to create
70
   * or delete a stat.
71
   * @param f_size functor that is provided the number of all stats that will be flushed to sinks.
72
   * Note that this is called only once, prior to any calls to f_stat.
73
   * @param f_stat functor that is provided one stat that will be flushed to sinks, at a time.
74
   */
75
  void forEachSinkedCounter(SizeFn f_size, StatFn<Counter> f_stat) const;
76
  void forEachSinkedGauge(SizeFn f_size, StatFn<Gauge> f_stat) const;
77
  void forEachSinkedTextReadout(SizeFn f_size, StatFn<TextReadout> f_stat) const;
78

            
79
  /**
80
   * Set the predicates to filter stats for sink.
81
   */
82
  void setSinkPredicates(std::unique_ptr<SinkPredicates>&& sink_predicates);
83
#ifndef ENVOY_CONFIG_COVERAGE
84
  void debugPrint();
85
#endif
86

            
87
  /**
88
   * @return a thread synchronizer object used for reproducing a race-condition in tests.
89
   */
90
29659601
  Thread::ThreadSynchronizer& sync() { return sync_; }
91

            
92
  /**
93
   * @return whether the allocator's mutex is locked, exposed for testing purposes.
94
   */
95
  bool isMutexLockedForTest();
96

            
97
  /**
98
   * Mark rejected stats as deleted by moving them to a different vector, so they don't show up
99
   * when iterating over stats, but prevent crashes when trying to access references to them.
100
   * Note that allocating a stat with the same name after calling this will
101
   * return a new stat. Hence callers should seek to avoid this situation, as is
102
   * done in ThreadLocalStore.
103
   */
104
  void markCounterForDeletion(const CounterSharedPtr& counter);
105
  void markGaugeForDeletion(const GaugeSharedPtr& gauge);
106
  void markTextReadoutForDeletion(const TextReadoutSharedPtr& text_readout);
107

            
108
protected:
109
  virtual Counter* makeCounterInternal(StatName name, StatName tag_extracted_name,
110
                                       const StatNameTagVector& stat_name_tags);
111

            
112
private:
113
  template <class BaseClass> friend class StatsSharedImpl;
114
  friend class CounterImpl;
115
  friend class GaugeImpl;
116
  friend class TextReadoutImpl;
117

            
118
  // A mutex is needed here to protect both the stats_ object from both
119
  // alloc() and free() operations. Although alloc() operations are called under existing locking,
120
  // free() operations are made from the destructors of the individual stat objects, which are not
121
  // protected by locks.
122
  mutable Thread::MutexBasicLockable mutex_;
123

            
124
  StatSet<Counter> counters_ ABSL_GUARDED_BY(mutex_);
125
  StatSet<Gauge> gauges_ ABSL_GUARDED_BY(mutex_);
126
  StatSet<TextReadout> text_readouts_ ABSL_GUARDED_BY(mutex_);
127

            
128
  template <typename StatType> using StatPointerSet = absl::flat_hash_set<StatType*>;
129
  // Stat pointers that participate in the flush to sink process.
130
  StatPointerSet<Counter> sinked_counters_ ABSL_GUARDED_BY(mutex_);
131
  StatPointerSet<Gauge> sinked_gauges_ ABSL_GUARDED_BY(mutex_);
132
  StatPointerSet<TextReadout> sinked_text_readouts_ ABSL_GUARDED_BY(mutex_);
133

            
134
  // Predicates used to filter stats to be flushed.
135
  std::unique_ptr<SinkPredicates> sink_predicates_;
136
  SymbolTable& symbol_table_;
137

            
138
  Thread::ThreadSynchronizer sync_;
139

            
140
  // Retain storage for deleted stats; these are no longer in maps because
141
  // the matcher-pattern was established after they were created. Since the
142
  // stats are held by reference in code that expects them to be there, we
143
  // can't actually delete the stats.
144
  //
145
  // It seems like it would be better to have each client that expects a stat
146
  // to exist to hold it as (e.g.) a CounterSharedPtr rather than a Counter&
147
  // but that would be fairly complex to change.
148
  std::vector<CounterSharedPtr> deleted_counters_ ABSL_GUARDED_BY(mutex_);
149
  std::vector<GaugeSharedPtr> deleted_gauges_ ABSL_GUARDED_BY(mutex_);
150
  std::vector<TextReadoutSharedPtr> deleted_text_readouts_ ABSL_GUARDED_BY(mutex_);
151
};
152

            
153
} // namespace Stats
154
} // namespace Envoy