mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[ML] Explain Log Rate Spikes: Histogram fixes. (#139933)
Fixes histogram styling, some alignments with discover chart. - Switch BarSeries to HistogramBarSeries. - Fix too generic IDs. - Align y axis ticks settings with Discover chart. - Fixes horizontal margins. - Fixes x domain to avoid empty buckets at start and end of histogram.
This commit is contained in:
parent
a3d39886de
commit
1ff209a603
4 changed files with 50 additions and 38 deletions
|
@ -10,10 +10,10 @@ import moment from 'moment';
|
|||
|
||||
import {
|
||||
Axis,
|
||||
BarSeries,
|
||||
BrushEndListener,
|
||||
Chart,
|
||||
ElementClickListener,
|
||||
HistogramBarSeries,
|
||||
Position,
|
||||
ScaleType,
|
||||
Settings,
|
||||
|
@ -132,11 +132,6 @@ export const DocumentCountChart: FC<DocumentCountChartProps> = ({
|
|||
// TODO Let user choose between ZOOM and BRUSH mode.
|
||||
const [viewMode] = useState<VIEW_MODE>(VIEW_MODE.BRUSH);
|
||||
|
||||
const xDomain = {
|
||||
min: timeRangeEarliest,
|
||||
max: timeRangeLatest,
|
||||
};
|
||||
|
||||
const adjustedChartPoints = useMemo(() => {
|
||||
// Display empty chart when no data in range
|
||||
if (chartPoints.length < 1) return [{ time: timeRangeEarliest, value: 0 }];
|
||||
|
@ -174,12 +169,16 @@ export const DocumentCountChart: FC<DocumentCountChartProps> = ({
|
|||
}, [chartPointsSplit, timeRangeEarliest, timeRangeLatest, interval]);
|
||||
|
||||
const snapTimestamps = useMemo(() => {
|
||||
return adjustedChartPoints
|
||||
.map((d) => d.time)
|
||||
.filter(function (arg: unknown): arg is number {
|
||||
return typeof arg === 'number';
|
||||
});
|
||||
}, [adjustedChartPoints]);
|
||||
const timestamps: number[] = [];
|
||||
let n = timeRangeEarliest;
|
||||
|
||||
while (n <= timeRangeLatest + interval) {
|
||||
timestamps.push(n);
|
||||
n += interval;
|
||||
}
|
||||
|
||||
return timestamps;
|
||||
}, [timeRangeEarliest, timeRangeLatest, interval]);
|
||||
|
||||
const timefilterUpdateHandler = useCallback(
|
||||
(ranges: { from: number; to: number }) => {
|
||||
|
@ -219,8 +218,8 @@ export const DocumentCountChart: FC<DocumentCountChartProps> = ({
|
|||
) {
|
||||
const wp = getWindowParameters(
|
||||
startRange + interval / 2,
|
||||
xDomain.min,
|
||||
xDomain.max + interval
|
||||
timeRangeEarliest,
|
||||
timeRangeLatest + interval
|
||||
);
|
||||
const wpSnap = getSnappedWindowParameters(wp, snapTimestamps);
|
||||
setOriginalWindowParameters(wpSnap);
|
||||
|
@ -326,7 +325,6 @@ export const DocumentCountChart: FC<DocumentCountChartProps> = ({
|
|||
}}
|
||||
>
|
||||
<Settings
|
||||
xDomain={xDomain}
|
||||
onBrushEnd={viewMode !== VIEW_MODE.BRUSH ? (onBrushEnd as BrushEndListener) : undefined}
|
||||
onElementClick={onElementClick}
|
||||
onProjectionAreaChange={({ projection }) => {
|
||||
|
@ -336,17 +334,21 @@ export const DocumentCountChart: FC<DocumentCountChartProps> = ({
|
|||
theme={chartTheme}
|
||||
baseTheme={chartBaseTheme}
|
||||
debugState={window._echDebugStateFlag ?? false}
|
||||
showLegend={false}
|
||||
showLegendExtra={false}
|
||||
/>
|
||||
<Axis id="aiops-histogram-left-axis" position={Position.Left} ticks={2} integersOnly />
|
||||
<Axis
|
||||
id="bottom"
|
||||
id="aiops-histogram-bottom-axis"
|
||||
position={Position.Bottom}
|
||||
showOverlappingTicks={true}
|
||||
tickFormat={(value) => xAxisFormatter.convert(value)}
|
||||
// temporary fix to reduce horizontal chart margin until fixed in Elastic Charts itself
|
||||
labelFormat={useLegacyTimeAxis ? undefined : () => ''}
|
||||
timeAxisLayerCount={useLegacyTimeAxis ? 0 : 2}
|
||||
style={useLegacyTimeAxis ? {} : MULTILAYER_TIME_AXIS_STYLE}
|
||||
/>
|
||||
<Axis id="left" position={Position.Left} />
|
||||
<BarSeries
|
||||
<HistogramBarSeries
|
||||
id={SPEC_ID}
|
||||
name={chartPointsSplit ? overallSeriesNameWithSplit : overallSeriesName}
|
||||
xScaleType={ScaleType.Time}
|
||||
|
@ -354,11 +356,11 @@ export const DocumentCountChart: FC<DocumentCountChartProps> = ({
|
|||
xAccessor="time"
|
||||
yAccessors={['value']}
|
||||
data={adjustedChartPoints}
|
||||
stackAccessors={[0]}
|
||||
timeZone={timeZone}
|
||||
yNice
|
||||
/>
|
||||
{chartPointsSplit && (
|
||||
<BarSeries
|
||||
<HistogramBarSeries
|
||||
id={`${SPEC_ID}_split`}
|
||||
name={splitSeriesName}
|
||||
xScaleType={ScaleType.Time}
|
||||
|
@ -366,9 +368,9 @@ export const DocumentCountChart: FC<DocumentCountChartProps> = ({
|
|||
xAccessor="time"
|
||||
yAccessors={['value']}
|
||||
data={adjustedChartPointsSplit}
|
||||
stackAccessors={[0]}
|
||||
timeZone={timeZone}
|
||||
color={['orange']}
|
||||
yNice
|
||||
/>
|
||||
)}
|
||||
{windowParameters && (
|
||||
|
@ -376,12 +378,12 @@ export const DocumentCountChart: FC<DocumentCountChartProps> = ({
|
|||
<DualBrushAnnotation
|
||||
id="aiopsBaseline"
|
||||
min={windowParameters.baselineMin}
|
||||
max={windowParameters.baselineMax - interval}
|
||||
max={windowParameters.baselineMax}
|
||||
/>
|
||||
<DualBrushAnnotation
|
||||
id="aiopsDeviation"
|
||||
min={windowParameters.deviationMin}
|
||||
max={windowParameters.deviationMax - interval}
|
||||
max={windowParameters.deviationMax}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
|
|
@ -4,7 +4,9 @@
|
|||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { useEffect, useState, FC } from 'react';
|
||||
import { min, max } from 'd3-array';
|
||||
|
||||
import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
|
||||
|
@ -48,24 +50,32 @@ export const DocumentCountContent: FC<DocumentCountContentProps> = ({
|
|||
setIsBrushCleared(windowParameters === undefined);
|
||||
}, [windowParameters]);
|
||||
|
||||
if (documentCountStats === undefined) {
|
||||
const bucketTimestamps = Object.keys(documentCountStats?.buckets ?? {}).map((time) => +time);
|
||||
const timeRangeEarliest = min(bucketTimestamps);
|
||||
const timeRangeLatest = max(bucketTimestamps);
|
||||
|
||||
if (
|
||||
documentCountStats === undefined ||
|
||||
documentCountStats.buckets === undefined ||
|
||||
timeRangeEarliest === undefined ||
|
||||
timeRangeLatest === undefined
|
||||
) {
|
||||
return totalCount !== undefined ? <TotalCountHeader totalCount={totalCount} /> : null;
|
||||
}
|
||||
|
||||
const { timeRangeEarliest, timeRangeLatest } = documentCountStats;
|
||||
if (timeRangeEarliest === undefined || timeRangeLatest === undefined)
|
||||
return <TotalCountHeader totalCount={totalCount} />;
|
||||
|
||||
let chartPoints: DocumentCountChartPoint[] = [];
|
||||
if (documentCountStats.buckets !== undefined) {
|
||||
const buckets: Record<string, number> = documentCountStats?.buckets;
|
||||
chartPoints = Object.entries(buckets).map(([time, value]) => ({ time: +time, value }));
|
||||
}
|
||||
const chartPoints: DocumentCountChartPoint[] = Object.entries(documentCountStats.buckets).map(
|
||||
([time, value]) => ({
|
||||
time: +time,
|
||||
value,
|
||||
})
|
||||
);
|
||||
|
||||
let chartPointsSplit: DocumentCountChartPoint[] | undefined;
|
||||
if (documentCountStatsSplit?.buckets !== undefined) {
|
||||
const buckets: Record<string, number> = documentCountStatsSplit?.buckets;
|
||||
chartPointsSplit = Object.entries(buckets).map(([time, value]) => ({ time: +time, value }));
|
||||
chartPointsSplit = Object.entries(documentCountStatsSplit?.buckets).map(([time, value]) => ({
|
||||
time: +time,
|
||||
value,
|
||||
}));
|
||||
}
|
||||
|
||||
function brushSelectionUpdate(d: WindowParameters, force: boolean) {
|
||||
|
|
|
@ -85,14 +85,14 @@ export default function ({ getPageObject, getService }: FtrProviderContext) {
|
|||
await aiops.explainLogRateSpikes.adjustBrushHandler(
|
||||
'aiopsBrushDeviation',
|
||||
'handle--e',
|
||||
targetPx
|
||||
targetPx + intervalPx
|
||||
);
|
||||
|
||||
// Adjust the left brush handle
|
||||
await aiops.explainLogRateSpikes.adjustBrushHandler(
|
||||
'aiopsBrushDeviation',
|
||||
'handle--w',
|
||||
targetPx - intervalPx
|
||||
targetPx
|
||||
);
|
||||
|
||||
// Get the new brush selection width for later comparison.
|
||||
|
|
|
@ -19,7 +19,7 @@ export const farequoteDataViewTestData: TestData = {
|
|||
fieldName: 'airline',
|
||||
fieldValue: 'AAL',
|
||||
logRate: 'Chart type:bar chart',
|
||||
pValue: '4.63e-14',
|
||||
pValue: '1.26e-13',
|
||||
impact: 'High',
|
||||
},
|
||||
],
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue