Skip to content

Commit

Permalink
[ML] Explain Log Rate Spikes: Histogram fixes. (#139933) (#140260)
Browse files Browse the repository at this point in the history
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.

(cherry picked from commit 1ff209a)

Co-authored-by: Walter Rafelsberger <walter@elastic.co>
  • Loading branch information
kibanamachine and walterra authored Sep 8, 2022
1 parent c938dd9 commit ef51737
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import moment from 'moment';

import {
Axis,
BarSeries,
BrushEndListener,
Chart,
ElementClickListener,
HistogramBarSeries,
Position,
ScaleType,
Settings,
Expand Down Expand Up @@ -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 }];
Expand Down Expand Up @@ -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 }) => {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 }) => {
Expand All @@ -336,52 +334,56 @@ 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}
yScaleType={ScaleType.Linear}
xAccessor="time"
yAccessors={['value']}
data={adjustedChartPoints}
stackAccessors={[0]}
timeZone={timeZone}
yNice
/>
{chartPointsSplit && (
<BarSeries
<HistogramBarSeries
id={`${SPEC_ID}_split`}
name={splitSeriesName}
xScaleType={ScaleType.Time}
yScaleType={ScaleType.Linear}
xAccessor="time"
yAccessors={['value']}
data={adjustedChartPointsSplit}
stackAccessors={[0]}
timeZone={timeZone}
color={['orange']}
yNice
/>
)}
{windowParameters && (
<>
<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}
/>
</>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -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) {
Expand Down
4 changes: 2 additions & 2 deletions x-pack/test/functional/apps/aiops/explain_log_rate_spikes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion x-pack/test/functional/apps/aiops/test_data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
},
],
Expand Down

0 comments on commit ef51737

Please sign in to comment.