Skip to content

Commit 0124977

Browse files
[ML] Fixes anomaly charts for rare detectors when model plot is enabled (#66075)
1 parent 533b481 commit 0124977

File tree

7 files changed

+45
-20
lines changed

7 files changed

+45
-20
lines changed

x-pack/plugins/ml/common/util/job_utils.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ export function mlFunctionToESAggregation(functionName: string): string | null;
4444

4545
export function isModelPlotEnabled(job: Job, detectorIndex: number, entityFields: any[]): boolean;
4646

47+
export function isModelPlotChartableForDetector(job: Job, detectorIndex: number): boolean;
48+
4749
export function getSafeAggregationName(fieldName: string, index: number): string;
4850

4951
export function getLatestDataOrBucketTimestamp(

x-pack/plugins/ml/common/util/job_utils.js

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -105,18 +105,20 @@ export function isModelPlotChartableForDetector(job, detectorIndex) {
105105
const dtr = dtrs[detectorIndex];
106106
const functionName = dtr.function;
107107

108-
// Model plot can be charted for any of the functions which map to ES aggregations,
108+
// Model plot can be charted for any of the functions which map to ES aggregations
109+
// (except rare, for which no model plot results are generated),
109110
// plus varp and info_content functions.
110111
isModelPlotChartable =
111-
mlFunctionToESAggregation(functionName) !== null ||
112-
[
113-
'varp',
114-
'high_varp',
115-
'low_varp',
116-
'info_content',
117-
'high_info_content',
118-
'low_info_content',
119-
].includes(functionName) === true;
112+
functionName !== 'rare' &&
113+
(mlFunctionToESAggregation(functionName) !== null ||
114+
[
115+
'varp',
116+
'high_varp',
117+
'low_varp',
118+
'info_content',
119+
'high_info_content',
120+
'low_info_content',
121+
].includes(functionName) === true);
120122
}
121123

122124
return isModelPlotChartable;

x-pack/plugins/ml/common/util/job_utils.test.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,14 @@ describe('ML - job utils', () => {
307307

308308
const job2 = {
309309
analysis_config: {
310-
detectors: [{ function: 'count' }, { function: 'info_content' }],
310+
detectors: [
311+
{ function: 'count' },
312+
{ function: 'info_content' },
313+
{
314+
function: 'rare',
315+
by_field_name: 'mlcategory',
316+
},
317+
],
311318
},
312319
model_plot_config: {
313320
enabled: true,
@@ -325,6 +332,10 @@ describe('ML - job utils', () => {
325332
test('returns true for info_content detector when model plot is enabled', () => {
326333
expect(isModelPlotChartableForDetector(job2, 1)).toBe(true);
327334
});
335+
336+
test('returns false for rare by mlcategory when model plot is enabled', () => {
337+
expect(isModelPlotChartableForDetector(job2, 2)).toBe(false);
338+
});
328339
});
329340

330341
describe('getPartitioningFieldNames', () => {

x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_charts_container_service.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { chartLimits, getChartType } from '../../util/chart_utils';
1919
import { getEntityFieldList } from '../../../../common/util/anomaly_utils';
2020
import {
2121
isSourceDataChartableForDetector,
22+
isModelPlotChartableForDetector,
2223
isModelPlotEnabled,
2324
} from '../../../../common/util/job_utils';
2425
import { mlResultsService } from '../../services/results_service';
@@ -420,7 +421,7 @@ function processRecordsForDisplay(anomalyRecords) {
420421
// is chartable, and if model plot is enabled for the job.
421422
const job = mlJobService.getJob(record.job_id);
422423
let isChartable = isSourceDataChartableForDetector(job, record.detector_index);
423-
if (isChartable === false) {
424+
if (isChartable === false && isModelPlotChartableForDetector(job, record.detector_index)) {
424425
// Check if model plot is enabled for this job.
425426
// Need to check the entity fields for the record in case the model plot config has a terms list.
426427
const entityFields = getEntityFieldList(record);

x-pack/plugins/ml/public/application/explorer/explorer_utils.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
import { getEntityFieldList } from '../../../common/util/anomaly_utils';
2121
import {
2222
isSourceDataChartableForDetector,
23+
isModelPlotChartableForDetector,
2324
isModelPlotEnabled,
2425
} from '../../../common/util/job_utils';
2526
import { parseInterval } from '../../../common/util/parse_interval';
@@ -636,7 +637,10 @@ export async function loadAnomaliesTableData(
636637
// TODO - when job_service is moved server_side, move this to server endpoint.
637638
const job = mlJobService.getJob(jobId);
638639
let isChartable = isSourceDataChartableForDetector(job, anomaly.detectorIndex);
639-
if (isChartable === false) {
640+
if (
641+
isChartable === false &&
642+
isModelPlotChartableForDetector(job, anomaly.detectorIndex)
643+
) {
640644
// Check if model plot is enabled for this job.
641645
// Need to check the entity fields for the record in case the model plot config has a terms list.
642646
// If terms is specified, model plot is only stored if both the partition and by fields appear in the list.

x-pack/plugins/ml/public/application/timeseriesexplorer/timeseries_search_service.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ import _ from 'lodash';
99
import { Observable } from 'rxjs';
1010
import { map } from 'rxjs/operators';
1111
import { ml } from '../services/ml_api_service';
12-
import { isModelPlotEnabled } from '../../../common/util/job_utils';
12+
import {
13+
isModelPlotChartableForDetector,
14+
isModelPlotEnabled,
15+
} from '../../../common/util/job_utils';
1316
// @ts-ignore
1417
import { buildConfigFromDetector } from '../util/chart_config_builder';
1518
import { mlResultsService } from '../services/results_service';
@@ -24,7 +27,10 @@ function getMetricData(
2427
latestMs: number,
2528
interval: string
2629
): Observable<ModelPlotOutput> {
27-
if (isModelPlotEnabled(job, detectorIndex, entityFields)) {
30+
if (
31+
isModelPlotChartableForDetector(job, detectorIndex) &&
32+
isModelPlotEnabled(job, detectorIndex, entityFields)
33+
) {
2834
// Extract the partition, by, over fields on which to filter.
2935
const criteriaFields = [];
3036
const detector = job.analysis_config.detectors[detectorIndex];

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

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import { ResizeChecker } from '../../../../../../src/plugins/kibana_utils/public
3636
import { ANOMALIES_TABLE_DEFAULT_QUERY_SIZE } from '../../../common/constants/search';
3737
import {
3838
isModelPlotEnabled,
39+
isModelPlotChartableForDetector,
3940
isSourceDataChartableForDetector,
4041
isTimeSeriesViewDetector,
4142
mlFunctionToESAggregation,
@@ -506,11 +507,9 @@ export class TimeSeriesExplorer extends React.Component {
506507
contextForecastData: undefined,
507508
focusChartData: undefined,
508509
focusForecastData: undefined,
509-
modelPlotEnabled: isModelPlotEnabled(
510-
currentSelectedJob,
511-
selectedDetectorIndex,
512-
entityControls
513-
),
510+
modelPlotEnabled:
511+
isModelPlotChartableForDetector(currentSelectedJob, selectedDetectorIndex) &&
512+
isModelPlotEnabled(currentSelectedJob, selectedDetectorIndex, entityControls),
514513
hasResults: false,
515514
dataNotChartable: false,
516515
}

0 commit comments

Comments
 (0)