/proc/self/cwd/source/common/stats/metric_impl.cc
Line | Count | Source (jump to first uncovered line) |
1 | | #include "source/common/stats/metric_impl.h" |
2 | | |
3 | | #include "envoy/stats/tag.h" |
4 | | |
5 | | #include "source/common/stats/symbol_table.h" |
6 | | |
7 | | namespace Envoy { |
8 | | namespace Stats { |
9 | | |
10 | 52.9M | MetricHelper::~MetricHelper() { |
11 | | // The storage must be cleaned by a subclass of MetricHelper in its |
12 | | // destructor, because the symbol-table is owned by the subclass. |
13 | | // Simply call MetricHelper::clear() in the subclass dtor. |
14 | 52.9M | ASSERT(!stat_names_.populated()); |
15 | 52.9M | } |
16 | | |
17 | | MetricHelper::MetricHelper(StatName name, StatName tag_extracted_name, |
18 | 52.9M | const StatNameTagVector& stat_name_tags, SymbolTable& symbol_table) { |
19 | | // Encode all the names and tags into transient storage so we can count the |
20 | | // required bytes. 2 is added to account for the name and tag_extracted_name, |
21 | | // and we multiply the number of tags by 2 to account for the name and value |
22 | | // of each tag. |
23 | 52.9M | const uint32_t num_names = 2 + 2 * stat_name_tags.size(); |
24 | 52.9M | absl::FixedArray<StatName> names(num_names); |
25 | 52.9M | names[0] = name; |
26 | 52.9M | names[1] = tag_extracted_name; |
27 | 52.9M | int index = 1; |
28 | 52.9M | for (auto& stat_name_tag : stat_name_tags) { |
29 | 715k | names[++index] = stat_name_tag.first; |
30 | 715k | names[++index] = stat_name_tag.second; |
31 | 715k | } |
32 | 52.9M | symbol_table.populateList(names.begin(), num_names, stat_names_); |
33 | 52.9M | } |
34 | | |
35 | 394M | StatName MetricHelper::statName() const { |
36 | 394M | StatName stat_name; |
37 | 394M | stat_names_.iterate([&stat_name](StatName s) -> bool { |
38 | 394M | stat_name = s; |
39 | 394M | return false; // Returning 'false' stops the iteration. |
40 | 394M | }); |
41 | 394M | return stat_name; |
42 | 394M | } |
43 | | |
44 | 0 | StatName MetricHelper::tagExtractedStatName() const { |
45 | | // The name is the first element in stat_names_. The second is the |
46 | | // tag-extracted-name. We don't have random access in that format, |
47 | | // so we iterate through them, skipping the first element (name), |
48 | | // and terminating the iteration after capturing the tag-extracted |
49 | | // name by returning false from the lambda. |
50 | 0 | StatName tag_extracted_stat_name; |
51 | 0 | bool skip = true; |
52 | 0 | stat_names_.iterate([&tag_extracted_stat_name, &skip](StatName s) -> bool { |
53 | 0 | if (skip) { |
54 | 0 | skip = false; |
55 | 0 | return true; |
56 | 0 | } |
57 | 0 | tag_extracted_stat_name = s; |
58 | 0 | return false; // Returning 'false' stops the iteration. |
59 | 0 | }); |
60 | 0 | return tag_extracted_stat_name; |
61 | 0 | } |
62 | | |
63 | 0 | void MetricHelper::iterateTagStatNames(const Metric::TagStatNameIterFn& fn) const { |
64 | 0 | enum { Name, TagExtractedName, TagName, TagValue } state = Name; |
65 | 0 | StatName tag_name; |
66 | | |
67 | | // StatNameList maintains a linear ordered collection of StatNames, and we |
68 | | // are mapping that into a tag-extracted name (the first element), followed |
69 | | // by alternating TagName and TagValue. So we use a little state machine |
70 | | // as we iterate through the stat_names_. |
71 | 0 | stat_names_.iterate([&state, &tag_name, &fn](StatName stat_name) -> bool { |
72 | 0 | switch (state) { |
73 | 0 | case Name: |
74 | 0 | state = TagExtractedName; |
75 | 0 | break; |
76 | 0 | case TagExtractedName: |
77 | 0 | state = TagName; |
78 | 0 | break; |
79 | 0 | case TagName: |
80 | 0 | tag_name = stat_name; |
81 | 0 | state = TagValue; |
82 | 0 | break; |
83 | 0 | case TagValue: |
84 | 0 | state = TagName; |
85 | 0 | if (!fn(tag_name, stat_name)) { |
86 | 0 | return false; // early exit. |
87 | 0 | } |
88 | 0 | break; |
89 | 0 | } |
90 | 0 | return true; |
91 | 0 | }); |
92 | 0 | ASSERT(state != TagValue); |
93 | 0 | } |
94 | | |
95 | 0 | TagVector MetricHelper::tags(const SymbolTable& symbol_table) const { |
96 | 0 | TagVector tags; |
97 | 0 | iterateTagStatNames([&tags, &symbol_table](StatName name, StatName value) -> bool { |
98 | 0 | tags.emplace_back(Tag{symbol_table.toString(name), symbol_table.toString(value)}); |
99 | 0 | return true; |
100 | 0 | }); |
101 | 0 | return tags; |
102 | 0 | } |
103 | | |
104 | | } // namespace Stats |
105 | | } // namespace Envoy |