stats: refactor to enable non-hot-restart stats to have distinct representation from hot-restart stats.#3606
Conversation
…network issues when running under docker. Signed-off-by: Joshua Marantz <jmarantz@google.com>
…istinct representations ot be created for non-hot-restart case. Signed-off-by: Joshua Marantz <jmarantz@google.com>
Signed-off-by: Joshua Marantz <jmarantz@google.com>
…-alloc case. Signed-off-by: Joshua Marantz <jmarantz@google.com>
Signed-off-by: Joshua Marantz <jmarantz@google.com>
Signed-off-by: Joshua Marantz <jmarantz@google.com>
Signed-off-by: Joshua Marantz <jmarantz@google.com>
|
Ready for a look I think. |
…alStore::counter() and gauge(). Signed-off-by: Joshua Marantz <jmarantz@google.com>
|
@ggreenway do you have time to take a look? |
mrice32
left a comment
There was a problem hiding this comment.
Looks good on first pass! A few comments.
include/envoy/stats/stats.h
Outdated
| * @return Counter* a counter, or nullptr if allocation failed. | ||
| */ | ||
| virtual RawStatData* alloc(const std::string& name) PURE; | ||
| virtual Counter* makeCounter(const std::string& name, std::string& tag_extracted_name, |
There was a problem hiding this comment.
It seems that we removed the free(), but we're still returning raw pointers. Can you document the ownership model? How is the StatDataAllocator informed of when the stat is no longer needed by the caller? Is the user allowed to just delete the raw pointer?
There was a problem hiding this comment.
Very good point here, and I think my design here needs a bit of rethinking in the context of how a caller would free stuff. The other comments I'll address later, and I'm flipping back to WIP-mode while I think about this :)
There was a problem hiding this comment.
Actually this was easy to deal with by just returning a shared_ptr at this level.
| * consumption. | ||
| */ | ||
| class RawStatDataAllocator { | ||
| class StatDataAllocator { |
There was a problem hiding this comment.
It seems like this is a general stat factory class that determines the impl for each type of stat (and how it is allocated). If it is able to choose the representation for gauges and counters, why not also allow it to make histograms?
There was a problem hiding this comment.
added TODO -- making a parallel path for histograms would require moving the histogram impl out of thread_local_store and into stats_impl, which seems OK to me, but not in this PR. @ramaraochavali @mattklein123 WDYT?
There was a problem hiding this comment.
@jmarantz originally I have added it to Stats_impl only. But later moved to thread_local_store based on @mattklein123 suggestion. I think it is ok to bring it back to stats impl.
| // result, creating it with the heap allocator. | ||
| template <class StatType> | ||
| StatType& | ||
| safeMakeStat(const std::string& name, |
There was a problem hiding this comment.
Can we add more documentation here about each argument. I'm only asking because the signature is reasonably complicated.
There was a problem hiding this comment.
OK I left some. I'm not sure it's super-illuminating as the semantics around tls_are rather complex :)
| return **tls_ref; | ||
| } | ||
|
|
||
| // We must now look in the central store so we must be locked. We grab a reference to the |
There was a problem hiding this comment.
Why did we remove this comment?
There was a problem hiding this comment.
good catch; replaced.
include/envoy/stats/stats.h
Outdated
|
|
||
| /** | ||
| * Abstract interface for allocating a RawStatData. | ||
| * Abstract interface for allocating statistics. Alternate |
There was a problem hiding this comment.
nit: remove Alternate since the interface doesn't impose a default.
Signed-off-by: Joshua Marantz <jmarantz@google.com>
|
I am swamped right now; not sure that I'll have time to review. |
mrice32
left a comment
There was a problem hiding this comment.
LGTM other than one minor comment about the interface.
include/envoy/stats/stats.h
Outdated
| * @return Counter* a counter, or nullptr if allocation failed. | ||
| */ | ||
| virtual RawStatData* alloc(const std::string& name) PURE; | ||
| virtual CounterSharedPtr makeCounter(const std::string& name, std::string& tag_extracted_name, |
There was a problem hiding this comment.
tag_extracted_name and tags are passed as references not so they can be modified and read by the caller, but so that they can be moved. I think a better way to communicate this in the interface is by making them rvalue references (for example: std::string&& tag_extracted_name), which will force all callers to wrap them in std::move() or pass an actual rvalue.
Also, the interface should document that if the returned CounterSharedPtr is nullptr, then these objects will not be moved/modified (we assume this at the callsite).
Similar comments for makeGauge().
Signed-off-by: Joshua Marantz <jmarantz@google.com>
| * @return Counter* a gauge, or nullptr if allocation failed. | ||
| */ | ||
| virtual void free(RawStatData& data) PURE; | ||
| virtual GaugeSharedPtr makeGauge(const std::string& name, std::string&& tag_extracted_name, |
There was a problem hiding this comment.
Please also document when these these rvalue references will be moved and when they will not (if allocation fails, they will not be moved, so that they may be used again by the caller).
Signed-off-by: Joshua Marantz <jmarantz@google.com>
mattklein123
left a comment
There was a problem hiding this comment.
One tiny nit. Sorry I thought I could power through this but this is a morning review. Will do first thing.
include/envoy/stats/stats.h
Outdated
| * @param name the full name of the stat. | ||
| * @param tag_extracted_name the name of the stat with tag-values stripped out. | ||
| * @param tags the extracted tag values. | ||
| * @return Counter* a counter, or nullptr if allocation failed, in which case tag_extracted_name |
There was a problem hiding this comment.
nit: doc comment out of date, same below
Signed-off-by: Joshua Marantz <jmarantz@google.com>
mattklein123
left a comment
There was a problem hiding this comment.
Looks great. Nice cleanup. One question on readability.
| Histogram& tlsHistogram(const std::string& name, ParentHistogramImpl& parent) override; | ||
|
|
||
| template <class StatType> | ||
| using MakeStatFn = std::shared_ptr<StatType> (StatDataAllocator::*)( |
There was a problem hiding this comment.
nit: This type of function pointer syntax took me by surprise and I suspect most people are not familiar with it. Is there any more readable way of doing this? Potentially a normal lambda that is passed an instance of StatDataAllocator? This is not a big deal, just throwing it out there.
There was a problem hiding this comment.
I can use std::function but I would have to make static method intermediates which I think is less readable.
In the past I have added macros for defining and calling pointer to member functions, which helps a bit I think. That's my preferred option. WDYT?
There is also std::invoke, which I had never used before. But I wasn't about to get that to with and I didn't think it was all that readable either.
There was a problem hiding this comment.
I can use std::function but I would have to make static method intermediates which I think is less readable.
In the past I have added macros for defining and calling pointer to member functions, which helps a bit I think. That's my preferred option. WDYT?
There is also std::invoke, which I had never used before. But I wasn't about to get that to with and I didn't think it was all that readable either.
There was a problem hiding this comment.
If you're going to use pointer to member function, I think macros are the preferred method for readability.
Why would you need static intermediates to use std::function? Can't you capture 'this' in the closure?
There was a problem hiding this comment.
You're right; I don't need a static intermediary, but I think the way the code is structured I do need an intermediate closure, because I'm not starting with 'this', I'm starting with two alternate allocators. I do have that working -- it's a little messy IMO -- and I'll push that for reference, and then I'll push the version where I use pointer to member functions, but via macros, and I'm fine with either of those.
…ction. Signed-off-by: Joshua Marantz <jmarantz@google.com>
…ros to aid readability. Signed-off-by: Joshua Marantz <jmarantz@google.com>
|
OK ptal at the two options: Use std::function (requires an inline intermediary): 3c75f26 Use pointer-to-member function, with macros to aid readability (current state of PR). I'm happy to go with either. |
|
I have a slight preference for the std::function version, but I think either is a big improvement. @ggreenway any preference? |
|
I also have a slight preference for the std::function version. I think fewer people will be confused by it; pointer to member function is an infrequently used language feature. |
…with macros to aid readability." This reverts commit b9eee85. Signed-off-by: Joshua Marantz <jmarantz@google.com>
|
std::function version is fine with me, that is now the state of this PR. |
Description:
This PR does some refactoring to make it easier to create an alternate stats representation for the non-hot-restart case. Note that it does not actually do that: just makes it easier by virtualizing makeCounter and makeGauge.
See #3585 for more discussion.
Risk Level: Medium
Testing: //test/...