Stats Accesslogger: support the scope singleton for limiting cardinality#43625
Stats Accesslogger: support the scope singleton for limiting cardinality#43625TAOXUY wants to merge 14 commits intoenvoyproxy:mainfrom
Conversation
|
CC @envoyproxy/api-shepherds: Your approval is needed for changes made to |
There was a problem hiding this comment.
Thanks for the contribution.
I always want to make the API simple and also easy to access for most general users. So, I won't prefer the way that need custom support from control plane (and I think this will not be supported in control plane, like Istio/EG, in a long time, that's say, it cannot make sense for most general users in long time)
So, if you like this feature, you can add a stats_prefix in the message Scope and use it in the stats logger directly, and document it clearly it will created a shared scope across multiple listeners and the hash or the stat_prefix of message Scope will be the unique identify.
Hi @wbpcode Thanks for the review and the feedback! I completely understand your point about keeping the API simple and accessible for general users, as well as the concerns regarding the timeline for control plane (like Istio/EG) support. However, we actually had an extensive discussion regarding this exact design choice in PR #40992. During that PR, we made decision on moving forward with the current design, namely adding a new resource for the global singleton registration/management. We agreed that directly configuring the singleton redundantly isn't ideal and as for istio, we can make changes to support those singleton resources. Given that this was previously thoroughly discussed and agreed upon there, I'd prefer to stick to the aligned approach unless there are new critical concerns that weren't covered. Let me know what you think! |
|
I I compromised at #40992 because you have paid too much time at that solution. TBH, until today, I still didn't see how can normal users benefit from #40992.
I agree it's not ideal but useful, simple and practical. And it actually be widely used in our code base. Even the dynamic config provider self are shared across listeners by this way. The tracer instances also use this way to be shared across listeners. We only need to ensure this way is not abused. In my personal opinion, practical and easy for users to use is always take the highest priority. We are design this feature as a tool to resolve problems rather than to design an artwork. Sure, it's only my personal opinion and preference, if we can show actual progress about this, |
Hi @wbpcode I wanted to clarify that the current PR actually supports a file-based subscription approach, which provides a practical path forward for OSS control planes like Istio or Envoy Gateway. Those control planes can use file-based(also dynamic configuring) xDS resources for these singletons today and I’ve even included a test case for this file-based approach in the integration tests to demonstrate how it works. The OSS control planes can extend with ADS-based configuring approach when needed. Let me know if this helps alleviate your concerns, or if you still feel a different approach would be better.
|
|
/retest |
1 similar comment
|
/retest |
|
Sorry, Tao. I still don't think it's a good idea before I see actual progress in control plane. File based xDS sure works good, but in actual practices, we may cannot mount the file into Envoy pod. That's say, the users need to pre-mounted the configuration file and cannot actually configure it dynamically. In another word, I didn't see the advantage except bring complexity and users' chaos. But I am not tough in this type technical debating because IMO, any solution can resolve problem is good solution. I try to keep my mind open. Let's ping @ggreenway for some input or suggestions. @ggreenway is initial designer of this extension and should have a clear understanding about the extension and how it should work for users. |
|
Another idea in my mind is that we should make loggers shared across all listeners based on singleton, like what we did to tracers. Then loggers and tracers will works in same way |
Thx for suggestions. Users can have different stats accesslogger configs for different listeners so this isn't ideal. |
|
@wbpcode PTAL on API |
|
@ggreenway ready to review |
|
/retest |
|
@ggreenway can you take another look on the implementation(the API shouldn't change too much)? @wbpcode can you help review the API? thx! |
|
@TAOXUY please merge main. |
DONE |
|
/retest |
1 similar comment
|
/retest |
wbpcode
left a comment
There was a problem hiding this comment.
LGTM overall with only three minor comments. Thanks so much for your update. 🙇
Signed-off-by: Xuyang Tao <taoxuy@google.com>
Signed-off-by: Xuyang Tao <taoxuy@google.com>
|
/retest |
1 similar comment
|
/retest |
|
@ggreenway could you take another look? Thx! |
| string stat_prefix = 1 [(validate.rules).string = {min_len: 1}]; | ||
| // Deprecated: please use ``stats_scope.prefix`` instead. | ||
| // It will override ``stats_scope.prefix`` if non-empty. | ||
| string stat_prefix = 1; |
There was a problem hiding this comment.
As noted by @wbpcode you need to add an annotation to specify that it is deprecated
| message ScopeConfig { | ||
| // Max number of counters allowed in this scope. 0 means no limit. | ||
| // When the limit is reached, new counters will not be created. | ||
| uint32 max_counters = 1; |
There was a problem hiding this comment.
But why not allow limiting to zero? What if I want to have 0 histograms to reduce memory use? That may not make sense for the stats access logger, but you're defining a common message, so this needs to be thought through in the general case.
| void setCleanupCallback(std::function<void()> callback) override { | ||
| cleanup_callback_ = std::move(callback); | ||
| } | ||
|
|
||
| ~IsolatedScopeImpl() override { | ||
| if (cleanup_callback_) { | ||
| cleanup_callback_(); | ||
| } | ||
| prefix_.free(store_.symbolTable()); | ||
| } |
There was a problem hiding this comment.
destructor should be ordered immediately after constructors.
|
|
||
| ScopeSharedPtr IsolatedStoreImpl::makeScope(StatName name, StatsMatcherSharedPtr matcher) { | ||
| return std::make_shared<IsolatedScopeImpl>(name, *this, std::move(matcher)); | ||
| return ScopeSharedPtr(new IsolatedScopeImpl(name, *this, std::move(matcher))); |
There was a problem hiding this comment.
Why did you change this? Should this be reverted?
| // [#protodoc-title: Scope] | ||
|
|
||
| // Configuration for limiting the number of stats in a scope. | ||
| message ScopeConfig { |
There was a problem hiding this comment.
Why is this a separate message, and not part of Scope? I think all the fields of both seem logically like part of ScopeConfig
|
|
||
| // The scope name, required for shared scopes. | ||
| // If empty, no sharing will happen. | ||
| string name = 4; |
There was a problem hiding this comment.
I don't think it makes sense to have both name and enable_sharing. I think just sharing_name or something would be enough, and empty means sharing is not enabled. That way there's no way to create an invalid config of enable_sharing is true and name is empty
| [] { return std::make_shared<ScopeProviderSingleton>(); }); | ||
|
|
||
| size_t hash = MessageUtil::hash(config); | ||
| absl::flat_hash_map<size_t, std::weak_ptr<Stats::Scope>>::iterator it = |
There was a problem hiding this comment.
| absl::flat_hash_map<size_t, std::weak_ptr<Stats::Scope>>::iterator it = | |
| auto it = |
|
|
||
| ScopeSharedPtr TestStore::makeScope(StatName name, StatsMatcherSharedPtr matcher) { | ||
| return std::make_shared<TestScope>(name, *this, std::move(matcher)); | ||
| return ScopeSharedPtr(new TestScope(name, *this, std::move(matcher))); |
|
/retest |
1 similar comment
|
/retest |
|
@ggreenway PTAL |
|
i think this is waiting on you @ggreenway |
|
@ggreenway PTAL |
ggreenway
left a comment
There was a problem hiding this comment.
This mostly LGTM, just a few small cleanup items
/wait
|
|
||
| ScopeSharedPtr TestStore::makeScope(StatName name, StatsMatcherSharedPtr matcher) { | ||
| return std::make_shared<TestScope>(name, *this, std::move(matcher)); | ||
| return ScopeSharedPtr(new TestScope(name, *this, std::move(matcher))); |
| "Either 'stat_prefix' or 'stats_scope' must be configured, but not both."); | ||
| } | ||
|
|
||
| #ifndef ENVOY_DISABLE_DEPRECATED_FEATURES |
There was a problem hiding this comment.
Use DEPRECATED_FEATURE_TEST instead of ifdef
| - source/common/formatter/stream_info_formatter.cc | ||
| - source/common/formatter/substitution_formatter.cc | ||
| - source/common/stats/tag_extractor_impl.cc | ||
| - source/common/stats/scope_provider_singleton.cc |
There was a problem hiding this comment.
this path doesn't exist; revert
Signed-off-by: Xuyang Tao <taoxuy@google.com>
Co-authored-by: Greg Greenway <ggreenway@apple.com> Signed-off-by: Xuyang Tao <taoxuy@google.com>

Commit Message:
Risk Level: lo
Testing: added
Docs Changes: updated
Release Notes: updated
Platform Specific Features: no