Skip to content

Commit

Permalink
[aiops] Adds mini histogram to grouped table.
Browse files Browse the repository at this point in the history
  • Loading branch information
walterra committed Sep 20, 2022
1 parent 33c6f4b commit f63cb57
Show file tree
Hide file tree
Showing 9 changed files with 164 additions and 18 deletions.
1 change: 1 addition & 0 deletions x-pack/packages/ml/agg_utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export type {
AggCardinality,
ChangePoint,
ChangePointGroup,
ChangePointGroupHistogram,
ChangePointHistogram,
ChangePointHistogramItem,
HistogramField,
Expand Down
10 changes: 10 additions & 0 deletions x-pack/packages/ml/agg_utils/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,14 @@ export interface ChangePointHistogram extends FieldValuePair {
histogram: ChangePointHistogramItem[];
}

/**
* Change point histogram data for a group of field/value pairs.
*/
export interface ChangePointGroupHistogram {
id: string;
histogram: ChangePointHistogramItem[];
}

interface ChangePointGroupItem extends FieldValuePair {
duplicate?: boolean;
}
Expand All @@ -95,6 +103,8 @@ interface ChangePointGroupItem extends FieldValuePair {
* Tree leaves
*/
export interface ChangePointGroup {
id: string;
group: ChangePointGroupItem[];
docCount: number;
histogram?: ChangePointHistogramItem[];
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,18 @@
* 2.0.
*/

import type { ChangePoint, ChangePointHistogram, ChangePointGroup } from '@kbn/ml-agg-utils';
import type {
ChangePoint,
ChangePointHistogram,
ChangePointGroup,
ChangePointGroupHistogram,
} from '@kbn/ml-agg-utils';

export const API_ACTION_NAME = {
ADD_CHANGE_POINTS: 'add_change_points',
ADD_CHANGE_POINTS_HISTOGRAM: 'add_change_points_histogram',
ADD_CHANGE_POINTS_GROUP: 'add_change_point_group',
ADD_CHANGE_POINTS_GROUP_HISTOGRAM: 'add_change_point_group_histogram',
ADD_ERROR: 'add_error',
RESET: 'reset',
UPDATE_LOADING_STATE: 'update_loading_state',
Expand Down Expand Up @@ -57,6 +63,20 @@ export function addChangePointsGroupAction(payload: ApiActionAddChangePointsGrou
};
}

interface ApiActionAddChangePointsGroupHistogram {
type: typeof API_ACTION_NAME.ADD_CHANGE_POINTS_GROUP_HISTOGRAM;
payload: ChangePointGroupHistogram[];
}

export function addChangePointsGroupHistogramAction(
payload: ApiActionAddChangePointsGroupHistogram['payload']
): ApiActionAddChangePointsGroupHistogram {
return {
type: API_ACTION_NAME.ADD_CHANGE_POINTS_GROUP_HISTOGRAM,
payload,
};
}

interface ApiActionAddError {
type: typeof API_ACTION_NAME.ADD_ERROR;
payload: string;
Expand Down Expand Up @@ -99,6 +119,7 @@ export type AiopsExplainLogRateSpikesApiAction =
| ApiActionAddChangePoints
| ApiActionAddChangePointsGroup
| ApiActionAddChangePointsHistogram
| ApiActionAddChangePointsGroupHistogram
| ApiActionAddError
| ApiActionReset
| ApiActionUpdateLoadingState;
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
export {
addChangePointsAction,
addChangePointsGroupAction,
addChangePointsGroupHistogramAction,
addChangePointsHistogramAction,
addErrorAction,
resetAction,
Expand Down
9 changes: 9 additions & 0 deletions x-pack/plugins/aiops/common/api/stream_reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@ export function streamReducer(
return { ...state, changePoints };
case API_ACTION_NAME.ADD_CHANGE_POINTS_GROUP:
return { ...state, changePointsGroups: action.payload };
case API_ACTION_NAME.ADD_CHANGE_POINTS_GROUP_HISTOGRAM:
const changePointsGroups = state.changePointsGroups.map((cpg) => {
const cpHistogram = action.payload.find((h) => h.id === cpg.id);
if (cpHistogram) {
cpg.histogram = cpHistogram.histogram;
}
return cpg;
});
return { ...state, changePointsGroups };
case API_ACTION_NAME.ADD_ERROR:
return { ...state, errors: [...state.errors, action.payload] };
case API_ACTION_NAME.RESET:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ export const ExplainLogRateSpikesAnalysis: FC<ExplainLogRateSpikesAnalysisProps>
}, []);

const groupTableItems = useMemo(() => {
const tableItems = data.changePointsGroups.map(({ group, docCount }, index) => {
const tableItems = data.changePointsGroups.map(({ group, docCount, histogram }, index) => {
const sortedGroup = group.sort((a, b) =>
a.fieldName > b.fieldName ? 1 : b.fieldName > a.fieldName ? -1 : 0
);
Expand All @@ -145,6 +145,7 @@ export const ExplainLogRateSpikesAnalysis: FC<ExplainLogRateSpikesAnalysisProps>
docCount,
group: dedupedGroup,
repeatedValues,
histogram,
};
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,26 @@ import {
EuiBasicTable,
EuiBasicTableColumn,
EuiButtonIcon,
EuiIcon,
EuiScreenReaderOnly,
EuiSpacer,
EuiTableSortingType,
EuiToolTip,
RIGHT_ALIGNMENT,
} from '@elastic/eui';

import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import type { ChangePoint } from '@kbn/ml-agg-utils';

import { useEuiTheme } from '../../hooks/use_eui_theme';

import { MiniHistogram } from '../mini_histogram';

import { SpikeAnalysisTableExpandedRow } from './spike_analysis_table_expanded_row';

const NARROW_COLUMN_WIDTH = '120px';

const PAGINATION_SIZE_OPTIONS = [5, 10, 20, 50];
const DEFAULT_SORT_FIELD = 'docCount';
const DEFAULT_SORT_DIRECTION = 'desc';
Expand All @@ -32,6 +41,7 @@ interface GroupTableItem {
docCount: number;
group: Record<string, any>;
repeatedValues: Record<string, any>;
histogram: ChangePoint['histogram'];
}

interface SpikeAnalysisTableProps {
Expand Down Expand Up @@ -170,6 +180,39 @@ export const SpikeAnalysisGroupsTable: FC<SpikeAnalysisTableProps> = ({
sortable: false,
textOnly: true,
},
{
'data-test-subj': 'aiopsSpikeAnalysisTableColumnLogRate',
width: NARROW_COLUMN_WIDTH,
field: 'pValue',
name: (
<EuiToolTip
position="top"
content={i18n.translate(
'xpack.aiops.correlations.failedTransactions.correlationsTable.logRateColumnTooltip',
{
defaultMessage:
'A visual representation of the impact of the field on the message rate difference',
}
)}
>
<>
<FormattedMessage
id="xpack.aiops.correlations.failedTransactions.correlationsTable.logRateLabel"
defaultMessage="Log rate"
/>
<EuiIcon size="s" color="subdued" type="questionInCircle" className="eui-alignTop" />
</>
</EuiToolTip>
),
render: (_, { histogram, id }) => (
<MiniHistogram
chartData={histogram}
isLoading={loading && histogram === undefined}
label="Group x"
/>
),
sortable: false,
},
{
'data-test-subj': 'aiopsSpikeAnalysisGroupsTableColumnDocCount',
field: 'docCount',
Expand Down
84 changes: 70 additions & 14 deletions x-pack/plugins/aiops/server/routes/explain_log_rate_spikes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { fetchHistogramsForFields } from '@kbn/ml-agg-utils';
import {
addChangePointsAction,
addChangePointsGroupAction,
addChangePointsGroupHistogramAction,
addChangePointsHistogramAction,
aiopsExplainLogRateSpikesSchema,
addErrorAction,
Expand Down Expand Up @@ -210,6 +211,21 @@ export const defineExplainLogRateSpikesRoute = (
return;
}

const histogramFields: [NumericHistogramField] = [
{ fieldName: request.body.timeFieldName, type: KBN_FIELD_TYPES.DATE },
];

const [overallTimeSeries] = (await fetchHistogramsForFields(
client,
request.body.index,
{ match_all: {} },
// fields
histogramFields,
// samplerShardSize
-1,
undefined
)) as [NumericChartData];

if (groupingEnabled) {
const { fields, df } = await fetchFrequentItems(
client,
Expand All @@ -236,22 +252,62 @@ export const defineExplainLogRateSpikesRoute = (
const changePointsGroups = getSimpleHierarchicalTreeLeaves(root, []);

push(addChangePointsGroupAction(markDuplicates(changePointsGroups)));
}

const histogramFields: [NumericHistogramField] = [
{ fieldName: request.body.timeFieldName, type: KBN_FIELD_TYPES.DATE },
];
if (changePointsGroups) {
await asyncForEach(changePointsGroups, async (cpg, index) => {
const histogramQuery = {
bool: {
filter: cpg.group.map((d) => ({
term: { [d.fieldName]: d.fieldValue },
})),
},
};

const [overallTimeSeries] = (await fetchHistogramsForFields(
client,
request.body.index,
{ match_all: {} },
// fields
histogramFields,
// samplerShardSize
-1,
undefined
)) as [NumericChartData];
const [cpgTimeSeries] = (await fetchHistogramsForFields(
client,
request.body.index,
histogramQuery,
// fields
[
{
fieldName: request.body.timeFieldName,
type: KBN_FIELD_TYPES.DATE,
interval: overallTimeSeries.interval,
min: overallTimeSeries.stats[0],
max: overallTimeSeries.stats[1],
},
],
// samplerShardSize
-1,
undefined
)) as [NumericChartData];

const histogram =
overallTimeSeries.data.map((o, i) => {
const current = cpgTimeSeries.data.find(
(d1) => d1.key_as_string === o.key_as_string
) ?? {
doc_count: 0,
};
return {
key: o.key,
key_as_string: o.key_as_string ?? '',
doc_count_change_point: current.doc_count,
doc_count_overall: Math.max(0, o.doc_count - current.doc_count),
};
}) ?? [];

push(
addChangePointsGroupHistogramAction([
{
id: cpg.id,
histogram,
},
])
);
});
}
}

// time series filtered by fields
if (changePoints) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
// import { omit, uniq } from 'lodash';

import type { ChangePointGroup, FieldValuePair } from '@kbn/ml-agg-utils';
import { stringHash } from '@kbn/ml-string-hash';

import type { ItemsetResult } from './fetch_frequent_items';

Expand Down Expand Up @@ -224,9 +225,12 @@ export function getSimpleHierarchicalTreeLeaves(
leaves: ChangePointGroup[],
level = 1
) {
// console.log(`${'-'.repeat(level)} ${tree.name} ${tree.children.length}`);
if (tree.children.length === 0) {
leaves.push({ group: tree.set, docCount: tree.docCount });
leaves.push({
id: `${stringHash(JSON.stringify(tree.set))}`,
group: tree.set,
docCount: tree.docCount,
});
} else {
for (const child of tree.children) {
const newLeaves = getSimpleHierarchicalTreeLeaves(child, [], level + 1);
Expand Down

0 comments on commit f63cb57

Please sign in to comment.