Line data Source code
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 392190 : 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 392190 : ASSERT(!stat_names_.populated()); 15 392190 : } 16 : 17 : MetricHelper::MetricHelper(StatName name, StatName tag_extracted_name, 18 392190 : 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 392190 : const uint32_t num_names = 2 + 2 * stat_name_tags.size(); 24 392190 : absl::FixedArray<StatName> names(num_names); 25 392190 : names[0] = name; 26 392190 : names[1] = tag_extracted_name; 27 392190 : int index = 1; 28 399796 : for (auto& stat_name_tag : stat_name_tags) { 29 57170 : names[++index] = stat_name_tag.first; 30 57170 : names[++index] = stat_name_tag.second; 31 57170 : } 32 392190 : symbol_table.populateList(names.begin(), num_names, stat_names_); 33 392190 : } 34 : 35 2412574 : StatName MetricHelper::statName() const { 36 2412574 : StatName stat_name; 37 2412574 : stat_names_.iterate([&stat_name](StatName s) -> bool { 38 2412561 : stat_name = s; 39 2412561 : return false; // Returning 'false' stops the iteration. 40 2412561 : }); 41 2412574 : return stat_name; 42 2412574 : } 43 : 44 38576 : 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 38576 : StatName tag_extracted_stat_name; 51 38576 : bool skip = true; 52 77152 : stat_names_.iterate([&tag_extracted_stat_name, &skip](StatName s) -> bool { 53 77152 : if (skip) { 54 38576 : skip = false; 55 38576 : return true; 56 38576 : } 57 38576 : tag_extracted_stat_name = s; 58 38576 : return false; // Returning 'false' stops the iteration. 59 77152 : }); 60 38576 : return tag_extracted_stat_name; 61 38576 : } 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