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

[Discover] Allow to store the configured ES|QL visualization v3 #175227

Merged
merged 165 commits into from
Apr 8, 2024

Conversation

jughosta
Copy link
Contributor

@jughosta jughosta commented Jan 22, 2024

Summary

On Discover page user can see a visualization for data view and ES|QL modes. For ES|QL mode it's also allowed to customize the visualization. This PR allows to save such customization together with a saved search.

In more details, various types of Lens visualization can be shown on Discover page:

  • If in the default (data view) mode, Unified Histogram shows a "formBased" histogram (type: UnifiedHistogramSuggestionType.histogramForDataView in this PR)
  • If in the ES|QL mode, 2 scenarios are possible (so far only these are customizable):
    • If Lens has suggestions for the current query, Unified Histogram shows one of them (type: UnifiedHistogramSuggestionType.lensSuggestion in this PR) Example query: from kibana_sample_data_logs | stats avg(bytes) by message.keyword
    • If Lens suggestion list is empty, Unified Histogram shows a "textBased" histogram (type: UnifiedHistogramSuggestionType.histogramForESQL in this PR). Example query: from kibana_sample_data_logs | limit 10

The main flow is that Unified Histogram first picks a suggestion (one of UnifiedHistogramSuggestionType type), then calculates lens attributes which are necessary to build Lens embeddable. With a saved search we are saving those calculated lens attributes under savedSearch.visContext. For handling this logic, I refactored useLensSuggestion, getLensAttributes into LensVisService.

Restoring a saved customization adds complexity to the flow as it should pick now not just any available suggestion but the suggestion which matches to the previously saved lens attributes.

Changes to the current query, time range, time field etc can make the current vis context incompatible and we have to drop the vis customization. This PR already includes this logic of invalidating the stored lens attributes if they are not compatible any more. New vis context will override the previous one when user presses Save for the current search. Until then, we try to restore the customization from the previously saved vis context (for example when the query changes back to the compatible one).

What can invalidate the saved vis context and drop the user's customization:

  • data view id
  • data view time field name
  • query/filters
  • time range if it has a different time interval
  • text based columns affect what lens suggestions are available

Flow of creating a new search:
1

Flow of editing a saved search:
2

Previous details

But I was stuck with how to make "Unsaved changes" badge work well when user tries to revert changes.

For testing in ES|QL mode I use from kibana_sample_data_logs | limit 10 as query, customize color of a lens histogram, and save it with a saved search. Next I check 2 cases:

  1. edit query limit from kibana_sample_data_logs | limit 100, see that vis customization gets reset which is expected, press "Revert changes" in the "Unsaved changes" badge => notice that reset did not work
  2. edit only histogram color, press "Revert changes" in the "Unsaved changes" badge => notice that reset did not work

Here are some nuances with the state management I am seeing which together do not allow to successfully revert unsaved changes:

  • For ES|QL histogram lens attributes include a modified query from kibana_sample_data_logs | limit 10 | EVAL timestamp=DATE_TRUNC(30 second, @timestamp) | stats results = count(*) by timestamp | rename timestamp as "@timestamp every 30 second" which means that not only changes to the original query but also a different time interval invalidates the saved lens attributes.
  • In ES|QL mode, query prop update is delayed for UnifiedHistogramContainer component until Discover finishes the documents fetch which means that Discover should make a request on revert changes. And It's not happening for (2) as it does not make sense for Discover to trigger refetch if only visContext changes so we should find another way. With (1) there is another problem that Discover visContext state gets hijacked by lens attributes invalidation logic (as query is not sync yet to UnifiedHistogram) before fetch is completed or get a chance to be fired. I tried delaying externalVisContext prop update too (to keep in sync with query update) but it does not help
    externalVisContext: stateContainer.appState.getState().visContext,
  • Unified Histogram should signal to Discover to start a refetch when current suggestion changes
    createCurrentSuggestionObservable(unifiedHistogram.state$).pipe(map(() => 'lens')),
    - for some reason this logic is required for "Revert changes" to work as it triggers the refetch. I would expect Discover on its own to notice the change in query and refetch data but it does not seem to be the case.
Other challenges
  • Since we are starting to save lens attributes inside a saved search object (similar to how Dashboard saves lens vis by value), we should integrate Lens migrations into saved search migrations logic. I made a quick PoC how it could look like here jughosta@4529711 This showed that adding Lens plugin as a dependency to saved search plugin causes lots of circular deps in Kibana. To resolve that I am suggesting to spit saved search plugin into 2 plugins [Discover] Split saved search plugin v2 #174939 - not the best solution but it seems impossible to split lens plugins instead.
    Updates here:
    - [x] revert the code regarding migrations and saved search plugin split
    - [x] create a github issue to handle client side migrations once their API is available [SavedSearch][Discover] Make sure that lens vis state is persisted after running client side migrations #179151
  • Discover syncs app state with URL which means that the new visContext (large lens attributes object) ends up in the URL too. We should exclude visContext from URL sync as it can make the URL too long.
    Updates here: we are not using appState for this any more
  • Changes from [Lens] value based ES|QL data source #171081 would need to be refactored and integrated into the new LensVisService.
  • Refactor after [ESQL] Add chart switch #177790
  • Handle a case when no chart is available for current ES|QL query
  • For ES|QL histogram lens attributes include a modified query from kibana_sample_data_logs | limit 10 | EVAL timestamp=DATE_TRUNC(30 second, @timestamp) | stats results = count(*) by timestamp | rename timestamp as "@timestamp every 30 second" which means that not only changes to the original query but also a different time range can reset the customization of lens vis as it gets a different time interval based on current time range
  • New update from Stratoula:

10x flaky test https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/5578

Checklist

jughosta and others added 30 commits January 5, 2024 17:50
… src/core/server/integration_tests/ci_checks'
…earch

# Conflicts:
#	src/plugins/discover/public/application/main/components/layout/use_discover_histogram.ts
@stratoula
Copy link
Contributor

stratoula commented Apr 5, 2024

I'm expecting users to want the dropdown above the chart to always reflect their most recent choice (even if made on the flyout).

This will be tricky technically. This is why I suggested to remove the suggestion dropdown from there and move it to the flyout which has all the logic. It will also be aligned with the dashboards.

For now I think is ok to go with the custom + mixed icon though.

@jughosta
Copy link
Contributor Author

jughosta commented Apr 5, 2024

@davismcphee

The only thing I noticed while testing that seemed unexpected was that the cancel flyout button did not revert the changes when changing the chart type for non-histogram visualizations

Thanks! Found what was causing it and pushed a fix.

@stratoula

For now I think is ok to go with the custom + mixed icon though.

I don't think we can import lens icons directly in Discover. What I tried instead is to reuse a previewIcon from another known and similar suggestion. Like this:

Screenshot 2024-04-05 at 15 31 24

@stratoula
Copy link
Contributor

Even better :) Thanx Julia will test again!

@MichaelMarcialis
Copy link
Contributor

@andreadelrio, @stratoula, @jughosta: Tossing my two cents in here. In the short-term, I feel we should either:

  1. Remove the suggested visualization types selector from above the visualization altogether. Instead, we can offer the full list of visualization types via the selector in the inline editing flyout (ehancing it with the latest Lens changes that now show all visualization types and whether they are compatible), or…
  2. Provide users the full list of available visualization types in the selector above (again, with the same warning affordances we provide in Lens that inform users of potential incompatibilities).

I believe doing so would alleviate us from having to show any kind of "customized" indicator, which is something I tend to prefer. My reason for this is because the entire visualization (and all of the user's customizations) can be undone with a simple edit to their ES|QL query. Indicating that it was "customized" might give users the false impression that it is in a kind of frozen state, when in fact it isn't.

In the long-term, this is just one of many reasons why I'm not a big fan of hijacking the document count histogram and replacing it with our "suggested" visualizations before the user has made any indications that they wish to create a visualization. I would love for us to explore alternative posibilities that allow us to only reveal such visualization suggestions when the user has expressed interest in creating one. Hopefully something we can explore iteratively as we proceed.

@stratoula
Copy link
Contributor

stratoula commented Apr 5, 2024

@MichaelMarcialis thanx

Remove the suggested visualization types selector from above the visualization altogether. Instead, we can offer the full list of visualization types via the selector in the inline editing flyout (ehancing it with the latest Lens changes that now show all visualization types and whether they are compatible), or…

I also suggested that and it will simplify the unified histogram code + there will be an alignment with the dashboard inline editing.

The second suggestion is much tricker, I would like to avoid bringing it to Discover.

@ninoslavmiskovic
Copy link
Contributor

++ @MichaelMarcialis & @stratoula on simplifying. I am also not a fan of the "customized" label and in general confusing having two chart types selectors.

We have a challenge with the discoverability of the "edit" icon, but perhaps we can test that as a separate issue.

@stratoula
Copy link
Contributor

Cool we are going to proceed with this change, @jughosta I can help next week to bring it to the finish line

@jughosta
Copy link
Contributor Author

jughosta commented Apr 5, 2024

Moving back to "draft" as the removal of the dropdown requires another refactoring.

@jughosta jughosta marked this pull request as draft April 5, 2024 20:32
Copy link
Contributor

@davismcphee davismcphee left a comment

Choose a reason for hiding this comment

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

Thanks for addressing my feedback, and I confirmed the issue I was seeing has been fixed 👍 I see from the comments we're making some more changes now, so I'll hold off on approving for now, but otherwise this would have been good to go on my end.

break;
case UnifiedHistogramExternalVisContextStatus.unknown:
// using `{}` to overwrite the value inside the saved search SO during saving
stateContainer.internalState.transitions.setOverriddenVisContextAfterInvalidation({});
Copy link
Contributor

Choose a reason for hiding this comment

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

Oh that's surprising, I was under the impression it was only undefined that gets skipped since I used null for clearing values recently in saved query SOs. In any case it's a minor concern and doesn't impact the functionality, so no big deal.

Comment on lines +49 to +52
const lensEditFlyoutCancelButton = document.getElementById('lnsCancelEditOnFlyFlyout');
if (lensEditFlyoutCancelButton) {
lensEditFlyoutCancelButton.click?.();
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Neither do I 😅 But I think it's worth tracking as a cleanup item since I'm sure we can find a nicer way to approach it later, but it's good for now.

Comment on lines +479 to +480
id: `${dataView.timeFieldName} every ${interval}`,
name: `${dataView.timeFieldName} every ${interval}`,
Copy link
Contributor

Choose a reason for hiding this comment

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

@stratoula can you help me understand why localizing won't work? It's not a big deal for this PR since it was already this way before, but I'd like to understand why.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah that makes sense. Not something to address for now anyway, mainly just thinking out loud.

Comment on lines 43 to 45
if (!table) {
delete newLayer.table;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Oh that's what I was missing, makes sense 👍

@stratoula
Copy link
Contributor

stratoula commented Apr 8, 2024

@jughosta, @davismcphee pinged me and told me that removing the suggestions logic is a big change and might not make it for 8.14. If this is the case, I would like to proceed with this PR as it is (with the mixed icon for the customized) but then priorite the removal in a follow up PR. So if it makes it, it would be awesome, if not, it will be merged early in the 8.15.

The reason I want this merged for 8.14 is because we are going for GA. I want the Discover SOs to save the vis state from this minor as I am expecting that the customers / users are going to start creating more SOs now that the ES|QL is going to be GA. Adding this feature in 8.15, means that many SOs are going to be created in 8.14 without the viz state so the customers need to update them in 8.15.

@ninoslavmiskovic
Copy link
Contributor

I agree with @stratoula with the importance of this and with the split of the PRs.

Would be optimal if it can make it with the removal of the suggestion, but the risk mitigation is the right path to increase chances of customers saving the state with the SOs when GA in 8.14. 👍

@jughosta jughosta marked this pull request as ready for review April 8, 2024 07:02
@jughosta
Copy link
Contributor Author

jughosta commented Apr 8, 2024

/ci

Copy link
Contributor

@stratoula stratoula left a comment

Choose a reason for hiding this comment

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

  • Vis Changes LGTM!
  • Discover SO behavior LGTM!
  • Suggestions / chart configuration changes LGTM!

I tested it thoroughly and it works great. Let's prioritize afterwards the removal of the suggestions dropdown

Great job @jughosta, I know that it was a tricky one 👏

@kibana-ci
Copy link
Collaborator

💚 Build Succeeded

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
unifiedHistogram 129 136 +7

Public APIs missing comments

Total count of every public API that lacks a comment. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats comments for more detailed information.

id before after diff
savedSearch 78 79 +1
unifiedHistogram 23 29 +6
total +7

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
discover 591.0KB 592.9KB +1.9KB
lens 1.4MB 1.4MB +113.0B
observabilityAIAssistantApp 140.4KB 140.4KB +45.0B
unifiedHistogram 69.6KB 75.5KB +5.9KB
total +7.9KB

Public APIs missing exports

Total count of every type that is part of your API that should be exported but is not. This will cause broken links in the API documentation system. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats exports for more detailed information.

id before after diff
savedSearch 3 4 +1
unifiedHistogram 2 5 +3
total +4

Page load bundle

Size of the bundles that are downloaded on every page load. Target size is below 100kb

id before after diff
savedSearch 11.6KB 11.6KB +48.0B
unifiedHistogram 6.2KB 8.7KB +2.5KB
total +2.5KB
Unknown metric groups

API count

id before after diff
savedSearch 79 80 +1
unifiedHistogram 55 62 +7
total +8

History

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

cc @jughosta

Copy link
Contributor

@davismcphee davismcphee left a comment

Choose a reason for hiding this comment

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

Since we've decided to proceed with the current implementation initially, I'd say this LGTM 👍 Great job on this, it was definitely a hard one but well worth it for users!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport:skip This commit does not require backporting Feature:Discover Discover Application Feature:ES|QL ES|QL related features in Kibana release_note:feature Makes this part of the condensed release notes Team:DataDiscovery Discover, search (e.g. data plugin and KQL), data views, saved searches. For ES|QL, use Team:ES|QL. Team:Obs AI Assistant Team:obs-knowledge Observability Experience Knowledge team v8.14.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[ES|QL][Discover] Allow to store the configured ES|QL visualization