[PoC] Discover profile state#271164
Draft
davismcphee wants to merge 5 commits into
Draft
Conversation
|
🤖 Jobs for this PR can be triggered through checkboxes. 🚧
ℹ️ To trigger the CI, please tick the checkbox below 👇
|
d60b8ab to
1dd905b
Compare
a40ea08 to
8c37532
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Introduces an extensible state-management layer that lets Discover profiles own state with different lifetimes — ephemeral UI, URL-synced, locally persisted, and locator-embedded — without each profile having to wire its own plumbing into the tab/Redux/URL stack.
Relates to #242987.
Motivation
Profiles like Metrics need state that survives tab switches, page refreshes, shared URLs, and locator links (dimension breakdowns, chart configs, view-mode toggles, etc.). Today the only generic slots are
appState/globalState, which don't fit ad-hoc profile shapes and don't expose lifetime distinctions. The goal is one declarative contract a profile can describe once, with a single host-side registry that routes each field to the right destination.Approach
A profile declares the shape of its state once, annotates each field with a lifetime ("type"), and reads/writes it through a per-tab adapter. The host inspects those descriptors to route state to Redux, the URL, local storage, and the locator. Profiles never touch any of those layers directly.
Key building blocks
ProfileStateDefinition<TState>—{ key, descriptor }wheredescriptoris{ [field]: { type: 'ui' | 'url' | 'persistent' } }.keynamespaces this state across profiles in the tab'sprofileStaterecord. (profile_state.ts)ProfileStateRegistry— Single registry onservices.profileStateRegistry. Definitions register once at plugin start viaregisterProfileStateDefinitions.pickStateByTypeis what every destination uses to filter the right fields out.ProfileStateAdapter<TState>— The simplified interface profiles use to read and write their state. It deliberately hides Redux, observables wiring, URL syncing, and storage from profile code, which means:TState, so there's no fixed schema profiles must conform to.toolkit.getStateAdapter(MY_DEF)and read/write the same state.ContextAwarenessToolkit.getStateAdapter— The already-existingtoolkitargument on extension points. Returns the adapter scoped to the current tab and definition.DataSourceContext.profileState— A data-source profile binds itself to a definition by returningprofileState: MY_DEFfrom itsresolvecontext. URL sync, locator emission, and restoration all key off this binding to know which definition is currently active for a tab.How each lifetime flows
UiUrl_pquery param ⇄ Redux_pand two-way synced with the URL while the bound profile is active.PersistentgetPersistentProfileStateon write and reload (tabs_storage_manager.ts).DiscoverAppLocatorParams.profileUrlStategetProfileUrlState; consumed by the share menu, search-session restoration, andappLocatorGetLocationCommon(which writes it to_p).Trying it out
kibana.dev.yml:FROM my-example-logs. Expand any row → Extensible State Example doc-viewer tab. The three selects exercise UI, Persistent, and URL state respectively.Examples
1. The adapter interface
2. Declare state
registerProfileStateDefinitionsis called once during plugin start (plugin.tsx), so a new definition only has to be added there.3. Bind state to a profile
Setting
profileStateon a data source profile's resolved context tells the URL sync layer which definition'sUrl-typed fields to two-way sync with_pwhile this profile is the active match for the tab. This is the only place a definition gets tied to a specific profile, and only for URL syncing — any state can still be consumed from any profile without a binding.4. Consume the same state across profile levels
Any profile — root, data source, or document — can pick up a definition through its toolkit and interact with it. This is useful when state needs to drive behavior across the whole hierarchy (e.g. a setting the chart, row controls, and cell renderers should all react to). The call site is identical regardless of the profile level:
5. Mutate state
Not yet covered
ProfileStateTypeyet; persisting profile state into the Discover Session saved object is TBD.historyMethod— accepted by the adapter API but not yet honored by the URL sync path.Checklist
release_note:breakinglabel should be applied in these situations.release_note:*label is applied per the guidelinesbackport:*labels.