Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/plugins/data/common/data_frames/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@ export interface IDataFrameResponse extends SearchResponse<any> {
took: number;
}

export interface IDataFrameResponseError {
status: number;
message: string;
}

export interface IDataFrameError extends IDataFrameResponse {
error: Error;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import './_recent_query.scss';

import { EuiButtonEmpty, EuiPopover, EuiText, EuiContextMenu, EuiPopoverTitle } from '@elastic/eui';

import React, { useState } from 'react';
import { SearchData } from '../../../../../discover/public';

export function QueryResult(props: { queryResult: SearchData }) {
console.log('QueryResult', props.queryResult);
const [isPopoverOpen, setPopover] = useState(false);
const onButtonClick = () => {
setPopover(!isPopoverOpen);
};

const status = props.queryResult.status;

if (status === 'ready') {
return (
<EuiButtonEmpty iconSide="left" iconType={'checkInCircleEmpty'} size="xs" onClick={() => {}}>
<EuiText size="xs" color="subdued">
{'Complete in ' + props.queryResult.queryTime + ' ms'}
</EuiText>
</EuiButtonEmpty>
);
}

return (
<EuiPopover
button={
<EuiButtonEmpty iconSide="left" iconType={'alert'} size="xs" onClick={onButtonClick}>
<EuiText size="xs" color="subdued">
{'Error'}
</EuiText>
</EuiButtonEmpty>
}
isOpen={isPopoverOpen}
closePopover={() => setPopover(false)}
panelPaddingSize="none"
anchorPosition={'downRight'}
>
<EuiPopoverTitle>Error message</EuiPopoverTitle>
<div style={{ width: '250px' }}>
<EuiText size="s">
{props.queryResult.errorMsg && props.queryResult.errorMsg.message}
</EuiText>
</div>
</EuiPopover>
);
}
4 changes: 4 additions & 0 deletions src/plugins/data/public/ui/query_editor/query_editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import { DatasetSelector } from '../dataset_selector';
import { QueryControls } from '../../query/query_string/language_service/get_query_control_links';
import { RecentQuery } from '../../query/query_string/language_service/recent_query';
import { DefaultInputProps } from './editors';
import { SearchData } from '../../../../discover/public';
import { QueryResult } from '../../query/query_string/language_service/query_result';

const LANGUAGE_ID_SQL = 'SQL';
monaco.languages.register({ id: LANGUAGE_ID_SQL });
Expand Down Expand Up @@ -59,6 +61,7 @@ export interface QueryEditorProps {
filterBar?: any;
prepend?: React.ComponentProps<typeof EuiCompressedFieldText>['prepend'];
savedQueryManagement?: any;
queryResult?: SearchData;
}

interface Props extends QueryEditorProps {
Expand Down Expand Up @@ -356,6 +359,7 @@ export default class QueryEditorUI extends Component<Props, State> {
<EuiText size="xs" color="subdued">
{this.props.query.dataset?.timeFieldName || ''}
</EuiText>,
<QueryResult queryResult={this.props.queryResult!} />,
],
end: [
<RecentQuery
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
OnRefreshProps,
prettyDuration,
} from '@elastic/eui';
import { BehaviorSubject } from 'rxjs';
import classNames from 'classnames';
import React, { useState } from 'react';
import { createPortal } from 'react-dom';
Expand All @@ -24,6 +25,7 @@ import { UI_SETTINGS } from '../../../common';
import { getQueryLog, PersistedLog } from '../../query';
import { NoDataPopover } from './no_data_popover';
import QueryEditorUI from './query_editor';
import { SearchData } from '../../../../discover/public';

const QueryEditor = withOpenSearchDashboards(QueryEditorUI);

Expand Down Expand Up @@ -54,6 +56,7 @@ export interface QueryEditorTopRowProps {
indicateNoData?: boolean;
datePickerRef?: React.RefObject<HTMLDivElement>;
savedQueryManagement?: any;
queryResult?: SearchData;
}

// Needed for React.lazy
Expand Down Expand Up @@ -186,6 +189,7 @@ export default function QueryEditorTopRow(props: QueryEditorTopRowProps) {
dataTestSubj={props.dataTestSubj}
filterBar={props.filterBar}
savedQueryManagement={props.savedQueryManagement}
queryResult={props.queryResult}
/>
</EuiFlexItem>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ export function createSearchBar({ core, storage, data }: StatefulSearchBarDeps)
datePickerRef={props.datePickerRef}
isFilterBarPortable={props.isFilterBarPortable}
{...overrideDefaultBehaviors(props)}
queryResult={props.queryResult}
/>
</OpenSearchDashboardsContextProvider>
);
Expand Down
4 changes: 4 additions & 0 deletions src/plugins/data/public/ui/search_bar/search_bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

import { InjectedIntl, injectI18n } from '@osd/i18n/react';
import classNames from 'classnames';
import { BehaviorSubject } from 'rxjs';
import { compact, get, isEqual } from 'lodash';
import React, { Component } from 'react';
import ResizeObserver from 'resize-observer-polyfill';
Expand All @@ -45,6 +46,7 @@ import { QueryEditorTopRow } from '../query_editor';
import QueryBarTopRow from '../query_string_input/query_bar_top_row';
import { SavedQueryMeta, SaveQueryForm } from '../saved_query_form';
import { FilterOptions } from '../filter_bar/filter_options';
import { SearchData } from '../../../../discover/public';

interface SearchBarInjectedDeps {
opensearchDashboards: OpenSearchDashboardsReactContextValue<IDataPluginServices>;
Expand Down Expand Up @@ -92,6 +94,7 @@ export interface SearchBarOwnProps {

onRefresh?: (payload: { dateRange: TimeRange }) => void;
indicateNoData?: boolean;
queryResult?: SearchData;
}

export type SearchBarProps = SearchBarOwnProps & SearchBarInjectedDeps;
Expand Down Expand Up @@ -550,6 +553,7 @@ class SearchBarUI extends Component<SearchBarProps, State> {
indicateNoData={this.props.indicateNoData}
datePickerRef={this.props.datePickerRef}
savedQueryManagement={searchBarMenu(false, true)}
queryResult={this.props.queryResult}
/>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@ export default function DiscoverCanvas({ setHeaderActionMenu, history, optionalR
{fetchState.status === ResultStatus.NO_RESULTS && (
<DiscoverNoResults timeFieldName={timeField} queryLanguage={''} />
)}
{fetchState.status === ResultStatus.ERROR && (
<DiscoverNoResults timeFieldName={timeField} queryLanguage={''} />
)}
{fetchState.status === ResultStatus.UNINITIALIZED && (
<DiscoverUninitialized onRefresh={() => refetch$.next()} />
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import { useDispatch, setSavedQuery, useSelector } from '../../utils/state_manag

import './discover_canvas.scss';
import { TopNavMenuItemRenderType } from '../../../../../navigation/public';
import { SearchData } from '../utils';
import { query } from '../../../../../console/server/lib/spec_definitions/js/query/dsl';

export interface TopNavProps {
opts: {
Expand All @@ -34,9 +36,10 @@ export interface TopNavProps {

export const TopNav = ({ opts, showSaveQuery, isEnhancementsEnabled }: TopNavProps) => {
const { services } = useOpenSearchDashboards<DiscoverViewServices>();
const { inspectorAdapters, savedSearch, indexPattern } = useDiscoverContext();
const { data$, inspectorAdapters, savedSearch, indexPattern } = useDiscoverContext();
const [indexPatterns, setIndexPatterns] = useState<IndexPattern[] | undefined>(undefined);
const [screenTitle, setScreenTitle] = useState<string>('');
const [queryResult, setQueryResult] = useState<SearchData | undefined>(undefined);
const state = useSelector((s) => s.discover);
const dispatch = useDispatch();

Expand Down Expand Up @@ -113,6 +116,15 @@ export const TopNav = ({ opts, showSaveQuery, isEnhancementsEnabled }: TopNavPro
);
}, [savedSearch?.title]);

useEffect(() => {
if (!data$) {
return;
}
const subscription = data$.subscribe((d) => {
setQueryResult(d);
});
}, [data$]);

const showDatePicker = useMemo(() => (indexPattern ? indexPattern.isTimeBased() : false), [
indexPattern,
]);
Expand Down Expand Up @@ -160,6 +172,7 @@ export const TopNav = ({ opts, showSaveQuery, isEnhancementsEnabled }: TopNavPro
datePickerRef={opts?.optionalRef?.datePickerRef}
groupActions={showActionsInGroup}
screenTitle={screenTitle}
queryResult={queryResult}
/>
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@

export * from './canvas';
export * from './panel';
export * from './utils';
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export { SearchData, ResultStatus } from './use_search';
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export enum ResultStatus {
LOADING = 'loading', // initial data load
READY = 'ready', // results came back
NO_RESULTS = 'none', // no results came back
ERROR = 'error', // error occurred
}

export interface SearchData {
Expand All @@ -50,6 +51,8 @@ export interface SearchData {
bucketInterval?: TimechartHeaderBucketInterval | {};
chartData?: Chart;
title?: string;
errorMsg?: any;
queryTime?: number;
}

export type SearchRefetch = 'refetch' | undefined;
Expand Down Expand Up @@ -149,6 +152,8 @@ export const useSearch = (services: DiscoverViewServices) => {

dataset = searchSource.getField('index');

let queryTime;

try {
// Only show loading indicator if we are fetching when the rows are empty
if (fetchStateRef.current.rows?.length === 0) {
Expand Down Expand Up @@ -180,6 +185,9 @@ export const useSearch = (services: DiscoverViewServices) => {
.ok({ json: fetchResp });
const hits = fetchResp.hits.total as number;
const rows = fetchResp.hits.hits;
//setQueryTime(inspectorRequest.getTime());
//console.log('queryTime', queryTime);
queryTime = inspectorRequest.getTime();
let bucketInterval = {};
let chartData;
for (const row of rows) {
Expand Down Expand Up @@ -216,17 +224,25 @@ export const useSearch = (services: DiscoverViewServices) => {
indexPattern?.title !== searchSource.getDataFrame()?.name
? searchSource.getDataFrame()?.name
: indexPattern?.title,
queryTime,
});
} catch (error) {
// If the request was aborted then no need to surface this error in the UI
if (error instanceof Error && error.name === 'AbortError') return;

data$.next({
status: ResultStatus.NO_RESULTS,
rows: [],
status: ResultStatus.ERROR,
errorMsg: error.body || error,
title:
indexPattern?.title !== searchSource.getDataFrame()?.name
? searchSource.getDataFrame()?.name
: indexPattern?.title,
queryTime,
});

data.search.showError(error as Error);
console.log('error', error.body);

//data.search.showError((error.body || error) as Error);
} finally {
initalSearchComplete.current = true;
}
Expand Down
1 change: 1 addition & 0 deletions src/plugins/discover/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,4 @@ export { SavedSearch, SavedSearchLoader, createSavedSearchesLoader } from './sav

export { ISearchEmbeddable, SEARCH_EMBEDDABLE_TYPE, SearchInput } from './embeddable';
export { DISCOVER_APP_URL_GENERATOR, DiscoverUrlGeneratorState } from './url_generator';
export { SearchData, ResultStatus } from './application/view_components';
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,8 @@ export class RequestResponder {
public error(response: Response): void {
this.finish(RequestStatus.ERROR, response);
}

public getTime() {
return this.request.time;
}
}
5 changes: 5 additions & 0 deletions src/plugins/navigation/public/top_nav_menu/top_nav_menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import { EuiFlexGroup, EuiFlexItem, EuiHeaderLinks, EuiText } from '@elastic/eui';
import classNames from 'classnames';
import React, { ReactElement, useRef } from 'react';
import { BehaviorSubject } from 'rxjs';

import { MountPoint } from '../../../../core/public';
import {
Expand All @@ -42,6 +43,7 @@ import { DataSourceMenuProps, createDataSourceMenu } from '../../../data_source_
import { MountPointPortal } from '../../../opensearch_dashboards_react/public';
import { TopNavMenuData } from './top_nav_menu_data';
import { TopNavMenuItem } from './top_nav_menu_item';
import { SearchData } from '../../../discover/public';

export enum TopNavMenuItemRenderType {
IN_PORTAL = 'in_portal',
Expand Down Expand Up @@ -82,6 +84,7 @@ export type TopNavMenuProps = Omit<StatefulSearchBarProps, 'showDatePicker'> &
* ```
*/
setMenuMountPoint?: (menuMount: MountPoint | undefined) => void;
queryResult?: SearchData;
};

/*
Expand All @@ -102,6 +105,7 @@ export function TopNavMenu(props: TopNavMenuProps): ReactElement | null {
dataSourceMenuConfig,
groupActions,
screenTitle,
queryResult,
...searchBarProps
} = props;

Expand Down Expand Up @@ -156,6 +160,7 @@ export function TopNavMenu(props: TopNavMenuProps): ReactElement | null {
<SearchBar
{...searchBarProps}
showDatePicker={![TopNavMenuItemRenderType.OMITTED, false].includes(showDatePicker!)}
queryResult={queryResult}
{...overrides}
/>
);
Expand Down
12 changes: 2 additions & 10 deletions src/plugins/query_enhancements/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,14 +125,6 @@ export class DataFramePolling<T, P = void> {
}
}

export const handleDataFrameError = (response: any) => {
const df = response.body;
if (df.error) {
const jsError = new Error(df.error.response);
return throwError(jsError);
}
};

export const fetch = (context: EnhancedFetchContext, query: Query, aggConfig?: QueryAggConfig) => {
const { http, path, signal } = context;
const body = JSON.stringify({ query: { ...query, format: 'jdbc' }, aggConfig });
Expand All @@ -143,7 +135,7 @@ export const fetch = (context: EnhancedFetchContext, query: Query, aggConfig?: Q
body,
signal,
})
).pipe(tap(handleDataFrameError));
);
};

export const fetchDataFrame = (context: EnhancedFetchContext, query: Query, df: IDataFrame) => {
Expand All @@ -156,7 +148,7 @@ export const fetchDataFrame = (context: EnhancedFetchContext, query: Query, df:
body,
signal,
})
).pipe(tap(handleDataFrameError));
);
};

export const fetchDataFramePolling = (context: EnhancedFetchContext, df: IDataFrame) => {
Expand Down
Loading