/* * SPDX-License-Identifier: Apache-2.0 * * The OpenSearch Contributors require contributions made to * this file be licensed under the Apache-2.0 license or a * compatible open source license. * * Modifications Copyright OpenSearch Contributors. See * GitHub history for details. */ import { EuiSpacer, EuiPageHeader, EuiTitle, EuiText, EuiFlexItem, EuiFlexGroup, EuiLink, EuiIcon, EuiButton, EuiLoadingSpinner, EuiFlexGrid, } from '@elastic/eui'; import React, { Fragment, useEffect, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { APP_PATH, BREADCRUMBS, PLUGIN_NAME, BASE_DOCS_LINK, } from '../../../utils/constants'; import { SAMPLE_TYPE } from '../../../../server/utils/constants'; import { GET_SAMPLE_DETECTORS_QUERY_PARAMS, GET_SAMPLE_INDICES_QUERY, } from '../../utils/constants'; import { AppState } from '../../../redux/reducers'; import { getDetectorList } from '../../../redux/reducers/ad'; import { createSampleData } from '../../../redux/reducers/sampleData'; import { getIndices, createIndex } from '../../../redux/reducers/opensearch'; import { createDetector, startDetector } from '../../../redux/reducers/ad'; import { sampleHttpResponses, sampleEcommerce, sampleHostHealth, } from '../utils/constants'; import { containsSampleIndex, getDetectorId, getSampleDetector, } from '../utils/helpers'; import { SampleDataBox } from '../components/SampleDataBox/SampleDataBox'; import { SampleDetailsFlyout } from '../components/SampleDetailsFlyout/SampleDetailsFlyout'; import { prettifyErrorMessage } from '../../../../server/utils/helpers'; import { CoreStart } from '../../../../../../src/core/public'; import { CoreServicesContext } from '../../../components/CoreServices/CoreServices'; import ContentPanel from '../../../components/ContentPanel/ContentPanel'; import { CreateWorkflowStepDetails } from '../components/CreateWorkflowStepDetails'; import { CreateWorkflowStepSeparator } from '../components/CreateWorkflowStepSeparator'; interface AnomalyDetectionOverviewProps { isLoadingDetectors: boolean; } export function AnomalyDetectionOverview(props: AnomalyDetectionOverviewProps) { const core = React.useContext(CoreServicesContext) as CoreStart; const dispatch = useDispatch(); const visibleSampleIndices = useSelector( (state: AppState) => state.opensearch.indices ); const allSampleDetectors = Object.values( useSelector((state: AppState) => state.ad.detectorList) ); const [isLoadingHttpData, setIsLoadingHttpData] = useState(false); const [isLoadingEcommerceData, setIsLoadingEcommerceData] = useState(false); const [isLoadingHostHealthData, setIsLoadingHostHealthData] = useState(false); const [showHttpResponseDetailsFlyout, setShowHttpResponseDetailsFlyout] = useState(false); const [showEcommerceDetailsFlyout, setShowEcommerceDetailsFlyout] = useState(false); const [showHostHealthDetailsFlyout, setShowHostHealthDetailsFlyout] = useState(false); const getAllSampleDetectors = async () => { await dispatch(getDetectorList(GET_SAMPLE_DETECTORS_QUERY_PARAMS)).catch( (error: any) => { console.error('Error getting all detectors: ', error); } ); }; const getAllSampleIndices = async () => { await dispatch(getIndices(GET_SAMPLE_INDICES_QUERY)).catch((error: any) => { console.error('Error getting all indices: ', error); }); }; // Set breadcrumbs on page initialization useEffect(() => { core.chrome.setBreadcrumbs([BREADCRUMBS.ANOMALY_DETECTOR]); }, []); // Getting all initial sample detectors & indices useEffect(() => { getAllSampleDetectors(); getAllSampleIndices(); }, []); // Create and populate sample index, create and start sample detector const handleLoadData = async ( sampleType: SAMPLE_TYPE, indexConfig: any, detectorConfig: any, setLoadingState: (isLoading: boolean) => void ) => { setLoadingState(true); let errorDuringAction = false; let errorMessage = ''; // Create the index (if it doesn't exist yet) if (!containsSampleIndex(visibleSampleIndices, sampleType)) { await dispatch(createIndex(indexConfig)).catch((error: any) => { errorDuringAction = true; errorMessage = 'Error creating sample index. ' + prettifyErrorMessage(error); console.error(errorMessage); }); } // Get the sample data from the server and bulk insert if (!errorDuringAction) { await dispatch(createSampleData(sampleType)).catch((error: any) => { errorDuringAction = true; errorMessage = prettifyErrorMessage(error.message); console.error('Error bulk inserting data: ', errorMessage); }); } // Create the detector if (!errorDuringAction) { await dispatch(createDetector(detectorConfig)) .then(function (response: any) { const detectorId = response.response.id; // Start the detector dispatch(startDetector(detectorId)).catch((error: any) => { errorDuringAction = true; errorMessage = prettifyErrorMessage(error.message); console.error('Error starting sample detector: ', errorMessage); }); }) .catch((error: any) => { errorDuringAction = true; errorMessage = prettifyErrorMessage(error.message); console.error('Error creating sample detector: ', errorMessage); }); } getAllSampleDetectors(); getAllSampleIndices(); setLoadingState(false); if (!errorDuringAction) { core.notifications.toasts.addSuccess( 'Successfully loaded the sample detector' ); } else { core.notifications.toasts.addDanger( `Unable to load all sample data, please try again. ${errorMessage}` ); } }; return props.isLoadingDetectors ? (
) : (

Anomaly detection

Create detector
The anomaly detection plugin automatically detects anomalies in your data in near real-time using the Random Cut Forest (RCF) algorithm.{' '} Learn more New to anomaly detection? Get a better understanding of how it works by creating a detector with one of the sample datasets. } horizontalRuleClassName="hide-horizontal-rule" > { setShowHttpResponseDetailsFlyout(true); setShowEcommerceDetailsFlyout(false); setShowHostHealthDetailsFlyout(false); }} onLoadData={() => { handleLoadData( SAMPLE_TYPE.HTTP_RESPONSES, sampleHttpResponses.indexConfig, sampleHttpResponses.detectorConfig, setIsLoadingHttpData ); }} isLoadingData={isLoadingHttpData} isDataLoaded={ getSampleDetector( allSampleDetectors, SAMPLE_TYPE.HTTP_RESPONSES ) !== undefined } detectorId={getDetectorId( allSampleDetectors, sampleHttpResponses.detectorName, sampleHttpResponses.legacyDetectorName )} /> { setShowHttpResponseDetailsFlyout(false); setShowEcommerceDetailsFlyout(true); setShowHostHealthDetailsFlyout(false); }} onLoadData={() => { handleLoadData( SAMPLE_TYPE.ECOMMERCE, sampleEcommerce.indexConfig, sampleEcommerce.detectorConfig, setIsLoadingEcommerceData ); }} isLoadingData={isLoadingEcommerceData} isDataLoaded={ getSampleDetector(allSampleDetectors, SAMPLE_TYPE.ECOMMERCE) !== undefined } detectorId={getDetectorId( allSampleDetectors, sampleEcommerce.detectorName, sampleEcommerce.legacyDetectorName )} /> { setShowHttpResponseDetailsFlyout(false); setShowEcommerceDetailsFlyout(false); setShowHostHealthDetailsFlyout(true); }} onLoadData={() => { handleLoadData( SAMPLE_TYPE.HOST_HEALTH, sampleHostHealth.indexConfig, sampleHostHealth.detectorConfig, setIsLoadingHostHealthData ); }} isLoadingData={isLoadingHostHealthData} isDataLoaded={ getSampleDetector( allSampleDetectors, SAMPLE_TYPE.HOST_HEALTH ) !== undefined } detectorId={getDetectorId( allSampleDetectors, sampleHostHealth.detectorName, sampleHostHealth.legacyDetectorName )} /> {showHttpResponseDetailsFlyout ? ( setShowHttpResponseDetailsFlyout(false)} /> ) : null} {showEcommerceDetailsFlyout ? ( setShowEcommerceDetailsFlyout(false)} /> ) : null} {showHostHealthDetailsFlyout ? ( setShowHostHealthDetailsFlyout(false)} /> ) : null}
); }