Skip to content

Commit

Permalink
[ML] Explain log rate spikes: Fix brush issues. (elastic#138113) (ela…
Browse files Browse the repository at this point in the history
…stic#138134)

- Fixes overlapping brush badges.
- Adds missing tooltips to brush badges.

(cherry picked from commit 9512635)

Co-authored-by: Walter Rafelsberger <[email protected]>
  • Loading branch information
kibanamachine and walterra authored Aug 4, 2022
1 parent 9e45b6b commit f213348
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,10 @@ export function DualBrush({
const xMax = x(max) ?? 0;
const minExtentPx = Math.round((xMax - xMin) / 100);

const baselineBrush = d3.select('#brush-baseline');
const baselineBrush = d3.select('#aiops-brush-baseline');
const baselineSelection = d3.brushSelection(baselineBrush.node() as SVGGElement);

const deviationBrush = d3.select('#brush-deviation');
const deviationBrush = d3.select('#aiops-brush-deviation');
const deviationSelection = d3.brushSelection(deviationBrush.node() as SVGGElement);

if (!isBrushXSelection(deviationSelection) || !isBrushXSelection(baselineSelection)) {
Expand Down Expand Up @@ -221,7 +221,7 @@ export function DualBrush({
.insert('g', '.brush')
.attr('class', 'brush')
.attr('id', (b: DualBrush) => {
return 'brush-' + b.id;
return 'aiops-brush-' + b.id;
})
.each((brushObject: DualBrush, i, n) => {
const x = d3.scaleLinear().domain([min, max]).rangeRound([0, widthRef.current]);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* 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 { EuiBadge, EuiText, EuiToolTip } from '@elastic/eui';
// @ts-ignore
import { formatDate } from '@elastic/eui/lib/services/format';

const DATE_FORMAT = 'YYYY-MM-DD';
const TIME_FORMAT = 'HH:mm:ss';

interface BrushBadgeProps {
label: string;
marginLeft: number;
timestampFrom: number;
timestampTo: number;
width: number;
}

export const BrushBadge: FC<BrushBadgeProps> = ({
label,
marginLeft,
timestampFrom,
timestampTo,
width,
}) => {
// If "from" and "to" are on the same day, we skip displaying the date twice.
const dateFrom = formatDate(timestampFrom, DATE_FORMAT);
const dateTo = formatDate(timestampTo, DATE_FORMAT);
const timeFrom = formatDate(timestampFrom, TIME_FORMAT);
const timeTo = formatDate(timestampTo, TIME_FORMAT);

return (
<div
css={{
position: 'absolute',
'margin-left': `${marginLeft}px`,
}}
>
<EuiToolTip
content={
<EuiText size="xs">
{dateFrom} {timeFrom} -{' '}
{dateFrom !== dateTo && (
<>
<br />
{dateTo}{' '}
</>
)}
{timeTo}
</EuiText>
}
position="top"
>
<EuiBadge css={{ width, 'text-align': 'center' }}>{label}</EuiBadge>
</EuiToolTip>
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,8 @@ import {
XYChartElementEvent,
XYBrushEvent,
} from '@elastic/charts';
import { EuiBadge } from '@elastic/eui';

import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import { IUiSettingsClient } from '@kbn/core/public';
import { DualBrush, DualBrushAnnotation } from '@kbn/aiops-components';
import { getSnappedWindowParameters, getWindowParameters } from '@kbn/aiops-utils';
Expand All @@ -33,6 +31,8 @@ import type { ChangePoint } from '@kbn/ml-agg-utils';

import { useAiOpsKibana } from '../../../kibana_context';

import { BrushBadge } from './brush_badge';

export interface DocumentCountChartPoint {
time: number | string;
value: number;
Expand All @@ -52,6 +52,9 @@ interface DocumentCountChartProps {

const SPEC_ID = 'document_count';

const BADGE_HEIGHT = 20;
const BADGE_WIDTH = 75;

enum VIEW_MODE {
ZOOM = 'zoom',
BRUSH = 'brush',
Expand All @@ -67,6 +70,19 @@ function getTimezone(uiSettings: IUiSettingsClient) {
}
}

function getBaselineBadgeOverflow(
windowParametersAsPixels: WindowParameters,
baselineBadgeWidth: number
) {
const { baselineMin, baselineMax, deviationMin } = windowParametersAsPixels;

const baselineBrushWidth = baselineMax - baselineMin;
const baselineBadgeActualMax = baselineMin + baselineBadgeWidth;
return deviationMin < baselineBadgeActualMax
? Math.max(0, baselineBadgeWidth - baselineBrushWidth)
: 0;
}

export const DocumentCountChart: FC<DocumentCountChartProps> = ({
brushSelectionUpdateHandler,
width,
Expand Down Expand Up @@ -239,47 +255,45 @@ export const DocumentCountChart: FC<DocumentCountChartProps> = ({
}, [viewMode]);

const isBrushVisible =
originalWindowParameters && mlBrushMarginLeft && mlBrushWidth && mlBrushWidth > 0;
originalWindowParameters &&
windowParameters &&
mlBrushMarginLeft &&
mlBrushWidth &&
mlBrushWidth > 0;

// Avoid overlap of brush badges when the brushes are quite narrow.
const baselineBadgeOverflow = windowParametersAsPixels
? getBaselineBadgeOverflow(windowParametersAsPixels, BADGE_WIDTH)
: 0;
const baselineBadgeMarginLeft =
(mlBrushMarginLeft ?? 0) + (windowParametersAsPixels?.baselineMin ?? 0);

return (
<>
{isBrushVisible && (
<div className="aiopsHistogramBrushes">
<div
css={{
position: 'absolute',
'margin-left': `${
mlBrushMarginLeft + (windowParametersAsPixels?.baselineMin ?? 0)
}px`,
}}
>
<EuiBadge>
<FormattedMessage
id="xpack.aiops.documentCountChart.baselineBadgeContent"
defaultMessage="Baseline"
/>
</EuiBadge>
</div>
<div
css={{
position: 'absolute',
'margin-left': `${
mlBrushMarginLeft + (windowParametersAsPixels?.deviationMin ?? 0)
}px`,
}}
>
<EuiBadge>
<FormattedMessage
id="xpack.aiops.documentCountChart.deviationBadgeContent"
defaultMessage="Deviation"
/>
</EuiBadge>
<div css={{ height: BADGE_HEIGHT }}>
<BrushBadge
label={i18n.translate('xpack.aiops.documentCountChart.baselineBadgeLabel', {
defaultMessage: 'Baseline',
})}
marginLeft={baselineBadgeMarginLeft - baselineBadgeOverflow}
timestampFrom={windowParameters.baselineMin}
timestampTo={windowParameters.baselineMax}
width={BADGE_WIDTH}
/>
<BrushBadge
label={i18n.translate('xpack.aiops.documentCountChart.deviationBadgeLabel', {
defaultMessage: 'Deviation',
})}
marginLeft={mlBrushMarginLeft + (windowParametersAsPixels?.deviationMin ?? 0)}
timestampFrom={windowParameters.deviationMin}
timestampTo={windowParameters.deviationMax}
width={BADGE_WIDTH}
/>
</div>
<div
css={{
position: 'relative',
clear: 'both',
'padding-top': '20px',
'margin-bottom': '-4px',
}}
>
Expand Down

0 comments on commit f213348

Please sign in to comment.