[Lens] Leverage original http request error (#79831)
This commit is contained in:
parent
16e1598c05
commit
cd84ace53d
|
@ -14,5 +14,6 @@ export interface ExpressionRenderError extends Error
|
|||
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [original](./kibana-plugin-plugins-expressions-public.expressionrendererror.original.md) | <code>Error</code> | |
|
||||
| [type](./kibana-plugin-plugins-expressions-public.expressionrendererror.type.md) | <code>string</code> | |
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRenderError](./kibana-plugin-plugins-expressions-public.expressionrendererror.md) > [original](./kibana-plugin-plugins-expressions-public.expressionrendererror.original.md)
|
||||
|
||||
## ExpressionRenderError.original property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
original?: Error;
|
||||
```
|
|
@ -20,5 +20,5 @@ export interface ReactExpressionRendererProps extends IExpressionLoaderParams
|
|||
| [onEvent](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.onevent.md) | <code>(event: ExpressionRendererEvent) => void</code> | |
|
||||
| [padding](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.padding.md) | <code>'xs' | 's' | 'm' | 'l' | 'xl'</code> | |
|
||||
| [reload$](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.reload_.md) | <code>Observable<unknown></code> | An observable which can be used to re-run the expression without destroying the component |
|
||||
| [renderError](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.rendererror.md) | <code>(error?: string | null) => React.ReactElement | React.ReactElement[]</code> | |
|
||||
| [renderError](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.rendererror.md) | <code>(message?: string | null, error?: ExpressionRenderError | null) => React.ReactElement | React.ReactElement[]</code> | |
|
||||
|
||||
|
|
|
@ -7,5 +7,5 @@
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
renderError?: (error?: string | null) => React.ReactElement | React.ReactElement[];
|
||||
renderError?: (message?: string | null, error?: ExpressionRenderError | null) => React.ReactElement | React.ReactElement[];
|
||||
```
|
||||
|
|
|
@ -40,6 +40,11 @@ export const createError = (err: string | ErrorLike): ExpressionValueError => ({
|
|||
: undefined,
|
||||
message: typeof err === 'string' ? err : String(err.message),
|
||||
name: typeof err === 'object' ? err.name || 'Error' : 'Error',
|
||||
original: err instanceof Error ? (err as SerializedError) : undefined,
|
||||
original:
|
||||
err instanceof Error
|
||||
? err
|
||||
: typeof err === 'object' && 'original' in err && err.original instanceof Error
|
||||
? err.original
|
||||
: undefined,
|
||||
},
|
||||
});
|
||||
|
|
|
@ -511,6 +511,8 @@ export class ExpressionRendererRegistry implements IRegistry<ExpressionRenderer>
|
|||
//
|
||||
// @public (undocumented)
|
||||
export interface ExpressionRenderError extends Error {
|
||||
// (undocumented)
|
||||
original?: Error;
|
||||
// (undocumented)
|
||||
type?: string;
|
||||
}
|
||||
|
@ -1095,7 +1097,7 @@ export interface ReactExpressionRendererProps extends IExpressionLoaderParams {
|
|||
padding?: 'xs' | 's' | 'm' | 'l' | 'xl';
|
||||
reload$?: Observable<unknown>;
|
||||
// (undocumented)
|
||||
renderError?: (error?: string | null) => React.ReactElement | React.ReactElement[];
|
||||
renderError?: (message?: string | null, error?: ExpressionRenderError | null) => React.ReactElement | React.ReactElement[];
|
||||
}
|
||||
|
||||
// Warning: (ae-missing-release-tag) "ReactExpressionRendererType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
|
|
|
@ -35,7 +35,10 @@ export interface ReactExpressionRendererProps extends IExpressionLoaderParams {
|
|||
className?: string;
|
||||
dataAttrs?: string[];
|
||||
expression: string | ExpressionAstExpression;
|
||||
renderError?: (error?: string | null) => React.ReactElement | React.ReactElement[];
|
||||
renderError?: (
|
||||
message?: string | null,
|
||||
error?: ExpressionRenderError | null
|
||||
) => React.ReactElement | React.ReactElement[];
|
||||
padding?: 'xs' | 's' | 'm' | 'l' | 'xl';
|
||||
onEvent?: (event: ExpressionRendererEvent) => void;
|
||||
/**
|
||||
|
@ -186,7 +189,10 @@ export const ReactExpressionRenderer = ({
|
|||
<div {...dataAttrs} className={classes}>
|
||||
{state.isEmpty && <EuiLoadingChart mono size="l" />}
|
||||
{state.isLoading && <EuiProgress size="xs" color="accent" position="absolute" />}
|
||||
{!state.isLoading && state.error && renderError && renderError(state.error.message)}
|
||||
{!state.isLoading &&
|
||||
state.error &&
|
||||
renderError &&
|
||||
renderError(state.error.message, state.error)}
|
||||
<div
|
||||
className="expExpressionRenderer__expression"
|
||||
style={expressionStyles}
|
||||
|
|
|
@ -55,6 +55,7 @@ export interface IExpressionLoaderParams {
|
|||
|
||||
export interface ExpressionRenderError extends Error {
|
||||
type?: string;
|
||||
original?: Error;
|
||||
}
|
||||
|
||||
export type RenderErrorHandlerFnType = (
|
||||
|
|
|
@ -14,6 +14,7 @@ import { CoreStart, CoreSetup } from 'kibana/public';
|
|||
import { ExecutionContextSearch } from 'src/plugins/expressions';
|
||||
import {
|
||||
ExpressionRendererEvent,
|
||||
ExpressionRenderError,
|
||||
ReactExpressionRendererType,
|
||||
} from '../../../../../../../src/plugins/expressions/public';
|
||||
import { Action } from '../state_management';
|
||||
|
@ -40,6 +41,7 @@ import {
|
|||
} from '../../../../../../../src/plugins/data/public';
|
||||
import { WorkspacePanelWrapper } from './workspace_panel_wrapper';
|
||||
import { DropIllustration } from '../../../assets/drop_illustration';
|
||||
import { getOriginalRequestErrorMessage } from '../../error_helper';
|
||||
|
||||
export interface WorkspacePanelProps {
|
||||
activeVisualizationId: string | null;
|
||||
|
@ -342,7 +344,8 @@ export const InnerVisualizationWrapper = ({
|
|||
searchContext={context}
|
||||
reload$={autoRefreshFetch$}
|
||||
onEvent={onEvent}
|
||||
renderError={(errorMessage?: string | null) => {
|
||||
renderError={(errorMessage?: string | null, error?: ExpressionRenderError | null) => {
|
||||
const visibleErrorMessage = getOriginalRequestErrorMessage(error) || errorMessage;
|
||||
return (
|
||||
<EuiFlexGroup style={{ maxWidth: '100%' }} direction="column" alignItems="center">
|
||||
<EuiFlexItem>
|
||||
|
@ -354,7 +357,7 @@ export const InnerVisualizationWrapper = ({
|
|||
defaultMessage="An error occurred when loading data."
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
{errorMessage ? (
|
||||
{visibleErrorMessage ? (
|
||||
<EuiFlexItem className="eui-textBreakAll" grow={false}>
|
||||
<EuiButtonEmpty
|
||||
onClick={() => {
|
||||
|
@ -369,7 +372,7 @@ export const InnerVisualizationWrapper = ({
|
|||
})}
|
||||
</EuiButtonEmpty>
|
||||
|
||||
{localState.expandError ? errorMessage : null}
|
||||
{localState.expandError ? visibleErrorMessage : null}
|
||||
</EuiFlexItem>
|
||||
) : null}
|
||||
</EuiFlexGroup>
|
||||
|
|
|
@ -13,6 +13,7 @@ import {
|
|||
ReactExpressionRendererType,
|
||||
} from 'src/plugins/expressions/public';
|
||||
import { ExecutionContextSearch } from 'src/plugins/expressions';
|
||||
import { getOriginalRequestErrorMessage } from '../error_helper';
|
||||
|
||||
export interface ExpressionWrapperProps {
|
||||
ExpressionRenderer: ReactExpressionRendererType;
|
||||
|
@ -50,7 +51,20 @@ export function ExpressionWrapper({
|
|||
padding="m"
|
||||
expression={expression}
|
||||
searchContext={searchContext}
|
||||
renderError={(error) => <div data-test-subj="expression-renderer-error">{error}</div>}
|
||||
renderError={(errorMessage, error) => (
|
||||
<div data-test-subj="expression-renderer-error">
|
||||
<EuiFlexGroup direction="column" alignItems="center" justifyContent="center">
|
||||
<EuiFlexItem>
|
||||
<EuiIcon type="alert" color="danger" />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiText size="s">
|
||||
{getOriginalRequestErrorMessage(error) || errorMessage}
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</div>
|
||||
)}
|
||||
onEvent={handleEvent}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* 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 { i18n } from '@kbn/i18n';
|
||||
|
||||
import { ExpressionRenderError } from 'src/plugins/expressions/public';
|
||||
|
||||
interface ElasticsearchErrorClause {
|
||||
type: string;
|
||||
reason: string;
|
||||
caused_by?: ElasticsearchErrorClause;
|
||||
}
|
||||
|
||||
interface RequestError extends Error {
|
||||
body?: { attributes?: { error: ElasticsearchErrorClause } };
|
||||
}
|
||||
|
||||
const isRequestError = (e: Error | RequestError): e is RequestError => {
|
||||
if ('body' in e) {
|
||||
return e.body?.attributes?.error?.caused_by !== undefined;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
function getNestedErrorClause({
|
||||
type,
|
||||
reason,
|
||||
caused_by: causedBy,
|
||||
}: ElasticsearchErrorClause): { type: string; reason: string } {
|
||||
if (causedBy) {
|
||||
return getNestedErrorClause(causedBy);
|
||||
}
|
||||
return { type, reason };
|
||||
}
|
||||
|
||||
export function getOriginalRequestErrorMessage(error?: ExpressionRenderError | null) {
|
||||
if (error && 'original' in error && error.original && isRequestError(error.original)) {
|
||||
const rootError = getNestedErrorClause(error.original.body!.attributes!.error);
|
||||
if (rootError.reason && rootError.type) {
|
||||
return i18n.translate('xpack.lens.editorFrame.expressionFailureMessage', {
|
||||
defaultMessage: 'Request error: {type}, {reason}',
|
||||
values: {
|
||||
reason: rootError.reason,
|
||||
type: rootError.type,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue