-
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: json optimization of histograms #3280
stats: json optimization of histograms #3280
Conversation
Signed-off-by: Rama <rama.rao@salesforce.com>
@mattklein123 @jmarantz @mrice32 |
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.
Mostly looks good. Just a few small comments on the docs.
docs/root/operations/admin.rst
Outdated
}, | ||
{ | ||
"histograms": { | ||
"supported_quantiles": [...], |
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.
Could you add real values here, so the user knows what the array will look like (as in, is it an array of doubles
or subobjects)?
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.
will add.
docs/root/operations/admin.rst
Outdated
"name": "example.histogram", | ||
"values": [ | ||
{ | ||
"interval": null, |
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.
As above, it would be nice to see an example of a histogram with non-null quantiles values since that will be the common case. But it'd also be nice to keep some sort of null
example so the user knows what a no-data hist will look like.
Side note: will this ever print histograms that have no samples in both cumulative and internal since that would mean its used()
method would return false
?
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 will make those changes. and regarding used, it currently prints all histograms. And I think it is a good point, it would be good filter the unused ones. I will make that change as well.
Signed-off-by: Rama <rama.rao@salesforce.com>
Signed-off-by: Rama <rama.rao@salesforce.com>
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.
release test is failing with server_fuzz_test unrelated to this. |
@ramaraochavali try merging master, @htuch put in a fix that might help. |
Signed-off-by: Rama <rama.rao@salesforce.com>
Signed-off-by: Rama <rama.rao@salesforce.com>
if (!shutting_down_) { | ||
ASSERT(!merge_in_progress_); |
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 just moved this check because, I hit the same issue in CI. Since #3289 fixes it properly we should be good.
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.
It'd be great to get that PR in first to avoid affecting this one :)
docs/root/operations/admin.rst
Outdated
|
||
{ | ||
"histograms": { | ||
"supported_quantiles": [ |
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.
the indentation in this description looks wrong. This line should be indented one more level than the previous one. Do you think it also makes sense, doc purpose, to put these 9 quantiles each on one line?
docs/root/operations/admin.rst
Outdated
"name": "cluster.external_auth_cluster.upstream_cx_length_ms", | ||
"values": [ | ||
{ | ||
"interval": 0, |
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.
for doc legibility purposes, consider this format:
"values": [
{"interval": 0, "cumulative": 0},
{"interval": 0, "cumulative": 0},
{"interval": 1.0435787, "cumulative": 1.0435787},
....
I assume the whitespace output is not actually what the json serializer actually emits, right? It would omit all whitespace?
docs/root/operations/admin.rst
Outdated
] | ||
} | ||
] | ||
} |
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 the missing indentation earlier forces a few lines of 1-char indent. All this is hard to see because of all the newlines above.
for (Json::ObjectSharedPtr obj_ptr : statsjson->getObjectArray("stats")) { | ||
if (obj_ptr->hasObject("histograms")) { | ||
histogram_count++; | ||
const Json::ObjectSharedPtr& histograms_ptr = obj_ptr->getObject("histograms"); |
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'm confused here: you are looking for 'histograms' plural so I was expecting another loop over all the histograms. Can you explain?
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 is a toplevel "histograms" element that has supported_quantiles array and computed_quantiels, which is again an array of actual histogram computed values in the form of "name" and "values" (interval and cumulative) - the last array is repeated as many times as there are histograms"
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'm still not entirely clear on the cardinality of variouis things from looking at the code. If we actually add a second histogram and make the test expect 2?
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.
no. it is still 1. The computed_quantiles array size would be equivalent to the number of histograms.
Cardinality of histograms : 1
Cardinality of supported_quantile array : 1
Cardinality if computed_quantiles array = number of histograms (with each element having histogram name and values array which has interval and cumulative values)
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.
Can you please add a second histogram to this test, so computed_quantiles array has length 2?
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 am not adding any histograms in the test. I just grab whatever the output is from /stats?format=json and validate that it has histograms, it would definitely some (but non predictable). I am not setting up any thing for this test.
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.
Ah, very cool. Let me rephrase my request. Can you make a new test where you add some specific histogram data with more than one histogram, and check the JSON output?
Signed-off-by: Rama <rama.rao@salesforce.com>
docs/root/operations/admin.rst
Outdated
] | ||
} | ||
"supported_quantiles": [ | ||
0,25,50,75,90,95,99,99.9,100 |
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.
nit: can you put a single space after each comma?
docs/root/operations/admin.rst
Outdated
], | ||
"computed_quantiles": [ | ||
{ | ||
"name": "cluster.external_auth_cluster.upstream_cx_length_ms", |
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.
make this 2-space-per-nesting indent consistently; here you have 3.
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.
It is two only. I checked by enabling white space. Github is showing like that.
|
||
const std::vector<Json::ObjectSharedPtr>& computed_quantiles = | ||
histograms_ptr->getObjectArray("computed_quantiles"); | ||
EXPECT_GT(computed_quantiles.size(), 0); |
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.
can we make this EXPECT_EQ something specific here?
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.
this count would be equivalent to number of histograms. I do not know exactly how many will come that is why I have added this GT zero condition.
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.
Isn't the number of histograms predictable in this test?
for (Json::ObjectSharedPtr obj_ptr : statsjson->getObjectArray("stats")) { | ||
if (obj_ptr->hasObject("histograms")) { | ||
histogram_count++; | ||
const Json::ObjectSharedPtr& histograms_ptr = obj_ptr->getObject("histograms"); |
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'm still not entirely clear on the cardinality of variouis things from looking at the code. If we actually add a second histogram and make the test expect 2?
Signed-off-by: Rama <rama.rao@salesforce.com>
docs/root/operations/admin.rst
Outdated
], | ||
"computed_quantiles": [ | ||
{ | ||
"name": "cluster.external_auth_cluster.upstream_cx_length_ms", |
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.
You have this:
+ {
+ "name": "cluster.external_auth_cluster.upstream_cx_length_ms",
I think it should be this:
+ {
+ "name": "cluster.external_auth_cluster.upstream_cx_length_ms",
if (!shutting_down_) { | ||
ASSERT(!merge_in_progress_); |
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.
It'd be great to get that PR in first to avoid affecting this one :)
|
||
const std::vector<Json::ObjectSharedPtr>& computed_quantiles = | ||
histograms_ptr->getObjectArray("computed_quantiles"); | ||
EXPECT_GT(computed_quantiles.size(), 0); |
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.
Isn't the number of histograms predictable in this test?
for (Json::ObjectSharedPtr obj_ptr : statsjson->getObjectArray("stats")) { | ||
if (obj_ptr->hasObject("histograms")) { | ||
histogram_count++; | ||
const Json::ObjectSharedPtr& histograms_ptr = obj_ptr->getObject("histograms"); |
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.
Can you please add a second histogram to this test, so computed_quantiles array has length 2?
Signed-off-by: Rama <rama.rao@salesforce.com>
@jmarantz since that is a private method used only at this place, I thought this test is sufficient. I am not sure if we can add tests for private methods in the current test infrastructure. Will have to check. If you think it adds value, I will do it next week |
you can structure the test exactly as it is here, if you like, via the admin interface, if that's easier; I just think it's reasonable to control the data. It's also possible to test private methods by friending the test-class and putting a helper there, or adding a TestingPeer class which is friended, if that helps unit-tests. |
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.
LGTM once @jmarantz's comments are resolved.
Signed-off-by: Rama <rama.rao@salesforce.com>
@jmarantz i will try adding the test next week. I did not get how I can structure the test with admin interface though. How will clear the existing histograms/add the histograms I want in the admin test - i do not have access to stats_store I guess. I have not looked at the code. Are you suggesting some thing different? May not getting your suggestion... |
RE test for >1 histogram: I would actually prefer you add it as a unit test anyway, which sounds easier. The 'private' issue is easily dealt with by either friending the test-class or a TestingPeer class, either of which can act as in intermediary to access a private method. |
Signed-off-by: Rama <rama.rao@salesforce.com>
test/server/http/admin_test.cc
Outdated
* This is a heap test allocator that works similar to how the shared memory allocator works in | ||
* terms of reference counting, etc. | ||
*/ | ||
class TestAllocator : public Stats::RawStatDataAllocator { |
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.
@jmarantz added a unit test that verifies the json format. PTAL. I had to copy this TestAllocator class as is from thread_local_store_test.cc as I found that it is the easiest way to generate histograms with stores. I do not know if there is any way to make this class across both the files, with out changing much..
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.
Can you move the TestAllocator class to test/test_common/utility.h so you don't have duplicated code?
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.
Yes. Moved
{"interval": null, "cumulative": 3.0665233}, | ||
{"interval": null, "cumulative": 6.046609}, | ||
{"interval": null, "cumulative": 229.57333}, | ||
{"interval": null, "cumulative": 260} |
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.
This looks great now. Much easier to read. Thanks!
|
||
std::string actual_json = statsAsJsonHandler(all_stats, store_->histograms()); | ||
|
||
const std::string expected_json = R"EOF({ |
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.
This reminds me; do we always generate pretty-printed JSON? I think it would be better to deliver it compact in production, though it's nice to have the test be pretty-printed for test.cc legibility.
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.
Yes. Currently we do generate pretty-printed JSON. Now I have added a parameter to control that and defaulted it to false and changed the test to print in pretty form. PTAL.
Signed-off-by: Rama <rama.rao@salesforce.com>
Signed-off-by: Rama <rama.rao@salesforce.com>
Signed-off-by: Rama <rama.rao@salesforce.com>
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.
Great, thanks for this! This test adds confidence for me (even though it might not have affected line-coverage).
test/test_common/utility.h
Outdated
return; | ||
} | ||
|
||
for (auto i = stats_.begin(); i != stats_.end(); i++) { |
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.
This was pre-existing, but you have a map here, can't we just remove it via the name? I don't really care about perf for the test but I think the code would just be:
if (stats_.erase(std::string(data.name()) == 0) {
FAIL();
}
which is fewer lines :)
source/server/http/admin.cc
Outdated
} | ||
quantile_obj.AddMember("interval", interval_value, allocator); | ||
Value cumulative_value; | ||
if (!std::isnan(histogram->cumulativeStatistics().computedQuantiles()[i])) { |
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.
Probably worth commenting here that as we are positionally associating this entry with a quantile, so we need to put in the {null, null} entry to keep other data aligned.
Signed-off-by: Rama <rama.rao@salesforce.com>
@jmarantz addressed the two comments. Should be good now. |
Signed-off-by: Rama rama.rao@salesforce.com
Description:
optimizes the json representation of histograms by sending all supported_quantile once and computed_quantlie array multiple times.
Risk Level: Low
Testing: Manual
Docs Changes: NA
Release Notes: NA
Fixes #3102
Fixes #3210