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

[ML] Add ML saved objects to Kibana saved objects management page #205177

Open
wants to merge 23 commits into
base: main
Choose a base branch
from

Conversation

qn895
Copy link
Member

@qn895 qn895 commented Dec 26, 2024

Summary

This PR adds the display of saved objects for anomaly detection jobs, data frame analytics jobs and trained models to the Kibana saved objects management page. Changes include:

  • Add ml-job saved object type into the allowed types. The allowed_type will exclude ml-job and ml-trained-model objects if missing ml canGetJobs capabilities. They are not hyper linked until new navigation routing is implemented.
Screenshot 2025-01-07 at 11 18 17

Spaces without ML permission will not show ML saved objects

Screen.Recording.2025-01-02.at.15.48.27.mov
  • The Export {count} objects reflects only exportable saved objects.

  • User that canGetJobs but not canCreateJob can only inspect, and will not be able to share object to spaces

Screenshot 2025-01-02 at 15 43 16
  • ml-job saved objects are not deletable. The Delete button will be disabled if any ML saved objects is selected, and a hint tooltip message will be shown.
  • ml-job saved objects are not exportable. The Export button will be disabled if any ML saved objects is selected, and a hint tooltip message will be shown.

Checklist

Check the PR satisfies following conditions.

Reviewers should verify this PR satisfies this list as well.

  • 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

Identify risks

Does this PR introduce any risks? For example, consider risks like hard to test bugs, performance regression, potential of data loss.

Describe the risk, its severity, and mitigation for each identified risk. Invite stakeholders and evaluate how to proceed before merging.

@qn895 qn895 self-assigned this Dec 26, 2024
@qn895 qn895 added v9.0.0 release_note:feature Makes this part of the condensed release notes :ml labels Dec 26, 2024
@qn895
Copy link
Member Author

qn895 commented Dec 26, 2024

/ci

1 similar comment
@qn895
Copy link
Member Author

qn895 commented Dec 30, 2024

/ci

@qn895 qn895 force-pushed the ml-kbn-saved-objs-in-management branch from 2543291 to 31c5c56 Compare December 30, 2024 21:13
@qn895
Copy link
Member Author

qn895 commented Dec 30, 2024

/ci

if (obj.id.startsWith(AD_PREFIX)) {
const jobId = obj.id.slice(AD_PREFIX.length);
return {
path: `/app/management/insightsAndAlerting/jobsListLink/${jobId}`,
Copy link
Contributor

Choose a reason for hiding this comment

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

Passing the jobId in the link is wasted currently as we don't use that in the ML management page to restore a filter to the query bar. But I guess it makes more sense to wait till the new management page is ready and then edit this link to provide a filtered link to that page?

Copy link
Member Author

Choose a reason for hiding this comment

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

As discussed, I'm removing the links for all ML objects for now until we have the PR for management page ready

return (
<FormattedMessage
id="savedObjectsManagement.objectsTable.table.hasMlObjects.deleteDisabledTooltip"
defaultMessage="Machine learning objects can’t be deleted."
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggest editing this to say something like Machine learning objects can only be deleted in the Machine Learning management page (last part of that message needs some work!).

Copy link
Member Author

Choose a reason for hiding this comment

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

Updated 1450c34 (#205177)
Screenshot 2025-01-02 at 15 59 19

@szabosteve Follow-up on my slack message, would love to get some feedback for this one liner.

Copy link
Contributor

Choose a reason for hiding this comment

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

@qn895 @peteharverson This tooltip message works fine. We could maybe phrase it a bit more action-oriented, something along the lines of:

Navigate to the Machine Learning management page to delete machine learning objects.

Copy link
Contributor

Choose a reason for hiding this comment

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

That text sounds good to me. Thanks @szabosteve

Copy link
Contributor

Choose a reason for hiding this comment

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

As discussed, until the new management pages are in, let's change this to say Navigate to the Machine Learning pages to delete machine learning objects.

const jobId = obj.id.slice(AD_PREFIX.length);
return {
path: `/app/management/insightsAndAlerting/jobsListLink/${jobId}`,
uiCapabilitiesPath: 'ml.canGetJobs',
Copy link
Member

Choose a reason for hiding this comment

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

Is it possible to add additional capabilities checks to control what actions a user can perform and whether or not the saved objects are listed?

I think should not list the SOs if the user does not have the minimum read permissions and should only be able to edit them if they have write permissions, e.g. for AD SOs:
canGetJobs AD job saved objects are listed but are read only.
canGetJobs && canCreateJobs AD job saved objects are listed and can be edited

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks! Added capabilities check here and here

@qn895
Copy link
Member Author

qn895 commented Jan 2, 2025

/ci

capabilityPath: 'ml.*',
});
const canSeeMLJobs =
mlCapabilities.ml.canGetJobs && mlCapabilities.ml.canGetDataFrameAnalytics;
Copy link
Member

@jgowdyelastic jgowdyelastic Jan 3, 2025

Choose a reason for hiding this comment

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

We can't group the two ML job types together, AD and DFA need to be separate.
In a serverless environment where the DFA feature is disabled, canGetDataFrameAnalytics will always be false. Same for AD feature.

Looking at what is contained inside mlJobType below, I'm not sure if this will be possible to filter these different job types server side.

A possible solution would be to change this check to an || and add some additional filtering on the client side when displaying table. The client side will also have the capabilities available.

@jgowdyelastic
Copy link
Member

Is it possible to hide this callout with a link to the "copy to spaces" flyout?

image

@qn895
Copy link
Member Author

qn895 commented Jan 3, 2025

/ci

@qn895
Copy link
Member Author

qn895 commented Jan 7, 2025

/ci

@qn895
Copy link
Member Author

qn895 commented Jan 7, 2025

/ci

@qn895
Copy link
Member Author

qn895 commented Jan 7, 2025

/ci

@qn895
Copy link
Member Author

qn895 commented Jan 8, 2025

/ci

@qn895 qn895 marked this pull request as ready for review January 8, 2025 05:13
@qn895 qn895 requested review from a team as code owners January 8, 2025 05:13
@elasticmachine
Copy link
Contributor

Pinging @elastic/ml-ui (:ml)

@jeramysoucy jeramysoucy self-requested a review January 9, 2025 18:31
@qn895 qn895 added the backport:version Backport to applied version labels label Jan 9, 2025
@elasticmachine
Copy link
Contributor

💛 Build succeeded, but was flaky

Failed CI Steps

Test Failures

  • [job] [logs] FTR Configs #86 / alerting api integration security and spaces enabled Alerts - Group 1 alerts backfill rule runs ad hoc backfill task should run all execution sets of a scheduled backfill and correctly generate alerts

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
savedObjectsManagement 101 102 +1

Async chunks

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

id before after diff
savedObjectsManagement 81.8KB 83.8KB +1.9KB
spaces 257.0KB 257.1KB +26.0B
total +1.9KB

Page load bundle

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

id before after diff
savedObjectsManagement 19.8KB 20.3KB +471.0B

History

cc @qn895

Copy link
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.

Latest changes LGTM

Copy link
Member

@afharo afharo left a comment

Choose a reason for hiding this comment

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

As a general comment, I'm not a big fan of leaking ML-specific requirements into the SOM code-base.

I wonder if there are any options (onExport/onImport hooks, read-only flag, getInAppUrl) that we can leverage to register all these via the API and inside the ML plugin instead.

Also, please, remove the async from the SOM plugin's lifecycle methods 🙏


constructor(private readonly context: PluginInitializerContext) {
this.logger = this.context.logger.get();
}

public setup({ http, capabilities }: CoreSetup) {
public async setup({ http, capabilities, getStartServices }: CoreSetup) {
Copy link
Member

Choose a reason for hiding this comment

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

The use of async lifecycle methods in plugins is deprecated and highly discouraged. It looks like it's not necessary anyway.

'savedObjectsManagement.objectsTable.table.deleteMLJobsAndModelsDisabledTooltip',
{
defaultMessage:
'Navigate to the Machine Learning management pages to delete machine learning jobs and trained models.',
Copy link
Member

Choose a reason for hiding this comment

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

Can we use management.getInAppUrl in the SO definition to take the users to the ML management pages instead?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes that's the plan. This is dependent on another PR that we will have merge soon. I'll add a todo to make notes.

let filteredSavedObjects = resp.saved_objects;
const mlCapabilities = this.props.applications.capabilities.ml as Record<string, boolean>;

const mlFilters: Record<string, boolean> = {
Copy link
Member

@jgowdyelastic jgowdyelastic Jan 10, 2025

Choose a reason for hiding this comment

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

In the original management page, if only the nlp feature is disabled, we do not list pytorch models, but we do list models from dfa jobs.
image

With this PR, we are still listing pytorch models.
image

The filtering code is here:

export function filterForEnabledFeatureModels<

It would be good to replicate this behaviour as I don't think elser should be listed if nlp is disabled.
However, it will not be easy as we don't have access to the underlying trained models and I'm not sure we should be loading them here.
We also do not currently have a serverless offering where nlp is disabled. So this is low risk.

* License v3.0 only", or the "Server Side Public License, v 1".
*/

export const ML_SAVED_OBJECT_TYPES = new Set(['ml-job', 'ml-trained-model']);
Copy link
Member

@jgowdyelastic jgowdyelastic Jan 10, 2025

Choose a reason for hiding this comment

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

I wonder if we should move the constants declared here to a package and also include this Set.

In this PR ml-job and ml-trained-model are used a few times and it would be safer if they all came from the same place.

@@ -43,6 +43,15 @@ export class ShareToSpaceSavedObjectsManagementAction extends SavedObjectsManage
!this.actionContext ||
!!this.actionContext.capabilities.savedObjectsManagement.shareIntoSpace;
const { namespaceType, hiddenType } = object.meta;

if (object?.type && object.type.startsWith('ml-')) {
const hasMlShareCapabilities =
Copy link
Member

Choose a reason for hiding this comment

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

this check is only looking at AD capabilities. If I disable AD in my yml file with xpack.ml.ad.enabled: false I can no longer share trained models or DFA jobs.

const anySelected = selectedSavedObjects.length > 0;
const allHidden =
anySelected && selectedSavedObjects.every(({ meta: { hiddenType } }) => hiddenType);

const deleteTooltip = () => {
Copy link
Member

Choose a reason for hiding this comment

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

There's a sneaky delete button at the top of the inspect saved object flyout.

image

@@ -378,7 +378,8 @@ export const ShareToSpaceFlyoutInternal = (props: ShareToSpaceFlyoutProps) => {
enableCreateCopyCallout &&
spaces.length > 1 &&
savedObjectTarget.namespaces.length === 1 &&
!arraysAreEqual(savedObjectTarget.namespaces, [ALL_SPACES_ID]);
!arraysAreEqual(savedObjectTarget.namespaces, [ALL_SPACES_ID]) &&
!savedObjectTarget.type.startsWith('ml');
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: The only concern I have here is that we're string matching to catch all ML SO types. This appears to work, but I am unfamiliar with all ML SO types. Could we make this more explicit, something like an "isMLType" utility function that we can ensure covers only, but all of, the ML SO types explicitly?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport:version Backport to applied version labels :ml release_note:feature Makes this part of the condensed release notes v9.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants