Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add MDS support on neo feature branch #725

Merged
merged 22 commits into from
Apr 15, 2024
Merged
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
1 change: 1 addition & 0 deletions opensearch_dashboards.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"configPath": [
"anomaly_detection_dashboards"
],
"optionalPlugins": ["dataSource","dataSourceManagement"],
"requiredPlugins": [
"opensearchDashboardsUtils",
"expressions",
Expand Down
11 changes: 9 additions & 2 deletions public/anomaly_detection_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ import { Provider } from 'react-redux';
import configureStore from './redux/configureStore';
import { CoreServicesContext } from './components/CoreServices/CoreServices';

export function renderApp(coreStart: CoreStart, params: AppMountParameters) {
export function renderApp(
coreStart: CoreStart,
params: AppMountParameters,
) {
const http = coreStart.http;
const store = configureStore(http);

Expand All @@ -29,13 +32,17 @@ export function renderApp(coreStart: CoreStart, params: AppMountParameters) {
} else {
require('@elastic/charts/dist/theme_only_light.css');
}

ReactDOM.render(
<Provider store={store}>
<Router>
<Route
render={(props) => (
<CoreServicesContext.Provider value={coreStart}>
<Main {...props} />
<Main
setHeaderActionMenu={params.setHeaderActionMenu}
{...props}
/>
</CoreServicesContext.Provider>
)}
/>
Expand Down
2 changes: 2 additions & 0 deletions public/models/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ export type Detector = {
taskState?: DETECTOR_STATE;
taskProgress?: number;
taskError?: string;
dataSourceId? : string;
};

export type DetectorListItem = {
Expand All @@ -218,6 +219,7 @@ export type DetectorListItem = {
lastUpdateTime: number;
enabledTime?: number;
detectorType?: string;
dataSourceId?: string;
};

export type EntityData = {
Expand Down
3 changes: 3 additions & 0 deletions public/pages/AnomalyCharts/containers/AnomaliesChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ export interface AnomaliesChartProps {
selectedCategoryFields?: any[];
handleCategoryFieldsChange(selectedOptions: any[]): void;
openOutOfRangeCallOut?: boolean;
dataSourceId?: string;
}

export const AnomaliesChart = React.memo((props: AnomaliesChartProps) => {
Expand Down Expand Up @@ -345,6 +346,7 @@ export const AnomaliesChart = React.memo((props: AnomaliesChartProps) => {
isHCDetector={props.isHCDetector}
isHistorical={props.isHistorical}
selectedHeatmapCell={props.selectedHeatmapCell}
dataSourceId={props.dataSourceId}
/>,
<EuiSpacer size="m" />,
<FeatureBreakDown
Expand Down Expand Up @@ -399,6 +401,7 @@ export const AnomaliesChart = React.memo((props: AnomaliesChartProps) => {
isHistorical={props.isHistorical}
onDatePickerRangeChange={handleDatePickerRangeChange}
openOutOfRangeCallOut={showOutOfRangeCallOut}
dataSourceId={props.dataSourceId}
/>
)}
</EuiFlexGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ interface AnomalyDetailsChartProps {
selectedHeatmapCell?: HeatmapCell;
onDatePickerRangeChange?(startDate: number, endDate: number): void;
openOutOfRangeCallOut?: boolean;
dataSourceId?: string;
}

export const AnomalyDetailsChart = React.memo(
Expand Down Expand Up @@ -174,7 +175,7 @@ export const AnomalyDetailsChart = React.memo(
zoomRange.endDate,
taskId
);
dispatch(searchResults(anomalyDataRangeQuery, resultIndex, true))
dispatch(searchResults(anomalyDataRangeQuery, resultIndex, props.dataSourceId, true))
.then((response: any) => {
// Only retrieve buckets that are in the anomaly results range. This is so
// we don't show aggregate results for where there is no data at all
Expand All @@ -193,7 +194,7 @@ export const AnomalyDetailsChart = React.memo(
taskId,
selectedAggId
);
dispatch(searchResults(historicalAggQuery, resultIndex, true))
dispatch(searchResults(historicalAggQuery, resultIndex, props.dataSourceId, true))
.then((response: any) => {
const aggregatedAnomalies = parseHistoricalAggregatedAnomalies(
response,
Expand Down Expand Up @@ -229,7 +230,7 @@ export const AnomalyDetailsChart = React.memo(
zoomRange.endDate,
taskId
);
dispatch(searchResults(anomalyDataRangeQuery, resultIndex, true))
dispatch(searchResults(anomalyDataRangeQuery, resultIndex, props.dataSourceId, true))
.then((response: any) => {
const dataStartDate = get(
response,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ interface AnomalyOccurrenceChartProps {
isHCDetector?: boolean;
isHistorical?: boolean;
selectedHeatmapCell?: HeatmapCell;
dataSourceId?: string;
}

export const AnomalyOccurrenceChart = React.memo(
Expand Down Expand Up @@ -82,6 +83,7 @@ export const AnomalyOccurrenceChart = React.memo(
isHCDetector={props.isHCDetector}
isHistorical={props.isHistorical}
selectedHeatmapCell={props.selectedHeatmapCell}
dataSourceId={props.dataSourceId}
/>
{props.isHCDetector && props.selectedHeatmapCell === undefined ? (
<EuiBadge className={'anomaly-detail-chart-center'} color={'default'}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ import { getMappings } from '../../../redux/reducers/opensearch';
// 1. Get detector
// 2. Gets index mapping
export const useFetchDetectorInfo = (
detectorId: string
detectorId: string,
dataSourceId: string
): {
detector: Detector;
hasError: boolean;
Expand All @@ -43,7 +44,8 @@ export const useFetchDetectorInfo = (
useEffect(() => {
const fetchDetector = async () => {
if (!detector) {
await dispatch(getDetector(detectorId));
// hardcoding the datasource id for now, will update it later when working on create page
await dispatch(getDetector(detectorId, dataSourceId));
}
if (selectedIndices) {
await dispatch(getMappings(selectedIndices));
Expand Down
2 changes: 2 additions & 0 deletions public/pages/Dashboard/Components/AnomaliesDistribution.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import { ALL_CUSTOM_AD_RESULT_INDICES } from '../../utils/constants';
import { searchResults } from '../../../redux/reducers/anomalyResults';
export interface AnomaliesDistributionChartProps {
selectedDetectors: DetectorListItem[];
dataSourceId?: string;
}

export const AnomaliesDistributionChart = (
Expand Down Expand Up @@ -66,6 +67,7 @@ export const AnomaliesDistributionChart = (
await getAnomalyDistributionForDetectorsByTimeRange(
searchResults,
props.selectedDetectors,
props.dataSourceId,
timeRange,
dispatch,
0,
Expand Down
7 changes: 5 additions & 2 deletions public/pages/Dashboard/Components/AnomaliesLiveChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ import { searchResults } from '../../../redux/reducers/anomalyResults';

export interface AnomaliesLiveChartProps {
selectedDetectors: DetectorListItem[];
dataSourceId?: string;
}

interface LiveTimeRangeState {
Expand Down Expand Up @@ -102,7 +103,8 @@ export const AnomaliesLiveChart = (props: AnomaliesLiveChartProps) => {
1,
true,
ALL_CUSTOM_AD_RESULT_INDICES,
false
false,
props.dataSourceId
);
} catch (err) {
console.log(
Expand All @@ -126,7 +128,8 @@ export const AnomaliesLiveChart = (props: AnomaliesLiveChartProps) => {
MAX_LIVE_DETECTORS,
false,
ALL_CUSTOM_AD_RESULT_INDICES,
false
false,
props.dataSourceId
);
setLiveAnomalyData(latestLiveAnomalyResult);

Expand Down
95 changes: 81 additions & 14 deletions public/pages/Dashboard/Container/DashboardOverview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@
* GitHub history for details.
*/

import React, { Fragment, useState, useEffect } from 'react';
import React, { Fragment, useState, useEffect, useMemo } from 'react';
import { AnomaliesLiveChart } from '../Components/AnomaliesLiveChart';
import { AnomaliesDistributionChart } from '../Components/AnomaliesDistribution';
import queryString from 'querystring';

import { useDispatch, useSelector } from 'react-redux';
import { get, isEmpty, cloneDeep } from 'lodash';
Expand All @@ -29,27 +30,38 @@ import {
} from '@elastic/eui';
import { AnomalousDetectorsList } from '../Components/AnomalousDetectorsList';
import {
GET_ALL_DETECTORS_QUERY_PARAMS,
ALL_DETECTORS_MESSAGE,
ALL_DETECTOR_STATES_MESSAGE,
ALL_INDICES_MESSAGE,
} from '../utils/constants';
import { AppState } from '../../../redux/reducers';
import { CatIndex, IndexAlias } from '../../../../server/models/types';
import { getVisibleOptions } from '../../utils/helpers';
import { CatIndex, IndexAlias, MDSQueryParams } from '../../../../server/models/types';
import { getAllDetectorsQueryParamsWithDataSourceId, getVisibleOptions } from '../../utils/helpers';
import { BREADCRUMBS } from '../../../utils/constants';
import { DETECTOR_STATE } from '../../../../server/utils/constants';
import { getDetectorStateOptions } from '../../DetectorsList/utils/helpers';
import { getDetectorStateOptions, getURLQueryParams } from '../../DetectorsList/utils/helpers';
import { DashboardHeader } from '../Components/utils/DashboardHeader';
import { EmptyDashboard } from '../Components/EmptyDashboard/EmptyDashboard';
import {
prettifyErrorMessage,
NO_PERMISSIONS_KEY_WORD,
} from '../../../../server/utils/helpers';
import { CoreServicesContext } from '../../../components/CoreServices/CoreServices';
import { CoreStart } from '../../../../../../src/core/public';
import { CoreStart, MountPoint } from '../../../../../../src/core/public';
import { DataSourceSelectableConfig } from '../../../../../../src/plugins/data_source_management/public';
import { getDataSourceManagementPlugin, getDataSourcePlugin, getNotifications, getSavedObjectsClient } from '../../../services';
import { RouteComponentProps } from 'react-router-dom';

export function DashboardOverview() {
interface OverviewProps extends RouteComponentProps {
setActionMenu: (menuMount: MountPoint | undefined) => void;
}

interface MDSOverviewState {
queryParams: MDSQueryParams;
selectedDataSourceId: string;
}

export function DashboardOverview(props: OverviewProps) {
const core = React.useContext(CoreServicesContext) as CoreStart;
const dispatch = useDispatch();
const adState = useSelector((state: AppState) => state.ad);
Expand All @@ -58,13 +70,21 @@ export function DashboardOverview() {
const errorGettingDetectors = adState.errorMessage;
const isLoadingDetectors = adState.requesting;

const dataSourceEnabled = getDataSourcePlugin().dataSourceEnabled;

const [currentDetectors, setCurrentDetectors] = useState(
Object.values(allDetectorList)
);
const [allDetectorsSelected, setAllDetectorsSelected] = useState(true);
const [selectedDetectorsName, setSelectedDetectorsName] = useState(
[] as string[]
);
const queryParams = getURLQueryParams(props.location);
const [MDSOverviewState, setMDSOverviewState] = useState<MDSOverviewState>({
queryParams,
selectedDataSourceId: queryParams.dataSourceId ? queryParams.dataSourceId : '',
});

const getDetectorOptions = (detectorsIdMap: {
[key: string]: DetectorListItem;
}) => {
Expand Down Expand Up @@ -108,6 +128,20 @@ export function DashboardOverview() {
setAllDetectorStatesSelected(isEmpty(selectedStates));
};

const handleDataSourceChange = ([event]) => {
const dataSourceId = event?.id;
if (!dataSourceId) {
getNotifications().toasts.addDanger(
prettifyErrorMessage('Unable to set data source.')
);
} else {
setMDSOverviewState({
queryParams: dataSourceId,
selectedDataSourceId: dataSourceId,
});
}
}

const opensearchState = useSelector((state: AppState) => state.opensearch);

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

const intializeDetectors = async () => {
dispatch(getDetectorList(GET_ALL_DETECTORS_QUERY_PARAMS));
dispatch(getIndices(''));
dispatch(getAliases(''));
dispatch(getDetectorList(getAllDetectorsQueryParamsWithDataSourceId(MDSOverviewState.selectedDataSourceId)));
dispatch(getIndices('', MDSOverviewState.selectedDataSourceId));
dispatch(getAliases('', MDSOverviewState.selectedDataSourceId));
};

useEffect(() => {
intializeDetectors();
}, []);
const { history, location } = props;
const updatedParams = {
dataSourceId: MDSOverviewState.selectedDataSourceId,
};
history.replace({
...location,
search: queryString.stringify(updatedParams),
})
if (dataSourceEnabled ? MDSOverviewState.selectedDataSourceId : true) {
intializeDetectors();
}
}, [MDSOverviewState]);

useEffect(() => {
if (errorGettingDetectors) {
Expand Down Expand Up @@ -193,13 +237,33 @@ export function DashboardOverview() {
filterSelectedDetectors(
selectedDetectorsName,
selectedDetectorStates,
selectedIndices
selectedIndices,
);
}, [selectedDetectorsName, selectedIndices, selectedDetectorStates]);

const DataSourceMenu =
getDataSourceManagementPlugin().ui.getDataSourceMenu<DataSourceSelectableConfig>();
const renderDataSourceComponent = useMemo(() => {
return (
<DataSourceMenu
setMenuMountPoint={props.setActionMenu}
componentType={'DataSourceSelectable'}
componentConfig={{
fullWidth: false,
activeOption:[{ id: MDSOverviewState.selectedDataSourceId }],
savedObjects: getSavedObjectsClient(),
notifications: getNotifications(),
onSelectedDataSources: (dataSources) =>
handleDataSourceChange(dataSources),
}}
/>
);
}, [getSavedObjectsClient(), getNotifications(), props.setActionMenu]);

return (
<div style={{ height: '1200px' }}>
<Fragment>
{dataSourceEnabled && renderDataSourceComponent}
<DashboardHeader hasDetectors={totalRealtimeDetectors > 0} />
{isLoadingDetectors ? (
<div>
Expand Down Expand Up @@ -248,12 +312,15 @@ export function DashboardOverview() {
</EuiFlexItem>
</EuiFlexGroup>
<EuiSpacer />
<AnomaliesLiveChart selectedDetectors={currentDetectors} />
<AnomaliesLiveChart
selectedDetectors={currentDetectors}
dataSourceId={MDSOverviewState.selectedDataSourceId} />
<EuiSpacer />
<EuiFlexGroup justifyContent="spaceBetween">
<EuiFlexItem grow={6}>
<AnomaliesDistributionChart
selectedDetectors={currentDetectors}
dataSourceId={MDSOverviewState.selectedDataSourceId}
/>
</EuiFlexItem>
<EuiFlexItem grow={3}>
Expand Down
Loading
Loading