Skip to content

Commit

Permalink
141189 alerts table performance (#141385)
Browse files Browse the repository at this point in the history
* retrieve data without loops and work with columns instead of ids

* not found column when category doesnt exist
  • Loading branch information
jcger authored Sep 27, 2022
1 parent 67a07e8 commit 76b2624
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,57 +7,59 @@

import { EuiDataGridColumn } from '@elastic/eui';

const remove = ({ columnIds, index }: { columnIds: string[]; index: number }) => {
return [...columnIds.slice(0, index), ...columnIds.slice(index + 1)];
const remove = ({ columns, index }: { columns: EuiDataGridColumn[]; index: number }) => {
return [...columns.slice(0, index), ...columns.slice(index + 1)];
};

const insert = ({
columnId,
columnIds,
column,
columns,
defaultColumns,
}: {
columnId: string;
columnIds: string[];
column: EuiDataGridColumn;
columns: EuiDataGridColumn[];
defaultColumns: EuiDataGridColumn[];
}) => {
const defaultIndex = defaultColumns.findIndex(
(column: EuiDataGridColumn) => column.id === columnId
(defaultColumn: EuiDataGridColumn) => defaultColumn.id === column.id
);
const isInDefaultConfig = defaultIndex >= 0;

// if the column isn't shown but it's part of the default config
// insert into the same position as in the default config
if (isInDefaultConfig) {
return [...columnIds.slice(0, defaultIndex), columnId, ...columnIds.slice(defaultIndex)];
return [...columns.slice(0, defaultIndex), column, ...columns.slice(defaultIndex)];
}

// if the column isn't shown and it's not part of the default config
// push it into the second position. Behaviour copied by t_grid, security
// does this to insert right after the timestamp column
return [columnIds[0], columnId, ...columnIds.slice(1)];
return [columns[0], column, ...columns.slice(1)];
};

/**
* @param param.columnId id of the column to be removed/inserted
* @param param.columnIds Current array of columnIds in the grid
* @param param.defaultColumns Those initial columns set up in the configuration before being modified by the user
* @returns the new list of columns to be shown
* @param param.column column to be removed/inserted
* @param param.columns current array of columns in the grid
* @param param.defaultColumns Initial columns set up in the configuration before being modified by the user
* @returns the new list of columns
*/
export const toggleColumn = ({
columnId,
columnIds,
column,
columns,
defaultColumns,
}: {
columnId: string;
columnIds: string[];
column: EuiDataGridColumn;
columns: EuiDataGridColumn[];
defaultColumns: EuiDataGridColumn[];
}): string[] => {
const currentIndex = columnIds.indexOf(columnId);
}): EuiDataGridColumn[] => {
const currentIndex = columns.findIndex(
(currentColumn: EuiDataGridColumn) => currentColumn.id === column.id
);
const isVisible = currentIndex >= 0;

if (isVisible) {
return remove({ columnIds, index: currentIndex });
return remove({ columns, index: currentIndex });
}

return insert({ defaultColumns, columnId, columnIds });
return insert({ defaultColumns, column, columns });
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@

import { EuiDataGridColumn } from '@elastic/eui';
import { IStorageWrapper } from '@kbn/kibana-utils-plugin/public';
import { AlertConsumers } from '@kbn/rule-data-utils';
import { BrowserField, BrowserFields } from '@kbn/rule-registry-plugin/common';
import { useCallback, useEffect, useState } from 'react';
import { AlertConsumers } from '@kbn/rule-data-utils';
import { AlertsTableStorage } from '../../alerts_table_state';
import { useFetchBrowserFieldCapabilities } from '../use_fetch_browser_fields_capabilities';
import { toggleColumn } from './toggle_column';
import { useFetchBrowserFieldCapabilities } from '../use_fetch_browser_fields_capabilities';

interface UseColumnsArgs {
featureIds: AlertConsumers[];
Expand All @@ -29,54 +29,76 @@ const fieldTypeToDataGridColumnTypeMapper = (fieldType: string | undefined) => {
return fieldType;
};

const getFieldCategoryFromColumnId = (columnId: string): string => {
const fieldName = columnId.split('.');

if (fieldName.length === 1) {
return 'base';
}

return fieldName[0];
};

/**
* EUI Data Grid expects the columns to have a property 'schema' defined for proper sorting
* this schema as its own types as can be check out in the docs so we add it here manually
* https://eui.elastic.co/#/tabular-content/data-grid-schema-columns
*/
const euiColumnFactory = (
column: EuiDataGridColumn,
browserFields: BrowserFields
columnId: string,
browserFields: BrowserFields,
defaultColumns: EuiDataGridColumn[]
): EuiDataGridColumn => {
const browserFieldsProps = getBrowserFieldProps(column.id, browserFields);
const defaultColumn = getColumnByColumnId(defaultColumns, columnId);
const column = defaultColumn ? defaultColumn : { id: columnId };

const browserFieldsProps = getBrowserFieldProps(columnId, browserFields);
return {
...column,
schema: fieldTypeToDataGridColumnTypeMapper(browserFieldsProps.type),
};
};

/**
* Searches in browser fields object for a specific field
*/
const getBrowserFieldProps = (
columnId: string,
browserFields: BrowserFields
): Partial<BrowserField> => {
for (const [, categoryDescriptor] of Object.entries(browserFields)) {
if (!categoryDescriptor.fields) {
continue;
}

for (const [fieldName, fieldDescriptor] of Object.entries(categoryDescriptor.fields)) {
if (fieldName === columnId) {
return fieldDescriptor;
}
}
const notFoundSpecs = { type: 'string' };

if (!browserFields || Object.keys(browserFields).length === 0) {
return notFoundSpecs;
}

const category = getFieldCategoryFromColumnId(columnId);
if (!browserFields[category]) {
return notFoundSpecs;
}

const categorySpecs = browserFields[category].fields;
if (!categorySpecs) {
return notFoundSpecs;
}
return { type: 'string' };

const fieldSpecs = categorySpecs[columnId];
return fieldSpecs ? fieldSpecs : notFoundSpecs;
};

const isPopulatedColumn = (column: EuiDataGridColumn) => Boolean(column.schema);

/**
* @param columns Columns to be considered in the alerts table
* @param browserFields constant object with all field capabilities
* @returns columns but with the info needed by the data grid to work as expected, e.g sorting
*/
const populateColumns = (
columns: EuiDataGridColumn[],
browserFields: BrowserFields
browserFields: BrowserFields,
defaultColumns: EuiDataGridColumn[]
): EuiDataGridColumn[] => {
return columns.map((column: EuiDataGridColumn) => {
return euiColumnFactory(column, browserFields);
return isPopulatedColumn(column)
? column
: euiColumnFactory(column.id, browserFields, defaultColumns);
});
};

Expand Down Expand Up @@ -128,10 +150,10 @@ export const useColumns = ({
useEffect(() => {
if (isBrowserFieldDataLoading !== false || isColumnsPopulated) return;

const populatedColumns = populateColumns(columns, browserFields);
const populatedColumns = populateColumns(columns, browserFields, defaultColumns);
setColumnsPopulated(true);
setColumns(populatedColumns);
}, [browserFields, columns, isBrowserFieldDataLoading, isColumnsPopulated]);
}, [browserFields, columns, defaultColumns, isBrowserFieldDataLoading, isColumnsPopulated]);

const setColumnsAndSave = useCallback(
(newColumns: EuiDataGridColumn[]) => {
Expand All @@ -156,15 +178,12 @@ export const useColumns = ({

const onToggleColumn = useCallback(
(columnId: string): void => {
const newColumnIds = toggleColumn({
columnId,
columnIds: getColumnIds(columns),
defaultColumns,
});
const column = euiColumnFactory(columnId, browserFields, defaultColumns);

const newColumns = newColumnIds.map((_columnId: string) => {
const column = getColumnByColumnId(defaultColumns, _columnId);
return euiColumnFactory(column ? column : { id: _columnId }, browserFields);
const newColumns = toggleColumn({
column,
columns,
defaultColumns,
});

setColumnsAndSave(newColumns);
Expand All @@ -173,7 +192,7 @@ export const useColumns = ({
);

const onResetColumns = useCallback(() => {
const populatedDefaultColumns = populateColumns(defaultColumns, browserFields);
const populatedDefaultColumns = populateColumns(defaultColumns, browserFields, defaultColumns);
setColumnsAndSave(populatedDefaultColumns);
}, [browserFields, defaultColumns, setColumnsAndSave]);

Expand Down

0 comments on commit 76b2624

Please sign in to comment.