From c2b8f4ecebb9c9ef65a68bafc4cf709060c0c2ef Mon Sep 17 00:00:00 2001 From: Ryland Herrick Date: Thu, 29 Oct 2020 16:52:59 -0500 Subject: [PATCH] [Search] Support non-shard error information in ES responses (#81967) (#82073) * Display top-level error reason if no shard info is available For EQL queries, error responses do not contain `failed_shards` information, and so our error toasts contained only a stack trace. With this addition, we'll fall back to the top-level `error.reason` if those fields are not present, giving the user better indication of what's going on without having to inspect the actual network response. * Prevent service from changing the shape of our errors This ensures a consistent interface for our kibana client errors, whether the error is raised directly from a `fetch` or emitted from a search strategy's observable; namely: that both contain this top-level `body` key. * Make our body property public This is the same visibility as the original error: if it were protected it wouldn't be very useful to consumers. * Adds a unit test for the interface adherence --- .../public/search/errors/es_error.test.tsx | 40 +++++++++++++++++++ .../data/public/search/errors/es_error.tsx | 11 +++-- .../data/public/search/errors/utils.ts | 4 ++ 3 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 src/plugins/data/public/search/errors/es_error.test.tsx diff --git a/src/plugins/data/public/search/errors/es_error.test.tsx b/src/plugins/data/public/search/errors/es_error.test.tsx new file mode 100644 index 0000000000000..db719eb6a70c9 --- /dev/null +++ b/src/plugins/data/public/search/errors/es_error.test.tsx @@ -0,0 +1,40 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { EsError } from './es_error'; +import { IEsError } from './types'; + +describe('EsError', () => { + it('contains the same body as the wrapped error', () => { + const error = { + body: { + attributes: { + error: { + type: 'top_level_exception_type', + reason: 'top-level reason', + }, + }, + }, + } as IEsError; + const esError = new EsError(error); + + expect(typeof esError.body).toEqual('object'); + expect(esError.body).toEqual(error.body); + }); +}); diff --git a/src/plugins/data/public/search/errors/es_error.tsx b/src/plugins/data/public/search/errors/es_error.tsx index 53d00159b836b..f1e7eaa707a06 100644 --- a/src/plugins/data/public/search/errors/es_error.tsx +++ b/src/plugins/data/public/search/errors/es_error.tsx @@ -22,22 +22,27 @@ import { EuiCodeBlock, EuiSpacer } from '@elastic/eui'; import { ApplicationStart } from 'kibana/public'; import { KbnError } from '../../../../kibana_utils/common'; import { IEsError } from './types'; -import { getRootCause } from './utils'; +import { getRootCause, getTopLevelCause } from './utils'; export class EsError extends KbnError { + readonly body: IEsError['body']; + constructor(protected readonly err: IEsError) { super('EsError'); + this.body = err.body; } public getErrorMessage(application: ApplicationStart) { const rootCause = getRootCause(this.err)?.reason; + const topLevelCause = getTopLevelCause(this.err)?.reason; + const cause = rootCause ?? topLevelCause; return ( <> - {rootCause ? ( + {cause ? ( - {rootCause} + {cause} ) : null} diff --git a/src/plugins/data/public/search/errors/utils.ts b/src/plugins/data/public/search/errors/utils.ts index d07d9b05e91e9..45a318904665f 100644 --- a/src/plugins/data/public/search/errors/utils.ts +++ b/src/plugins/data/public/search/errors/utils.ts @@ -26,6 +26,10 @@ export function getFailedShards(err: IEsError) { return failedShards ? failedShards[0] : undefined; } +export function getTopLevelCause(err: IEsError) { + return err.body?.attributes?.error; +} + export function getRootCause(err: IEsError) { return getFailedShards(err)?.reason; }