-
Notifications
You must be signed in to change notification settings - Fork 5.5k
stats: Shared scopes phase 1, changes scope APIs to use ScopeSharedPtr, leaving ScopePtr alias behind #19791
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 5 commits
dfac8eb
fa3229e
80a85ac
f3b90e7
a0782ea
6e81807
10c6ce3
b87e4d3
3e6e71d
1e54c9d
b7516cd
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 |
|---|---|---|
|
|
@@ -24,19 +24,48 @@ using CounterOptConstRef = absl::optional<std::reference_wrapper<const Counter>> | |
| using GaugeOptConstRef = absl::optional<std::reference_wrapper<const Gauge>>; | ||
| using HistogramOptConstRef = absl::optional<std::reference_wrapper<const Histogram>>; | ||
| using TextReadoutOptConstRef = absl::optional<std::reference_wrapper<const TextReadout>>; | ||
| using ScopePtr = std::unique_ptr<Scope>; | ||
| using ConstScopeSharedPtr = std::shared_ptr<const Scope>; | ||
| using ScopeSharedPtr = std::shared_ptr<Scope>; | ||
|
|
||
| // TODO(jmarantz): In the initial transformation to store Scope as shared_ptr, | ||
| // we don't change all the references, as that would result in an unreviewable | ||
| // PR that combines a small number of semantic changes and a large number of | ||
| // files with trivial changes. Furthermore, code that depends on the Envoy stats | ||
| // infrastructure that's not in this repo will stop compiling when we remove | ||
| // ScopePtr. We should fully remove this alias in a future PR and change all the | ||
| // references, once known parthers that might break from this change of a chance | ||
| // to do the global replace in their own repos. | ||
| using ScopePtr = ScopeSharedPtr; | ||
|
|
||
| template <class StatType> using IterateFn = std::function<bool(const RefcountPtr<StatType>&)>; | ||
|
|
||
| /** | ||
| * A named scope for stats. Scopes are a grouping of stats that can be acted on as a unit if needed | ||
| * (for example to free/delete all of them). | ||
| * | ||
| * We enable use of shared pointers for Scopes to make it possible for the admin | ||
| * stats handler to safely capture all the scope references and remain robust to | ||
| * other threads deleting those scopes while rendering an admin stats page. | ||
| * | ||
| * We use std::shared_ptr rather than Stats::RefcountPtr, which we use for other | ||
| * stats, because: | ||
| * * existing uses of shared_ptr<Scope> exist in the Wasm extension and would need | ||
| * to be rewritten to allow for RefcountPtr<Scope>. | ||
| * * the main advantage of RefcountPtr is it's smaller per instance by (IIRC) 16 | ||
| * bytes, but there are not typically enough scopes that the extra per-scope | ||
| * overhead would matter. | ||
| * * It's a little less coding to use enable_shared_from_this compared to adding | ||
| * a ref_count to the scope object, for each of its implementations. | ||
| */ | ||
| class Scope { | ||
| class Scope : public std::enable_shared_from_this<Scope> { | ||
| public: | ||
| virtual ~Scope() = default; | ||
|
|
||
| /** @return a shared_ptr for this */ | ||
| ScopeSharedPtr makeShared() { return shared_from_this(); } | ||
|
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. I think this should be named
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. good point: done. |
||
| /** @return a const shared_ptr for this */ | ||
| ConstScopeSharedPtr makeConstShared() const { return shared_from_this(); } | ||
|
|
||
| /** | ||
| * Allocate a new scope. NOTE: The implementation should correctly handle overlapping scopes | ||
| * that point to the same reference counted backing stats. This allows a new scope to be | ||
|
|
@@ -46,7 +75,7 @@ class Scope { | |
| * | ||
| * @param name supplies the scope's namespace prefix. | ||
| */ | ||
| virtual ScopePtr createScope(const std::string& name) PURE; | ||
| virtual ScopeSharedPtr createScope(const std::string& name) PURE; | ||
|
|
||
| /** | ||
| * Allocate a new scope. NOTE: The implementation should correctly handle overlapping scopes | ||
|
|
@@ -55,7 +84,7 @@ class Scope { | |
| * | ||
| * @param name supplies the scope's namespace prefix. | ||
| */ | ||
| virtual ScopePtr scopeFromStatName(StatName name) PURE; | ||
| virtual ScopeSharedPtr scopeFromStatName(StatName name) PURE; | ||
|
|
||
| /** | ||
| * Deliver an individual histogram value to all registered sinks. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -34,14 +34,20 @@ IsolatedStoreImpl::IsolatedStoreImpl(SymbolTable& symbol_table) | |
| return alloc_.makeTextReadout(name, name, StatNameTagVector{}); | ||
| }), | ||
| null_counter_(new NullCounterImpl(symbol_table)), | ||
| null_gauge_(new NullGaugeImpl(symbol_table)) {} | ||
| null_gauge_(new NullGaugeImpl(symbol_table)), | ||
| default_scope_(std::make_shared<ScopePrefixer>("", *this)) {} | ||
|
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. Can we run into a situation wherein we have a shared_ptr to ScopePrefixer for the admin panel, but not the underlying scope?
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 lifetime concerns are not changed by this PR; the Store needs to outlive all the Scopes declared from it. In general if you instantiate any Scope-derived object on the stack, and you will get some time of failure (e.g. a weak_ptr exception). That is why I changed default_scope_ to be allocated with make_shared, enabling #19693 to hold onto a reference to it, and mirroring the implementation in thread_local_store.cc. |
||
|
|
||
| ScopePtr IsolatedStoreImpl::createScope(const std::string& name) { | ||
| return std::make_unique<ScopePrefixer>(name, *this); | ||
| IsolatedStoreImpl::~IsolatedStoreImpl() = default; | ||
|
|
||
| ScopeSharedPtr IsolatedStoreImpl::createScope(const std::string& name) { | ||
| StatNameManagedStorage stat_name_storage(Utility::sanitizeStatsName(name), alloc_.symbolTable()); | ||
| return scopeFromStatName(stat_name_storage.statName()); | ||
| } | ||
|
|
||
| ScopePtr IsolatedStoreImpl::scopeFromStatName(StatName name) { | ||
| return std::make_unique<ScopePrefixer>(name, *this); | ||
| ScopeSharedPtr IsolatedStoreImpl::scopeFromStatName(StatName name) { | ||
| ScopeSharedPtr scope = std::make_shared<ScopePrefixer>(name, *this); | ||
| scopes_.push_back(scope); | ||
| return scope; | ||
| } | ||
|
|
||
| } // namespace Stats | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -132,6 +132,7 @@ class IsolatedStoreImpl : public StoreImpl { | |
| public: | ||
| IsolatedStoreImpl(); | ||
| explicit IsolatedStoreImpl(SymbolTable& symbol_table); | ||
| ~IsolatedStoreImpl() override; | ||
|
|
||
| // Stats::Scope | ||
| Counter& counterFromStatNameWithTags(const StatName& name, | ||
|
|
@@ -140,8 +141,8 @@ class IsolatedStoreImpl : public StoreImpl { | |
| Counter& counter = counters_.get(joiner.nameWithTags()); | ||
| return counter; | ||
| } | ||
| ScopePtr createScope(const std::string& name) override; | ||
| ScopePtr scopeFromStatName(StatName name) override; | ||
| ScopeSharedPtr createScope(const std::string& name) override; | ||
| ScopeSharedPtr scopeFromStatName(StatName name) override; | ||
| void deliverHistogramToSinks(const Histogram&, uint64_t) override {} | ||
| Gauge& gaugeFromStatNameWithTags(const StatName& name, StatNameTagVectorOptConstRef tags, | ||
| Gauge::ImportMode import_mode) override { | ||
|
|
@@ -234,10 +235,12 @@ class IsolatedStoreImpl : public StoreImpl { | |
|
|
||
| void forEachScope(SizeFn f_size, StatFn<const Scope> f_stat) const override { | ||
| if (f_size != nullptr) { | ||
| f_size(1); | ||
| f_size(scopes_.size() + 1); | ||
|
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. This is unrelated to this change but because of this change we can now do the API correctly? Is that right?
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. Sorry, which API are you referring to?
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.
|
||
| } | ||
| f_stat(*default_scope_); | ||
| for (const ScopeSharedPtr& scope : scopes_) { | ||
| f_stat(*scope); | ||
| } | ||
| const Scope& scope = *this; | ||
| f_stat(scope); | ||
| } | ||
|
|
||
| Stats::StatName prefix() const override { return StatName(); } | ||
|
|
@@ -265,6 +268,8 @@ class IsolatedStoreImpl : public StoreImpl { | |
| IsolatedStatsCache<TextReadout> text_readouts_; | ||
| RefcountPtr<NullCounterImpl> null_counter_; | ||
| RefcountPtr<NullGaugeImpl> null_gauge_; | ||
| ScopeSharedPtr default_scope_; | ||
| std::vector<ScopeSharedPtr> scopes_; | ||
| }; | ||
|
|
||
| } // 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.
?
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.
looks good; done by hand to avoid what I fear would be a DCO violation :) Committing shortly.