Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ML] Explain Log Rate Spikes: Support table hovering with main chart sync on group level #141099

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 21 additions & 5 deletions x-pack/plugins/aiops/public/application/utils/query_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { Query } from '@kbn/es-query';
import { isPopulatedObject } from '@kbn/ml-is-populated-object';
import type { ChangePoint } from '@kbn/ml-agg-utils';
import type { GroupTableItem } from '../../components/spike_analysis_table/spike_analysis_table_groups';

/*
* Contains utility functions for building and processing queries.
Expand All @@ -29,7 +30,8 @@ export function buildBaseFilterCriteria(
latestMs?: number,
query?: Query['query'],
selectedChangePoint?: ChangePoint,
includeSelectedChangePoint = true
includeSelectedChangePoint = true,
selectedGroup?: GroupTableItem | null
): estypes.QueryDslQueryContainer[] {
const filterCriteria = [];
if (timeFieldName && earliestMs && latestMs) {
Expand All @@ -47,18 +49,32 @@ export function buildBaseFilterCriteria(
if (query && typeof query === 'object') {
filterCriteria.push(query);
}
const groupFilter = [];

if (selectedChangePoint && includeSelectedChangePoint) {
filterCriteria.push({
term: { [selectedChangePoint.fieldName]: selectedChangePoint.fieldValue },
});
if (selectedGroup) {
for (const fieldName in selectedGroup.group) {
if (selectedGroup.group.hasOwnProperty(fieldName)) {
groupFilter.push({ term: { [fieldName]: selectedGroup.group[fieldName] } });
}
}
}

if (includeSelectedChangePoint) {
if (selectedChangePoint) {
filterCriteria.push({
term: { [selectedChangePoint.fieldName]: selectedChangePoint.fieldValue },
});
} else if (selectedGroup) {
filterCriteria.push(...groupFilter);
}
} else if (selectedChangePoint && !includeSelectedChangePoint) {
filterCriteria.push({
bool: {
must_not: [
{
term: { [selectedChangePoint.fieldName]: selectedChangePoint.fieldValue },
},
...groupFilter,
],
},
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import type { ApiExplainLogRateSpikes } from '../../../common/api';

import { SpikeAnalysisGroupsTable } from '../spike_analysis_table';
import { SpikeAnalysisTable } from '../spike_analysis_table';
import { GroupTableItem } from '../spike_analysis_table/spike_analysis_table_groups';

const groupResultsMessage = i18n.translate(
'xpack.aiops.spikeAnalysisTable.groupedSwitchLabel.groupResults',
Expand All @@ -56,6 +57,7 @@ interface ExplainLogRateSpikesAnalysisProps {
onPinnedChangePoint?: (changePoint: ChangePoint | null) => void;
onSelectedChangePoint?: (changePoint: ChangePoint | null) => void;
selectedChangePoint?: ChangePoint;
onSelectedGroup?: (group: GroupTableItem | null) => void;
}

export const ExplainLogRateSpikesAnalysis: FC<ExplainLogRateSpikesAnalysisProps> = ({
Expand All @@ -67,6 +69,7 @@ export const ExplainLogRateSpikesAnalysis: FC<ExplainLogRateSpikesAnalysisProps>
onPinnedChangePoint,
onSelectedChangePoint,
selectedChangePoint,
onSelectedGroup,
}) => {
const { http } = useAiopsAppContext();
const basePath = http.basePath.get() ?? '';
Expand Down Expand Up @@ -244,6 +247,7 @@ export const ExplainLogRateSpikesAnalysis: FC<ExplainLogRateSpikesAnalysisProps>
onPinnedChangePoint={onPinnedChangePoint}
onSelectedChangePoint={onSelectedChangePoint}
selectedChangePoint={selectedChangePoint}
onSelectedGroup={onSelectedGroup}
dataViewId={dataView.id}
/>
) : null}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import { SearchPanel } from '../search_panel';

import { restorableDefaults } from './explain_log_rate_spikes_app_state';
import { ExplainLogRateSpikesAnalysis } from './explain_log_rate_spikes_analysis';
import type { GroupTableItem } from '../spike_analysis_table/spike_analysis_table_groups';

// TODO port to `@emotion/react` once `useEuiBreakpoint` is available https://github.com/elastic/eui/pull/6057
import './explain_log_rate_spikes_page.scss';
Expand Down Expand Up @@ -94,6 +95,7 @@ export const ExplainLogRateSpikesPage: FC<ExplainLogRateSpikesPageProps> = ({

const [pinnedChangePoint, setPinnedChangePoint] = useState<ChangePoint | null>(null);
const [selectedChangePoint, setSelectedChangePoint] = useState<ChangePoint | null>(null);
const [selectedGroup, setSelectedGroup] = useState<GroupTableItem | null>(null);

// If a row is pinned, still overrule with a potentially hovered row.
const currentSelectedChangePoint = useMemo(() => {
Expand All @@ -116,7 +118,8 @@ export const ExplainLogRateSpikesPage: FC<ExplainLogRateSpikesPageProps> = ({
{ currentDataView: dataView, currentSavedSearch },
aiopsListState,
setGlobalState,
currentSelectedChangePoint
currentSelectedChangePoint,
selectedGroup
);

const { totalCount, documentCountStats, documentCountStatsCompare } = documentStats;
Expand Down Expand Up @@ -167,6 +170,7 @@ export const ExplainLogRateSpikesPage: FC<ExplainLogRateSpikesPageProps> = ({
setWindowParameters(undefined);
setPinnedChangePoint(null);
setSelectedChangePoint(null);
setSelectedGroup(null);
}

return (
Expand Down Expand Up @@ -225,7 +229,9 @@ export const ExplainLogRateSpikesPage: FC<ExplainLogRateSpikesPageProps> = ({
clearSelectionHandler={clearSelection}
documentCountStats={documentCountStats}
documentCountStatsSplit={
currentSelectedChangePoint ? documentCountStatsCompare : undefined
currentSelectedChangePoint || selectedGroup
? documentCountStatsCompare
: undefined
}
totalCount={totalCount}
changePoint={currentSelectedChangePoint}
Expand All @@ -246,6 +252,7 @@ export const ExplainLogRateSpikesPage: FC<ExplainLogRateSpikesPageProps> = ({
onPinnedChangePoint={setPinnedChangePoint}
onSelectedChangePoint={setSelectedChangePoint}
selectedChangePoint={currentSelectedChangePoint}
onSelectedGroup={setSelectedGroup}
/>
)}
{windowParameters === undefined && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { getFailedTransactionsCorrelationImpactLabel } from './get_failed_transa

const NARROW_COLUMN_WIDTH = '120px';
const ACTIONS_COLUMN_WIDTH = '60px';
const NOT_AVAILABLE = '--';

const PAGINATION_SIZE_OPTIONS = [5, 10, 20, 50];
const DEFAULT_SORT_FIELD = 'pValue';
Expand Down Expand Up @@ -169,13 +170,16 @@ export const SpikeAnalysisTable: FC<SpikeAnalysisTableProps> = ({
</>
</EuiToolTip>
),
render: (_, { histogram, fieldName, fieldValue }) => (
<MiniHistogram
chartData={histogram}
isLoading={loading && histogram === undefined}
label={`${fieldName}:${fieldValue}`}
/>
),
render: (_, { histogram, fieldName, fieldValue }) => {
if (!histogram) return NOT_AVAILABLE;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this change necessary? The chartData prop for the MiniHistogram component is optional. Returning like this will also not trigger isLoading for the mini histogram component.

return (
<MiniHistogram
chartData={histogram}
isLoading={loading && histogram === undefined}
label={`${fieldName}:${fieldValue}`}
/>
);
},
sortable: false,
},
{
Expand Down Expand Up @@ -229,6 +233,7 @@ export const SpikeAnalysisTable: FC<SpikeAnalysisTableProps> = ({
</EuiToolTip>
),
render: (_, { pValue }) => {
if (!pValue) return NOT_AVAILABLE;
const label = getFailedTransactionsCorrelationImpactLabel(pValue);
return label ? <EuiBadge color={label.color}>{label.impact}</EuiBadge> : null;
},
Expand Down
Loading