Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions include/envoy/stats/stats.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,30 @@ class Metric {
*/
virtual StatName tagExtractedStatName() const PURE;

// Function to be called from iterateTagStatNames passing name and value as StatNames.
using TagStatNameIterFn = std::function<bool(StatName, StatName)>;

/**
* Iterates over all tags, calling a functor for each name/value pair. The
* functor can return 'true' to continue or 'false' to stop the
* iteration.
*
* @param fn The functor to call for StatName pair.
*/
virtual void iterateTagStatNames(const TagStatNameIterFn& fn) const PURE;

// Function to be called from iterateTags passing name and value as const Tag&.
using TagIterFn = std::function<bool(const Tag&)>;

/**
* Iterates over all tags, calling a functor for each one. The
* functor can return 'true' to continue or 'false' to stop the
* iteration.
*
* @param fn The functor to call for each Tag.
*/
virtual void iterateTags(const TagIterFn& fn) const PURE;

/**
* Indicates whether this metric has been updated since the server was started.
*/
Expand Down
36 changes: 28 additions & 8 deletions source/common/stats/metric_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -46,33 +46,53 @@ StatName MetricImpl::tagExtractedStatName() const {
return stat_name;
}

std::vector<Tag> MetricImpl::tags() const {
std::vector<Tag> tags;
void MetricImpl::iterateTagStatNames(const TagStatNameIterFn& fn) const {
enum { TagExtractedName, TagName, TagValue } state = TagExtractedName;
Tag tag;
const SymbolTable& symbol_table = symbolTable();
StatName key;
Comment thread
jmarantz marked this conversation as resolved.
Outdated

// StatNameList maintains a linear ordered collection of StatNames, and we
// are mapping that into a tag-extracted name (the first element), followed
// by alternating TagName and TagValue. So we use a little state machine
// as we iterate through the stat_names_.
stat_names_.iterate([&tags, &state, &tag, &symbol_table](StatName stat_name) -> bool {
stat_names_.iterate([&state, &key, &fn](StatName stat_name) -> bool {
switch (state) {
case TagExtractedName:
state = TagName;
break;
case TagName:
tag.name_ = symbol_table.toString(stat_name);
key = stat_name;
state = TagValue;
break;
case TagValue:
tag.value_ = symbol_table.toString(stat_name);
tags.emplace_back(tag);
if (!fn(key, stat_name)) {
return false; // early exit.
}
state = TagName;
break;
}
return true;
});
ASSERT(state != TagValue);
}

void MetricImpl::iterateTags(const TagIterFn& fn) const {
const SymbolTable& symbol_table = symbolTable();
iterateTagStatNames([&fn, &symbol_table](StatName name, StatName value) -> bool {
return fn(Tag{symbol_table.toString(name), symbol_table.toString(value)});
});
}

std::vector<Tag> MetricImpl::tags() const {
std::vector<Tag> tags;

// StatNameList maintains a linear ordered collection of StatNames, and we
// are mapping that into a tag-extracted name (the first element), followed
// by alternating TagName and TagValue. So we use a little state machine
// as we iterate through the stat_names_.
Comment thread
jmarantz marked this conversation as resolved.
Outdated
iterateTags([&tags](const Tag& tag) -> bool {
tags.emplace_back(tag);
return true;
});
return tags;
}

Expand Down
2 changes: 2 additions & 0 deletions source/common/stats/metric_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ class MetricImpl : public virtual Metric {
std::string tagExtractedName() const override;
std::vector<Tag> tags() const override;
StatName tagExtractedStatName() const override;
void iterateTagStatNames(const TagStatNameIterFn& fn) const override;
void iterateTags(const TagIterFn& fn) const override;

protected:
/**
Expand Down
19 changes: 19 additions & 0 deletions test/mocks/stats/mocks.cc
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,25 @@ void MockMetric::setTagExtractedName(absl::string_view name) {
std::make_unique<StatNameManagedStorage>(tagExtractedName(), *symbol_table_);
}

void MockMetric::iterateTags(const TagIterFn& fn) const {
for (const Tag& tag : tags_) {
if (!fn(tag)) {
return;
}
}
}

void MockMetric::iterateTagStatNames(const TagStatNameIterFn& fn) const {
SymbolTable& symbol_table = const_cast<SymbolTable&>(symbolTable());
for (const Tag& tag : tags_) {
StatNameManagedStorage name(tag.name_, symbol_table);
StatNameManagedStorage value(tag.value_, symbol_table);
if (!fn(name.statName(), value.statName())) {
return;
}
}
}

void MockMetric::MetricName::MetricName::operator=(absl::string_view name) {
name_ = std::string(name);
stat_name_storage_ = std::make_unique<StatNameStorage>(name, mock_metric_.symbolTable());
Expand Down
2 changes: 2 additions & 0 deletions test/mocks/stats/mocks.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ class MockMetric : public virtual Metric {
return tag_extracted_name_.empty() ? name() : tag_extracted_name_;
}
StatName tagExtractedStatName() const override { return tag_extracted_stat_name_->statName(); }
void iterateTagStatNames(const TagStatNameIterFn& fn) const override;
void iterateTags(const TagIterFn& fn) const override;

Test::Global<FakeSymbolTableImpl> symbol_table_; // Must outlive name_.
MetricName name_;
Expand Down