Skip to content
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

[Lens] Custom labels for ranges #79628

Merged
merged 13 commits into from
Oct 14, 2020
Merged

Conversation

flash1293
Copy link
Contributor

Fixes #77878

This PR adds optional custom labels for ranges and exposes them in Lens similar to custom labels for filters.

Screenshot 2020-10-06 at 10 33 07

Screenshot 2020-10-06 at 10 32 58

Screenshot 2020-10-06 at 10 32 53

This includes some small changes in the range AggType and range field formatter as well to map the label from the agg config into the result table and to pick up the custom label if present when formatting the value. Also, the label has to be excluded when building a filter out of a range value

@lukeelmers
Copy link
Member

Stumbled across this. I know it's still in draft mode 🙈 but just wanted to add a note that whenever we implement a proper range expression type as explained in #67908, we'll also need to make sure there's a label arg on that expression function.

Currently the expression function for the range agg simply takes stringified JSON { from: 0, to: 1 }, but eventually we'll need something like range from=0 to=1 label="hi" to be provided as a subexpression for the arg.

If you want to do that here, feel free -- but no pressure. I'm mainly noting it so that we don't forget.

@flash1293 flash1293 marked this pull request as ready for review October 7, 2020 15:10
@flash1293 flash1293 requested a review from a team October 7, 2020 15:10
@flash1293 flash1293 requested a review from a team as a code owner October 7, 2020 15:10
@flash1293 flash1293 added Team:AppArch Team:Visualizations Visualization editors, elastic-charts and infrastructure labels Oct 7, 2020
@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-app-arch (Team:AppArch)

@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-app (Team:KibanaApp)

Copy link
Contributor

@dej611 dej611 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested it locally but couldn't make it work for other than the first range interval label:

Screenshot 2020-10-07 at 18 13 20

Screenshot 2020-10-07 at 18 13 33

Screenshot 2020-10-07 at 18 14 00

@dej611
Copy link
Contributor

dej611 commented Oct 7, 2020

I think there's an issue with the remapping of the esaggs responses, as when I remove the first item the second ones which becomes the only range it's still without the custom range

remap-range-labels

@flash1293
Copy link
Contributor Author

Great catch, @dej611 I will check it out

@botelastic botelastic bot added the Feature:ExpressionLanguage Interpreter expression language (aka canvas pipeline) label Oct 8, 2020
@flash1293
Copy link
Contributor Author

@dej611 I didn't handle partial ranges correctly, it should be fixed now.

@flash1293 flash1293 requested a review from dej611 October 8, 2020 09:57
Copy link
Contributor

@dej611 dej611 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did a code review. Will check the PR locally with the new changes

src/plugins/data/common/search/aggs/buckets/range_key.ts Outdated Show resolved Hide resolved
this.gte = bucket.from == null ? -Infinity : bucket.from;
this.lt = bucket.to == null ? +Infinity : bucket.to;
this.label = allRanges ? RangeKey.findCustomLabel(this.gte, this.lt, allRanges) : undefined;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Passing bucket.from/to here can simplify the code in the findCustomLabel a bit (removing non-finite check).
They effectively equivalent, but the current version is more verbose.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also the ternary operator can be dropped as the missing ranges would be handled by findCustomLabel

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch for the ternary operator, I'm not sure whether it makes it much easier because we still have to look for null/undefined.

src/plugins/data/common/search/aggs/buckets/range_key.ts Outdated Show resolved Hide resolved
src/plugins/data/common/search/aggs/buckets/range_key.ts Outdated Show resolved Hide resolved
@flash1293
Copy link
Contributor Author

Thanks @dej611 , pushed some changes

Copy link
Contributor

@dej611 dej611 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

Copy link
Contributor

@wylieconlon wylieconlon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I use the same custom label for non-equal ranges, the result is that I get a chart with missing data. This looks like a bug to me, where I've configured two ranges called "asdf" and only one is shown:

Screen Shot 2020-10-08 at 4 21 23 PM

expect(format.convert({ gte: 1, lt: 20, label: 'custom' })).toBe('custom');
// underlying formatter is not called because custom label can be used directly
expect(getFormat).toHaveBeenCalledTimes(0);
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a test for handling multiple overlapping ranges?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What kind of test are you expecting? The formatter only ever gets a single value passed in. Do you want to cover the behavior of the built-in cache?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I left this in the wrong place- I was worried about the duplicate label case, but this is the wrong place to test it.

onChange={(newLabel) => {
const newRange = {
...tempRange,
label: newLabel,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this resets to the empty string to indicate that it's empty, is that going to cause problems with equality? Imagine the steps 1. Create custom label 2. Delete custom label 3. Formats correctly?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested, this doesn't cause any issues

@flash1293
Copy link
Contributor Author

flash1293 commented Oct 8, 2020

I think the missing bar is caused by the chart only working with the formatted label so there is no difference in the two data points and only one of them is shown. We can either try to mess with chart serializers and formatters or just not allow this case, show an error in the popover and never persist such a state (which would be my preferred option)

@flash1293
Copy link
Contributor Author

@wylieconlon I tested and we have the same behavior for "Filters" - you are allowed to create two separate filters with the same custom label and only one bar will be shown. While it's not the best behavior, it's at least consistent, so I would like to keep it for the scope of this PR and open a separate bug issue to solve it consistently.

Copy link
Contributor

@wylieconlon wylieconlon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@flash1293 I'm fine with the decision to allow duplicate labels in this PR, but I'll create a follow-up issue to track it as a minor annoyance.

expect(format.convert({ gte: 1, lt: 20, label: 'custom' })).toBe('custom');
// underlying formatter is not called because custom label can be used directly
expect(getFormat).toHaveBeenCalledTimes(0);
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I left this in the wrong place- I was worried about the duplicate label case, but this is the wrong place to test it.

@flash1293
Copy link
Contributor Author

@elasticmachine merge upstream

Copy link
Member

@lukeelmers lukeelmers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code LGTM - tested Chrome (macOS). Just had one question

@@ -67,11 +68,11 @@ export const getRangeBucketAgg = ({ getFieldFormatsStart }: RangeBucketAggDepend
keyCaches.set(agg, keys);
}

const id = RangeKey.idBucket(bucket);
const id = RangeKey.idBucket(bucket, agg.params.ranges);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forgive me if this is a naive question -- but why is it necessary to change the format of the bucket id to include the label? I assume this is solving an edge case, but it wasn't completely clear to me from reading the discussion above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was under the impression it's necessary to not run into cached RangeKey objects with outdated labels, but I realized the cache is only used for a single request, so it's not an issue. Removed it

@kibanamachine
Copy link
Contributor

💚 Build Succeeded

Metrics [docs]

async chunks size

id before after diff
lens 1.0MB 1.0MB +629.0B

page load bundle size

id before after diff
data 1.1MB 1.1MB +1.4KB
expressions 198.5KB 198.5KB +51.0B
total +1.4KB

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

@flash1293 flash1293 merged commit 5fd7ad3 into elastic:master Oct 14, 2020
flash1293 added a commit to flash1293/kibana that referenced this pull request Oct 14, 2020
@@ -159,6 +164,25 @@ export const RangePopover = ({
</EuiFlexItem>
</EuiFlexGroup>
</EuiFormRow>
<EuiFormRow>
<LabelInput
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @flash1293, I saw this one got merged already, but you make this input compressed since it lives in a popover and will then match the range inputs better.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature:ExpressionLanguage Interpreter expression language (aka canvas pipeline) Feature:Lens release_note:enhancement Team:Visualizations Visualization editors, elastic-charts and infrastructure v7.11.0 v8.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Lens] Allow custom labels for ranges
8 participants