Skip to content

Commit

Permalink
UX improvements for correlation engine (opensearch-project#561)
Browse files Browse the repository at this point in the history
* passing props for date time filter (opensearch-project#551)

Signed-off-by: Amardeepsingh Siglani <[email protected]>

* added loading state

Signed-off-by: Amardeepsingh Siglani <[email protected]>

* ux improvements

Signed-off-by: Amardeepsingh Siglani <[email protected]>

* transform vega-lite files for jest testing

Signed-off-by: Amardeepsingh Siglani <[email protected]>

---------

Signed-off-by: Amardeepsingh Siglani <[email protected]>
  • Loading branch information
amsiglan committed May 5, 2023
1 parent f3680f4 commit 5435504
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 41 deletions.
34 changes: 29 additions & 5 deletions public/pages/Correlations/components/CorrelationGraph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,41 @@
*/

import React from 'react';
import Graph from 'react-graph-vis';
import Graph, { Edge, GraphEvents, Network, Node, Options } from 'react-graph-vis';
import 'vis-network/dist/dist/vis-network.min.css';
import { EuiLoadingChart } from '@elastic/eui';

export const CorrelationGraph = ({ graph: { nodes, edges }, options, events }) => {
return (
interface CorrelationGraphProps {
loadingData: boolean;
graph: {
nodes: Node[];
edges: Edge[];
};
options: Options;
events: GraphEvents;
getNetwork: (network: Network) => void;
}

export const CorrelationGraph: React.FC<CorrelationGraphProps> = ({
graph: { nodes, edges },
options,
events,
loadingData,
getNetwork,
}) => {
return loadingData ? (
<div style={{ margin: '75px 47%' }}>
<EuiLoadingChart size="xl" className="chart-view-container-loading" />
</div>
) : (
<Graph
key={`network`}
identifier={`network`}
identifier={`sa-correlations-network`}
graph={{ nodes, edges }}
options={options}
events={events}
style={{ border: '1px solid' }}
style={{ border: '1px solid', backgroundColor: '#ffffff' }}
getNetwork={getNetwork}
/>
);
};
102 changes: 66 additions & 36 deletions public/pages/Correlations/containers/CorrelationsContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import {
defaultSeverityFilterItemOptions,
emptyGraphData,
getAbbrFromLogType,
getLabelFromLogType,
getSeverityColor,
getSeverityLabel,
graphRenderOptions,
} from '../utils/constants';
import {
Expand All @@ -29,6 +31,7 @@ import {
EuiText,
EuiEmptyPrompt,
EuiButton,
EuiBadge,
} from '@elastic/eui';
import { CorrelationsExperimentalBanner } from '../components/ExperimentalBanner';
import { FilterItem, FilterGroup } from '../components/FilterGroup';
Expand All @@ -45,6 +48,8 @@ import { DataStore } from '../../../store/DataStore';
import { FindingItemType } from '../../Findings/containers/Findings/Findings';
import datemath from '@elastic/datemath';
import { ruleSeverity } from '../../Rules/utils/constants';
import { renderToStaticMarkup } from 'react-dom/server';
import { Network } from 'react-graph-vis';

interface CorrelationsProps
extends RouteComponentProps<
Expand All @@ -68,10 +73,13 @@ interface CorrelationsState {
specificFindingInfo?: SpecificFindingCorrelations;
logTypeFilterOptions: FilterItem[];
severityFilterOptions: FilterItem[];
loadingGraphData: boolean;
}

export class Correlations extends React.Component<CorrelationsProps, CorrelationsState> {
static contextType = CoreServicesContext;
private correlationGraphNetwork?: Network;

constructor(props: CorrelationsProps) {
super(props);
this.state = {
Expand All @@ -80,6 +88,7 @@ export class Correlations extends React.Component<CorrelationsProps, Correlation
logTypeFilterOptions: [...defaultLogTypeFilterItemOptions],
severityFilterOptions: [...defaultSeverityFilterItemOptions],
specificFindingInfo: undefined,
loadingGraphData: false,
};
}

Expand Down Expand Up @@ -153,10 +162,12 @@ export class Correlations extends React.Component<CorrelationsProps, Correlation
const end = datemath.parse(this.endTime);
const startTime = start?.valueOf() || Date.now();
const endTime = end?.valueOf() || Date.now();
this.setState({ loadingGraphData: true });
let allCorrelations = await DataStore.correlations.getAllCorrelationsInWindow(
startTime.toString(),
endTime.toString()
);
this.setState({ loadingGraphData: false });
allCorrelations = allCorrelations.filter((corr) => {
return this.shouldShowFinding(corr.finding1) && this.shouldShowFinding(corr.finding2);
});
Expand Down Expand Up @@ -256,6 +267,7 @@ export class Correlations extends React.Component<CorrelationsProps, Correlation
multi: 'html',
size: 12,
},
chosen: true,
});
}

Expand All @@ -264,23 +276,34 @@ export class Correlations extends React.Component<CorrelationsProps, Correlation
from: f1.id,
to: f2.id,
id: `${f1.id}:${f2.id}`,
chosen: false,
});
}

private createNodeTooltip = (finding: CorrelationFinding) => {
const tooltip = document.createElement('div');
private createNodeTooltip = ({ detectionRule, timestamp, logType }: CorrelationFinding) => {
const tooltipContent = (
<div style={{ backgroundColor: '#535353', color: '#ffffff', padding: '8px' }}>
<EuiFlexGroup alignItems="center">
<EuiFlexItem grow={false}>
<EuiBadge color={getSeverityColor(detectionRule.severity)}>
{getSeverityLabel(detectionRule.severity)}
</EuiBadge>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<strong>{getLabelFromLogType(logType)}</strong>
</EuiFlexItem>
</EuiFlexGroup>
<EuiSpacer size="s" />
<EuiText>{timestamp}</EuiText>
</div>
);

function createRow(text: string) {
const row = document.createElement('p');
row.innerText = text;
row.style.padding = '5px';
return row;
}
const tooltipContentHTML = renderToStaticMarkup(tooltipContent);

tooltip.appendChild(createRow(`Log type: ${finding.logType}`));
tooltip.appendChild(createRow(finding.timestamp));
const tooltip = document.createElement('div');
tooltip.innerHTML = tooltipContentHTML;

return tooltip;
return tooltip.firstElementChild;
};

private onTimeChange = ({ start, end }: { start: string; end: string }) => {
Expand Down Expand Up @@ -324,6 +347,7 @@ export class Correlations extends React.Component<CorrelationsProps, Correlation
const specificFindingInfo = await DataStore.correlations.getCorrelatedFindings(id, logType);
this.setState({ specificFindingInfo });
this.updateGraphDataState(specificFindingInfo);
this.correlationGraphNetwork?.selectNodes([id], false);
};

resetFilters = () => {
Expand All @@ -339,6 +363,36 @@ export class Correlations extends React.Component<CorrelationsProps, Correlation
});
};

setNetwork = (network: Network) => {
this.correlationGraphNetwork = network;
};

renderCorrelationsGraph(loadingData: boolean) {
return this.state.graphData.graph.nodes.length > 0 || loadingData ? (
<CorrelationGraph
loadingData={loadingData}
graph={this.state.graphData.graph}
options={{ ...graphRenderOptions }}
events={this.state.graphData.events}
getNetwork={this.setNetwork}
/>
) : (
<EuiEmptyPrompt
title={
<EuiTitle>
<h1>No correlations found</h1>
</EuiTitle>
}
body={<p>There are no correlated findings in the system.</p>}
actions={[
<EuiButton fill={true} color="primary" href={`#${ROUTES.CORRELATION_RULE_CREATE}`}>
Create correlation rule
</EuiButton>,
]}
/>
);
}

render() {
const findingCardsData = this.state.specificFindingInfo;

Expand Down Expand Up @@ -476,31 +530,7 @@ export class Correlations extends React.Component<CorrelationsProps, Correlation
</EuiFlexGroup>

<EuiSpacer />
{this.state.graphData.graph.nodes.length > 0 ? (
<CorrelationGraph
graph={this.state.graphData.graph}
options={{ ...graphRenderOptions }}
events={this.state.graphData.events}
/>
) : (
<EuiEmptyPrompt
title={
<EuiTitle>
<h1>No correlations found</h1>
</EuiTitle>
}
body={<p>There are no correlated findings in the system.</p>}
actions={[
<EuiButton
fill={true}
color="primary"
href={`#${ROUTES.CORRELATION_RULE_CREATE}`}
>
Create correlation rule
</EuiButton>,
]}
/>
)}
{this.renderCorrelationsGraph(this.state.loadingGraphData)}
</EuiPanel>
</EuiFlexItem>
</EuiFlexGroup>
Expand Down
1 change: 1 addition & 0 deletions public/pages/Correlations/utils/constants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export const graphRenderOptions = {
dragNodes: false,
multiselect: true,
tooltipDelay: 50,
hover: true,
},
};

Expand Down

0 comments on commit 5435504

Please sign in to comment.