-
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
Differentiate load-by-reference for embeddables #111191
Comments
Pinging @elastic/kibana-security (Team:Security) |
Pinging @elastic/kibana-presentation (Team:Presentation) |
IMO, embeddables should not know anything about Saved Objects or any other objects or any other way of loading the data. It should be up to each embeddable type to implement (or not) any persistence mechanism. Ideally we would pull out any mentions of "saved objects" out of the Embeddable plugin. And then it is up to each embeddable where its data is stored. |
As Vadim said, there should be no concept of 'by value' or 'by reference' on the Embeddable API side, nor should there be any concept of 'loaded via saved object' vs 'loaded through snapshot URL' there. That said, I think we can still differentiate between Scenario 3 and Scenario 4 on a case by case basis for each embeddable that loads a saved object. One way to do this would be by interfacing with the Dashboard Container before loading the saved object:
// if the embeddable is by reference...
if (this.getRoot().isContainer &&
this.getRoot().type !== DASHBOARD_CONTAINER_TYPE &&
!(this.getRoot() as DashboardContainer).isLoadedFromId()) {
// load saved object via SavedObjectsClient.resolve
} else {
// load saved object via SavedObjectsClient.get
} |
Sure, apologies if the issue description came off as prescriptive, I just meant that we should find a way to differentiate 👍
Nice idea! |
For now, this is only a dashboard problem yes! Canvas cannot be shared as a snapshot in the same way. |
I have a feeling that this issue is wrongly stated, or i am not understanding it well.
|
To me it looks like we need a general solution (not something embeddable, or worse, dashboard specific) that would allow us to identify whenever we are loading the saved objects if the object Ids are Application should theoretically have that knowledge. So we could create a very simple service that every app can then use:
and then internally in the savedObjectsClient.get we could do a check against this and figure our if we want to resolve or not. Saved objects client could internally also log all the partial matches to the service, and app could fetch this and notify the user about it. |
As mentioned above, I noticed this behavior in the PR that changed Lens to use the Lens creates an So, it seems pretty clear that the Lens embeddable is fetching the Lens saved object. Am I missing something?
Let me try to phrase, then! An Embeddable can be loaded by reference or by value. If it is loaded by reference, and it fetches the saved object, it really needs to know where the reference ID came from. Was it from a saved object (e.g., a dashboard saved object)? Or was it from a URL (e.g., a dashboard snapshot URL)? Does that make sense?
Yes, and as I mentioned above in the Lens example, the Lens embeddable is fetching its own saved object. But in the case where it is loading the object by reference, it doesn't have enough context to know whether it should use
I'm sorry, I don't really follow. When you are looking at a dashboard, if you copy the snapshot URL, it dumps the contents of the saved object (including its references) to a URL. That can't be migrated, at least not today.
That's an interesting idea. It's a harder problem when you think about transitive references... for example, a dashboard snapshot URL with a reference to a lens saved object that has a reference to an index pattern. In an ideal world we would:
but if the application sets a "context" when the page loads, then we don't have that nuance, all consumers would either So it would be better if each saved object in the graph could set such a "context" individually for its child references, but it certainly doesn't sound like there's an easy solution for that... |
Closing this for now because sharing an entire dashboard snapshot URL with panels is now extremely unlikely, and we have a warning in place to prevent it. Additionally, most panels are now By Value. IMO it would be alright at this point for the Embeddables which can be by reference to use only get instead of resolve, and in the extremely rare case where an unmigrated legacy ID from pre 8.0 is loaded into the dashboard panels via a bookmarked URL it would throw a 404. @vadimkibana @ppisljar if you think it is still important to allow Embeddable implementations to differentiate when loading their saved objects, we can re-open this and look into prioritizing it. |
Overview
Embeddables (visualizations) can be loaded in two ways:
type
andid
An example:
The primary consumer of embeddables today is the dashboard plugin. When you create a new dashboard, then you add a panel, it is a wrapper for an embeddable. You can add this by value (in which case, the embeddable's attributes are persisted in the dashboard's
panelJson
field), or you can add this by reference (in which case, the visualization is persisted as a separate saved object, and the object'stype
/id
are added to the dashboard'sreferences
field.If an embeddable is loaded by reference, the consumer (the dashboard plugin in this case) passes the reference to the embeddable, and the embeddable is responsible for fetching the saved object in question.
In the 8.0 release, we are implementing a breaking change that will regenerate all object IDs (#100489). Any saved object that can be loaded through a "deep link" URL must be retrieved using the
SavedObjectsClient.resolve
API.When considering embeddables, there is another dimension to this: dashboards themselves can either be persisted as a saved object in Elasticsearch or as a "snapshot URL".
That means we have four different scenarios when loading embeddables:
SavedObjectsClient.get
SavedObjectsClient.get
Regarding the breaking change: only scenario (4) needs to be retrieved with
SavedObjectsClient.resolve
. However,However, while implementing #110059 I discovered that embeddables can' tell the difference between scenarios (3) and (4) above. So in that PR, all embedded Lens visualizations loaded by reference were changed to be retrieved with
SavedObjectsClient.resolve
.What's the problem?
As mentioned in the Sharing Saved Objects developer guide (FAQ 6), saved objects should only retrieved with
SavedObjectsClient.resolve
when loaded through a deep link URL. There are several reasons for this:resolve
is less performantresolve
is a temporary stop-gap to get us over this conversion hump without breaking existing deep link URLs, but we eventually want to get rid of it. To that end, we are trying to minimize usage ofresolve
, and we are collecting usage data on how often it's used / what the different outcomes are.aliasMatch
andconflict
outcomes versus theexactMatch
outcome; this usage data gets diluted if plugins callresolve
in a situation where the outcome will always be `exactMatch1.aliasMatch
andconflict
outcomes more often than necessary if they useresolve
in non-deep-link situations.TL;DR
To minimize the usage of
resolve
, we need for embeddables to be able to differentiate between scenarios (3) and (4) above, so they can go back to usingSavedObjectsClient.get
for scenario (3).This is not required for the 8.0 release, but would preferably be done in the early 8.x timeframe.
I expect this change will need to be made by @elastic/kibana-app-services, and then consumers of embeddables will need to change their implementation accordingly.
The text was updated successfully, but these errors were encountered: