Skip to content

Commit 59dae3d

Browse files
authored
[ML] Add popover help in Single Metric Viewer (#101446)
1 parent 664cc5f commit 59dae3d

File tree

2 files changed

+125
-51
lines changed

2 files changed

+125
-51
lines changed

x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js

Lines changed: 61 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import {
3333
EuiBadge,
3434
} from '@elastic/eui';
3535
import { ResizeChecker } from '../../../../../../src/plugins/kibana_utils/public';
36+
import { TimeSeriesExplorerHelpPopover } from './timeseriesexplorer_help_popover';
3637

3738
import { ANOMALIES_TABLE_DEFAULT_QUERY_SIZE } from '../../../common/constants/search';
3839
import {
@@ -1083,58 +1084,67 @@ export class TimeSeriesExplorer extends React.Component {
10831084
hasResults === true && (
10841085
<div>
10851086
<div className="results-container">
1086-
<EuiTitle className="panel-title">
1087-
<h2 style={{ display: 'inline' }}>
1088-
<span>
1089-
{i18n.translate('xpack.ml.timeSeriesExplorer.singleTimeSeriesAnalysisTitle', {
1090-
defaultMessage: 'Single time series analysis of {functionLabel}',
1091-
values: { functionLabel: chartDetails.functionLabel },
1092-
})}
1093-
</span>
1094-
&nbsp;
1095-
{chartDetails.entityData.count === 1 && (
1096-
<span className="entity-count-text">
1097-
{chartDetails.entityData.entities.length > 0 && '('}
1098-
{chartDetails.entityData.entities
1099-
.map((entity) => {
1100-
return `${entity.fieldName}: ${entity.fieldValue}`;
1101-
})
1102-
.join(', ')}
1103-
{chartDetails.entityData.entities.length > 0 && ')'}
1104-
</span>
1105-
)}
1106-
{chartDetails.entityData.count !== 1 && (
1107-
<span className="entity-count-text">
1108-
{chartDetails.entityData.entities.map((countData, i) => {
1109-
return (
1110-
<Fragment key={countData.fieldName}>
1111-
{i18n.translate(
1112-
'xpack.ml.timeSeriesExplorer.countDataInChartDetailsDescription',
1113-
{
1114-
defaultMessage:
1115-
'{openBrace}{cardinalityValue} distinct {fieldName} {cardinality, plural, one {} other { values}}{closeBrace}',
1116-
values: {
1117-
openBrace: i === 0 ? '(' : '',
1118-
closeBrace:
1119-
i === chartDetails.entityData.entities.length - 1 ? ')' : '',
1120-
cardinalityValue:
1121-
countData.cardinality === 0
1122-
? allValuesLabel
1123-
: countData.cardinality,
1124-
cardinality: countData.cardinality,
1125-
fieldName: countData.fieldName,
1126-
},
1127-
}
1128-
)}
1129-
{i !== chartDetails.entityData.entities.length - 1 ? ', ' : ''}
1130-
</Fragment>
1131-
);
1132-
})}
1087+
<EuiFlexGroup gutterSize="xs" alignItems="center">
1088+
<EuiTitle className="panel-title">
1089+
<h2 style={{ display: 'inline' }}>
1090+
<span>
1091+
{i18n.translate(
1092+
'xpack.ml.timeSeriesExplorer.singleTimeSeriesAnalysisTitle',
1093+
{
1094+
defaultMessage: 'Single time series analysis of {functionLabel}',
1095+
values: { functionLabel: chartDetails.functionLabel },
1096+
}
1097+
)}
11331098
</span>
1134-
)}
1135-
</h2>
1136-
</EuiTitle>
1137-
1099+
&nbsp;
1100+
{chartDetails.entityData.count === 1 && (
1101+
<span className="entity-count-text">
1102+
{chartDetails.entityData.entities.length > 0 && '('}
1103+
{chartDetails.entityData.entities
1104+
.map((entity) => {
1105+
return `${entity.fieldName}: ${entity.fieldValue}`;
1106+
})
1107+
.join(', ')}
1108+
{chartDetails.entityData.entities.length > 0 && ')'}
1109+
</span>
1110+
)}
1111+
{chartDetails.entityData.count !== 1 && (
1112+
<span className="entity-count-text">
1113+
{chartDetails.entityData.entities.map((countData, i) => {
1114+
return (
1115+
<Fragment key={countData.fieldName}>
1116+
{i18n.translate(
1117+
'xpack.ml.timeSeriesExplorer.countDataInChartDetailsDescription',
1118+
{
1119+
defaultMessage:
1120+
'{openBrace}{cardinalityValue} distinct {fieldName} {cardinality, plural, one {} other { values}}{closeBrace}',
1121+
values: {
1122+
openBrace: i === 0 ? '(' : '',
1123+
closeBrace:
1124+
i === chartDetails.entityData.entities.length - 1
1125+
? ')'
1126+
: '',
1127+
cardinalityValue:
1128+
countData.cardinality === 0
1129+
? allValuesLabel
1130+
: countData.cardinality,
1131+
cardinality: countData.cardinality,
1132+
fieldName: countData.fieldName,
1133+
},
1134+
}
1135+
)}
1136+
{i !== chartDetails.entityData.entities.length - 1 ? ', ' : ''}
1137+
</Fragment>
1138+
);
1139+
})}
1140+
</span>
1141+
)}
1142+
</h2>
1143+
</EuiTitle>
1144+
<EuiFlexItem grow={false}>
1145+
<TimeSeriesExplorerHelpPopover />
1146+
</EuiFlexItem>
1147+
</EuiFlexGroup>
11381148
<EuiFlexGroup style={{ float: 'right' }}>
11391149
{showModelBoundsCheckbox && (
11401150
<EuiFlexItem grow={false}>
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import React, { useState } from 'react';
9+
import { i18n } from '@kbn/i18n';
10+
import { FormattedMessage } from '@kbn/i18n/react';
11+
import { HelpPopover, HelpPopoverButton } from '../components/help_popover/help_popover';
12+
13+
export const TimeSeriesExplorerHelpPopover = () => {
14+
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
15+
16+
return (
17+
<HelpPopover
18+
anchorPosition="upCenter"
19+
button={
20+
<HelpPopoverButton
21+
onClick={() => {
22+
setIsPopoverOpen(!isPopoverOpen);
23+
}}
24+
/>
25+
}
26+
closePopover={() => setIsPopoverOpen(false)}
27+
isOpen={isPopoverOpen}
28+
title={i18n.translate('xpack.ml.timeSeriesExplorer.popoverTitle', {
29+
defaultMessage: 'Single time series analysis',
30+
})}
31+
>
32+
<p>
33+
<FormattedMessage
34+
id="xpack.ml.timeSeriesExplorer.popoverBasicExplanation"
35+
defaultMessage="This chart illustrates the actual data values over time for a specific detector. You can examine an event by sliding the time selector and changing its length. For the most accurate view, set the zoom size to auto."
36+
/>
37+
</p>
38+
<p>
39+
<FormattedMessage
40+
id="xpack.ml.timeSeriesExplorer.popoverAnomalyExplanation"
41+
defaultMessage="An anomaly score is calculated for each bucket time interval, with a value from 0 to 100. Anomalous events are highlighted in colors that indicate their severity. If an anomaly is depicted with a cross symbol instead of a dot, it has a medium or high multi-bucket impact. This extra analysis can catch anomalies even when they fall within the bounds of expected behavior."
42+
/>
43+
</p>
44+
<p>
45+
<FormattedMessage
46+
id="xpack.ml.timeSeriesExplorer.popoverForecastExplanation"
47+
defaultMessage="If you create a forecast, predicted data values are added to the chart. A shaded area around these values represents the confidence level; as you forecast further into the future, the confidence level generally decreases."
48+
/>
49+
</p>
50+
<p>
51+
<FormattedMessage
52+
id="xpack.ml.timeSeriesExplorer.popoverAnnotationsExplanation"
53+
defaultMessage="You can also optionally annotate your job results by drag-selecting a period of time in the chart and adding a description. Some annotations are generated automatically to indicate noteworthy occurrences."
54+
/>
55+
</p>
56+
<p>
57+
<FormattedMessage
58+
id="xpack.ml.timeSeriesExplorer.popoverModelPlotExplanation"
59+
defaultMessage="If model plot is enabled, you can optionally show model bounds, which are represented by a shaded area in the chart. As the job analyzes more data, it learns to more closely predict the expected patterns of behavior."
60+
/>
61+
</p>
62+
</HelpPopover>
63+
);
64+
};

0 commit comments

Comments
 (0)