From 0cd0348287c007a2367b66f2f3be4376b24b8529 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Mon, 30 Mar 2020 14:41:15 +0100 Subject: [PATCH 1/3] [ML] Fixing reporting of http request errors --- x-pack/plugins/ml/common/util/errors.ts | 19 +++++++++++++++ .../data_frame_analytics/common/analytics.ts | 2 +- .../use_create_analytics_form.test.tsx | 3 ++- .../use_create_analytics_form.ts | 14 +---------- .../post_save_options/post_save_options.tsx | 3 ++- .../pages/components/summary_step/summary.tsx | 5 ++-- .../application/services/job_service.js | 12 +++++----- .../calendars/list/delete_calendars.js | 24 ++++++++++--------- .../util/{ml_error.js => ml_error.ts} | 6 +++-- 9 files changed, 51 insertions(+), 37 deletions(-) create mode 100644 x-pack/plugins/ml/common/util/errors.ts rename x-pack/plugins/ml/public/application/util/{ml_error.js => ml_error.ts} (86%) diff --git a/x-pack/plugins/ml/common/util/errors.ts b/x-pack/plugins/ml/common/util/errors.ts new file mode 100644 index 000000000000..4446624bf2e7 --- /dev/null +++ b/x-pack/plugins/ml/common/util/errors.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { isErrorResponse } from '../types/errors'; + +export function getErrorMessage(error: any) { + if (isErrorResponse(error)) { + return `${error.body.error}: ${error.body.message}`; + } + + if (typeof error === 'object' && typeof error.message === 'string') { + return error.message; + } + + return JSON.stringify(error); +} diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts index 95a8dfbb308f..e8f59ea7a65b 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts @@ -11,7 +11,7 @@ import { Subscription } from 'rxjs'; import { cloneDeep } from 'lodash'; import { ml } from '../../services/ml_api_service'; import { Dictionary } from '../../../../common/types/common'; -import { getErrorMessage } from '../pages/analytics_management/hooks/use_create_analytics_form'; +import { getErrorMessage } from '../../../../common/util/errors'; import { SavedSearchQuery } from '../../contexts/ml'; import { SortDirection } from '../../components/ml_in_memory_table'; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/use_create_analytics_form.test.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/use_create_analytics_form.test.tsx index 1a248f8559ff..182e50a5d74d 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/use_create_analytics_form.test.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/use_create_analytics_form.test.tsx @@ -10,7 +10,8 @@ import { mountHook } from 'test_utils/enzyme_helpers'; import { MlContext } from '../../../../../contexts/ml'; import { kibanaContextValueMock } from '../../../../../contexts/ml/__mocks__/kibana_context_value'; -import { getErrorMessage, useCreateAnalyticsForm } from './use_create_analytics_form'; +import { useCreateAnalyticsForm } from './use_create_analytics_form'; +import { getErrorMessage } from '../../../../../../../common/util/errors'; const getMountedHook = () => mountHook( diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/use_create_analytics_form.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/use_create_analytics_form.ts index 86c43b232738..34f1d0426490 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/use_create_analytics_form.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/use_create_analytics_form.ts @@ -9,7 +9,7 @@ import { useReducer } from 'react'; import { i18n } from '@kbn/i18n'; import { SimpleSavedObject } from 'kibana/public'; -import { isErrorResponse } from '../../../../../../../common/types/errors'; +import { getErrorMessage } from '../../../../../../../common/util/errors'; import { DeepReadonly } from '../../../../../../../common/types/common'; import { ml } from '../../../../../services/ml_api_service'; import { useMlContext } from '../../../../../contexts/ml'; @@ -41,18 +41,6 @@ export interface CreateAnalyticsFormProps { state: State; } -export function getErrorMessage(error: any) { - if (isErrorResponse(error)) { - return `${error.body.error}: ${error.body.message}`; - } - - if (typeof error === 'object' && typeof error.message === 'string') { - return error.message; - } - - return JSON.stringify(error); -} - export const useCreateAnalyticsForm = (): CreateAnalyticsFormProps => { const mlContext = useMlContext(); const [state, dispatch] = useReducer(reducer, getInitialState()); diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/summary_step/components/post_save_options/post_save_options.tsx b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/summary_step/components/post_save_options/post_save_options.tsx index c24c018f50d7..2e7cc9c413a2 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/summary_step/components/post_save_options/post_save_options.tsx +++ b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/summary_step/components/post_save_options/post_save_options.tsx @@ -10,6 +10,7 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { JobRunner } from '../../../../../common/job_runner'; import { useMlKibana } from '../../../../../../../contexts/kibana'; +import { getErrorMessage } from '../../../../../../../../../common/util/errors'; // @ts-ignore import { CreateWatchFlyout } from '../../../../../../jobs_list/components/create_watch_flyout/index'; @@ -69,7 +70,7 @@ export const PostSaveOptions: FC = ({ jobRunner }) => { defaultMessage: `Error starting job`, } ), - text: error.message, + text: getErrorMessage(error), }); } } diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/summary_step/summary.tsx b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/summary_step/summary.tsx index 75994b535889..d8cd0f5e4f1f 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/summary_step/summary.tsx +++ b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/summary_step/summary.tsx @@ -24,6 +24,7 @@ import { mlJobService } from '../../../../../services/job_service'; import { JsonEditorFlyout, EDITOR_MODE } from '../common/json_editor_flyout'; import { DatafeedPreviewFlyout } from '../common/datafeed_preview_flyout'; import { JOB_TYPE } from '../../../../../../../common/constants/new_job'; +import { getErrorMessage } from '../../../../../../../common/util/errors'; import { isSingleMetricJobCreator, isAdvancedJobCreator } from '../../../common/job_creator'; import { JobDetails } from './components/job_details'; import { DatafeedDetails } from './components/datafeed_details'; @@ -75,7 +76,7 @@ export const SummaryStep: FC = ({ setCurrentStep, isCurrentStep }) => title: i18n.translate('xpack.ml.newJob.wizard.summaryStep.createJobError', { defaultMessage: `Job creation error`, }), - text: error.message, + text: getErrorMessage(error), }); setCreatingJob(false); } @@ -94,7 +95,7 @@ export const SummaryStep: FC = ({ setCurrentStep, isCurrentStep }) => title: i18n.translate('xpack.ml.newJob.wizard.summaryStep.createJobError', { defaultMessage: `Job creation error`, }), - text: error.message, + text: getErrorMessage(error), }); setCreatingJob(false); } diff --git a/x-pack/plugins/ml/public/application/services/job_service.js b/x-pack/plugins/ml/public/application/services/job_service.js index 0454d40e7892..bbfec49ac138 100644 --- a/x-pack/plugins/ml/public/application/services/job_service.js +++ b/x-pack/plugins/ml/public/application/services/job_service.js @@ -169,12 +169,12 @@ class JobService { function error(err) { console.log('jobService error getting list of jobs:', err); - msgs.error( + msgs.notify.error( i18n.translate('xpack.ml.jobService.jobsListCouldNotBeRetrievedErrorMessage', { defaultMessage: 'Jobs list could not be retrieved', }) ); - msgs.error('', err); + msgs.notify.error('', err); reject({ jobs, err }); } }); @@ -256,12 +256,12 @@ class JobService { function error(err) { console.log('JobService error getting list of jobs:', err); - msgs.error( + msgs.notify.error( i18n.translate('xpack.ml.jobService.jobsListCouldNotBeRetrievedErrorMessage', { defaultMessage: 'Jobs list could not be retrieved', }) ); - msgs.error('', err); + msgs.notify.error('', err); reject({ jobs, err }); } }); @@ -302,12 +302,12 @@ class JobService { function error(err) { console.log('loadDatafeeds error getting list of datafeeds:', err); - msgs.error( + msgs.notify.error( i18n.translate('xpack.ml.jobService.datafeedsListCouldNotBeRetrievedErrorMessage', { defaultMessage: 'datafeeds list could not be retrieved', }) ); - msgs.error('', err); + msgs.notify.error('', err); reject({ jobs, err }); } }); diff --git a/x-pack/plugins/ml/public/application/settings/calendars/list/delete_calendars.js b/x-pack/plugins/ml/public/application/settings/calendars/list/delete_calendars.js index f06812b2a912..50777485903d 100644 --- a/x-pack/plugins/ml/public/application/settings/calendars/list/delete_calendars.js +++ b/x-pack/plugins/ml/public/application/settings/calendars/list/delete_calendars.js @@ -7,6 +7,7 @@ import { getToastNotifications } from '../../../util/dependency_cache'; import { ml } from '../../../services/ml_api_service'; import { i18n } from '@kbn/i18n'; +import { getErrorMessage } from '../../../../../common/util/errors'; export async function deleteCalendars(calendarsToDelete, callback) { if (calendarsToDelete === undefined || calendarsToDelete.length === 0) { @@ -36,17 +37,18 @@ export async function deleteCalendars(calendarsToDelete, callback) { await ml.deleteCalendar({ calendarId }); } catch (error) { console.log('Error deleting calendar:', error); - const errorMessage = i18n.translate( - 'xpack.ml.calendarsList.deleteCalendars.deletingCalendarErrorMessage', - { - defaultMessage: 'An error occurred deleting calendar {calendarId}{errorMessage}', - values: { - calendarId: calendar.calendar_id, - errorMessage: error.message ? ` : ${error.message}` : '', - }, - } - ); - toastNotifications.addDanger(errorMessage); + toastNotifications.addDanger({ + title: i18n.translate( + 'xpack.ml.calendarsList.deleteCalendars.deletingCalendarErrorMessage', + { + defaultMessage: 'An error occurred deleting calendar {calendarId}', + values: { + calendarId: calendar.calendar_id, + }, + } + ), + text: getErrorMessage(error), + }); } } diff --git a/x-pack/plugins/ml/public/application/util/ml_error.js b/x-pack/plugins/ml/public/application/util/ml_error.ts similarity index 86% rename from x-pack/plugins/ml/public/application/util/ml_error.js rename to x-pack/plugins/ml/public/application/util/ml_error.ts index c970b4296844..2a0280404c18 100644 --- a/x-pack/plugins/ml/public/application/util/ml_error.js +++ b/x-pack/plugins/ml/public/application/util/ml_error.ts @@ -7,12 +7,14 @@ import { KbnError } from '../../../../../../src/plugins/kibana_utils/public'; export class MLRequestFailure extends KbnError { + origError: any; + resp: any; // takes an Error object and and optional response object // if error is falsy (null) the response object will be used // notify will show the full expandable stack trace of the response if a response object is used and no error is passed in. - constructor(error, resp) { + constructor(error: any, resp: any) { error = error || {}; - super(error.message || JSON.stringify(resp), MLRequestFailure); + super(error.message || JSON.stringify(resp)); this.origError = error; this.resp = typeof resp === 'string' ? JSON.parse(resp) : resp; From f7c3b648ef57569b758b2b9280f4b09dfb8c5f38 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Mon, 30 Mar 2020 15:48:32 +0100 Subject: [PATCH 2/3] fixing types --- .../hooks/use_create_analytics_form/index.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/index.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/index.ts index 0eb3d7180c20..9df0b542f50a 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/index.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/index.ts @@ -4,8 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { - useCreateAnalyticsForm, - CreateAnalyticsFormProps, - getErrorMessage, -} from './use_create_analytics_form'; +export { useCreateAnalyticsForm, CreateAnalyticsFormProps } from './use_create_analytics_form'; From de47bf67029bcdc01fd213f01f0ff355d37e38f2 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Mon, 30 Mar 2020 16:58:34 +0100 Subject: [PATCH 3/3] updating translations --- x-pack/plugins/translations/translations/ja-JP.json | 1 - x-pack/plugins/translations/translations/zh-CN.json | 1 - 2 files changed, 2 deletions(-) diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index f2ea8f8c6dd0..1f7a1294fe78 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -7420,7 +7420,6 @@ "xpack.ml.calendarsEdit.newEventModal.startDateAriaLabel": "開始日", "xpack.ml.calendarsEdit.newEventModal.toLabel": "終了:", "xpack.ml.calendarsList.deleteCalendars.calendarsLabel": "{calendarsToDeleteCount} 件のカレンダー", - "xpack.ml.calendarsList.deleteCalendars.deletingCalendarErrorMessage": "カレンダー {calendarId} の削除中にエラーが発生しました: {errorMessage}", "xpack.ml.calendarsList.deleteCalendars.deletingCalendarsNotificationMessage": "{messageId} を削除中", "xpack.ml.calendarsList.deleteCalendars.deletingCalendarSuccessNotificationMessage": "{messageId} が選択されました", "xpack.ml.calendarsList.deleteCalendarsModal.cancelButtonLabel": "キャンセル", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 0dd584e32a24..f93216662ca7 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -7420,7 +7420,6 @@ "xpack.ml.calendarsEdit.newEventModal.startDateAriaLabel": "开始日期", "xpack.ml.calendarsEdit.newEventModal.toLabel": "到:", "xpack.ml.calendarsList.deleteCalendars.calendarsLabel": "{calendarsToDeleteCount} 个日历", - "xpack.ml.calendarsList.deleteCalendars.deletingCalendarErrorMessage": "删除日历 {calendarId} 时出错。{errorMessage}", "xpack.ml.calendarsList.deleteCalendars.deletingCalendarsNotificationMessage": "正在删除 {messageId}", "xpack.ml.calendarsList.deleteCalendars.deletingCalendarSuccessNotificationMessage": "已删除 {messageId}", "xpack.ml.calendarsList.deleteCalendarsModal.cancelButtonLabel": "取消",