Skip to content

Commit

Permalink
fix regression and keep sorting consistent with log rate analysis for…
Browse files Browse the repository at this point in the history
… the contextual insight for observability
  • Loading branch information
alvarezmelissa87 committed Oct 1, 2024
1 parent c034dc5 commit 559451f
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 35 deletions.
3 changes: 3 additions & 0 deletions x-pack/packages/ml/agg_utils/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,9 @@ export interface SignificantItem extends FieldValuePair {

/** Indicates if the significant item is unique within a group. */
unique?: boolean;

/** Calculates a numerical value based on bg_count and doc_count for which to sort log rate change */
logRateChangeSort?: number;
}

interface SignificantItemHistogramItemBase {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
*/

import type { FC } from 'react';
import React, { useEffect, useMemo } from 'react';
import { isEqual } from 'lodash';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { orderBy, isEqual } from 'lodash';
import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';

import { useEuiBackgroundColor, EuiInMemoryTable } from '@elastic/eui';
import type { EuiTableSortingType } from '@elastic/eui';
import { useEuiBackgroundColor, EuiBasicTable } from '@elastic/eui';

import type { SignificantItem } from '@kbn/ml-agg-utils';
import { useTableState } from '@kbn/ml-in-memory-table';
import {
setPinnedSignificantItem,
setSelectedSignificantItem,
Expand Down Expand Up @@ -51,7 +51,14 @@ export const LogRateAnalysisResultsTable: FC<LogRateAnalysisResultsTableProps> =
const euiTheme = useEuiTheme();
const primaryBackgroundColor = useEuiBackgroundColor('primary');

const allSignificantItems = useAppSelector((s) => s.logRateAnalysisResults.significantItems);
const allItems = useAppSelector((s) => s.logRateAnalysisResults.significantItems);

const allSignificantItems = useMemo(() => {
return allItems.map((item) => ({
...item,
logRateChangeSort: item.bg_count > 0 ? item.doc_count / item.bg_count : item.doc_count,
}));
}, [allItems]);

const significantItems = useMemo(() => {
if (!groupFilter) {
Expand Down Expand Up @@ -85,16 +92,13 @@ export const LogRateAnalysisResultsTable: FC<LogRateAnalysisResultsTableProps> =
);

const dispatch = useAppDispatch();

const { onTableChange, pagination, sorting } = useTableState<SignificantItem>(
significantItems ?? [],
zeroDocsFallback ? DEFAULT_SORT_FIELD_ZERO_DOCS_FALLBACK : DEFAULT_SORT_FIELD,
zeroDocsFallback ? DEFAULT_SORT_DIRECTION_ZERO_DOCS_FALLBACK : DEFAULT_SORT_DIRECTION,
{
pageIndex: 0,
pageSize: 10,
pageSizeOptions: PAGINATION_SIZE_OPTIONS,
}
const [pageIndex, setPageIndex] = useState(0);
const [pageSize, setPageSize] = useState(10);
const [sortField, setSortField] = useState<keyof SignificantItem>(
zeroDocsFallback ? DEFAULT_SORT_FIELD_ZERO_DOCS_FALLBACK : DEFAULT_SORT_FIELD
);
const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>(
zeroDocsFallback ? DEFAULT_SORT_DIRECTION_ZERO_DOCS_FALLBACK : DEFAULT_SORT_DIRECTION
);

const columns = useColumns(
Expand All @@ -106,26 +110,83 @@ export const LogRateAnalysisResultsTable: FC<LogRateAnalysisResultsTableProps> =
groupFilter !== undefined
);

const onChange = useCallback((tableSettings: any) => {
if (tableSettings.page) {
const { index, size } = tableSettings.page;
setPageIndex(index);
setPageSize(size);
}

if (tableSettings.sort) {
const { field, direction } = tableSettings.sort;
setSortField(field);
setSortDirection(direction);
}
}, []);

const { pagination, pageOfItems, sorting } = useMemo(() => {
const pageStart = pageIndex * pageSize;
const itemCount = significantItems?.length ?? 0;

let items: SignificantItem[] = significantItems ?? [];
// console.log('--- SORT FIELD ---', sortField.props.children[0]);

const sortIteratees = [
(item: SignificantItem) => {
if (item && typeof item[sortField] === 'string') {
// @ts-ignore Object is possibly null or undefined
return item[sortField].toLowerCase();
}
return item[sortField];
},
];
const sortDirections = [sortDirection];

// Only if the table is sorted by p-value, add a secondary sort by doc count.
if (sortField === 'pValue') {
sortIteratees.push((item: SignificantItem) => item.doc_count);
sortDirections.push(sortDirection);
}

items = orderBy(significantItems, sortIteratees, sortDirections);

return {
pageOfItems: items.slice(pageStart, pageStart + pageSize),
pagination: {
pageIndex,
pageSize,
totalItemCount: itemCount,
pageSizeOptions: PAGINATION_SIZE_OPTIONS,
},
sorting: {
sort: {
field: sortField,
direction: sortDirection,
},
},
};
}, [pageIndex, pageSize, sortField, sortDirection, significantItems]);

useEffect(() => {
// If no row is hovered or pinned or the user switched to a new page,
// fall back to set the first row into a hovered state to make the
// main document count chart show a comparison view by default.
if (
(selectedSignificantItem === null ||
!significantItems.some((item) => isEqual(item, selectedSignificantItem))) &&
!pageOfItems.some((item) => isEqual(item, selectedSignificantItem))) &&
pinnedSignificantItem === null &&
significantItems.length > 0 &&
pageOfItems.length > 0 &&
selectedGroup === null &&
pinnedGroup === null
) {
dispatch(setSelectedSignificantItem(significantItems[0]));
dispatch(setSelectedSignificantItem(pageOfItems[0]));
}

// If a user switched pages and a pinned row is no longer visible
// on the current page, set the status of pinned rows back to `null`.
if (
pinnedSignificantItem !== null &&
!significantItems.some((item) => isEqual(item, pinnedSignificantItem)) &&
!pageOfItems.some((item) => isEqual(item, pinnedSignificantItem)) &&
selectedGroup === null &&
pinnedGroup === null
) {
Expand All @@ -135,7 +196,7 @@ export const LogRateAnalysisResultsTable: FC<LogRateAnalysisResultsTableProps> =
dispatch,
selectedGroup,
selectedSignificantItem,
significantItems,
pageOfItems,
pinnedGroup,
pinnedSignificantItem,
]);
Expand Down Expand Up @@ -185,15 +246,15 @@ export const LogRateAnalysisResultsTable: FC<LogRateAnalysisResultsTableProps> =
// running the analysis and will hide this table.

return (
<EuiInMemoryTable<SignificantItem>
<EuiBasicTable
data-test-subj="aiopsLogRateAnalysisResultsTable"
compressed
items={significantItems}
items={pageOfItems}
columns={columns}
pagination={pagination}
sorting={sorting}
pagination={pagination.totalItemCount > pagination.pageSize ? pagination : undefined}
sorting={sorting as EuiTableSortingType<SignificantItem>}
loading={false}
onChange={onTableChange}
onChange={onChange}
rowProps={(significantItem) => {
return {
'data-test-subj': `aiopsLogRateAnalysisResultsTableRow row-${significantItem.fieldName}-${significantItem.fieldValue}`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -397,13 +397,14 @@ export const useColumns = (
['Impact']: {
'data-test-subj': 'aiopsLogRateAnalysisResultsTableColumnImpact',
width: '8%',
field: 'pValue',
name: isGroupsTable ? GroupImpactColumnName : ImpactColumnName, // content={isGroupsTable ? groupImpactMessage : impactMessage}
render: ({ pValue }: SignificantItem) => {
render: (_, { pValue }: SignificantItem) => {
if (typeof pValue !== 'number') return NOT_AVAILABLE;
const label = getFailedTransactionsCorrelationImpactLabel(pValue);
return label ? <EuiBadge color={label.color}>{label.impact}</EuiBadge> : null;
},
sortable: ({ pValue }) => pValue,
sortable: true,
valign: 'middle',
},
['Baseline rate']: {
Expand Down Expand Up @@ -494,15 +495,10 @@ export const useColumns = (
},
['Log rate change']: {
'data-test-subj': 'aiopsLogRateAnalysisResultsTableColumnLogRateChange',
field: 'logRateChangeSort',
name: LogRateColumnName,
sortable: isGroupsTable
? undefined
: ({ doc_count: docCount, bg_count: bgCount }: SignificantItem) => {
if (logRateChangeNotAvailable) return NOT_AVAILABLE;
const logRateChange = getLogRateChangeValues(docCount, bgCount);
return logRateChange.factor;
},
render: ({ doc_count: docCount, bg_count: bgCount }: SignificantItem) => {
sortable: isGroupsTable ? false : true,
render: (_, { doc_count: docCount, bg_count: bgCount }: SignificantItem) => {
if (logRateChangeNotAvailable) return NOT_AVAILABLE;
const logRateChange = getLogRateChangeValues(docCount, bgCount);

Expand Down

0 comments on commit 559451f

Please sign in to comment.