-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
stats: refactoring MetricImpl without strings #4190
Changes from 3 commits
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 |
---|---|---|
|
@@ -5,6 +5,8 @@ | |
|
||
#include "envoy/stats/stats.h" | ||
|
||
#include "common/common/assert.h" | ||
|
||
namespace Envoy { | ||
namespace Stats { | ||
|
||
|
@@ -14,10 +16,9 @@ namespace Stats { | |
*/ | ||
class MetricImpl : public virtual Metric { | ||
public: | ||
MetricImpl(const std::string& name, std::string&& tag_extracted_name, std::vector<Tag>&& tags) | ||
: name_(name), tag_extracted_name_(std::move(tag_extracted_name)), tags_(std::move(tags)) {} | ||
MetricImpl(std::string&& tag_extracted_name, std::vector<Tag>&& tags) | ||
: tag_extracted_name_(std::move(tag_extracted_name)), tags_(std::move(tags)) {} | ||
|
||
const std::string& name() const override { return name_; } | ||
const std::string& tagExtractedName() const override { return tag_extracted_name_; } | ||
const std::vector<Tag>& tags() const override { return tags_; } | ||
|
||
|
@@ -30,7 +31,6 @@ class MetricImpl : public virtual Metric { | |
}; | ||
|
||
private: | ||
const std::string name_; | ||
const std::string tag_extracted_name_; | ||
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. It looks like we could get rid of this too; we'd have to change consumers of tagExtractedName() and tags() to compute them on demand from TagProducerImpl::produceTags(). That could be a separate PR. I don't know what the CPU cost of that would be; if that happens during operation, or would be only while setting up a stats sinks. @mrice32 , WDYT? If not, the tag_extracted_name_ string would be ripe for symbolizing later. 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'm OK with spinning this off into a separate PR, but yeah, if we do this for one variable we might well do it for several. |
||
const std::vector<Tag> tags_; | ||
}; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,10 +27,13 @@ class MockCounter : public Counter { | |
MockCounter(); | ||
~MockCounter(); | ||
|
||
// Note: cannot be mocked because it is accessed as a Property in a gmock EXPECT_CALL. This | ||
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. FWIW I still don't understand what this means and why it happens (I realize this was copied). 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. |
||
// creates a deadlock in gmock and is an unintended use of mock functions. | ||
const std::string name() const override { return name_; }; | ||
|
||
MOCK_METHOD1(add, void(uint64_t amount)); | ||
MOCK_METHOD0(inc, void()); | ||
MOCK_METHOD0(latch, uint64_t()); | ||
MOCK_CONST_METHOD0(name, const std::string&()); | ||
MOCK_CONST_METHOD0(tagExtractedName, const std::string&()); | ||
MOCK_CONST_METHOD0(tags, const std::vector<Tag>&()); | ||
MOCK_METHOD0(reset, void()); | ||
|
@@ -49,10 +52,13 @@ class MockGauge : public Gauge { | |
MockGauge(); | ||
~MockGauge(); | ||
|
||
// Note: cannot be mocked because it is accessed as a Property in a gmock EXPECT_CALL. This | ||
// creates a deadlock in gmock and is an unintended use of mock functions. | ||
const std::string name() const override { return name_; }; | ||
|
||
MOCK_METHOD1(add, void(uint64_t amount)); | ||
MOCK_METHOD0(dec, void()); | ||
MOCK_METHOD0(inc, void()); | ||
MOCK_CONST_METHOD0(name, const std::string&()); | ||
MOCK_CONST_METHOD0(tagExtractedName, const std::string&()); | ||
MOCK_CONST_METHOD0(tags, const std::vector<Tag>&()); | ||
MOCK_METHOD1(set, void(uint64_t value)); | ||
|
@@ -73,7 +79,7 @@ class MockHistogram : public Histogram { | |
|
||
// Note: cannot be mocked because it is accessed as a Property in a gmock EXPECT_CALL. This | ||
// creates a deadlock in gmock and is an unintended use of mock functions. | ||
const std::string& name() const override { return name_; }; | ||
const std::string name() const override { return name_; }; | ||
|
||
MOCK_CONST_METHOD0(tagExtractedName, const std::string&()); | ||
MOCK_CONST_METHOD0(tags, const std::vector<Tag>&()); | ||
|
@@ -92,7 +98,7 @@ class MockParentHistogram : public ParentHistogram { | |
|
||
// Note: cannot be mocked because it is accessed as a Property in a gmock EXPECT_CALL. This | ||
// creates a deadlock in gmock and is an unintended use of mock functions. | ||
const std::string& name() const override { return name_; }; | ||
const std::string name() const override { return name_; }; | ||
void merge() override {} | ||
const std::string summary() const override { return ""; }; | ||
|
||
|
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.
do you need to make this change in this PR? I understand why you'd need to make it in the SymbolTable PR.
Ditto for the other changes where you were returning a reference and now you are returning a copy.
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.
I think it has to be this way because we are relying on the private member variable
name_
insideRawStatData
.name_
is achar[]
, so we could return a string_view to it or a string of it, but not a string ref. If we returned a string_view I think we would have to rework lots of other function interfaces where we expect a string. (lookups in maps, etc.)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.
Right, makes sense. In the context of this PR, string_view is the right option. You'll have to return string-by-value if/when we move to SymbolTable.
The advantage of your approach here (returning string-by-value) is that it will work for SymbolTable. Switching callers to take string_view is optimal in this PR, but would actually would be the wrong direction to go if we are heading to SymbolTable. I'm hopeful the compiler will tell us if we write:
if name() returns a string-by-value. If not, in the SymbolTable PR, you can just rename the method (even temporarily) to force you to examine all methods via compiler errors.
So I think my feeling is you should do the right thing or this PR and return a string_view.
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.
I want to keep this as-is, since we might have to convert this back into a string at one of the aforementioned interfaces/callsites, and since an incumbent symbol_table PR will play more cleanly with a string interface. Converting this to a string_view everywhere means the reworking of maps and structures which store strings now to store
container<string_view, _, StringViewHash_, StringViewCompare_>
, and they'll just end up churning again intocontainer<StatNamePtr, _, StatNamePtrHash_, StatNamePtrCompare_>
.