-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
[Uptime] Improve monitor charts query #30561
[Uptime] Improve monitor charts query #30561
Conversation
Pinging @elastic/uptime |
💔 Build Failed |
I know this is in progress, but I'd like to add a piece of feedback. The query changes are great. Is there a concrete need for the reformatting to be moved to the server? The chart takes a weird format. That responsibility seems more tightly coupled to the Eui widget than anything else. From a performance standpoint where that transformation happens seems negligible. If we do that formatting on the server that doesn't have much of an impact today due to the GQL API being private. However, if we decide to create a public GQL API in the future that makes things awkward. Generally speaking APIs are cleaner if they are more agnostic of consumer details. |
💚 Build Succeeded |
Yeah that makes sense, we should remove that bit from this change. |
37faba6
to
6eea265
Compare
💚 Build Succeeded |
description="The 'ms' is an abbreviation for 'milliseconds'." | ||
/> | ||
</EuiFlexItem> | ||
{!!duration && ( |
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 we're ok to just omit this element if there's no duration
for some reason. There should always be one though.
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.
++
💔 Build Failed |
💚 Build Succeeded |
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.
Functionality is great, but I think the code could use some tweaks. See included comments :)
"The timeseries value for this point in time." | ||
x: UnsignedInteger! | ||
"The min duration value in microseconds at this time." | ||
y0: Float |
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 realllly dislike the y0
, y
distinction, but I'm OK with it here since this is a private API.
If we ever make it public I'd like it to be yMin
,yMax
or similar. I'll leave it to you whether you feel it should be changed for this PR.
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.
Oh ok - I don't have any objection to changing the name. I don't like that convention either.
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.
} | ||
|
||
"Represents the average monitor duration ms at a point in time." | ||
type MonitorDurationAveragePoint { |
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 feel like at some later point we'll have more generic CartesianPoint
types, but I'm fine with this for now.
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 tend to think of these chart-related bits of code as in a state of flux that will be overwritten/deleted (because we're going to need to re-implement the charts when new EUI components are available). We will want to take care that we approach it with nuance and sensibility when we overwrite what we have today.
const mappedBuckets = buckets.map(bucket => { | ||
const x = get(bucket, 'key'); | ||
const docCount = get(bucket, 'doc_count', 0); | ||
statusMaxCount = Math.max(docCount, statusMaxCount); |
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 needs comments for clarity, it's pretty confusing what's going on here. A comment saying "This can be used to calculate the maximum Y bounds for a chart" would be quite helpful.
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 added some comments in 3ccdd1d, please elaborate if you still think it's unclear.
durationMaxValue, | ||
statusMaxCount, | ||
}; | ||
return mappedBuckets.reduce( |
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.
Is map/reduce getting us much here?
As a fan of FP (and former lisper) I like MR, but it seems to be interfering with code clarity here. We have an entire intermediate set of variables created in the map
phase that only exists to be discarded and renamed in the reduce phase.
This would be more clear to read using a simple forEach
that mutated the counter
object. Something like the untested code below:
const result: MonitorChart = {
durationArea: [],
durationLine: [],
status: [],
durationMaxValue: 0,
statusMaxCount: 0,
};
buckets.forEach(bucket => {
const x = get(bucket, 'key');
const docCount = get(bucket, 'doc_count', 0);
result.statusMaxCount = Math.max(docCount, result.statusMaxCount);
result.durationMaxValue = Math.max(result.durationMaxValue, get(bucket, 'duration.max', 0));
result.durationArea.push({ x, y0: get(bucket, 'duration.min', null), y: get(bucket, 'duration.max', null)});
result.durationLine.push({ x, y: get(bucket, 'duration.avg', null) });
result.status.push(formatStatusBuckets(x, get(bucket, 'status.buckets', []), docCount));
});
return result;
Alternatively, if you did want to use map reduce, I'd skip the map
phase completely. The goal here is to turn a list (of buckets) into a single value. That corresponds to a reduce. The code as it stands uses a map phase to expose an intermediate state. However, that intermediate state is, I would argue, confusing, because it doesn't do much other than rename variables. You could do something similar to the forEach
above, but use reduce
instead. Like (also untested):
const result: MonitorChart = {
durationArea: [],
durationLine: [],
status: [],
durationMaxValue: 0,
statusMaxCount: 0,
};
return buckets.reduce( (bucket, acc) => {
const x = get(bucket, 'key');
const docCount = get(bucket, 'doc_count', 0);
result.statusMaxCount = Math.max(docCount, result.statusMaxCount);
result.durationMaxValue = Math.max(result.durationMaxValue, get(bucket, 'duration.max', 0));
result.durationArea.push({ x, y0: get(bucket, 'duration.min', null), y: get(bucket, 'duration.max', null)});
result.durationLine.push({ x, y: get(bucket, 'duration.avg', null) });
result.status.push(formatStatusBuckets(x, get(bucket, 'status.buckets', []), docCount));
return result;
}, result);
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.
First of all - thank you for taking the time to write all this out.
Secondly I agree with your points. Sometimes we are focused on the code's output so much we forget that others will need to read it in the future, and we implement the very first solution that comes to mind. I think your first solution is best. If we need to declare an accumulator variable before the functions no matter what, it makes sense to access it from the simplest possible block, which in this case would be forEach
.
Please review 3ccdd1d when you have a chance.
💚 Build Succeeded |
…tional component and add unit test.
💚 Build Succeeded |
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. Looking good!
jenkins test this |
@andrewvc I'm going to re-test just because these changes were last built two weeks ago. If CI passes we'll be good to merge IMO. |
💔 Build Failed |
💚 Build Succeeded |
* Refactor chart querying. * Fix monitor chart query. * Refactor several inline computations to helper functions. Improve schema naming. * Move unit conversion to client, remove bare conversion values. * Add API tests for monitor charts. * Add test for conversion function. * Add type annotations to latest schema additions. * Fix typo. * Refactor based on PR feedback, add comments asked for in PR feedback. * Rename fields in schema, update tests. Extract monitor charts to functional component and add unit test.
* Refactor chart querying. * Fix monitor chart query. * Refactor several inline computations to helper functions. Improve schema naming. * Move unit conversion to client, remove bare conversion values. * Add API tests for monitor charts. * Add test for conversion function. * Add type annotations to latest schema additions. * Fix typo. * Refactor based on PR feedback, add comments asked for in PR feedback. * Rename fields in schema, update tests. Extract monitor charts to functional component and add unit test.
* Refactor chart querying. * Fix monitor chart query. * Refactor several inline computations to helper functions. Improve schema naming. * Move unit conversion to client, remove bare conversion values. * Add API tests for monitor charts. * Add test for conversion function. * Add type annotations to latest schema additions. * Fix typo. * Refactor based on PR feedback, add comments asked for in PR feedback. * Rename fields in schema, update tests. Extract monitor charts to functional component and add unit test.
* Refactor chart querying. * Fix monitor chart query. * Refactor several inline computations to helper functions. Improve schema naming. * Move unit conversion to client, remove bare conversion values. * Add API tests for monitor charts. * Add test for conversion function. * Add type annotations to latest schema additions. * Fix typo. * Refactor based on PR feedback, add comments asked for in PR feedback. * Rename fields in schema, update tests. Extract monitor charts to functional component and add unit test.
Summary
Resolves #29843.
This change would update the query used for fetching monitor chart data, and clean up computations done on the client that probably belong in the server.
Testing this PR
The changes enacted will have visual results, so aside from providing code review you should be able to see it's working as intended.
val / (1000 * 1000)
. A request tohttps://www.elastic.co
is not going to complete in0.15ms
.https://www.elastic.co
should not take150,000ms
either.This PR is in progress, and shouldn't be reviewed until #30441 is merged.