diff --git a/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseries_search_service.ts b/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseries_search_service.ts index 044d166ca5efa1..05adc2355ef3c6 100644 --- a/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseries_search_service.ts +++ b/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseries_search_service.ts @@ -6,6 +6,7 @@ */ import { each, find, get, filter } from 'lodash'; +import type { ES_AGGREGATION } from '@kbn/ml-anomaly-utils'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; @@ -15,7 +16,6 @@ import { isModelPlotChartableForDetector, isModelPlotEnabled, } from '../../../common/util/job_utils'; -// @ts-ignore import { buildConfigFromDetector } from '../util/chart_config_builder'; import { mlResultsService } from '../services/results_service'; import { ModelPlotOutput } from '../services/results_service/result_service_rx'; @@ -113,29 +113,48 @@ function getMetricData( } } -// Builds chart detail information (charting function description and entity counts) used -// in the title area of the time series chart. -// Queries Elasticsearch if necessary to obtain the distinct count of entities -// for which data is being plotted. +interface TimeSeriesExplorerChartDetails { + success: boolean; + results: { + functionLabel: string | null; + entityData: { count?: number; entities: Array<{ fieldName: string; cardinality?: number }> }; + }; +} + +/** + * Builds chart detail information (charting function description and entity counts) used + * in the title area of the time series chart. + * Queries Elasticsearch if necessary to obtain the distinct count of entities + * for which data is being plotted. + * @param job Job config info + * @param detectorIndex The index of the detector in the job config + * @param entityFields Array of field name - field value pairs + * @param earliestMs Earliest timestamp in milliseconds + * @param latestMs Latest timestamp in milliseconds + * @param metricFunctionDescription The underlying function (min, max, avg) for "metric" detector type + * @returns chart data to plot for Single Metric Viewer/Time series explorer + */ function getChartDetails( job: Job, detectorIndex: number, - entityFields: any[], + entityFields: MlEntityField[], earliestMs: number, - latestMs: number + latestMs: number, + metricFunctionDescription?: ES_AGGREGATION ) { return new Promise((resolve, reject) => { - const obj: any = { + const obj: TimeSeriesExplorerChartDetails = { success: true, results: { functionLabel: '', entityData: { entities: [] } }, }; - const chartConfig = buildConfigFromDetector(job, detectorIndex); + const chartConfig = buildConfigFromDetector(job, detectorIndex, metricFunctionDescription); + let functionLabel: string | null = chartConfig.metricFunction; if (chartConfig.metricFieldName !== undefined) { - functionLabel += ' '; - functionLabel += chartConfig.metricFieldName; + functionLabel += ` ${chartConfig.metricFieldName}`; } + obj.results.functionLabel = functionLabel; const blankEntityFields = filter(entityFields, (entity) => { diff --git a/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js b/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js index 757f4cb06543e4..89fca7147297c9 100644 --- a/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js +++ b/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js @@ -436,17 +436,17 @@ export class TimeSeriesExplorer extends React.Component { chartDataError: undefined, ...(fullRefresh ? { - chartDetails: undefined, - contextChartData: undefined, - contextForecastData: undefined, - focusChartData: undefined, - focusForecastData: undefined, - modelPlotEnabled: - isModelPlotChartableForDetector(currentSelectedJob, selectedDetectorIndex) && - isModelPlotEnabled(currentSelectedJob, selectedDetectorIndex, entityControls), - hasResults: false, - dataNotChartable: false, - } + chartDetails: undefined, + contextChartData: undefined, + contextForecastData: undefined, + focusChartData: undefined, + focusForecastData: undefined, + modelPlotEnabled: + isModelPlotChartableForDetector(currentSelectedJob, selectedDetectorIndex) && + isModelPlotEnabled(currentSelectedJob, selectedDetectorIndex, entityControls), + hasResults: false, + dataNotChartable: false, + } : {}), }, () => { @@ -607,7 +607,8 @@ export class TimeSeriesExplorer extends React.Component { detectorIndex, entityControls, searchBounds.min.valueOf(), - searchBounds.max.valueOf() + searchBounds.max.valueOf(), + this.props.functionDescription ) .then((resp) => { stateUpdate.chartDetails = resp.results; diff --git a/x-pack/plugins/ml/public/application/util/chart_config_builder.ts b/x-pack/plugins/ml/public/application/util/chart_config_builder.ts index e9c322d30a6e56..c1057fc335e82c 100644 --- a/x-pack/plugins/ml/public/application/util/chart_config_builder.ts +++ b/x-pack/plugins/ml/public/application/util/chart_config_builder.ts @@ -19,9 +19,19 @@ import { Job } from '../../../common/types/anomaly_detection_jobs'; import { mlFunctionToESAggregation } from '../../../common/util/job_utils'; -// Builds the basic configuration to plot a chart of the source data -// analyzed by the the detector at the given index from the specified ML job. -export function buildConfigFromDetector(job: Job, detectorIndex: number) { +/** + * Builds the basic configuration to plot a chart of the source data + * analyzed by the the detector at the given index from the specified ML job. + * @param job Job config info + * @param detectorIndex The index of the detector in the job config + * @param metricFunctionDescription The underlying function (min, max, avg) for "metric" detector type + * @returns + */ +export function buildConfigFromDetector( + job: Job, + detectorIndex: number, + metricFunctionDescription?: ES_AGGREGATION +) { const analysisConfig = job.analysis_config; const detector = analysisConfig.detectors[detectorIndex]; @@ -38,6 +48,9 @@ export function buildConfigFromDetector(job: Job, detectorIndex: number) { datafeedConfig: job.datafeed_config!, summaryCountFieldName: job.analysis_config.summary_count_field_name, }; + if (detector.function === ML_JOB_AGGREGATION.METRIC && metricFunctionDescription !== undefined) { + config.metricFunction = metricFunctionDescription; + } if (detector.field_name !== undefined) { config.metricFieldName = detector.field_name;