Skip to content

[Discover] Context awareness toolkit#253183

Merged
davismcphee merged 42 commits into
elastic:mainfrom
davismcphee:discover-context-awareness-toolkit
May 30, 2026
Merged

[Discover] Context awareness toolkit#253183
davismcphee merged 42 commits into
elastic:mainfrom
davismcphee:discover-context-awareness-toolkit

Conversation

@davismcphee
Copy link
Copy Markdown
Contributor

@davismcphee davismcphee commented Feb 15, 2026

Summary

This PR introduces a context awareness toolkit that gives profile extension points a centralized way to trigger actions in the host context (add filters, open tabs, update queries, etc.):

flowchart LR
    subgraph Hosts["Host creates toolkit"]
        MA["Main App"]
        EM["Embeddable"]
        CP["Context Page"]
    end

    Hosts --> TK["Toolkit<br/><code>addFilter, openInNewTab,<br/>updateESQLQuery, setExpandedDoc, ...</code>"]

    TK --> SPM["ScopedProfilesManager"]

    SPM -->|"{ context, toolkit }"| Prof["Profile Accessors<br/><i>cell renderers, chart section,<br/>doc viewer, cell actions, ...</i>"]

    Prof -->|"toolkit.actions.*"| Hosts
Loading

Why

Profile extension points need to trigger actions in the host app, but there was no central way to do this. Each host (Discover, embeddable, surrounding docs) passed actions down through extension point params, resulting in a lot of duplication and no consistent interface.

How it works

The toolkit gets injected into profile accessors alongside the existing context param, so extensions receive (prev, { context, toolkit }) and can call things like toolkit.actions.addFilter(...) directly.

Each host constructs its own toolkit implementation:

  • Main app — actions dispatch to tab-scoped Redux thunks
  • Embeddable — actions use dashboard triggers and local state
  • Context page — actions use the filter manager and React state

This decouples what profiles can do from how each host implements it, and makes adding new host contexts straightforward. It also lays the foundation for extensible state management for profiles, which can also be centralized and exposed via the toolkit.

Cleanup

  • Removes duplicate action implementations across Discover, the embeddable, and surrounding docs
  • Unifies filter handling into a single thunk that supports both KQL/Lucene and ES|QL WHERE clauses
  • Simplifies DiscoverLayout by moving filter action code out of the component

Prep work related to #242987.

Checklist

  • Any text added follows EUI's writing guidelines, uses sentence case text and includes i18n support
  • Documentation was added for features that require explanation or tutorials
  • Unit or functional tests were updated or added to match the most common scenarios
  • If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the docker list
  • This was checked for breaking HTTP API changes, and any breaking changes have been approved by the breaking-change committee. The release_note:breaking label should be applied in these situations.
  • Flaky Test Runner was used on any tests changed
  • The PR description includes the appropriate Release Notes section, and the correct release_note:* label is applied per the guidelines
  • Review the backport guidelines and apply applicable backport:* labels.

@davismcphee davismcphee self-assigned this Feb 15, 2026
@davismcphee davismcphee added Feature:Discover Discover Application refactoring release_note:skip Skip the PR/issue when compiling release notes backport:skip This PR does not require backporting Team:DataDiscovery Discover, search (data plugin and KQL), data views, saved searches. For ES|QL, use Team:ES|QL. t// labels Mar 7, 2026
@elasticmachine
Copy link
Copy Markdown
Contributor

💚 Build Succeeded

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
discover 1978 1981 +3

Async chunks

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

id before after diff
discover 1.6MB 1.6MB +2.7KB

Page load bundle

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

id before after diff
discover 25.5KB 25.5KB +27.0B
Unknown metric groups

async chunk count

id before after diff
discover 43 44 +1

History

cc @davismcphee

*/
export const useStableCallback = <T extends (...args: never[]) => unknown>(fn: T | undefined) => {
const ref = useRef(fn);
export const useStableCallback = <T extends (...args: Parameters<T>) => ReturnType<T>>(fn: T) => {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I originally wrote this hook a long time ago as part of Unified Histogram, and it was moved to this package a few weeks ago to share. I reimplemented the pattern for part of this PR and a bot suggested I use this instead, which makes sense. But the original version isn't totally safe due to timing around useEffect, so I wanted to update it to a better pattern. I can extract this into a separate PR if there are concerns.

@davismcphee davismcphee marked this pull request as ready for review May 24, 2026 23:59
@davismcphee davismcphee requested review from a team as code owners May 24, 2026 23:59
@infra-vault-gh-plugin-prod
Copy link
Copy Markdown

Pinging @elastic/kibana-data-discovery (Team:DataDiscovery)

Copy link
Copy Markdown
Contributor

@jughosta jughosta left a comment

Choose a reason for hiding this comment

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

LGTM, have not noticed any issues when testing 👍

Thanks for creating the centralized way of managing the provided actions!

Comment on lines +70 to +71
private cachedRootContext: ContextWithProfileId<RootContext>;
private cachedRootProfile: AppliedProfile;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why do we now need the "cached" versions?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Sorry, forgot to respond to this. It's because of this change. Calling this.getRootProfile() now resolves the root profile each time instead of sharing one instance, so we can inject the current tab's toolkit. Now we cache it locally in the scoped manager and only resolve again when the root context has actually changed.

@iblancof iblancof self-requested a review May 27, 2026 07:05
Copy link
Copy Markdown
Contributor

@iblancof iblancof left a comment

Choose a reason for hiding this comment

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

The obs-exploration code changes LGTM 👍🏻
Also did a local test, and everything looked good.

Copy link
Copy Markdown
Contributor

@rStelmach rStelmach left a comment

Choose a reason for hiding this comment

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

obs-onboarding part LGTM

Copy link
Copy Markdown
Contributor

@peteharverson peteharverson left a comment

Choose a reason for hiding this comment

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

ML changes for patterns profile LGTM

Copy link
Copy Markdown
Contributor

@PhilippeOberti PhilippeOberti left a comment

Choose a reason for hiding this comment

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

Desk tested and code LGTM

@davismcphee davismcphee enabled auto-merge (squash) May 29, 2026 23:24
@kibanamachine
Copy link
Copy Markdown
Contributor

💛 Build succeeded, but was flaky

Failed CI Steps

Test Failures

  • [job] [logs] FTR Configs #150 / Cloud Security Posture - Group 5 (KSPM + Flyouts) Security Alerts Page - Graph visualization expanded flyout - filter by node

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
discover 2129 2132 +3

Async chunks

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

id before after diff
alertingVTwo 963.3KB 963.2KB -98.0B
discover 1.9MB 1.9MB +1.9KB
esql 930.7KB 930.6KB -55.0B
total +1.8KB

Page load bundle

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

id before after diff
discover 28.9KB 28.9KB +25.0B
Unknown metric groups

async chunk count

id before after diff
discover 53 54 +1

History

cc @davismcphee

@davismcphee davismcphee merged commit 6c6e833 into elastic:main May 30, 2026
31 checks passed
@davismcphee davismcphee deleted the discover-context-awareness-toolkit branch May 30, 2026 02:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport:skip This PR does not require backporting Feature:Discover Discover Application refactoring release_note:skip Skip the PR/issue when compiling release notes Team:DataDiscovery Discover, search (data plugin and KQL), data views, saved searches. For ES|QL, use Team:ES|QL. t// v9.5.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants