/proc/self/cwd/source/common/stats/stat_merger.h
Line | Count | Source |
1 | | #pragma once |
2 | | |
3 | | #include "envoy/stats/store.h" |
4 | | |
5 | | #include "source/common/protobuf/protobuf.h" |
6 | | #include "source/common/stats/symbol_table.h" |
7 | | |
8 | | #include "absl/container/flat_hash_map.h" |
9 | | |
10 | | namespace Envoy { |
11 | | namespace Stats { |
12 | | |
13 | | // Responsible for the sensible merging of two instances of the same stat from two different |
14 | | // (typically hot restart parent+child) Envoy processes. |
15 | | class StatMerger { |
16 | | public: |
17 | | using DynamicsMap = absl::flat_hash_map<std::string, DynamicSpans>; |
18 | | |
19 | | // Holds state needed to construct StatName with mixed dynamic/symbolic |
20 | | // components, based on a map. |
21 | | class DynamicContext { |
22 | | public: |
23 | | DynamicContext(SymbolTable& symbol_table) |
24 | 797 | : symbol_table_(symbol_table), symbolic_pool_(symbol_table), dynamic_pool_(symbol_table) {} |
25 | | |
26 | | /** |
27 | | * Generates a StatName with mixed dynamic/symbolic components based on |
28 | | * the string and the dynamic_map obtained from encodeSegments. |
29 | | * |
30 | | * @param name The string corresponding to the desired StatName. |
31 | | * @param map a map indicating which spans of tokens in the stat-name are dynamic. |
32 | | * @return the generated StatName, valid as long as the DynamicContext. |
33 | | */ |
34 | | StatName makeDynamicStatName(const std::string& name, const DynamicsMap& map); |
35 | | |
36 | | private: |
37 | | SymbolTable& symbol_table_; |
38 | | StatNamePool symbolic_pool_; |
39 | | StatNameDynamicPool dynamic_pool_; |
40 | | SymbolTable::StoragePtr storage_ptr_; |
41 | | }; |
42 | | |
43 | | StatMerger(Stats::Store& target_store); |
44 | | ~StatMerger(); |
45 | | |
46 | | /** |
47 | | * Merge the values of stats_proto into stats_store. Counters are always |
48 | | * straightforward addition, while gauges default to addition but have |
49 | | * exceptions. |
50 | | * |
51 | | * @param counter_deltas map of counter changes from parent |
52 | | * @param gauges map of gauge changes from parent |
53 | | * @param dynamics information about which segments of the names are dynamic. |
54 | | */ |
55 | | void mergeStats(const Protobuf::Map<std::string, uint64_t>& counter_deltas, |
56 | | const Protobuf::Map<std::string, uint64_t>& gauges, |
57 | | const DynamicsMap& dynamics = DynamicsMap()); |
58 | | |
59 | | /** |
60 | | * Indicates that a gauge's value from the hot-restart parent should be |
61 | | * retained, combining it with the child data. By default, data is transferred |
62 | | * from parent gauges only during the hot-restart process, but the parent |
63 | | * contribution is subtracted from the child when the parent terminates. This |
64 | | * makes sense for gauges such as active connection counts, but is not |
65 | | * appropriate for server.hot_restart_generation. |
66 | | * |
67 | | * This function must be called immediately prior to destruction of the |
68 | | * StatMerger instance. |
69 | | * |
70 | | * @param gauge_name The gauge to be retained. |
71 | | */ |
72 | | void retainParentGaugeValue(Stats::StatName gauge_name); |
73 | | |
74 | | private: |
75 | | void mergeCounters(const Protobuf::Map<std::string, uint64_t>& counter_deltas, |
76 | | const DynamicsMap& dynamics_map); |
77 | | void mergeGauges(const Protobuf::Map<std::string, uint64_t>& gauges, |
78 | | const DynamicsMap& dynamics_map); |
79 | | |
80 | | StatNameHashSet parent_gauges_; |
81 | | // A stats Scope for our in-the-merging-process counters to live in. Scopes conceptually hold |
82 | | // shared_ptrs to the stats that live in them, with the question of which stats are living in a |
83 | | // given scope determined by which stat names have been accessed via that scope. E.g., if you |
84 | | // access a stat named "some.shared" directly through the ordinary store, and then access a |
85 | | // stat named "shared" in a scope configured with the prefix "some.", there is now a single |
86 | | // stat named some.shared pointed to by both. As another example, if you access the stat |
87 | | // "single" in the "some" scope, there will be a stat named "some.single" pointed to by just |
88 | | // that scope. Now, if you delete the scope, some.shared will stick around, but some.single |
89 | | // will be destroyed. |
90 | | // |
91 | | // All of that is relevant here because it is used to get a certain desired behavior. |
92 | | // Specifically, stats must be kept up to date with values from the parent throughout hot |
93 | | // restart, but once the restart completes, they must be dropped without a trace if the child has |
94 | | // not taken action (independent of the hot restart stat merging) that would lead to them getting |
95 | | // created in the store. By storing these stats in a scope (with an empty prefix), we can |
96 | | // preserve all stats throughout the hot restart. Then, when the restart completes, dropping |
97 | | // the scope will drop exactly those stats whose names have not already been accessed through |
98 | | // another store/scope. |
99 | | ScopeSharedPtr temp_scope_; |
100 | | }; |
101 | | |
102 | | } // namespace Stats |
103 | | } // namespace Envoy |