Skip to content

Commit

Permalink
[2.x] Backport query assist (#1369)
Browse files Browse the repository at this point in the history
Signed-off-by: Joshua Li <[email protected]>
Co-authored-by: Paul Sebastian <[email protected]>
  • Loading branch information
joshuali925 and paulstn authored Jan 23, 2024
1 parent d9bd287 commit d4d8dbc
Show file tree
Hide file tree
Showing 54 changed files with 4,001 additions and 1,745 deletions.
2 changes: 2 additions & 0 deletions common/constants/data_sources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

export const DATA_SOURCE_NAME_URL_PARAM_KEY = 'datasourceName';
export const DATA_SOURCE_TYPE_URL_PARAM_KEY = 'datasourceType';
export const OLLY_QUESTION_URL_PARAM_KEY = 'olly_q';
export const INDEX_URL_PARAM_KEY = 'indexPattern';
export const DEFAULT_DATA_SOURCE_TYPE = 'DEFAULT_INDEX_PATTERNS';
export const DEFAULT_DATA_SOURCE_NAME = 'Default cluster';
export const DEFAULT_DATA_SOURCE_OBSERVABILITY_DISPLAY_NAME = 'OpenSearch';
Expand Down
1 change: 1 addition & 0 deletions common/constants/explorer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const RAW_QUERY = 'rawQuery';
export const FINAL_QUERY = 'finalQuery';
export const SELECTED_DATE_RANGE = 'selectedDateRange';
export const INDEX = 'index';
export const OLLY_QUERY_ASSISTANT = 'ollyQueryAssistant';
export const SELECTED_PATTERN_FIELD = 'selectedPatternField';
export const PATTERN_REGEX = 'patternRegex';
export const FILTERED_PATTERN = 'filteredPattern';
Expand Down
12 changes: 12 additions & 0 deletions common/constants/query_assist.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

const QUERY_ASSIST_API_PREFIX = '/api/observability/query_assist';
export const QUERY_ASSIST_API = {
GENERATE_PPL: `${QUERY_ASSIST_API_PREFIX}/generate_ppl`,
SUMMARIZE: `${QUERY_ASSIST_API_PREFIX}/summarize`,
};

export const ML_COMMONS_API_PREFIX = '/_plugins/_ml';
4 changes: 4 additions & 0 deletions common/constants/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,3 +256,7 @@ export const S3_DATASOURCE_TYPE = 'S3_DATASOURCE';
export const ASYNC_QUERY_SESSION_ID = 'async-query-session-id';

export const DIRECT_DUMMY_QUERY = 'select 1';

export const DEFAULT_START_TIME = 'now-15m';
export const QUERY_ASSIST_START_TIME = 'now-40y';
export const QUERY_ASSIST_END_TIME = 'now';
8 changes: 3 additions & 5 deletions opensearch_dashboards.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
"urlForwarding",
"visualizations"
],
"optionalPlugins": [
"managementOverview",
"assistantDashboards"
]
}
"optionalPlugins": ["managementOverview", "assistantDashboards"],
"configPath": ["observability"]
}
Binary file removed public/.DS_Store
Binary file not shown.
12 changes: 6 additions & 6 deletions public/components/common/live_tail/live_tail_button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
* SPDX-License-Identifier: Apache-2.0
*/

//Define pop over interval options for live tail button in your plugin
// Define pop over interval options for live tail button in your plugin

import { EuiButton } from "@elastic/eui";
import React, { useMemo } from "react";
import { LiveTailProps } from "common/types/explorer";
import { EuiButton } from '@elastic/eui';
import React, { useMemo } from 'react';
import { LiveTailProps } from 'common/types/explorer';

//Live Tail Button
// Live Tail Button
export const LiveTailButton = ({
isLiveTailOn,
isLiveTailPopoverOpen,
Expand All @@ -20,7 +20,7 @@ export const LiveTailButton = ({
const liveButton = useMemo(() => {
return (
<EuiButton
iconType={isLiveTailOn ? "stop" : "play"}
iconType={isLiveTailOn ? 'stop' : 'clock'}
iconSide="left"
onClick={() => setIsLiveTailPopoverOpen(!isLiveTailPopoverOpen)}
data-test-subj={dataTestSubj}
Expand Down
1,826 changes: 1,016 additions & 810 deletions public/components/common/search/__tests__/__snapshots__/search.test.tsx.snap

Large diffs are not rendered by default.

10 changes: 6 additions & 4 deletions public/components/common/search/__tests__/search.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,24 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { configure, mount, shallow } from 'enzyme';
import { configure, mount } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import React from 'react';
import { createStore } from '@reduxjs/toolkit';
import { applyMiddleware, createStore } from '@reduxjs/toolkit';
import { rootReducer } from '../../../../framework/redux/reducers';
import { Provider } from 'react-redux';
import { Search } from '../search';
import thunk from 'redux-thunk';
import { initialTabId } from '../../../../framework/redux/store/shared_state';

describe('Explorer Search component', () => {
configure({ adapter: new Adapter() });
const store = createStore(rootReducer);
const store = createStore(rootReducer, applyMiddleware(thunk));

it('renders basic component', () => {
const wrapper = mount(
<Provider store={store}>
<Search />
<Search tabId={initialTabId} />
</Provider>
);
wrapper.update();
Expand Down
49 changes: 37 additions & 12 deletions public/components/common/search/date_picker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,50 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { EuiSuperDatePicker, EuiToolTip } from '@elastic/eui';
import React from 'react';
import { EuiSuperDatePicker } from '@elastic/eui';
import { IDatePickerProps } from './search';
import { uiSettingsService } from '../../../../common/utils';
import { coreRefs } from '../../../framework/core_refs';
import { IDatePickerProps } from './search';
import {
QUERY_ASSIST_END_TIME,
QUERY_ASSIST_START_TIME,
} from '../../../../common/constants/shared';

export function DatePicker(props: IDatePickerProps) {
const { startTime, endTime, handleTimePickerChange, handleTimeRangePickerRefresh } = props;
const {
startTime,
endTime,
handleTimePickerChange,
handleTimeRangePickerRefresh,
isAppAnalytics,
} = props;

const handleTimeChange = (e: any) => handleTimePickerChange([e.start, e.end]);
const allowTimeChanging = !coreRefs.queryAssistEnabled || isAppAnalytics;

return (
<EuiSuperDatePicker
data-test-subj="pplSearchDatePicker"
start={startTime}
end={endTime}
dateFormat={uiSettingsService.get('dateFormat')}
onTimeChange={handleTimeChange}
onRefresh={handleTimeRangePickerRefresh}
className="osdQueryBar__datePicker"
/>
<>
<EuiToolTip
position="bottom"
content={
allowTimeChanging
? false
: 'Date range has been disabled to accomodate timerange of all datasets'
}
>
<EuiSuperDatePicker
data-test-subj="pplSearchDatePicker"
start={allowTimeChanging ? startTime : QUERY_ASSIST_START_TIME}
end={allowTimeChanging ? endTime : QUERY_ASSIST_END_TIME}
dateFormat={uiSettingsService.get('dateFormat')}
onTimeChange={handleTimeChange}
onRefresh={handleTimeRangePickerRefresh}
className="osdQueryBar__datePicker"
showUpdateButton={false}
isDisabled={!allowTimeChanging}
/>
</EuiToolTip>
</>
);
}
83 changes: 83 additions & 0 deletions public/components/common/search/query_area.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { EuiCodeEditor, EuiFlexGroup, EuiFlexItem, EuiPanel } from '@elastic/eui';
import React, { useEffect, useMemo } from 'react';
import { coreRefs } from '../../../framework/core_refs';
import { QueryAssistInput } from '../../event_analytics/explorer/query_assist/input';
import { useFetchEvents } from '../../event_analytics/hooks/use_fetch_events';

export function QueryArea({
tabId,
handleQueryChange,
handleTimePickerChange,
handleTimeRangePickerRefresh,
runQuery,
tempQuery,
setNeedsUpdate,
setFillRun,
selectedIndex,
nlqInput,
setNlqInput,
pplService,
}: any) {
const requestParams = { tabId };
const { getAvailableFields } = useFetchEvents({
pplService,
requestParams,
});

// use effect that sets the editor text and populates sidebar field for a particular index upon initialization
const memoizedGetAvailableFields = useMemo(() => getAvailableFields, []);
const memoizedHandleQueryChange = useMemo(() => handleQueryChange, []);
useEffect(() => {
const indexQuery = `source = ${selectedIndex[0].label}`;
memoizedHandleQueryChange(indexQuery);
memoizedGetAvailableFields(indexQuery);
}, [selectedIndex, memoizedGetAvailableFields, memoizedHandleQueryChange]);

return (
<EuiPanel paddingSize="m">
<EuiFlexGroup gutterSize="m" direction="column">
<EuiFlexItem>
<EuiCodeEditor
theme="textmate"
width="100%"
height="4rem"
showPrintMargin={false}
setOptions={{
fontSize: '14px',
}}
aria-label="Code Editor"
onChange={(query) => {
handleQueryChange(query);
// query is considered updated when the last run query is not the same as whats in the editor
// setUpdatedQuery(runQuery !== query);
setNeedsUpdate(runQuery !== query);
}}
onFocus={() => setFillRun(true)}
onBlur={() => setFillRun(false)}
value={tempQuery}
wrapEnabled={true}
/>
</EuiFlexItem>
{coreRefs.queryAssistEnabled && (
<EuiFlexItem>
<QueryAssistInput
tabId={tabId}
handleTimePickerChange={handleTimePickerChange}
handleQueryChange={handleQueryChange}
handleTimeRangePickerRefresh={handleTimeRangePickerRefresh}
setNeedsUpdate={setNeedsUpdate}
selectedIndex={selectedIndex}
nlqInput={nlqInput}
setNlqInput={setNlqInput}
/>
</EuiFlexItem>
)}
</EuiFlexGroup>
</EuiPanel>
);
}
111 changes: 111 additions & 0 deletions public/components/common/search/query_assist_summarization.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import {
EuiAccordion,
EuiBadge,
EuiCallOut,
EuiFlexGroup,
EuiFlexItem,
EuiIcon,
EuiLink,
EuiMarkdownFormat,
EuiPanel,
EuiSpacer,
EuiText,
} from '@elastic/eui';
import React from 'react';
import chatLogo from '../../datasources/icons/query-assistant-logo.svg';

export function QueryAssistSummarization({
queryAssistantSummarization,
setNlqInput,
showFlyout,
}: any) {
return (
<EuiPanel>
<EuiAccordion
id="summarization-accordion"
buttonContent="AI Insights"
initialIsOpen
isLoading={queryAssistantSummarization?.summaryLoading ?? false}
isLoadingMessage="Loading summary.."
extraAction={
<EuiFlexGroup direction="row" alignItems="center" gutterSize="s">
<EuiFlexItem grow={false}>
<EuiText color="subdued">
<small>Generated by Opensearch Assistant</small>
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiIcon type={chatLogo} size="l" />
</EuiFlexItem>
</EuiFlexGroup>
}
>
{queryAssistantSummarization?.summary?.length > 0 && (
<>
<EuiSpacer size="m" />
{queryAssistantSummarization?.isPPLError ? (
<>
<EuiCallOut title="There was an error" color="danger" iconType="alert">
<EuiMarkdownFormat>{queryAssistantSummarization.summary}</EuiMarkdownFormat>
</EuiCallOut>
<EuiSpacer size="s" />
<EuiFlexGroup wrap gutterSize="s">
<EuiFlexItem grow={false}>
<EuiText size="s">Suggestions:</EuiText>
</EuiFlexItem>
{queryAssistantSummarization.suggestedQuestions.map((question) => (
<EuiFlexItem grow={false}>
<EuiBadge
color="hollow"
iconType="chatRight"
iconSide="left"
onClick={() => setNlqInput(question)}
onClickAriaLabel="Set input to the suggested question"
>
{question}
</EuiBadge>
</EuiFlexItem>
))}
<EuiFlexItem grow={false}>
<EuiBadge
color="hollow"
iconType="questionInCircle"
iconSide="left"
onClick={showFlyout}
onClickAriaLabel="Show PPL documentation"
>
PPL Documentation
</EuiBadge>
</EuiFlexItem>
</EuiFlexGroup>
</>
) : (
<EuiPanel color="subdued" style={{ marginLeft: 16, marginRight: 16 }}>
<EuiMarkdownFormat>{queryAssistantSummarization.summary}</EuiMarkdownFormat>
</EuiPanel>
)}
<EuiSpacer size="m" />
<EuiText color="subdued">
<small>
The OpenSearch Assistant may produce inaccurate information. Verify all information
before using it in any environment or workload. Share feedback via{' '}
<EuiLink href="https://forum.opensearch.org/t/feedback-opensearch-assistant/16741">
Forum
</EuiLink>{' '}
or{' '}
<EuiLink href="https://opensearch.slack.com/channels/assistant-feedback">
Slack
</EuiLink>
</small>
</EuiText>
</>
)}
</EuiAccordion>
</EuiPanel>
);
}
Loading

0 comments on commit d4d8dbc

Please sign in to comment.