Skip to content

Commit dae03a3

Browse files
add MDS support on neo feature branch (#725)
* update snapshots Signed-off-by: Jackie Han <jkhanjob@gmail.com> * add snpshot Signed-off-by: Jackie Han <jkhanjob@gmail.com> * add data source client Signed-off-by: Jackie Han <jkhanjob@gmail.com> * test * neo List Detectors page Signed-off-by: Jackie Han <jkhanjob@gmail.com> * add opensearch_dashboards.json file Signed-off-by: Jackie Han <jkhanjob@gmail.com> * neo List Detectors page Signed-off-by: Jackie Han <jkhanjob@gmail.com> * test Signed-off-by: Jackie Han <jkhanjob@gmail.com> * Support MDS on DetectorDetails page Signed-off-by: Jackie Han <jkhanjob@gmail.com> * change 4/7 Signed-off-by: Jackie Han <jkhanjob@gmail.com> * version change Signed-off-by: Jackie Han <jkhanjob@gmail.com> * list detector list change Signed-off-by: Jackie Han <jkhanjob@gmail.com> * Support MDS on List, Detail, Dashboard, Overview pages Signed-off-by: Jackie Han <jkhanjob@gmail.com> * change version back to 3.0 Signed-off-by: Jackie Han <jkhanjob@gmail.com> * revert version change Signed-off-by: Jackie Han <jkhanjob@gmail.com> * make dataSourceId optional in DetectorListItem type Signed-off-by: Jackie Han <jkhanjob@gmail.com> * update imports Signed-off-by: Jackie Han <jkhanjob@gmail.com> * remove used function Signed-off-by: Jackie Han <jkhanjob@gmail.com> * cleanup Signed-off-by: Jackie Han <jkhanjob@gmail.com> * add getter and setter for dataSource plugin Signed-off-by: Jackie Han <jkhanjob@gmail.com> --------- Signed-off-by: Jackie Han <jkhanjob@gmail.com>
1 parent e5cf2d8 commit dae03a3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1120
-469
lines changed

opensearch_dashboards.json

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"configPath": [
66
"anomaly_detection_dashboards"
77
],
8+
"optionalPlugins": ["dataSource","dataSourceManagement"],
89
"requiredPlugins": [
910
"opensearchDashboardsUtils",
1011
"expressions",

public/anomaly_detection_app.tsx

+9-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@ import { Provider } from 'react-redux';
1818
import configureStore from './redux/configureStore';
1919
import { CoreServicesContext } from './components/CoreServices/CoreServices';
2020

21-
export function renderApp(coreStart: CoreStart, params: AppMountParameters) {
21+
export function renderApp(
22+
coreStart: CoreStart,
23+
params: AppMountParameters,
24+
) {
2225
const http = coreStart.http;
2326
const store = configureStore(http);
2427

@@ -29,13 +32,17 @@ export function renderApp(coreStart: CoreStart, params: AppMountParameters) {
2932
} else {
3033
require('@elastic/charts/dist/theme_only_light.css');
3134
}
35+
3236
ReactDOM.render(
3337
<Provider store={store}>
3438
<Router>
3539
<Route
3640
render={(props) => (
3741
<CoreServicesContext.Provider value={coreStart}>
38-
<Main {...props} />
42+
<Main
43+
setHeaderActionMenu={params.setHeaderActionMenu}
44+
{...props}
45+
/>
3946
</CoreServicesContext.Provider>
4047
)}
4148
/>

public/models/interfaces.ts

+2
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ export type Detector = {
205205
taskState?: DETECTOR_STATE;
206206
taskProgress?: number;
207207
taskError?: string;
208+
dataSourceId? : string;
208209
};
209210

210211
export type DetectorListItem = {
@@ -218,6 +219,7 @@ export type DetectorListItem = {
218219
lastUpdateTime: number;
219220
enabledTime?: number;
220221
detectorType?: string;
222+
dataSourceId?: string;
221223
};
222224

223225
export type EntityData = {

public/pages/AnomalyCharts/containers/AnomaliesChart.tsx

+3
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ export interface AnomaliesChartProps {
8585
selectedCategoryFields?: any[];
8686
handleCategoryFieldsChange(selectedOptions: any[]): void;
8787
openOutOfRangeCallOut?: boolean;
88+
dataSourceId?: string;
8889
}
8990

9091
export const AnomaliesChart = React.memo((props: AnomaliesChartProps) => {
@@ -345,6 +346,7 @@ export const AnomaliesChart = React.memo((props: AnomaliesChartProps) => {
345346
isHCDetector={props.isHCDetector}
346347
isHistorical={props.isHistorical}
347348
selectedHeatmapCell={props.selectedHeatmapCell}
349+
dataSourceId={props.dataSourceId}
348350
/>,
349351
<EuiSpacer size="m" />,
350352
<FeatureBreakDown
@@ -399,6 +401,7 @@ export const AnomaliesChart = React.memo((props: AnomaliesChartProps) => {
399401
isHistorical={props.isHistorical}
400402
onDatePickerRangeChange={handleDatePickerRangeChange}
401403
openOutOfRangeCallOut={showOutOfRangeCallOut}
404+
dataSourceId={props.dataSourceId}
402405
/>
403406
)}
404407
</EuiFlexGroup>

public/pages/AnomalyCharts/containers/AnomalyDetailsChart.tsx

+4-3
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ interface AnomalyDetailsChartProps {
113113
selectedHeatmapCell?: HeatmapCell;
114114
onDatePickerRangeChange?(startDate: number, endDate: number): void;
115115
openOutOfRangeCallOut?: boolean;
116+
dataSourceId?: string;
116117
}
117118

118119
export const AnomalyDetailsChart = React.memo(
@@ -174,7 +175,7 @@ export const AnomalyDetailsChart = React.memo(
174175
zoomRange.endDate,
175176
taskId
176177
);
177-
dispatch(searchResults(anomalyDataRangeQuery, resultIndex, true))
178+
dispatch(searchResults(anomalyDataRangeQuery, resultIndex, props.dataSourceId, true))
178179
.then((response: any) => {
179180
// Only retrieve buckets that are in the anomaly results range. This is so
180181
// we don't show aggregate results for where there is no data at all
@@ -193,7 +194,7 @@ export const AnomalyDetailsChart = React.memo(
193194
taskId,
194195
selectedAggId
195196
);
196-
dispatch(searchResults(historicalAggQuery, resultIndex, true))
197+
dispatch(searchResults(historicalAggQuery, resultIndex, props.dataSourceId, true))
197198
.then((response: any) => {
198199
const aggregatedAnomalies = parseHistoricalAggregatedAnomalies(
199200
response,
@@ -229,7 +230,7 @@ export const AnomalyDetailsChart = React.memo(
229230
zoomRange.endDate,
230231
taskId
231232
);
232-
dispatch(searchResults(anomalyDataRangeQuery, resultIndex, true))
233+
dispatch(searchResults(anomalyDataRangeQuery, resultIndex, props.dataSourceId, true))
233234
.then((response: any) => {
234235
const dataStartDate = get(
235236
response,

public/pages/AnomalyCharts/containers/AnomalyOccurrenceChart.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ interface AnomalyOccurrenceChartProps {
4444
isHCDetector?: boolean;
4545
isHistorical?: boolean;
4646
selectedHeatmapCell?: HeatmapCell;
47+
dataSourceId?: string;
4748
}
4849

4950
export const AnomalyOccurrenceChart = React.memo(
@@ -82,6 +83,7 @@ export const AnomalyOccurrenceChart = React.memo(
8283
isHCDetector={props.isHCDetector}
8384
isHistorical={props.isHistorical}
8485
selectedHeatmapCell={props.selectedHeatmapCell}
86+
dataSourceId={props.dataSourceId}
8587
/>
8688
{props.isHCDetector && props.selectedHeatmapCell === undefined ? (
8789
<EuiBadge className={'anomaly-detail-chart-center'} color={'default'}>

public/pages/CreateDetectorSteps/hooks/useFetchDetectorInfo.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ import { getMappings } from '../../../redux/reducers/opensearch';
2121
// 1. Get detector
2222
// 2. Gets index mapping
2323
export const useFetchDetectorInfo = (
24-
detectorId: string
24+
detectorId: string,
25+
dataSourceId: string
2526
): {
2627
detector: Detector;
2728
hasError: boolean;
@@ -43,7 +44,8 @@ export const useFetchDetectorInfo = (
4344
useEffect(() => {
4445
const fetchDetector = async () => {
4546
if (!detector) {
46-
await dispatch(getDetector(detectorId));
47+
// hardcoding the datasource id for now, will update it later when working on create page
48+
await dispatch(getDetector(detectorId, dataSourceId));
4749
}
4850
if (selectedIndices) {
4951
await dispatch(getMappings(selectedIndices));

public/pages/Dashboard/Components/AnomaliesDistribution.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import { ALL_CUSTOM_AD_RESULT_INDICES } from '../../utils/constants';
3535
import { searchResults } from '../../../redux/reducers/anomalyResults';
3636
export interface AnomaliesDistributionChartProps {
3737
selectedDetectors: DetectorListItem[];
38+
dataSourceId?: string;
3839
}
3940

4041
export const AnomaliesDistributionChart = (
@@ -66,6 +67,7 @@ export const AnomaliesDistributionChart = (
6667
await getAnomalyDistributionForDetectorsByTimeRange(
6768
searchResults,
6869
props.selectedDetectors,
70+
props.dataSourceId,
6971
timeRange,
7072
dispatch,
7173
0,

public/pages/Dashboard/Components/AnomaliesLiveChart.tsx

+5-2
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ import { searchResults } from '../../../redux/reducers/anomalyResults';
5757

5858
export interface AnomaliesLiveChartProps {
5959
selectedDetectors: DetectorListItem[];
60+
dataSourceId?: string;
6061
}
6162

6263
interface LiveTimeRangeState {
@@ -102,7 +103,8 @@ export const AnomaliesLiveChart = (props: AnomaliesLiveChartProps) => {
102103
1,
103104
true,
104105
ALL_CUSTOM_AD_RESULT_INDICES,
105-
false
106+
false,
107+
props.dataSourceId
106108
);
107109
} catch (err) {
108110
console.log(
@@ -126,7 +128,8 @@ export const AnomaliesLiveChart = (props: AnomaliesLiveChartProps) => {
126128
MAX_LIVE_DETECTORS,
127129
false,
128130
ALL_CUSTOM_AD_RESULT_INDICES,
129-
false
131+
false,
132+
props.dataSourceId
130133
);
131134
setLiveAnomalyData(latestLiveAnomalyResult);
132135

public/pages/Dashboard/Container/DashboardOverview.tsx

+81-14
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@
99
* GitHub history for details.
1010
*/
1111

12-
import React, { Fragment, useState, useEffect } from 'react';
12+
import React, { Fragment, useState, useEffect, useMemo } from 'react';
1313
import { AnomaliesLiveChart } from '../Components/AnomaliesLiveChart';
1414
import { AnomaliesDistributionChart } from '../Components/AnomaliesDistribution';
15+
import queryString from 'querystring';
1516

1617
import { useDispatch, useSelector } from 'react-redux';
1718
import { get, isEmpty, cloneDeep } from 'lodash';
@@ -29,27 +30,38 @@ import {
2930
} from '@elastic/eui';
3031
import { AnomalousDetectorsList } from '../Components/AnomalousDetectorsList';
3132
import {
32-
GET_ALL_DETECTORS_QUERY_PARAMS,
3333
ALL_DETECTORS_MESSAGE,
3434
ALL_DETECTOR_STATES_MESSAGE,
3535
ALL_INDICES_MESSAGE,
3636
} from '../utils/constants';
3737
import { AppState } from '../../../redux/reducers';
38-
import { CatIndex, IndexAlias } from '../../../../server/models/types';
39-
import { getVisibleOptions } from '../../utils/helpers';
38+
import { CatIndex, IndexAlias, MDSQueryParams } from '../../../../server/models/types';
39+
import { getAllDetectorsQueryParamsWithDataSourceId, getVisibleOptions } from '../../utils/helpers';
4040
import { BREADCRUMBS } from '../../../utils/constants';
4141
import { DETECTOR_STATE } from '../../../../server/utils/constants';
42-
import { getDetectorStateOptions } from '../../DetectorsList/utils/helpers';
42+
import { getDetectorStateOptions, getURLQueryParams } from '../../DetectorsList/utils/helpers';
4343
import { DashboardHeader } from '../Components/utils/DashboardHeader';
4444
import { EmptyDashboard } from '../Components/EmptyDashboard/EmptyDashboard';
4545
import {
4646
prettifyErrorMessage,
4747
NO_PERMISSIONS_KEY_WORD,
4848
} from '../../../../server/utils/helpers';
4949
import { CoreServicesContext } from '../../../components/CoreServices/CoreServices';
50-
import { CoreStart } from '../../../../../../src/core/public';
50+
import { CoreStart, MountPoint } from '../../../../../../src/core/public';
51+
import { DataSourceSelectableConfig } from '../../../../../../src/plugins/data_source_management/public';
52+
import { getDataSourceManagementPlugin, getDataSourcePlugin, getNotifications, getSavedObjectsClient } from '../../../services';
53+
import { RouteComponentProps } from 'react-router-dom';
5154

52-
export function DashboardOverview() {
55+
interface OverviewProps extends RouteComponentProps {
56+
setActionMenu: (menuMount: MountPoint | undefined) => void;
57+
}
58+
59+
interface MDSOverviewState {
60+
queryParams: MDSQueryParams;
61+
selectedDataSourceId: string;
62+
}
63+
64+
export function DashboardOverview(props: OverviewProps) {
5365
const core = React.useContext(CoreServicesContext) as CoreStart;
5466
const dispatch = useDispatch();
5567
const adState = useSelector((state: AppState) => state.ad);
@@ -58,13 +70,21 @@ export function DashboardOverview() {
5870
const errorGettingDetectors = adState.errorMessage;
5971
const isLoadingDetectors = adState.requesting;
6072

73+
const dataSourceEnabled = getDataSourcePlugin().dataSourceEnabled;
74+
6175
const [currentDetectors, setCurrentDetectors] = useState(
6276
Object.values(allDetectorList)
6377
);
6478
const [allDetectorsSelected, setAllDetectorsSelected] = useState(true);
6579
const [selectedDetectorsName, setSelectedDetectorsName] = useState(
6680
[] as string[]
6781
);
82+
const queryParams = getURLQueryParams(props.location);
83+
const [MDSOverviewState, setMDSOverviewState] = useState<MDSOverviewState>({
84+
queryParams,
85+
selectedDataSourceId: queryParams.dataSourceId ? queryParams.dataSourceId : '',
86+
});
87+
6888
const getDetectorOptions = (detectorsIdMap: {
6989
[key: string]: DetectorListItem;
7090
}) => {
@@ -108,6 +128,20 @@ export function DashboardOverview() {
108128
setAllDetectorStatesSelected(isEmpty(selectedStates));
109129
};
110130

131+
const handleDataSourceChange = ([event]) => {
132+
const dataSourceId = event?.id;
133+
if (!dataSourceId) {
134+
getNotifications().toasts.addDanger(
135+
prettifyErrorMessage('Unable to set data source.')
136+
);
137+
} else {
138+
setMDSOverviewState({
139+
queryParams: dataSourceId,
140+
selectedDataSourceId: dataSourceId,
141+
});
142+
}
143+
}
144+
111145
const opensearchState = useSelector((state: AppState) => state.opensearch);
112146

113147
const [selectedIndices, setSelectedIndices] = useState([] as string[]);
@@ -157,14 +191,24 @@ export function DashboardOverview() {
157191
};
158192

159193
const intializeDetectors = async () => {
160-
dispatch(getDetectorList(GET_ALL_DETECTORS_QUERY_PARAMS));
161-
dispatch(getIndices(''));
162-
dispatch(getAliases(''));
194+
dispatch(getDetectorList(getAllDetectorsQueryParamsWithDataSourceId(MDSOverviewState.selectedDataSourceId)));
195+
dispatch(getIndices('', MDSOverviewState.selectedDataSourceId));
196+
dispatch(getAliases('', MDSOverviewState.selectedDataSourceId));
163197
};
164198

165199
useEffect(() => {
166-
intializeDetectors();
167-
}, []);
200+
const { history, location } = props;
201+
const updatedParams = {
202+
dataSourceId: MDSOverviewState.selectedDataSourceId,
203+
};
204+
history.replace({
205+
...location,
206+
search: queryString.stringify(updatedParams),
207+
})
208+
if (dataSourceEnabled ? MDSOverviewState.selectedDataSourceId : true) {
209+
intializeDetectors();
210+
}
211+
}, [MDSOverviewState]);
168212

169213
useEffect(() => {
170214
if (errorGettingDetectors) {
@@ -193,13 +237,33 @@ export function DashboardOverview() {
193237
filterSelectedDetectors(
194238
selectedDetectorsName,
195239
selectedDetectorStates,
196-
selectedIndices
240+
selectedIndices,
197241
);
198242
}, [selectedDetectorsName, selectedIndices, selectedDetectorStates]);
199243

244+
const DataSourceMenu =
245+
getDataSourceManagementPlugin().ui.getDataSourceMenu<DataSourceSelectableConfig>();
246+
const renderDataSourceComponent = useMemo(() => {
247+
return (
248+
<DataSourceMenu
249+
setMenuMountPoint={props.setActionMenu}
250+
componentType={'DataSourceSelectable'}
251+
componentConfig={{
252+
fullWidth: false,
253+
activeOption:[{ id: MDSOverviewState.selectedDataSourceId }],
254+
savedObjects: getSavedObjectsClient(),
255+
notifications: getNotifications(),
256+
onSelectedDataSources: (dataSources) =>
257+
handleDataSourceChange(dataSources),
258+
}}
259+
/>
260+
);
261+
}, [getSavedObjectsClient(), getNotifications(), props.setActionMenu]);
262+
200263
return (
201264
<div style={{ height: '1200px' }}>
202265
<Fragment>
266+
{dataSourceEnabled && renderDataSourceComponent}
203267
<DashboardHeader hasDetectors={totalRealtimeDetectors > 0} />
204268
{isLoadingDetectors ? (
205269
<div>
@@ -248,12 +312,15 @@ export function DashboardOverview() {
248312
</EuiFlexItem>
249313
</EuiFlexGroup>
250314
<EuiSpacer />
251-
<AnomaliesLiveChart selectedDetectors={currentDetectors} />
315+
<AnomaliesLiveChart
316+
selectedDetectors={currentDetectors}
317+
dataSourceId={MDSOverviewState.selectedDataSourceId} />
252318
<EuiSpacer />
253319
<EuiFlexGroup justifyContent="spaceBetween">
254320
<EuiFlexItem grow={6}>
255321
<AnomaliesDistributionChart
256322
selectedDetectors={currentDetectors}
323+
dataSourceId={MDSOverviewState.selectedDataSourceId}
257324
/>
258325
</EuiFlexItem>
259326
<EuiFlexItem grow={3}>

0 commit comments

Comments
 (0)