[ML] Display anomaly actual in chart tooltip when model plot enabled (#54364) (#54465)

* [ML] Display anomaly actual in chart tooltip when model plot enabled

* [ML] Fixes translations for chart tooltip fixes

* [ML] Edits to chart tooltip div following review
This commit is contained in:
Pete Harverson 2020-01-10 16:53:40 +00:00 committed by GitHub
parent 100613950d
commit 73236985e0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 161 additions and 162 deletions

View file

@ -37,8 +37,7 @@ function useRefWithCallback() {
if (left + tooltipWidth > contentWidth) {
// the tooltip is hanging off the side of the page,
// so move it to the other side of the target
const markerWidthAdjustment = 25;
left = left - (tooltipWidth + offset.x + markerWidthAdjustment);
left = left - (tooltipWidth + offset.x);
}
const top = targetPosition.top + offset.y - parentBounding.top;

View file

@ -1523,12 +1523,12 @@ const TimeseriesChartIntl = injectI18n(
} else {
tooltipData.push({
name: intl.formatMessage({
id: 'xpack.ml.timeSeriesExplorer.timeSeriesChart.modelPlotEnabled.valueLabel',
defaultMessage: 'value',
id: 'xpack.ml.timeSeriesExplorer.timeSeriesChart.modelPlotEnabled.actualLabel',
defaultMessage: 'actual',
}),
value: formatValue(marker.value, marker.function, fieldFormat),
value: formatValue(marker.actual, marker.function, fieldFormat),
seriesKey,
yAccessor: 'value',
yAccessor: 'actual',
});
tooltipData.push({
name: intl.formatMessage({

View file

@ -1394,156 +1394,158 @@ export class TimeSeriesExplorer extends React.Component {
jobs.length > 0 &&
(fullRefresh === false || loading === false) &&
hasResults === true && (
<EuiText className="results-container">
{/* Make sure ChartTooltip is inside this plain wrapping element so positioning can be infered correctly. */}
<div>
{/* Make sure ChartTooltip is inside this plain wrapping element without padding so positioning can be infered correctly. */}
<ChartTooltip />
<span className="panel-title">
{i18n.translate('xpack.ml.timeSeriesExplorer.singleTimeSeriesAnalysisTitle', {
defaultMessage: 'Single time series analysis of {functionLabel}',
values: { functionLabel: chartDetails.functionLabel },
})}
</span>
&nbsp;
{chartDetails.entityData.count === 1 && (
<span className="entity-count-text">
{chartDetails.entityData.entities.length > 0 && '('}
{chartDetails.entityData.entities
.map(entity => {
return `${entity.fieldName}: ${entity.fieldValue}`;
})
.join(', ')}
{chartDetails.entityData.entities.length > 0 && ')'}
</span>
)}
{chartDetails.entityData.count !== 1 && (
<span className="entity-count-text">
{chartDetails.entityData.entities.map((countData, i) => {
return (
<Fragment key={countData.fieldName}>
{i18n.translate(
'xpack.ml.timeSeriesExplorer.countDataInChartDetailsDescription',
{
defaultMessage:
'{openBrace}{cardinalityValue} distinct {fieldName} {cardinality, plural, one {} other { values}}{closeBrace}',
values: {
openBrace: i === 0 ? '(' : '',
closeBrace:
i === chartDetails.entityData.entities.length - 1 ? ')' : '',
cardinalityValue:
countData.cardinality === 0
? allValuesLabel
: countData.cardinality,
cardinality: countData.cardinality,
fieldName: countData.fieldName,
},
}
)}
{i !== chartDetails.entityData.entities.length - 1 ? ', ' : ''}
</Fragment>
);
<EuiText className="results-container">
<span className="panel-title">
{i18n.translate('xpack.ml.timeSeriesExplorer.singleTimeSeriesAnalysisTitle', {
defaultMessage: 'Single time series analysis of {functionLabel}',
values: { functionLabel: chartDetails.functionLabel },
})}
</span>
)}
<EuiFlexGroup style={{ float: 'right' }}>
{showModelBoundsCheckbox && (
<EuiFlexItem grow={false}>
<EuiCheckbox
id="toggleModelBoundsCheckbox"
label={i18n.translate('xpack.ml.timeSeriesExplorer.showModelBoundsLabel', {
defaultMessage: 'show model bounds',
})}
checked={showModelBounds}
onChange={this.toggleShowModelBoundsHandler}
/>
</EuiFlexItem>
&nbsp;
{chartDetails.entityData.count === 1 && (
<span className="entity-count-text">
{chartDetails.entityData.entities.length > 0 && '('}
{chartDetails.entityData.entities
.map(entity => {
return `${entity.fieldName}: ${entity.fieldValue}`;
})
.join(', ')}
{chartDetails.entityData.entities.length > 0 && ')'}
</span>
)}
{showAnnotationsCheckbox && (
<EuiFlexItem grow={false}>
<EuiCheckbox
id="toggleAnnotationsCheckbox"
label={i18n.translate('xpack.ml.timeSeriesExplorer.annotationsLabel', {
defaultMessage: 'annotations',
})}
checked={showAnnotations}
onChange={this.toggleShowAnnotationsHandler}
/>
</EuiFlexItem>
)}
{showForecastCheckbox && (
<EuiFlexItem grow={false}>
<EuiCheckbox
id="toggleShowForecastCheckbox"
label={i18n.translate('xpack.ml.timeSeriesExplorer.showForecastLabel', {
defaultMessage: 'show forecast',
})}
checked={showForecast}
onChange={this.toggleShowForecastHandler}
/>
</EuiFlexItem>
)}
</EuiFlexGroup>
<div className="ml-timeseries-chart" data-test-subj="mlSingleMetricViewerChart">
<TimeseriesChart
{...chartProps}
detectorIndex={detectorId}
renderFocusChartOnly={renderFocusChartOnly}
selectedJob={selectedJob}
showAnnotations={showAnnotations}
showForecast={showForecast}
showModelBounds={showModelBounds}
timefilter={timefilter}
/>
</div>
{showAnnotations && focusAnnotationData.length > 0 && (
<div>
<span className="panel-title">
{i18n.translate('xpack.ml.timeSeriesExplorer.annotationsTitle', {
defaultMessage: 'Annotations',
{chartDetails.entityData.count !== 1 && (
<span className="entity-count-text">
{chartDetails.entityData.entities.map((countData, i) => {
return (
<Fragment key={countData.fieldName}>
{i18n.translate(
'xpack.ml.timeSeriesExplorer.countDataInChartDetailsDescription',
{
defaultMessage:
'{openBrace}{cardinalityValue} distinct {fieldName} {cardinality, plural, one {} other { values}}{closeBrace}',
values: {
openBrace: i === 0 ? '(' : '',
closeBrace:
i === chartDetails.entityData.entities.length - 1 ? ')' : '',
cardinalityValue:
countData.cardinality === 0
? allValuesLabel
: countData.cardinality,
cardinality: countData.cardinality,
fieldName: countData.fieldName,
},
}
)}
{i !== chartDetails.entityData.entities.length - 1 ? ', ' : ''}
</Fragment>
);
})}
</span>
<AnnotationsTable
annotations={focusAnnotationData}
isSingleMetricViewerLinkVisible={false}
isNumberBadgeVisible={true}
)}
<EuiFlexGroup style={{ float: 'right' }}>
{showModelBoundsCheckbox && (
<EuiFlexItem grow={false}>
<EuiCheckbox
id="toggleModelBoundsCheckbox"
label={i18n.translate('xpack.ml.timeSeriesExplorer.showModelBoundsLabel', {
defaultMessage: 'show model bounds',
})}
checked={showModelBounds}
onChange={this.toggleShowModelBoundsHandler}
/>
</EuiFlexItem>
)}
{showAnnotationsCheckbox && (
<EuiFlexItem grow={false}>
<EuiCheckbox
id="toggleAnnotationsCheckbox"
label={i18n.translate('xpack.ml.timeSeriesExplorer.annotationsLabel', {
defaultMessage: 'annotations',
})}
checked={showAnnotations}
onChange={this.toggleShowAnnotationsHandler}
/>
</EuiFlexItem>
)}
{showForecastCheckbox && (
<EuiFlexItem grow={false}>
<EuiCheckbox
id="toggleShowForecastCheckbox"
label={i18n.translate('xpack.ml.timeSeriesExplorer.showForecastLabel', {
defaultMessage: 'show forecast',
})}
checked={showForecast}
onChange={this.toggleShowForecastHandler}
/>
</EuiFlexItem>
)}
</EuiFlexGroup>
<div className="ml-timeseries-chart" data-test-subj="mlSingleMetricViewerChart">
<TimeseriesChart
{...chartProps}
detectorIndex={detectorId}
renderFocusChartOnly={renderFocusChartOnly}
selectedJob={selectedJob}
showAnnotations={showAnnotations}
showForecast={showForecast}
showModelBounds={showModelBounds}
timefilter={timefilter}
/>
<EuiSpacer size="l" />
</div>
)}
<AnnotationFlyout />
<span className="panel-title">
{i18n.translate('xpack.ml.timeSeriesExplorer.anomaliesTitle', {
defaultMessage: 'Anomalies',
})}
</span>
<EuiFlexGroup
direction="row"
gutterSize="l"
responsive={true}
className="ml-anomalies-controls"
>
<EuiFlexItem grow={false} style={{ width: '170px' }}>
<EuiFormRow
label={i18n.translate('xpack.ml.timeSeriesExplorer.severityThresholdLabel', {
defaultMessage: 'Severity threshold',
})}
>
<SelectSeverity />
</EuiFormRow>
</EuiFlexItem>
<EuiFlexItem grow={false} style={{ width: '170px' }}>
<EuiFormRow
label={i18n.translate('xpack.ml.timeSeriesExplorer.intervalLabel', {
defaultMessage: 'Interval',
})}
>
<SelectInterval />
</EuiFormRow>
</EuiFlexItem>
</EuiFlexGroup>
<EuiSpacer size="m" />
</EuiText>
{showAnnotations && focusAnnotationData.length > 0 && (
<div>
<span className="panel-title">
{i18n.translate('xpack.ml.timeSeriesExplorer.annotationsTitle', {
defaultMessage: 'Annotations',
})}
</span>
<AnnotationsTable
annotations={focusAnnotationData}
isSingleMetricViewerLinkVisible={false}
isNumberBadgeVisible={true}
/>
<EuiSpacer size="l" />
</div>
)}
<AnnotationFlyout />
<span className="panel-title">
{i18n.translate('xpack.ml.timeSeriesExplorer.anomaliesTitle', {
defaultMessage: 'Anomalies',
})}
</span>
<EuiFlexGroup
direction="row"
gutterSize="l"
responsive={true}
className="ml-anomalies-controls"
>
<EuiFlexItem grow={false} style={{ width: '170px' }}>
<EuiFormRow
label={i18n.translate('xpack.ml.timeSeriesExplorer.severityThresholdLabel', {
defaultMessage: 'Severity threshold',
})}
>
<SelectSeverity />
</EuiFormRow>
</EuiFlexItem>
<EuiFlexItem grow={false} style={{ width: '170px' }}>
<EuiFormRow
label={i18n.translate('xpack.ml.timeSeriesExplorer.intervalLabel', {
defaultMessage: 'Interval',
})}
>
<SelectInterval />
</EuiFormRow>
</EuiFlexItem>
</EuiFlexGroup>
<EuiSpacer size="m" />
</EuiText>
</div>
)}
{arePartitioningFieldsProvided && jobs.length > 0 && (
<AnomaliesTable tableData={tableData} filter={this.tableFilter} timefilter={timefilter} />

View file

@ -441,9 +441,6 @@
"common.ui.flotCharts.tueLabel": "火",
"common.ui.flotCharts.wedLabel": "水",
"common.ui.management.breadcrumb": "管理",
"management.connectDataDisplayName": "データに接続",
"management.displayName": "管理",
"management.nav.menu": "管理メニュー",
"common.ui.modals.cancelButtonLabel": "キャンセル",
"common.ui.notify.fatalError.errorStatusMessage": "エラー {errStatus} {errStatusText}: {errMessage}",
"common.ui.notify.fatalError.unavailableServerErrorMessage": "HTTP リクエストが接続に失敗しました。Kibana サーバーが実行されていて、ご使用のブラウザの接続が正常に動作していることを確認するか、システム管理者にお問い合わせください。",
@ -519,6 +516,12 @@
"common.ui.aggTypes.scaleMetricsLabel": "メトリック値のスケーリング (廃止)",
"common.ui.aggTypes.scaleMetricsTooltip": "これを有効にすると、手動最低間隔を選択し、広い間隔が使用された場合、カウントと合計メトリックが手動で選択された間隔にスケーリングされます。",
"common.ui.aggTypes.buckets.ranges.rangesFormatMessage": "{gte} {from} と {lt} {to}",
"management.connectDataDisplayName": "データに接続",
"management.displayName": "管理",
"management.nav.menu": "管理メニュー",
"management.editIndexPattern.createIndex.defaultButtonDescription": "すべてのデータに完全集約を実行",
"management.editIndexPattern.createIndex.defaultButtonText": "標準インデックスパターン",
"management.editIndexPattern.createIndex.defaultTypeName": "インデックスパターン",
"timelion.savedObjectFinder.addNewItemButtonLabel": "新規 {item} を追加",
"timelion.savedObjectFinder.manageItemsButtonLabel": "{items} の管理",
"timelion.savedObjectFinder.noMatchesFoundDescription": "一致する {items} が見つかりません。",
@ -853,9 +856,6 @@
"timelion.vis.intervalLabel": "間隔",
"timelion.help.functions.notAllowedGraphiteUrl": "この Graphite URL は kibana.yml ファイルで構成されていません。\n 「'timelion.graphiteUrls」で kibana.yml ファイルの Graphite サーバーリストを構成して\n Kibana の高度な設定で選択してください",
"timelion.emptyExpressionErrorMessage": "Timelion エラー式が入力されていません",
"management.editIndexPattern.createIndex.defaultButtonDescription": "すべてのデータに完全集約を実行",
"management.editIndexPattern.createIndex.defaultButtonText": "標準インデックスパターン",
"management.editIndexPattern.createIndex.defaultTypeName": "インデックスパターン",
"core.ui.overlays.banner.attentionTitle": "注意",
"core.ui.overlays.banner.closeButtonLabel": "閉じる",
"core.ui.chrome.headerGlobalNav.goHomePageIconAriaLabel": "ホームページに移動",
@ -8059,7 +8059,6 @@
"xpack.ml.timeSeriesExplorer.timeSeriesChart.anomalyScoreLabel": "異常スコア",
"xpack.ml.timeSeriesExplorer.timeSeriesChart.modelPlotEnabled.lowerBoundsLabel": "下の境界",
"xpack.ml.timeSeriesExplorer.timeSeriesChart.modelPlotEnabled.upperBoundsLabel": "上の境界",
"xpack.ml.timeSeriesExplorer.timeSeriesChart.modelPlotEnabled.valueLabel": "値",
"xpack.ml.timeSeriesExplorer.timeSeriesChart.moreThanOneUnusualByFieldValuesLabel": "{numberOfCauses} 個の {plusSign}異常な{byFieldName}値",
"xpack.ml.timeSeriesExplorer.timeSeriesChart.multiBucketImpactLabel": "複数バケットの影響",
"xpack.ml.timeSeriesExplorer.timeSeriesChart.scheduledEventsLabel": "予定イベント {counter}",

View file

@ -441,9 +441,6 @@
"common.ui.flotCharts.tueLabel": "周二",
"common.ui.flotCharts.wedLabel": "周三",
"common.ui.management.breadcrumb": "管理",
"management.connectDataDisplayName": "连接数据",
"management.displayName": "管理",
"management.nav.menu": "管理菜单",
"common.ui.modals.cancelButtonLabel": "取消",
"common.ui.notify.fatalError.errorStatusMessage": "错误 {errStatus} {errStatusText}{errMessage}",
"common.ui.notify.fatalError.unavailableServerErrorMessage": "HTTP 请求无法连接。请检查 Kibana 服务器是否正在运行以及您的浏览器是否具有有效的连接,或请联系您的系统管理员。",
@ -520,6 +517,12 @@
"common.ui.aggTypes.scaleMetricsLabel": "缩放指标值(已弃用)",
"common.ui.aggTypes.scaleMetricsTooltip": "如果选择手动最小时间间隔并将使用较大的时间间隔,则启用此设置将使计数和求和指标缩放到手动选择的时间间隔。",
"common.ui.aggTypes.buckets.ranges.rangesFormatMessage": "{gte} {from} 且 {lt} {to}",
"management.connectDataDisplayName": "连接数据",
"management.displayName": "管理",
"management.nav.menu": "管理菜单",
"management.editIndexPattern.createIndex.defaultButtonDescription": "对任何数据执行完全聚合",
"management.editIndexPattern.createIndex.defaultButtonText": "标准索引模式",
"management.editIndexPattern.createIndex.defaultTypeName": "索引模式",
"timelion.savedObjectFinder.addNewItemButtonLabel": "添加新的 {item}",
"timelion.savedObjectFinder.manageItemsButtonLabel": "管理 {items}",
"timelion.savedObjectFinder.noMatchesFoundDescription": "未找到任何匹配的 {items}。",
@ -854,9 +857,6 @@
"timelion.vis.intervalLabel": "时间间隔",
"timelion.help.functions.notAllowedGraphiteUrl": "在 kibana.yml 文件中未配置此 Graphite URL。\n 请在 kibana.yml 文件中“timelion.graphiteUrls”下配置 Graphite 服务器列表,并\n 从 Kibana 的高级设置中选择一个",
"timelion.emptyExpressionErrorMessage": "Timelion 错误:未提供表达式",
"management.editIndexPattern.createIndex.defaultButtonDescription": "对任何数据执行完全聚合",
"management.editIndexPattern.createIndex.defaultButtonText": "标准索引模式",
"management.editIndexPattern.createIndex.defaultTypeName": "索引模式",
"core.ui.overlays.banner.attentionTitle": "注意",
"core.ui.overlays.banner.closeButtonLabel": "关闭",
"core.ui.chrome.headerGlobalNav.goHomePageIconAriaLabel": "前往主页",
@ -8087,7 +8087,6 @@
"xpack.ml.timeSeriesExplorer.timeSeriesChart.anomalyScoreLabel": "异常分数",
"xpack.ml.timeSeriesExplorer.timeSeriesChart.modelPlotEnabled.lowerBoundsLabel": "下边界",
"xpack.ml.timeSeriesExplorer.timeSeriesChart.modelPlotEnabled.upperBoundsLabel": "上边界",
"xpack.ml.timeSeriesExplorer.timeSeriesChart.modelPlotEnabled.valueLabel": "值",
"xpack.ml.timeSeriesExplorer.timeSeriesChart.moreThanOneUnusualByFieldValuesLabel": "{numberOfCauses}{plusSign} 异常 {byFieldName} 值",
"xpack.ml.timeSeriesExplorer.timeSeriesChart.multiBucketImpactLabel": "多存储桶影响",
"xpack.ml.timeSeriesExplorer.timeSeriesChart.scheduledEventsLabel": "已计划事件{counter}",