Skip to content

Commit

Permalink
[SecuritySolution] Data Quality dashboard in serverless (#163733)
Browse files Browse the repository at this point in the history
  • Loading branch information
angorayc authored Aug 25, 2023
1 parent e8127e2 commit 8da14b7
Show file tree
Hide file tree
Showing 67 changed files with 1,107 additions and 132 deletions.
1 change: 1 addition & 0 deletions x-pack/.i18nrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"xpack.discoverLogExplorer": "plugins/discover_log_explorer",
"xpack.crossClusterReplication": "plugins/cross_cluster_replication",
"xpack.elasticAssistant": "packages/kbn-elastic-assistant",
"xpack.ecsDataQualityDashboard": "plugins/ecs_data_quality_dashboard",
"xpack.embeddableEnhanced": "plugins/embeddable_enhanced",
"xpack.endpoint": "plugins/endpoint",
"xpack.enterpriseSearch": "plugins/enterprise_search",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,13 @@ import { IlmPhasesEmptyPrompt } from '../../../ilm_phases_empty_prompt';
import { IndicesDetails } from './indices_details';
import { StorageDetails } from './storage_details';
import { PatternRollup, SelectedIndex } from '../../../types';
import { useDataQualityContext } from '../../data_quality_context';

export interface Props {
addSuccessToast: (toast: { title: string }) => void;
baseTheme: Theme;
canUserCreateAndReadCases: () => boolean;
endDate?: string | null;
formatBytes: (value: number | undefined) => string;
formatNumber: (value: number | undefined) => string;
getGroupByFieldsOnClick: (
Expand Down Expand Up @@ -53,8 +56,8 @@ export interface Props {
patternIndexNames: Record<string, string[]>;
patternRollups: Record<string, PatternRollup>;
patterns: string[];
startDate?: string | null;
theme?: PartialTheme;
baseTheme: Theme;
updatePatternIndexNames: ({
indexNames,
pattern,
Expand All @@ -68,6 +71,7 @@ export interface Props {
const DataQualityDetailsComponent: React.FC<Props> = ({
addSuccessToast,
canUserCreateAndReadCases,
endDate,
formatBytes,
formatNumber,
getGroupByFieldsOnClick,
Expand All @@ -77,18 +81,20 @@ const DataQualityDetailsComponent: React.FC<Props> = ({
patternIndexNames,
patternRollups,
patterns,
startDate,
theme,
baseTheme,
updatePatternIndexNames,
updatePatternRollup,
}) => {
const { isILMAvailable } = useDataQualityContext();
const [selectedIndex, setSelectedIndex] = useState<SelectedIndex | null>(null);

const onIndexSelected = useCallback(async ({ indexName, pattern }: SelectedIndex) => {
setSelectedIndex({ indexName, pattern });
}, []);

if (ilmPhases.length === 0) {
if (isILMAvailable && ilmPhases.length === 0) {
return <IlmPhasesEmptyPrompt />;
}

Expand All @@ -107,6 +113,7 @@ const DataQualityDetailsComponent: React.FC<Props> = ({
<IndicesDetails
addSuccessToast={addSuccessToast}
canUserCreateAndReadCases={canUserCreateAndReadCases}
endDate={endDate}
formatBytes={formatBytes}
formatNumber={formatNumber}
getGroupByFieldsOnClick={getGroupByFieldsOnClick}
Expand All @@ -120,6 +127,7 @@ const DataQualityDetailsComponent: React.FC<Props> = ({
patternRollups={patternRollups}
selectedIndex={selectedIndex}
setSelectedIndex={setSelectedIndex}
startDate={startDate}
updatePatternIndexNames={updatePatternIndexNames}
updatePatternRollup={updatePatternRollup}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { PatternRollup, SelectedIndex } from '../../../../types';
export interface Props {
addSuccessToast: (toast: { title: string }) => void;
canUserCreateAndReadCases: () => boolean;
endDate?: string | null;
formatBytes: (value: number | undefined) => string;
formatNumber: (value: number | undefined) => string;
getGroupByFieldsOnClick: (
Expand Down Expand Up @@ -53,6 +54,7 @@ export interface Props {
patterns: string[];
selectedIndex: SelectedIndex | null;
setSelectedIndex: (selectedIndex: SelectedIndex | null) => void;
startDate?: string | null;
theme?: PartialTheme;
baseTheme: Theme;
updatePatternIndexNames: ({
Expand All @@ -68,6 +70,7 @@ export interface Props {
const IndicesDetailsComponent: React.FC<Props> = ({
addSuccessToast,
canUserCreateAndReadCases,
endDate,
formatBytes,
formatNumber,
getGroupByFieldsOnClick,
Expand All @@ -79,6 +82,7 @@ const IndicesDetailsComponent: React.FC<Props> = ({
patterns,
selectedIndex,
setSelectedIndex,
startDate,
theme,
baseTheme,
updatePatternIndexNames,
Expand All @@ -90,6 +94,7 @@ const IndicesDetailsComponent: React.FC<Props> = ({
<Pattern
addSuccessToast={addSuccessToast}
canUserCreateAndReadCases={canUserCreateAndReadCases}
endDate={endDate}
formatBytes={formatBytes}
formatNumber={formatNumber}
getGroupByFieldsOnClick={getGroupByFieldsOnClick}
Expand All @@ -101,6 +106,7 @@ const IndicesDetailsComponent: React.FC<Props> = ({
patternRollup={patternRollups[pattern]}
selectedIndex={selectedIndex}
setSelectedIndex={setSelectedIndex}
startDate={startDate}
theme={theme}
baseTheme={baseTheme}
updatePatternIndexNames={updatePatternIndexNames}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ describe('helpers', () => {
const pattern = 'auditbeat-*';
const flattenedBuckets = getFlattenedBuckets({
ilmPhases,
isILMAvailable: true,
patternRollups,
});

Expand Down Expand Up @@ -129,12 +130,45 @@ describe('helpers', () => {
},
]);
});

test('it returns the expected legend items when isILMAvailable is false', () => {
const pattern = 'auditbeat-*';
const flattenedBuckets = getFlattenedBuckets({
ilmPhases,
isILMAvailable: false,
patternRollups,
});
expect(getLegendItemsForPattern({ pattern, flattenedBuckets })).toEqual([
{
color: euiThemeVars.euiColorSuccess,
ilmPhase: null,
index: '.ds-auditbeat-8.6.1-2023.02.07-000001',
pattern: 'auditbeat-*',
sizeInBytes: 18791790,
},
{
color: euiThemeVars.euiColorDanger,
ilmPhase: null,
index: 'auditbeat-custom-index-1',
pattern: 'auditbeat-*',
sizeInBytes: 28409,
},
{
color: euiThemeVars.euiColorDanger,
ilmPhase: null,
index: 'auditbeat-custom-empty-index-1',
pattern: 'auditbeat-*',
sizeInBytes: 247,
},
]);
});
});

describe('getLegendItems', () => {
test('it returns the expected legend items', () => {
const flattenedBuckets = getFlattenedBuckets({
ilmPhases,
isILMAvailable: true,
patternRollups,
});

Expand Down Expand Up @@ -205,6 +239,7 @@ describe('helpers', () => {
expect(
getFlattenedBuckets({
ilmPhases,
isILMAvailable: true,
patternRollups,
})
).toEqual([
Expand Down Expand Up @@ -250,6 +285,57 @@ describe('helpers', () => {
},
]);
});

test('it returns the expected flattened buckets when isILMAvailable is false', () => {
expect(
getFlattenedBuckets({
ilmPhases,
isILMAvailable: false,
patternRollups,
})
).toEqual([
{
ilmPhase: undefined,
incompatible: 0,
indexName: '.internal.alerts-security.alerts-default-000001',
pattern: '.alerts-security.alerts-default',
sizeInBytes: 0,
},
{
ilmPhase: undefined,
incompatible: 0,
indexName: '.ds-auditbeat-8.6.1-2023.02.07-000001',
pattern: 'auditbeat-*',
sizeInBytes: 18791790,
},
{
ilmPhase: undefined,
incompatible: 1,
indexName: 'auditbeat-custom-empty-index-1',
pattern: 'auditbeat-*',
sizeInBytes: 247,
},
{
ilmPhase: undefined,
incompatible: 3,
indexName: 'auditbeat-custom-index-1',
pattern: 'auditbeat-*',
sizeInBytes: 28409,
},
{
ilmPhase: undefined,
indexName: '.ds-packetbeat-8.6.1-2023.02.04-000001',
pattern: 'packetbeat-*',
sizeInBytes: 512194751,
},
{
ilmPhase: undefined,
indexName: '.ds-packetbeat-8.5.3-2023.02.04-000001',
pattern: 'packetbeat-*',
sizeInBytes: 584326147,
},
]);
});
});

describe('getFillColor', () => {
Expand All @@ -276,6 +362,7 @@ describe('helpers', () => {
test('it returns the expected map', () => {
const flattenedBuckets = getFlattenedBuckets({
ilmPhases,
isILMAvailable: true,
patternRollups,
});

Expand Down Expand Up @@ -363,6 +450,7 @@ describe('helpers', () => {
const layer0FillColor = 'transparent';
const flattenedBuckets = getFlattenedBuckets({
ilmPhases,
isILMAvailable: true,
patternRollups,
});
const pathToFlattenedBucketMap = getPathToFlattenedBucketMap(flattenedBuckets);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,11 @@ export const getLegendItems = ({

export const getFlattenedBuckets = ({
ilmPhases,
isILMAvailable,
patternRollups,
}: {
ilmPhases: string[];
isILMAvailable: boolean;
patternRollups: Record<string, PatternRollup>;
}): FlattenedBucket[] =>
Object.values(patternRollups).reduce<FlattenedBucket[]>((acc, patternRollup) => {
Expand All @@ -111,13 +113,15 @@ export const getFlattenedBuckets = ({
);
const { ilmExplain, pattern, results, stats } = patternRollup;

if (ilmExplain != null && stats != null) {
if (((isILMAvailable && ilmExplain != null) || !isILMAvailable) && stats != null) {
return [
...acc,
...Object.entries(stats).reduce<FlattenedBucket[]>(
(validStats, [indexName, indexStats]) => {
const ilmPhase = getIlmPhase(ilmExplain[indexName]);
const isSelectedPhase = ilmPhase != null && ilmPhasesMap[ilmPhase] != null;
const ilmPhase = getIlmPhase(ilmExplain?.[indexName], isILMAvailable);
const isSelectedPhase =
(isILMAvailable && ilmPhase != null && ilmPhasesMap[ilmPhase] != null) ||
!isILMAvailable;

if (isSelectedPhase) {
const incompatible =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { getFlattenedBuckets } from './helpers';
import { StorageTreemap } from '../../../storage_treemap';
import { DEFAULT_MAX_CHART_HEIGHT, StorageTreemapContainer } from '../../../tabs/styles';
import { PatternRollup, SelectedIndex } from '../../../../types';
import { useDataQualityContext } from '../../../data_quality_context';

export interface Props {
formatBytes: (value: number | undefined) => string;
Expand All @@ -32,13 +33,16 @@ const StorageDetailsComponent: React.FC<Props> = ({
theme,
baseTheme,
}) => {
const { isILMAvailable } = useDataQualityContext();

const flattenedBuckets = useMemo(
() =>
getFlattenedBuckets({
ilmPhases,
isILMAvailable,
patternRollups,
}),
[ilmPhases, patternRollups]
[ilmPhases, isILMAvailable, patternRollups]
);

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ import { useResultsRollup } from '../../use_results_rollup';

interface Props {
addSuccessToast: (toast: { title: string }) => void;
baseTheme: Theme;
canUserCreateAndReadCases: () => boolean;
endDate?: string | null;
formatBytes: (value: number | undefined) => string;
formatNumber: (value: number | undefined) => string;
getGroupByFieldsOnClick: (
Expand Down Expand Up @@ -52,13 +54,14 @@ interface Props {
}) => void;
patterns: string[];
setLastChecked: (lastChecked: string) => void;
startDate?: string | null;
theme?: PartialTheme;
baseTheme: Theme;
}

const BodyComponent: React.FC<Props> = ({
addSuccessToast,
canUserCreateAndReadCases,
endDate,
formatBytes,
formatNumber,
getGroupByFieldsOnClick,
Expand All @@ -68,6 +71,7 @@ const BodyComponent: React.FC<Props> = ({
openCreateCaseFlyout,
patterns,
setLastChecked,
startDate,
theme,
baseTheme,
}) => {
Expand Down Expand Up @@ -115,7 +119,9 @@ const BodyComponent: React.FC<Props> = ({
<EuiFlexItem>
<DataQualityDetails
addSuccessToast={addSuccessToast}
baseTheme={baseTheme}
canUserCreateAndReadCases={canUserCreateAndReadCases}
endDate={endDate}
formatBytes={formatBytes}
formatNumber={formatNumber}
getGroupByFieldsOnClick={getGroupByFieldsOnClick}
Expand All @@ -125,8 +131,8 @@ const BodyComponent: React.FC<Props> = ({
patterns={patterns}
patternIndexNames={patternIndexNames}
patternRollups={patternRollups}
startDate={startDate}
theme={theme}
baseTheme={baseTheme}
updatePatternIndexNames={updatePatternIndexNames}
updatePatternRollup={updatePatternRollup}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ const mockTelemetryEvents = {
reportDataQualityCheckAllCompleted: mockReportDataQualityCheckAllClicked,
};
const ContextWrapper: React.FC = ({ children }) => (
<DataQualityProvider httpFetch={mockHttpFetch} telemetryEvents={mockTelemetryEvents}>
<DataQualityProvider
httpFetch={mockHttpFetch}
telemetryEvents={mockTelemetryEvents}
isILMAvailable={true}
>
{children}
</DataQualityProvider>
);
Expand Down Expand Up @@ -52,4 +56,11 @@ describe('DataQualityContext', () => {

expect(telemetryEvents).toEqual(mockTelemetryEvents);
});

test('it should return the isILMAvailable param', async () => {
const { result } = renderHook(useDataQualityContext, { wrapper: ContextWrapper });
const isILMAvailable = await result.current.isILMAvailable;

expect(isILMAvailable).toEqual(true);
});
});
Loading

0 comments on commit 8da14b7

Please sign in to comment.