Skip to content

Commit 10c730b

Browse files
committed
Support MDS on DetectorDetails page
Signed-off-by: Jackie Han <jkhanjob@gmail.com>
1 parent 8a94a9b commit 10c730b

File tree

17 files changed

+258
-134
lines changed

17 files changed

+258
-134
lines changed

public/models/interfaces.ts

+1
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 = {

public/pages/CreateDetectorSteps/hooks/useFetchDetectorInfo.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ export const useFetchDetectorInfo = (
4343
useEffect(() => {
4444
const fetchDetector = async () => {
4545
if (!detector) {
46-
await dispatch(getDetector(detectorId));
46+
// hardcoding the datasource id for now, will update it later when working on create page
47+
await dispatch(getDetector(detectorId, '4585f560-d1ef-11ee-aa63-2181676cc573'));
4748
}
4849
if (selectedIndices) {
4950
await dispatch(getMappings(selectedIndices));

public/pages/DetectorConfig/containers/DetectorConfig.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { getDetector } from '../../../redux/reducers/ad';
2121
import { EuiLoadingSpinner } from '@elastic/eui';
2222
interface DetectorConfigProps extends RouteComponentProps {
2323
detectorId: string;
24+
dataSourceId: string;
2425
onEditFeatures(): void;
2526
onEditDetector(): void;
2627
}
@@ -32,7 +33,7 @@ export function DetectorConfig(props: DetectorConfigProps) {
3233
);
3334

3435
useEffect(() => {
35-
dispatch(getDetector(props.detectorId));
36+
dispatch(getDetector(props.detectorId, props.dataSourceId));
3637
}, []);
3738

3839
return (

public/pages/DetectorDetail/containers/DetectorDetail.tsx

+39-13
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ import {
2424
EuiLoadingSpinner,
2525
EuiButton,
2626
} from '@elastic/eui';
27-
import { CoreStart } from '../../../../../../src/core/public';
27+
import { CoreStart, MountPoint } from '../../../../../../src/core/public';
2828
import { CoreServicesContext } from '../../../components/CoreServices/CoreServices';
2929
import { get, isEmpty } from 'lodash';
30-
import { RouteComponentProps, Switch, Route, Redirect } from 'react-router-dom';
30+
import { RouteComponentProps, Switch, Route, Redirect, useLocation } from 'react-router-dom';
3131
import { useDispatch, useSelector } from 'react-redux';
3232
import { useFetchDetectorInfo } from '../../CreateDetectorSteps/hooks/useFetchDetectorInfo';
3333
import { useHideSideNavBar } from '../../main/hooks/useHideSideNavBar';
@@ -58,12 +58,16 @@ import {
5858
import { DETECTOR_STATE } from '../../../../server/utils/constants';
5959
import { CatIndex } from '../../../../server/models/types';
6060
import { containsIndex } from '../utils/helpers';
61+
import { DataSourceManagementPluginSetup, DataSourceViewConfig } from '../../../../../../src/plugins/data_source_management/public';
6162

6263
export interface DetectorRouterProps {
6364
detectorId?: string;
6465
}
65-
interface DetectorDetailProps
66-
extends RouteComponentProps<DetectorRouterProps> {}
66+
interface DetectorDetailProps extends RouteComponentProps<DetectorRouterProps> {
67+
dataSourceEnabled: boolean;
68+
dataSourceManagement: DataSourceManagementPluginSetup;
69+
setActionMenu: (menuMount: MountPoint | undefined) => void;
70+
}
6771

6872
const tabs = [
6973
{
@@ -103,6 +107,11 @@ export const DetectorDetail = (props: DetectorDetailProps) => {
103107
const core = React.useContext(CoreServicesContext) as CoreStart;
104108
const dispatch = useDispatch();
105109
const detectorId = get(props, 'match.params.detectorId', '') as string;
110+
111+
const location = useLocation();
112+
const queryParams = new URLSearchParams(location.search);
113+
const dataSourceId = queryParams.get('dataSourceId') as string;
114+
106115
const { detector, hasError, isLoadingDetector, errorMessage } =
107116
useFetchDetectorInfo(detectorId);
108117
const { monitor, fetchMonitorError, isLoadingMonitor } =
@@ -156,7 +165,7 @@ export const DetectorDetail = (props: DetectorDetailProps) => {
156165
// detector starts, result index recreated or user switches tabs to re-fetch detector)
157166
useEffect(() => {
158167
const getInitialIndices = async () => {
159-
await dispatch(getIndices('')).catch((error: any) => {
168+
await dispatch(getIndices('', dataSourceId)).catch((error: any) => {
160169
console.error(error);
161170
core.notifications.toasts.addDanger('Error getting all indices');
162171
});
@@ -201,23 +210,23 @@ export const DetectorDetail = (props: DetectorDetailProps) => {
201210
...detectorDetailModel,
202211
selectedTab: DETECTOR_DETAIL_TABS.CONFIGURATIONS,
203212
});
204-
props.history.push(`/detectors/${detectorId}/configurations`);
213+
props.history.push(`/detectors/${detectorId}/configurations?dataSourceId=${dataSourceId}`);
205214
}, []);
206215

207216
const handleSwitchToHistoricalTab = useCallback(() => {
208217
setDetectorDetailModel({
209218
...detectorDetailModel,
210219
selectedTab: DETECTOR_DETAIL_TABS.HISTORICAL,
211220
});
212-
props.history.push(`/detectors/${detectorId}/historical`);
221+
props.history.push(`/detectors/${detectorId}/historical?dataSourceId=${dataSourceId}`);
213222
}, []);
214223

215224
const handleTabChange = (route: DETECTOR_DETAIL_TABS) => {
216225
setDetectorDetailModel({
217226
...detectorDetailModel,
218227
selectedTab: route,
219228
});
220-
props.history.push(`/detectors/${detectorId}/${route}`);
229+
props.history.push(`/detectors/${detectorId}/${route}?dataSourceId=${dataSourceId}`);
221230
};
222231

223232
const hideMonitorCalloutModal = () => {
@@ -261,8 +270,8 @@ export const DetectorDetail = (props: DetectorDetailProps) => {
261270
// Await for the start detector call to succeed before displaying toast.
262271
// Don't wait for get detector call; the page will be updated
263272
// via hooks automatically when the new detector info is returned.
264-
await dispatch(startDetector(detectorId));
265-
dispatch(getDetector(detectorId));
273+
await dispatch(startDetector(detectorId, dataSourceId));
274+
dispatch(getDetector(detectorId, dataSourceId));
266275
core.notifications.toasts.addSuccess(
267276
`Successfully started the detector job`
268277
);
@@ -278,10 +287,10 @@ export const DetectorDetail = (props: DetectorDetailProps) => {
278287
const handleStopAdJob = async (detectorId: string, listener?: Listener) => {
279288
try {
280289
if (isRTJobRunning) {
281-
await dispatch(stopDetector(detectorId));
290+
await dispatch(stopDetector(detectorId, dataSourceId));
282291
}
283292
if (isHistoricalJobRunning) {
284-
await dispatch(stopHistoricalDetector(detectorId));
293+
await dispatch(stopHistoricalDetector(detectorId, dataSourceId));
285294
}
286295
core.notifications.toasts.addSuccess(
287296
`Successfully stopped the ${runningJobsAsString}`
@@ -302,7 +311,7 @@ export const DetectorDetail = (props: DetectorDetailProps) => {
302311

303312
const handleDelete = useCallback(async (detectorId: string) => {
304313
try {
305-
await dispatch(deleteDetector(detectorId));
314+
await dispatch(deleteDetector(detectorId, dataSourceId));
306315
core.notifications.toasts.addSuccess(`Successfully deleted the detector`);
307316
hideDeleteDetectorModal();
308317
props.history.push('/detectors');
@@ -350,6 +359,8 @@ export const DetectorDetail = (props: DetectorDetailProps) => {
350359
></EuiCallOut>
351360
) : null;
352361

362+
const DataSourceMenu = props.dataSourceManagement.ui.getDataSourceMenu<DataSourceViewConfig>();
363+
353364
return (
354365
<React.Fragment>
355366
{!isEmpty(detector) && !hasError ? (
@@ -361,6 +372,18 @@ export const DetectorDetail = (props: DetectorDetailProps) => {
361372
: { ...lightStyles, flexGrow: 'unset' }),
362373
}}
363374
>
375+
376+
{props.dataSourceEnabled && (
377+
<DataSourceMenu
378+
setMenuMountPoint={props.setActionMenu}
379+
componentType={'DataSourceView'}
380+
componentConfig={{
381+
// give a placeholder label for now, will update it once neo team allows empty label field
382+
activeOption: [{label: 'labelPlaceHolder', id: dataSourceId}],
383+
fullWidth: true
384+
}}
385+
/>
386+
)}
364387
<EuiFlexGroup
365388
justifyContent="spaceBetween"
366389
style={{ padding: '10px' }}
@@ -542,6 +565,7 @@ export const DetectorDetail = (props: DetectorDetailProps) => {
542565
<AnomalyResults
543566
{...resultsProps}
544567
detectorId={detectorId}
568+
dataSourceId={dataSourceId}
545569
onStartDetector={() => handleStartAdJob(detectorId)}
546570
onStopDetector={() => handleStopAdJob(detectorId)}
547571
onSwitchToConfiguration={handleSwitchToConfigurationTab}
@@ -556,6 +580,7 @@ export const DetectorDetail = (props: DetectorDetailProps) => {
556580
<HistoricalDetectorResults
557581
{...configProps}
558582
detectorId={detectorId}
583+
dataSourceId={dataSourceId}
559584
/>
560585
)}
561586
/>
@@ -566,6 +591,7 @@ export const DetectorDetail = (props: DetectorDetailProps) => {
566591
<DetectorConfig
567592
{...configProps}
568593
detectorId={detectorId}
594+
dataSourceId={dataSourceId}
569595
onEditFeatures={handleEditFeature}
570596
onEditDetector={handleEditDetector}
571597
/>

public/pages/DetectorResults/containers/AnomalyHistory.tsx

+13-8
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ import { prettifyErrorMessage } from '../../../../server/utils/helpers';
9898

9999
interface AnomalyHistoryProps {
100100
detector: Detector;
101+
dataSourceId: string;
101102
monitor: Monitor | undefined;
102103
isFeatureDataMissing?: boolean;
103104
isHistorical?: boolean;
@@ -126,6 +127,7 @@ export const AnomalyHistory = (props: AnomalyHistoryProps) => {
126127
props.isHistorical && props.detector?.detectionDateRange
127128
? props.detector.detectionDateRange.endTime
128129
: moment().valueOf();
130+
const dataSourceId = props.dataSourceId;
129131
const [dateRange, setDateRange] = useState<DateRange>({
130132
startDate: initialStartDate,
131133
endDate: initialEndDate,
@@ -223,7 +225,7 @@ export const AnomalyHistory = (props: AnomalyHistoryProps) => {
223225
taskId.current,
224226
modelId
225227
);
226-
return dispatch(searchResults(params, resultIndex, true));
228+
return dispatch(searchResults(params, resultIndex, dataSourceId, true));
227229
})
228230
: [];
229231

@@ -252,7 +254,7 @@ export const AnomalyHistory = (props: AnomalyHistoryProps) => {
252254
modelId
253255
);
254256
const anomalySummaryResponse = await dispatch(
255-
searchResults(anomalySummaryQuery, resultIndex, true)
257+
searchResults(anomalySummaryQuery, resultIndex, dataSourceId, true)
256258
);
257259
allPureAnomalies.push(parsePureAnomalies(anomalySummaryResponse));
258260
}
@@ -275,7 +277,7 @@ export const AnomalyHistory = (props: AnomalyHistoryProps) => {
275277
taskId.current,
276278
modelId
277279
);
278-
return dispatch(searchResults(params, resultIndex, true));
280+
return dispatch(searchResults(params, resultIndex, dataSourceId, true));
279281
}
280282
);
281283

@@ -308,7 +310,7 @@ export const AnomalyHistory = (props: AnomalyHistoryProps) => {
308310
modelId
309311
);
310312
const bucketizedAnomalyResultResponse = await dispatch(
311-
searchResults(bucketizedAnomalyResultsQuery, resultIndex, true)
313+
searchResults(bucketizedAnomalyResultsQuery, resultIndex, dataSourceId, true)
312314
);
313315
allBucketizedAnomalyResults.push(
314316
parseBucketizedAnomalyResults(bucketizedAnomalyResultResponse)
@@ -408,7 +410,7 @@ export const AnomalyHistory = (props: AnomalyHistoryProps) => {
408410
);
409411
const detectorResultResponse = props.isHistorical
410412
? await dispatch(
411-
getDetectorResults(taskId.current, params, true, resultIndex, true)
413+
getDetectorResults(taskId.current, dataSourceId, params, true, resultIndex, true)
412414
).catch((error: any) => {
413415
setIsLoading(false);
414416
setIsLoadingAnomalyResults(false);
@@ -417,6 +419,7 @@ export const AnomalyHistory = (props: AnomalyHistoryProps) => {
417419
: await dispatch(
418420
getDetectorResults(
419421
props.detector.id,
422+
dataSourceId,
420423
params,
421424
false,
422425
resultIndex,
@@ -536,6 +539,7 @@ export const AnomalyHistory = (props: AnomalyHistoryProps) => {
536539
const result = await dispatch(
537540
getTopAnomalyResults(
538541
detectorId,
542+
dataSourceId,
539543
get(props, 'isHistorical', false),
540544
query
541545
)
@@ -553,7 +557,7 @@ export const AnomalyHistory = (props: AnomalyHistoryProps) => {
553557
props.isHistorical,
554558
taskId.current
555559
);
556-
const result = await dispatch(searchResults(query, resultIndex, true));
560+
const result = await dispatch(searchResults(query, resultIndex, dataSourceId, true));
557561
topEntityAnomalySummaries = parseTopEntityAnomalySummaryResults(
558562
result,
559563
isMultiCategory
@@ -572,7 +576,7 @@ export const AnomalyHistory = (props: AnomalyHistoryProps) => {
572576
props.isHistorical,
573577
taskId.current
574578
);
575-
return dispatch(searchResults(entityResultQuery, resultIndex, true));
579+
return dispatch(searchResults(entityResultQuery, resultIndex, dataSourceId, true));
576580
}
577581
);
578582

@@ -644,6 +648,7 @@ export const AnomalyHistory = (props: AnomalyHistoryProps) => {
644648
return dispatch(
645649
getDetectorResults(
646650
props.isHistorical ? taskId.current : props.detector?.id,
651+
dataSourceId,
647652
params,
648653
props.isHistorical ? true : false,
649654
resultIndex,
@@ -722,7 +727,7 @@ export const AnomalyHistory = (props: AnomalyHistoryProps) => {
722727
heatmapCell.entityList
723728
);
724729

725-
const result = await dispatch(searchResults(query, resultIndex, true));
730+
const result = await dispatch(searchResults(query, resultIndex, dataSourceId, true));
726731

727732
// Gets top child entities as an Entity[][],
728733
// where each entry in the array is a unique combination of entity values

public/pages/DetectorResults/containers/AnomalyResults.tsx

+11-5
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ import { DEFAULT_SHINGLE_SIZE } from '../../../utils/constants';
7070

7171
interface AnomalyResultsProps extends RouteComponentProps {
7272
detectorId: string;
73+
dataSourceId: string;
7374
onStartDetector(): void;
7475
onStopDetector(): void;
7576
onSwitchToConfiguration(): void;
@@ -80,7 +81,8 @@ export function AnomalyResults(props: AnomalyResultsProps) {
8081
const core = React.useContext(CoreServicesContext) as CoreStart;
8182
const dispatch = useDispatch();
8283
const detectorId = props.detectorId;
83-
const detector = useSelector(
84+
const dataSourceId = props.dataSourceId;
85+
const detector = useSelector(
8486
(state: AppState) => state.ad.detectors[detectorId]
8587
);
8688

@@ -90,11 +92,11 @@ export function AnomalyResults(props: AnomalyResultsProps) {
9092
BREADCRUMBS.DETECTORS,
9193
{ text: detector ? detector.name : '' },
9294
]);
93-
dispatch(getDetector(detectorId));
95+
dispatch(getDetector(detectorId, dataSourceId));
9496
}, []);
9597

9698
const fetchDetector = async () => {
97-
dispatch(getDetector(detectorId));
99+
dispatch(getDetector(detectorId, dataSourceId));
98100
};
99101

100102
useEffect(() => {
@@ -247,7 +249,7 @@ export function AnomalyResults(props: AnomalyResultsProps) {
247249
try {
248250
const resultIndex = get(detector, 'resultIndex', '');
249251
const detectorResultResponse = await dispatch(
250-
getDetectorResults(detectorId, params, false, resultIndex, true)
252+
getDetectorResults(detectorId, dataSourceId, params, false, resultIndex, true)
251253
);
252254
const featuresData = get(
253255
detectorResultResponse,
@@ -550,10 +552,14 @@ export function AnomalyResults(props: AnomalyResultsProps) {
550552
</EuiFlexItem>
551553
</EuiFlexGroup>
552554
) : null}
553-
<AnomalyResultsLiveChart detector={detector} />
555+
<AnomalyResultsLiveChart
556+
detector={detector}
557+
dataSourceId={dataSourceId}
558+
/>
554559
<EuiSpacer size="l" />
555560
<AnomalyHistory
556561
detector={detector}
562+
dataSourceId={dataSourceId}
557563
monitor={monitor}
558564
isFeatureDataMissing={isDetectorMissingData}
559565
isNotSample={true}

public/pages/DetectorResults/containers/AnomalyResultsLiveChart.tsx

+3
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ import { getDetectorLiveResults } from '../../../redux/reducers/liveAnomalyResul
6060

6161
interface AnomalyResultsLiveChartProps {
6262
detector: Detector;
63+
dataSourceId: string;
6364
}
6465

6566
export const AnomalyResultsLiveChart = (
@@ -80,6 +81,7 @@ export const AnomalyResultsLiveChart = (
8081
'detectionInterval.period.interval',
8182
1
8283
);
84+
const dataSourceId = props.dataSourceId;
8385
const startDateTime = moment().subtract(
8486
detectionInterval * LIVE_CHART_CONFIG.MONITORING_INTERVALS,
8587
'minutes'
@@ -133,6 +135,7 @@ export const AnomalyResultsLiveChart = (
133135
await dispatch(
134136
getDetectorLiveResults(
135137
detectorId,
138+
dataSourceId,
136139
queryParams,
137140
false,
138141
resultIndex,

0 commit comments

Comments
 (0)