Skip to content

Commit

Permalink
Update error handling in viz container (#247)
Browse files Browse the repository at this point in the history
* update error handling in viz container

Signed-off-by: Shenoy Pratik <[email protected]>

* fixed comments & minor changes

Signed-off-by: Shenoy Pratik <[email protected]>

---------

Signed-off-by: Shenoy Pratik <[email protected]>
  • Loading branch information
ps48 authored Feb 6, 2023
1 parent 37421ba commit cc9dafe
Show file tree
Hide file tree
Showing 8 changed files with 186 additions and 65 deletions.
5 changes: 5 additions & 0 deletions common/types/custom_panels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,8 @@ export interface pplResponse {
size: number;
status: number;
}

export interface VizContainerError {
errorMessage: string;
errorDetails?: string;
}
20 changes: 14 additions & 6 deletions public/components/custom_panels/custom_panel_view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,11 @@ import {
CREATE_PANEL_MESSAGE,
CUSTOM_PANELS_API_PREFIX,
} from '../../../common/constants/custom_panels';
import { SavedVisualizationType, VisualizationType } from '../../../common/types/custom_panels';
import {
SavedVisualizationType,
VisualizationType,
VizContainerError,
} from '../../../common/types/custom_panels';
import { PanelGrid } from './panel_modules/panel_grid';
import { getCustomModal } from './helpers/modal_containers';
import PPLService from '../../services/requests/ppl';
Expand All @@ -60,6 +64,7 @@ import {
} from '../common/search/autocomplete_logic';
import { AddVisualizationPopover } from './helpers/add_visualization_popover';
import { DeleteModal } from '../common/helpers/delete_modal';
import _ from 'lodash';

/*
* "CustomPanelsView" module used to render an Operational Panel
Expand Down Expand Up @@ -336,12 +341,15 @@ export const CustomPanelView = (props: CustomPanelViewProps) => {
const visData: SavedVisualizationType = await fetchVisualizationById(
http,
visualizationId,
(value: string) => setToast(value, 'danger')
(error: VizContainerError) => setToast(error.errorMessage, 'danger')
);
const moreIndices = parseForIndices(visData.query);
for (let j = 0; j < moreIndices.length; j++) {
if (!indices.includes(moreIndices[j])) {
indices.push(moreIndices[j]);

if (!_.isEmpty(visData)) {
const moreIndices = parseForIndices(visData.query);
for (let j = 0; j < moreIndices.length; j++) {
if (!indices.includes(moreIndices[j])) {
indices.push(moreIndices[j]);
}
}
}
}
Expand Down
40 changes: 24 additions & 16 deletions public/components/custom_panels/helpers/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ import { PPL_DATE_FORMAT, PPL_INDEX_REGEX } from '../../../../common/constants/s
import PPLService from '../../../services/requests/ppl';
import { CoreStart } from '../../../../../../src/core/public';
import { CUSTOM_PANELS_API_PREFIX } from '../../../../common/constants/custom_panels';
import { VisualizationType, SavedVisualizationType } from '../../../../common/types/custom_panels';
import {
VisualizationType,
SavedVisualizationType,
VizContainerError,
} from '../../../../common/types/custom_panels';
import { Visualization } from '../../visualizations/visualization';
import { getVizContainerProps } from '../../../components/visualizations/charts/helpers';
import { QueryManager } from '../../../../common/query_manager';
Expand Down Expand Up @@ -134,20 +138,21 @@ const pplServiceRequestor = async (
type: string,
setVisualizationData: React.Dispatch<React.SetStateAction<any[]>>,
setIsLoading: React.Dispatch<React.SetStateAction<boolean>>,
setIsError: React.Dispatch<React.SetStateAction<string>>
setIsError: React.Dispatch<React.SetStateAction<VizContainerError>>
) => {
await pplService
.fetch({ query: finalQuery, format: 'viz' })
.then((res) => {
if (res === undefined) setIsError('Please check the validity of PPL Filter');
if (res === undefined)
setIsError({ errorMessage: 'Please check the validity of PPL Filter' });
setVisualizationData(res);
})
.catch((error: Error) => {
const errorMessage = JSON.parse(error.body.message);
setIsError(
errorMessage.error.reason + '. ' + errorMessage.error.details ||
'Issue in fetching visualization'
);
setIsError({
errorMessage: errorMessage.error.reason || 'Issue in fetching visualization',
errorDetails: errorMessage.error.details,
});
console.error(error.body);
})
.finally(() => {
Expand All @@ -159,7 +164,7 @@ const pplServiceRequestor = async (
export const fetchVisualizationById = async (
http: CoreStart['http'],
savedVisualizationId: string,
setIsError: (value: string) => void
setIsError: (error: VizContainerError) => void
) => {
let savedVisualization = {} as SavedVisualizationType;
await http
Expand All @@ -168,7 +173,9 @@ export const fetchVisualizationById = async (
savedVisualization = res.visualization;
})
.catch((err) => {
setIsError(`Could not locate saved visualization id:${savedVisualizationId}`);
setIsError({
errorMessage: `Could not locate saved visualization id: ${savedVisualizationId}`,
});
console.error('Issue in fetching the saved Visualization by Id', err);
});
return savedVisualization;
Expand All @@ -183,19 +190,19 @@ export const getQueryResponse = (
endTime: string,
setVisualizationData: React.Dispatch<React.SetStateAction<any[]>>,
setIsLoading: React.Dispatch<React.SetStateAction<boolean>>,
setIsError: React.Dispatch<React.SetStateAction<string>>,
setIsError: React.Dispatch<React.SetStateAction<VizContainerError>>,
filterQuery = '',
timestampField = 'timestamp'
) => {
setIsLoading(true);
setIsError('');
setIsError({} as VizContainerError);

let finalQuery = '';
try {
finalQuery = queryAccumulator(query, timestampField, startTime, endTime, filterQuery);
} catch (error) {
const errorMessage = 'Issue in building final query';
setIsError(errorMessage);
setIsError({ errorMessage: errorMessage });
console.error(errorMessage, error);
setIsLoading(false);
return;
Expand All @@ -218,13 +225,14 @@ export const renderSavedVisualization = async (
setVisualizationData: React.Dispatch<React.SetStateAction<Plotly.Data[]>>,
setVisualizationMetaData: React.Dispatch<React.SetStateAction<undefined>>,
setIsLoading: React.Dispatch<React.SetStateAction<boolean>>,
setIsError: React.Dispatch<React.SetStateAction<string>>
setIsError: React.Dispatch<React.SetStateAction<VizContainerError>>
) => {
setIsLoading(true);
setIsError('');
setIsError({} as VizContainerError);

let visualization = {} as SavedVisualizationType;
let updatedVisualizationQuery = '';

visualization = await fetchVisualizationById(http, savedVisualizationId, setIsError);

if (_.isEmpty(visualization)) {
Expand Down Expand Up @@ -307,11 +315,11 @@ export const renderCatalogVisualization = async (
setVisualizationData: React.Dispatch<React.SetStateAction<Plotly.Data[]>>,
setVisualizationMetaData: React.Dispatch<React.SetStateAction<undefined>>,
setIsLoading: React.Dispatch<React.SetStateAction<boolean>>,
setIsError: React.Dispatch<React.SetStateAction<string>>,
setIsError: React.Dispatch<React.SetStateAction<VizContainerError>>,
spanResolution?: string
) => {
setIsLoading(true);
setIsError('');
setIsError({} as VizContainerError);

const visualizationType = 'line';
const visualizationTimeField = '@timestamp';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@
}
}

.viz-error-btn {
height: 26px;
line-height: 26px;
font-size: 0.8rem;
}

.visualization-div {
width: 100%;
height: 90%;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ import {
renderSavedVisualization,
} from '../../helpers/utils';
import './visualization_container.scss';
import { VizContainerError } from '../../../../../common/types/custom_panels';
import _ from 'lodash';

/*
* Visualization container - This module is a placeholder to add visualizations in react-grid-layout
Expand Down Expand Up @@ -99,42 +101,66 @@ export const VisualizationContainer = ({
const [visualizationMetaData, setVisualizationMetaData] = useState();
const [visualizationData, setVisualizationData] = useState<Plotly.Data[]>([]);
const [isLoading, setIsLoading] = useState(true);
const [isError, setIsError] = useState('');
const [isError, setIsError] = useState({} as VizContainerError);
const onActionsMenuClick = () => setIsPopoverOpen((currPopoverOpen) => !currPopoverOpen);
const closeActionsMenu = () => setIsPopoverOpen(false);

const [isModalVisible, setIsModalVisible] = useState(false);
const [modalContent, setModalContent] = useState(<></>);

const closeModal = () => setIsModalVisible(false);
const showModal = () => setIsModalVisible(true);
const showModal = (modalType: string) => {
if (modalType === 'catalogModal')
setModalContent(
<EuiModal onClose={closeModal}>
<EuiModalHeader>
<EuiModalHeaderTitle>
<h1>{visualizationMetaData.name}</h1>
</EuiModalHeaderTitle>
</EuiModalHeader>

let modal;
<EuiModalBody>
This PPL Query is generated in runtime from selected data source
<EuiSpacer />
<EuiCodeBlock language="html" isCopyable>
{visualizationMetaData.query}
</EuiCodeBlock>
</EuiModalBody>

if (isModalVisible) {
modal = (
<EuiModal onClose={closeModal}>
<EuiModalHeader>
<EuiModalHeaderTitle>
<h1>{visualizationMetaData.name}</h1>
</EuiModalHeaderTitle>
</EuiModalHeader>
<EuiModalFooter>
<EuiButton onClick={closeModal} fill>
Close
</EuiButton>
</EuiModalFooter>
</EuiModal>
);
else
setModalContent(
<EuiModal onClose={closeModal}>
<EuiModalHeader>
<EuiModalHeaderTitle>
<h1>{isError.errorMessage}</h1>
</EuiModalHeaderTitle>
</EuiModalHeader>

<EuiModalBody>
This PPL Query is generated in runtime from selected data source
<EuiSpacer />
<EuiCodeBlock language="html" isCopyable>
{visualizationMetaData.query}
</EuiCodeBlock>
</EuiModalBody>
<EuiModalBody>
Error Details
<EuiSpacer />
<EuiCodeBlock language="html" isCopyable>
{isError.errorDetails}
</EuiCodeBlock>
</EuiModalBody>

<EuiModalFooter>
<EuiButton onClick={closeModal} fill>
Close
</EuiButton>
</EuiModalFooter>
</EuiModal>
);
}
<EuiModalFooter>
<EuiButton onClick={closeModal} fill>
Close
</EuiButton>
</EuiModalFooter>
</EuiModal>
);

setIsModalVisible(true);
};

let popoverPanel = [
<EuiContextMenuItem
Expand Down Expand Up @@ -177,7 +203,7 @@ export const VisualizationContainer = ({
disabled={disablePopover}
onClick={() => {
closeActionsMenu();
showModal();
showModal('catalogModal');
}}
>
View query
Expand Down Expand Up @@ -228,13 +254,25 @@ export const VisualizationContainer = ({
<div className="visualization-div">
{isLoading ? (
<EuiLoadingChart size="xl" mono className="visualization-loading-chart" />
) : isError !== '' ? (
) : !_.isEmpty(isError) ? (
<div className="visualization-error-div">
<EuiIcon type="alert" color="danger" size="s" />
<EuiSpacer size="s" />
<EuiText size="s">
<p>{isError}</p>
<p>{isError.errorMessage}</p>
</EuiText>
{isError.hasOwnProperty('errorDetails') && isError.errorDetails !== '' ? (
<EuiButton
className="viz-error-btn"
color="danger"
onClick={() => showModal('errorModal')}
size="s"
>
See error details
</EuiButton>
) : (
<></>
)}
</div>
) : (
displayVisualization(visualizationMetaData, visualizationData, visualizationType)
Expand Down Expand Up @@ -301,7 +339,7 @@ export const VisualizationContainer = ({
</div>
{memoisedVisualizationBox}
</EuiPanel>
{modal}
{isModalVisible && modalContent}
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,9 @@
height: 3vh;
max-width: 500px;
}

.viz-error-btn {
height: 26px;
line-height: 26px;
font-size: 0.8rem;
}
Loading

0 comments on commit cc9dafe

Please sign in to comment.