-
Notifications
You must be signed in to change notification settings - Fork 5.5k
Stats: Filter stats to be flushed to sinks #18805
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
deb76f8
6215133
5c593e3
e0f6a99
58d423a
d82fb8f
b8c7472
e0ddece
9b29368
c669b51
97d10c4
dee92bf
bfb1f42
cd77cb3
e5a3439
a4d76cb
1d27687
722e5ec
260ff78
7d96f81
670d7a1
948f2c2
90790a0
eff2e29
cec764f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,6 +18,9 @@ | |
| namespace Envoy { | ||
| namespace Stats { | ||
|
|
||
| class Sink; | ||
| class SinkPredicates; | ||
|
|
||
| /** | ||
| * Abstract interface for allocating statistics. Implementations can | ||
| * be created utilizing a single fixed-size block suitable for | ||
|
|
@@ -84,6 +87,18 @@ class Allocator { | |
| virtual void forEachTextReadout(std::function<void(std::size_t)> f_size, | ||
| std::function<void(Stats::TextReadout&)> f_stat) const PURE; | ||
|
|
||
| virtual void forEachSinkedCounter(std::function<void(std::size_t)> f_size, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. optional: wdyt of having
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
| std::function<void(Stats::Counter&)> f_stat) const PURE; | ||
| virtual void forEachSinkedGauge(std::function<void(std::size_t)> f_size, | ||
| std::function<void(Stats::Gauge&)> f_stat) const PURE; | ||
| virtual void forEachSinkedTextReadout(std::function<void(std::size_t)> f_size, | ||
| std::function<void(Stats::TextReadout&)> f_stat) const PURE; | ||
|
|
||
| /** | ||
| * Set the predicates to filter stats for sink. | ||
| */ | ||
| virtual void setSinkPredicates(const SinkPredicates& sink_predicates) PURE; | ||
|
|
||
| // TODO(jmarantz): create a parallel mechanism to instantiate histograms. At | ||
| // the moment, histograms don't fit the same pattern of counters and gauges | ||
| // as they are not actually created in the context of a stats allocator. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -48,6 +48,23 @@ class MetricSnapshot { | |
| virtual SystemTime snapshotTime() const PURE; | ||
| }; | ||
|
|
||
| /** | ||
| * A class to define predicates to filter stats for flushing to sinks. | ||
| */ | ||
| class SinkPredicates { | ||
| public: | ||
| virtual ~SinkPredicates() = default; | ||
|
|
||
| /// @return true if @param counter needs to be flushed to sinks. | ||
| virtual bool includeCounter(const Counter& counter) const PURE; | ||
| /// @return true if @param gague needs to be flushed to sinks. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. style: empty line after each method before next doc-comment
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed |
||
| virtual bool includeGauge(const Gauge& gauge) const PURE; | ||
| /// @return true if @param text_readout needs to be flushed to sinks. | ||
| virtual bool includeTextReadout(const TextReadout& text_readout) const PURE; | ||
| /// @return true if @param histogram needs to be flushed to sinks. | ||
| virtual bool includeHistogram(const Histogram& histogram) const PURE; | ||
| }; | ||
|
|
||
| /** | ||
| * A sink for stats. Each sink is responsible for writing stats to a backing store. | ||
| */ | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -24,6 +24,7 @@ class Instance; | |
| namespace Stats { | ||
|
|
||
| class Sink; | ||
| class SinkPredicates; | ||
|
|
||
| /** | ||
| * A store for all known counters, gauges, and timers. | ||
|
|
@@ -65,6 +66,21 @@ class Store : public Scope { | |
|
|
||
| virtual void forEachTextReadout(std::function<void(std::size_t)> f_size, | ||
| std::function<void(Stats::TextReadout&)> f_stat) const PURE; | ||
|
|
||
| virtual void forEachHistogram(std::function<void(std::size_t)> f_size, | ||
| std::function<void(Stats::ParentHistogram&)> f_stat) const PURE; | ||
| /** | ||
| * Iterate over all stats that need to be flushed for sink. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. doxygen params for these
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My older comments were actually not correct :-( Fixed. |
||
| */ | ||
| virtual void forEachSinkedCounter(std::function<void(std::size_t)> f_size, | ||
| std::function<void(Stats::Counter&)> f_stat) const PURE; | ||
| virtual void forEachSinkedGauge(std::function<void(std::size_t)> f_size, | ||
| std::function<void(Stats::Gauge&)> f_stat) const PURE; | ||
| virtual void forEachSinkedTextReadout(std::function<void(std::size_t)> f_size, | ||
| std::function<void(Stats::TextReadout&)> f_stat) const PURE; | ||
| virtual void | ||
| forEachSinkedHistogram(std::function<void(std::size_t)> f_size, | ||
| std::function<void(Stats::ParentHistogram&)> f_stat) const PURE; | ||
| }; | ||
|
|
||
| using StorePtr = std::unique_ptr<Store>; | ||
|
|
@@ -123,6 +139,11 @@ class StoreRoot : public Store { | |
| * method would be asserted. | ||
| */ | ||
| virtual void mergeHistograms(PostMergeCb merge_complete_cb) PURE; | ||
|
|
||
| /** | ||
| * Set the predicates to filter stats for sink. | ||
| */ | ||
| virtual void setSinkPredicates(const SinkPredicates& sink_predicates) PURE; | ||
| }; | ||
|
|
||
| using StoreRootPtr = std::unique_ptr<StoreRoot>; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,6 +3,7 @@ | |
| #include <algorithm> | ||
| #include <cstdint> | ||
|
|
||
| #include "envoy/stats/sink.h" | ||
| #include "envoy/stats/stats.h" | ||
| #include "envoy/stats/symbol_table.h" | ||
|
|
||
|
|
@@ -144,6 +145,7 @@ class CounterImpl : public StatsSharedImpl<Counter> { | |
| void removeFromSetLockHeld() ABSL_EXCLUSIVE_LOCKS_REQUIRED(alloc_.mutex_) override { | ||
| const size_t count = alloc_.counters_.erase(statName()); | ||
| ASSERT(count == 1); | ||
| alloc_.sinked_counters_.erase(this); | ||
| } | ||
|
|
||
| // Stats::Counter | ||
|
|
@@ -188,6 +190,7 @@ class GaugeImpl : public StatsSharedImpl<Gauge> { | |
| void removeFromSetLockHeld() override ABSL_EXCLUSIVE_LOCKS_REQUIRED(alloc_.mutex_) { | ||
| const size_t count = alloc_.gauges_.erase(statName()); | ||
| ASSERT(count == 1); | ||
| alloc_.sinked_gauges_.erase(this); | ||
| } | ||
|
|
||
| // Stats::Gauge | ||
|
|
@@ -260,6 +263,7 @@ class TextReadoutImpl : public StatsSharedImpl<TextReadout> { | |
| void removeFromSetLockHeld() ABSL_EXCLUSIVE_LOCKS_REQUIRED(alloc_.mutex_) override { | ||
| const size_t count = alloc_.text_readouts_.erase(statName()); | ||
| ASSERT(count == 1); | ||
| alloc_.sinked_text_readouts_.erase(this); | ||
| } | ||
|
|
||
| // Stats::TextReadout | ||
|
|
@@ -289,6 +293,11 @@ CounterSharedPtr AllocatorImpl::makeCounter(StatName name, StatName tag_extracte | |
| } | ||
| auto counter = CounterSharedPtr(makeCounterInternal(name, tag_extracted_name, stat_name_tags)); | ||
| counters_.insert(counter.get()); | ||
| // Add counter to sinked_counters_ if it matches the sink predicate. | ||
| if (sink_predicates_ && sink_predicates_->includeCounter(*counter)) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: |
||
| auto val = sinked_counters_.insert(counter.get()); | ||
| ASSERT(val.second); | ||
| } | ||
| return counter; | ||
| } | ||
|
|
||
|
|
@@ -305,6 +314,11 @@ GaugeSharedPtr AllocatorImpl::makeGauge(StatName name, StatName tag_extracted_na | |
| auto gauge = | ||
| GaugeSharedPtr(new GaugeImpl(name, *this, tag_extracted_name, stat_name_tags, import_mode)); | ||
| gauges_.insert(gauge.get()); | ||
| // Add gauge to sinked_gauges_ if it matches the sink predicate. | ||
| if (sink_predicates_ && sink_predicates_->includeGauge(*gauge)) { | ||
| auto val = sinked_gauges_.insert(gauge.get()); | ||
| ASSERT(val.second); | ||
| } | ||
| return gauge; | ||
| } | ||
|
|
||
|
|
@@ -320,6 +334,11 @@ TextReadoutSharedPtr AllocatorImpl::makeTextReadout(StatName name, StatName tag_ | |
| auto text_readout = | ||
| TextReadoutSharedPtr(new TextReadoutImpl(name, *this, tag_extracted_name, stat_name_tags)); | ||
| text_readouts_.insert(text_readout.get()); | ||
| // Add text_readout to sinked_text_readouts_ if it matches the sink predicate. | ||
| if (sink_predicates_ && sink_predicates_->includeTextReadout(*text_readout)) { | ||
| auto val = sinked_text_readouts_.insert(text_readout.get()); | ||
| ASSERT(val.second); | ||
| } | ||
| return text_readout; | ||
| } | ||
|
|
||
|
|
@@ -369,6 +388,71 @@ void AllocatorImpl::forEachTextReadout(std::function<void(std::size_t)> f_size, | |
| } | ||
| } | ||
|
|
||
| void AllocatorImpl::forEachSinkedCounter(std::function<void(std::size_t)> f_size, | ||
| std::function<void(Stats::Counter&)> f_stat) const { | ||
| if (sink_predicates_ != nullptr) { | ||
| Thread::LockGuard lock(mutex_); | ||
| f_size(sinked_counters_.size()); | ||
| for (auto counter : sinked_counters_) { | ||
| f_stat(*counter); | ||
| } | ||
| } else { | ||
| forEachCounter(f_size, f_stat); | ||
| } | ||
| } | ||
|
|
||
| void AllocatorImpl::forEachSinkedGauge(std::function<void(std::size_t)> f_size, | ||
| std::function<void(Stats::Gauge&)> f_stat) const { | ||
| if (sink_predicates_ != nullptr) { | ||
| Thread::LockGuard lock(mutex_); | ||
| f_size(sinked_gauges_.size()); | ||
| for (auto gauge : sinked_gauges_) { | ||
| f_stat(*gauge); | ||
| } | ||
| } else { | ||
| forEachGauge(f_size, f_stat); | ||
| } | ||
| } | ||
|
|
||
| void AllocatorImpl::forEachSinkedTextReadout( | ||
| std::function<void(std::size_t)> f_size, | ||
| std::function<void(Stats::TextReadout&)> f_stat) const { | ||
| if (sink_predicates_ != nullptr) { | ||
| Thread::LockGuard lock(mutex_); | ||
| f_size(sinked_text_readouts_.size()); | ||
| for (auto text_readout : sinked_text_readouts_) { | ||
| f_stat(*text_readout); | ||
| } | ||
| } else { | ||
| forEachTextReadout(f_size, f_stat); | ||
| } | ||
| } | ||
|
|
||
| void AllocatorImpl::setSinkPredicates(const SinkPredicates& sink_predicates) { | ||
| Thread::LockGuard lock(mutex_); | ||
| ASSERT(sink_predicates_ == nullptr); | ||
| sink_predicates_ = &sink_predicates; | ||
|
|
||
| // Add counters to the set of sinked counters. | ||
| for (auto& counter : counters_) { | ||
| if (sink_predicates_->includeCounter(*counter)) { | ||
| sinked_counters_.emplace(counter); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't you clear all of these before this function is called? Not sure when this can get called but seems like the safe thing to do? If not can you comment why?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The function is meant to be called just once, but there's nothing enforcing this other than the check that sink_predicates_ is nullptr further up in this method. Added lines to clear the sets of sinked stats. |
||
| } | ||
| } | ||
| // Add gauges to the set of sinked gauges. | ||
| for (auto& gauge : gauges_) { | ||
| if (sink_predicates_->includeGauge(*gauge)) { | ||
| sinked_gauges_.insert(gauge); | ||
| } | ||
| } | ||
| // Add text_readouts to the set of sinked text readouts. | ||
| for (auto& text_readout : text_readouts_) { | ||
| if (sink_predicates_->includeTextReadout(*text_readout)) { | ||
| sinked_text_readouts_.insert(text_readout); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void AllocatorImpl::markCounterForDeletion(const CounterSharedPtr& counter) { | ||
| Thread::LockGuard lock(mutex_); | ||
| auto iter = counters_.find(counter->statName()); | ||
|
|
@@ -380,6 +464,7 @@ void AllocatorImpl::markCounterForDeletion(const CounterSharedPtr& counter) { | |
| // Duplicates are ASSERTed in ~AllocatorImpl. | ||
| deleted_counters_.emplace_back(*iter); | ||
| counters_.erase(iter); | ||
| sinked_counters_.erase(counter.get()); | ||
| } | ||
|
|
||
| void AllocatorImpl::markGaugeForDeletion(const GaugeSharedPtr& gauge) { | ||
|
|
@@ -393,6 +478,7 @@ void AllocatorImpl::markGaugeForDeletion(const GaugeSharedPtr& gauge) { | |
| // Duplicates are ASSERTed in ~AllocatorImpl. | ||
| deleted_gauges_.emplace_back(*iter); | ||
| gauges_.erase(iter); | ||
| sinked_gauges_.erase(gauge.get()); | ||
| } | ||
|
|
||
| void AllocatorImpl::markTextReadoutForDeletion(const TextReadoutSharedPtr& text_readout) { | ||
|
|
@@ -406,6 +492,7 @@ void AllocatorImpl::markTextReadoutForDeletion(const TextReadoutSharedPtr& text_ | |
| // Duplicates are ASSERTed in ~AllocatorImpl. | ||
| deleted_text_readouts_.emplace_back(*iter); | ||
| text_readouts_.erase(iter); | ||
| sinked_text_readouts_.erase(text_readout.get()); | ||
| } | ||
|
|
||
| } // namespace Stats | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
doxygen for this method.