Skip to content

Commit

Permalink
[Enterprise Search] Model state change error handling (#172409)
Browse files Browse the repository at this point in the history
## Summary

This PR adds error handling to model actions (deploy, start) in the ML
model selection list. If either of these API calls fail, an error is
displayed. The error stays on the screen until the flyout is reopened or
another model action succeeds.

Unfortunately there's no straightforward way to surface the root cause,
so we display a generic error message to check the Kibana logs (which do
contain the cause).

<img width="1443" alt="Screenshot 2023-12-01 at 17 50 52"
src="https://github.com/elastic/kibana/assets/14224983/d9fe2633-33ee-47ef-a47a-3bd401216853">

### Checklist

- [x] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [ ] [Flaky Test
Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was
used on any tests changed
- [x] Any UI touched in this PR is usable by keyboard only (learn more
about [keyboard accessibility](https://webaim.org/techniques/keyboard/))
- [x] Any UI touched in this PR does not create any new axe failures
(run axe in browser:
[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),
[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))
- [x] This renders correctly on smaller devices using a responsive
layout. (You can test this [in your
browser](https://www.browserstack.com/guide/responsive-testing-on-local-server))
  • Loading branch information
demjened authored Dec 2, 2023
1 parent c88d4a7 commit 7ad94e9
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import React from 'react';
import { useValues, useActions } from 'kea';

import {
EuiCallOut,
EuiFieldText,
EuiForm,
EuiFormRow,
Expand All @@ -28,6 +29,7 @@ import { IndexViewLogic } from '../../index_view_logic';

import { EMPTY_PIPELINE_CONFIGURATION, MLInferenceLogic } from './ml_inference_logic';
import { ModelSelect } from './model_select';
import { ModelSelectLogic } from './model_select_logic';
import { PipelineSelectOption } from './pipeline_select_option';

const PIPELINE_SELECT_PLACEHOLDER_VALUE = 'pipeline_placeholder$$';
Expand Down Expand Up @@ -56,6 +58,7 @@ export const ConfigurePipeline: React.FC = () => {
const { selectExistingPipeline, setInferencePipelineConfiguration } =
useActions(MLInferenceLogic);
const { ingestionMethod } = useValues(IndexViewLogic);
const { modelStateChangeError } = useValues(ModelSelectLogic);
const { pipelineName } = configuration;

const nameError = formErrors.pipelineName !== undefined && pipelineName.length > 0;
Expand Down Expand Up @@ -133,6 +136,22 @@ export const ConfigurePipeline: React.FC = () => {
}
/>
</EuiFormRow>
{modelStateChangeError && (
<>
<EuiSpacer />
<EuiCallOut
title={i18n.translate(
'xpack.enterpriseSearch.content.indices.pipelines.addInferencePipelineModal.steps.configure.modelStateChangeError.title',
{ defaultMessage: 'Error changing model state' }
)}
color="danger"
iconType="error"
>
{modelStateChangeError}
</EuiCallOut>
<EuiSpacer />
</>
)}
<EuiFormRow
fullWidth
label={i18n.translate(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import { LogicMounter } from '../../../../../__mocks__/kea_logic';

import { HttpError } from '../../../../../../../common/types/api';
import { MlModel, MlModelDeploymentState } from '../../../../../../../common/types/ml';
import { CachedFetchModelsApiLogic } from '../../../../api/ml_models/cached_fetch_models_api_logic';
import {
Expand Down Expand Up @@ -124,6 +125,22 @@ describe('ModelSelectLogic', () => {
});
});

describe('modelStateChangeError', () => {
it('gets error from API error response', () => {
const error = {
body: {
error: 'some-error',
message: 'some-error-message',
statusCode: 500,
},
} as HttpError;

StartModelApiLogic.actions.apiError(error);

expect(ModelSelectLogic.values.modelStateChangeError).toEqual('some-error-message');
});
});

describe('selectableModels', () => {
it('gets models data from API response', () => {
CachedFetchModelsApiLogic.actions.apiSuccess(FETCH_MODELS_API_DATA_RESPONSE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { kea, MakeLogicType } from 'kea';

import { HttpError, Status } from '../../../../../../../common/types/api';
import { MlModel } from '../../../../../../../common/types/ml';
import { getErrorsFromHttpResponse } from '../../../../../shared/flash_messages/handle_api_errors';
import {
CachedFetchModelsApiLogic,
CachedFetchModlesApiLogicActions,
Expand All @@ -25,16 +26,18 @@ import {

export interface ModelSelectActions {
createModel: (modelId: string) => { modelId: string };
createModelError: CreateModelApiLogicActions['apiError'];
createModelMakeRequest: CreateModelApiLogicActions['makeRequest'];
createModelSuccess: CreateModelApiLogicActions['apiSuccess'];

fetchModels: () => void;
fetchModelsMakeRequest: CachedFetchModlesApiLogicActions['makeRequest'];
fetchModelsError: CachedFetchModlesApiLogicActions['apiError'];
fetchModelsMakeRequest: CachedFetchModlesApiLogicActions['makeRequest'];
fetchModelsSuccess: CachedFetchModlesApiLogicActions['apiSuccess'];
startPollingModels: CachedFetchModlesApiLogicActions['startPolling'];

startModel: (modelId: string) => { modelId: string };
startModelError: CreateModelApiLogicActions['apiError'];
startModelMakeRequest: StartModelApiLogicActions['makeRequest'];
startModelSuccess: StartModelApiLogicActions['apiSuccess'];
}
Expand All @@ -45,6 +48,7 @@ export interface ModelSelectValues {
createModelStatus: Status;
isLoading: boolean;
isInitialLoading: boolean;
modelStateChangeError: string | undefined;
modelsData: FetchModelsApiResponse | undefined;
modelsStatus: Status;
selectableModels: MlModel[];
Expand Down Expand Up @@ -118,6 +122,14 @@ export const ModelSelectLogic = kea<MakeLogicType<ModelSelectValues, ModelSelect
(createModelStatus: Status, startModelStatus: Status) =>
createModelStatus === Status.LOADING || startModelStatus === Status.LOADING,
],
modelStateChangeError: [
() => [selectors.createModelError, selectors.startModelError],
(createModelError?: HttpError, startModelError?: HttpError) => {
if (!createModelError && !startModelError) return undefined;

return getErrorsFromHttpResponse(createModelError ?? startModelError!)[0];
},
],
selectableModels: [
() => [selectors.modelsData],
(response: FetchModelsApiResponse) => response ?? [],
Expand Down

0 comments on commit 7ad94e9

Please sign in to comment.