diff --git a/x-pack/packages/ml/agg_utils/src/index.ts b/x-pack/packages/ml/agg_utils/src/index.ts index 62ff0a4564a54..ecab763d3e12e 100644 --- a/x-pack/packages/ml/agg_utils/src/index.ts +++ b/x-pack/packages/ml/agg_utils/src/index.ts @@ -16,6 +16,7 @@ export type { AggCardinality, ChangePoint, ChangePointHistogram, + ChangePointHistogramItem, HistogramField, NumericColumnStats, NumericColumnStatsMap, diff --git a/x-pack/packages/ml/agg_utils/src/types.ts b/x-pack/packages/ml/agg_utils/src/types.ts index 82be50b4adcf9..d5e7f9a122315 100644 --- a/x-pack/packages/ml/agg_utils/src/types.ts +++ b/x-pack/packages/ml/agg_utils/src/types.ts @@ -64,7 +64,7 @@ export interface ChangePoint extends FieldValuePair { histogram?: ChangePointHistogramItem[]; } -interface ChangePointHistogramItem { +export interface ChangePointHistogramItem { doc_count_overall: number; doc_count_change_point: number; key: number; diff --git a/x-pack/plugins/aiops/public/components/mini_histogram/index.ts b/x-pack/plugins/aiops/public/components/mini_histogram/index.ts new file mode 100644 index 0000000000000..d3a7d590d80dc --- /dev/null +++ b/x-pack/plugins/aiops/public/components/mini_histogram/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { MiniHistogram } from './mini_histogram'; diff --git a/x-pack/plugins/aiops/public/components/mini_histogram/mini_histogram.tsx b/x-pack/plugins/aiops/public/components/mini_histogram/mini_histogram.tsx new file mode 100644 index 0000000000000..2e5e6d23f46f9 --- /dev/null +++ b/x-pack/plugins/aiops/public/components/mini_histogram/mini_histogram.tsx @@ -0,0 +1,71 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FC } from 'react'; + +import { Chart, BarSeries, PartialTheme, ScaleType, Settings } from '@elastic/charts'; + +import type { ChangePointHistogramItem } from '@kbn/ml-agg-utils'; + +interface MiniHistogramProps { + chartData: ChangePointHistogramItem[]; + label: string; +} + +export const MiniHistogram: FC<MiniHistogramProps> = ({ chartData, label }) => { + const theme: PartialTheme = { + chartMargins: { + left: 0, + right: 0, + top: 0, + bottom: 0, + }, + chartPaddings: { + left: 0, + right: 0, + top: 0, + bottom: 0, + }, + scales: { + barsPadding: 0.1, + }, + }; + + return ( + <div + style={{ + width: '80px', + height: '24px', + margin: '0px', + }} + > + <Chart> + <Settings theme={theme} showLegend={false} /> + <BarSeries + id="Other" + xScaleType={ScaleType.Time} + yScaleType={ScaleType.Linear} + xAccessor={'key'} + yAccessors={['doc_count_overall']} + data={chartData} + stackAccessors={[0]} + // color={['lightblue']} + /> + <BarSeries + id={`${label}`} + xScaleType={ScaleType.Time} + yScaleType={ScaleType.Linear} + xAccessor={'key'} + yAccessors={['doc_count_change_point']} + data={chartData} + stackAccessors={[0]} + color={['orange']} + /> + </Chart> + </div> + ); +}; diff --git a/x-pack/plugins/aiops/public/components/spike_analysis_table/spike_analysis_table.tsx b/x-pack/plugins/aiops/public/components/spike_analysis_table/spike_analysis_table.tsx index 7578a979fa49c..8b6e8a3dd6219 100644 --- a/x-pack/plugins/aiops/public/components/spike_analysis_table/spike_analysis_table.tsx +++ b/x-pack/plugins/aiops/public/components/spike_analysis_table/spike_analysis_table.tsx @@ -6,10 +6,12 @@ */ import React, { FC, useCallback, useMemo, useState } from 'react'; -import { EuiBadge, EuiBasicTable, EuiBasicTableColumn, RIGHT_ALIGNMENT } from '@elastic/eui'; +import { EuiBadge, EuiBasicTable, EuiBasicTableColumn } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import type { ChangePoint } from '@kbn/ml-agg-utils'; -import { ImpactBar } from './impact_bar'; + +import { MiniHistogram } from '../mini_histogram'; + import { getFailedTransactionsCorrelationImpactLabel } from './get_failed_transactions_correlation_impact_label'; const PAGINATION_SIZE_OPTIONS = [5, 10, 20, 50]; @@ -29,25 +31,45 @@ export const SpikeAnalysisTable: FC<Props> = ({ changePointData, error, loading const columns: Array<EuiBasicTableColumn<ChangePoint>> = [ { - field: 'score', + field: 'fieldName', + name: i18n.translate( + 'xpack.aiops.correlations.failedTransactions.correlationsTable.fieldNameLabel', + { defaultMessage: 'Field name' } + ), + sortable: true, + }, + { + field: 'fieldValue', + name: i18n.translate( + 'xpack.aiops.correlations.failedTransactions.correlationsTable.fieldValueLabel', + { defaultMessage: 'Field value' } + ), + render: (_, { fieldValue }) => String(fieldValue).slice(0, 50), + sortable: true, + }, + { + field: 'pValue', name: ( <> {i18n.translate( - 'xpack.aiops.correlations.failedTransactions.correlationsTable.pValueLabel', + 'xpack.aiops.correlations.failedTransactions.correlationsTable.logRateLabel', { - defaultMessage: 'Score', + defaultMessage: 'Log rate', } )} </> ), - align: RIGHT_ALIGNMENT, - render: (_, { score }) => { - return ( - <> - <ImpactBar size="m" value={Number(score.toFixed(2))} label={score.toFixed(2)} /> - </> - ); + render: (_, { histogram, fieldName, fieldValue }) => { + return histogram ? ( + <MiniHistogram chartData={histogram} label={`${fieldName}:${fieldValue}`} /> + ) : null; }, + sortable: false, + }, + { + field: 'pValue', + name: 'p-value', + render: (pValue: number) => pValue.toPrecision(3), sortable: true, }, { @@ -68,29 +90,6 @@ export const SpikeAnalysisTable: FC<Props> = ({ changePointData, error, loading }, sortable: true, }, - { - field: 'fieldName', - name: i18n.translate( - 'xpack.aiops.correlations.failedTransactions.correlationsTable.fieldNameLabel', - { defaultMessage: 'Field name' } - ), - sortable: true, - }, - { - field: 'fieldValue', - name: i18n.translate( - 'xpack.aiops.correlations.failedTransactions.correlationsTable.fieldValueLabel', - { defaultMessage: 'Field value' } - ), - render: (_, { fieldValue }) => String(fieldValue).slice(0, 50), - sortable: true, - }, - { - field: 'pValue', - name: 'p-value', - render: (pValue: number) => pValue.toPrecision(3), - sortable: true, - }, ]; const onChange = useCallback((tableSettings) => { @@ -119,7 +118,10 @@ export const SpikeAnalysisTable: FC<Props> = ({ changePointData, error, loading <EuiBasicTable compressed columns={columns} - items={pageOfItems ?? []} + // Temporary default sorting by ascending pValue until we add native table sorting + items={pageOfItems.sort((a, b) => { + return (a?.pValue ?? 1) - (b?.pValue ?? 0); + })} noItemsMessage={noDataText} onChange={onChange} pagination={pagination} diff --git a/x-pack/plugins/aiops/server/routes/explain_log_rate_spikes.ts b/x-pack/plugins/aiops/server/routes/explain_log_rate_spikes.ts index 34cdb3c51dc22..65ed2065d7ade 100644 --- a/x-pack/plugins/aiops/server/routes/explain_log_rate_spikes.ts +++ b/x-pack/plugins/aiops/server/routes/explain_log_rate_spikes.ts @@ -156,6 +156,19 @@ export const defineExplainLogRateSpikesRoute = ( } } + if (changePoints?.length === 0) { + push( + updateLoadingStateAction({ + ccsWarning: false, + loaded: 1, + loadingState: `Done.`, + }) + ); + + end(); + return; + } + const histogramFields: [NumericHistogramField] = [ { fieldName: request.body.timeFieldName, type: KBN_FIELD_TYPES.DATE }, ];