[ML] Fixes anomaly charts for rare detectors when model plot is enabled (#66075)

This commit is contained in:
Pete Harverson 2020-05-12 14:53:48 +01:00 committed by GitHub
parent 533b4810ca
commit 0124977830
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 45 additions and 20 deletions

View file

@ -44,6 +44,8 @@ export function mlFunctionToESAggregation(functionName: string): string | null;
export function isModelPlotEnabled(job: Job, detectorIndex: number, entityFields: any[]): boolean;
export function isModelPlotChartableForDetector(job: Job, detectorIndex: number): boolean;
export function getSafeAggregationName(fieldName: string, index: number): string;
export function getLatestDataOrBucketTimestamp(

View file

@ -105,18 +105,20 @@ export function isModelPlotChartableForDetector(job, detectorIndex) {
const dtr = dtrs[detectorIndex];
const functionName = dtr.function;
// Model plot can be charted for any of the functions which map to ES aggregations,
// Model plot can be charted for any of the functions which map to ES aggregations
// (except rare, for which no model plot results are generated),
// plus varp and info_content functions.
isModelPlotChartable =
mlFunctionToESAggregation(functionName) !== null ||
[
'varp',
'high_varp',
'low_varp',
'info_content',
'high_info_content',
'low_info_content',
].includes(functionName) === true;
functionName !== 'rare' &&
(mlFunctionToESAggregation(functionName) !== null ||
[
'varp',
'high_varp',
'low_varp',
'info_content',
'high_info_content',
'low_info_content',
].includes(functionName) === true);
}
return isModelPlotChartable;

View file

@ -307,7 +307,14 @@ describe('ML - job utils', () => {
const job2 = {
analysis_config: {
detectors: [{ function: 'count' }, { function: 'info_content' }],
detectors: [
{ function: 'count' },
{ function: 'info_content' },
{
function: 'rare',
by_field_name: 'mlcategory',
},
],
},
model_plot_config: {
enabled: true,
@ -325,6 +332,10 @@ describe('ML - job utils', () => {
test('returns true for info_content detector when model plot is enabled', () => {
expect(isModelPlotChartableForDetector(job2, 1)).toBe(true);
});
test('returns false for rare by mlcategory when model plot is enabled', () => {
expect(isModelPlotChartableForDetector(job2, 2)).toBe(false);
});
});
describe('getPartitioningFieldNames', () => {

View file

@ -19,6 +19,7 @@ import { chartLimits, getChartType } from '../../util/chart_utils';
import { getEntityFieldList } from '../../../../common/util/anomaly_utils';
import {
isSourceDataChartableForDetector,
isModelPlotChartableForDetector,
isModelPlotEnabled,
} from '../../../../common/util/job_utils';
import { mlResultsService } from '../../services/results_service';
@ -420,7 +421,7 @@ function processRecordsForDisplay(anomalyRecords) {
// is chartable, and if model plot is enabled for the job.
const job = mlJobService.getJob(record.job_id);
let isChartable = isSourceDataChartableForDetector(job, record.detector_index);
if (isChartable === false) {
if (isChartable === false && isModelPlotChartableForDetector(job, record.detector_index)) {
// Check if model plot is enabled for this job.
// Need to check the entity fields for the record in case the model plot config has a terms list.
const entityFields = getEntityFieldList(record);

View file

@ -20,6 +20,7 @@ import {
import { getEntityFieldList } from '../../../common/util/anomaly_utils';
import {
isSourceDataChartableForDetector,
isModelPlotChartableForDetector,
isModelPlotEnabled,
} from '../../../common/util/job_utils';
import { parseInterval } from '../../../common/util/parse_interval';
@ -636,7 +637,10 @@ export async function loadAnomaliesTableData(
// TODO - when job_service is moved server_side, move this to server endpoint.
const job = mlJobService.getJob(jobId);
let isChartable = isSourceDataChartableForDetector(job, anomaly.detectorIndex);
if (isChartable === false) {
if (
isChartable === false &&
isModelPlotChartableForDetector(job, anomaly.detectorIndex)
) {
// Check if model plot is enabled for this job.
// Need to check the entity fields for the record in case the model plot config has a terms list.
// If terms is specified, model plot is only stored if both the partition and by fields appear in the list.

View file

@ -9,7 +9,10 @@ import _ from 'lodash';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { ml } from '../services/ml_api_service';
import { isModelPlotEnabled } from '../../../common/util/job_utils';
import {
isModelPlotChartableForDetector,
isModelPlotEnabled,
} from '../../../common/util/job_utils';
// @ts-ignore
import { buildConfigFromDetector } from '../util/chart_config_builder';
import { mlResultsService } from '../services/results_service';
@ -24,7 +27,10 @@ function getMetricData(
latestMs: number,
interval: string
): Observable<ModelPlotOutput> {
if (isModelPlotEnabled(job, detectorIndex, entityFields)) {
if (
isModelPlotChartableForDetector(job, detectorIndex) &&
isModelPlotEnabled(job, detectorIndex, entityFields)
) {
// Extract the partition, by, over fields on which to filter.
const criteriaFields = [];
const detector = job.analysis_config.detectors[detectorIndex];

View file

@ -36,6 +36,7 @@ import { ResizeChecker } from '../../../../../../src/plugins/kibana_utils/public
import { ANOMALIES_TABLE_DEFAULT_QUERY_SIZE } from '../../../common/constants/search';
import {
isModelPlotEnabled,
isModelPlotChartableForDetector,
isSourceDataChartableForDetector,
isTimeSeriesViewDetector,
mlFunctionToESAggregation,
@ -506,11 +507,9 @@ export class TimeSeriesExplorer extends React.Component {
contextForecastData: undefined,
focusChartData: undefined,
focusForecastData: undefined,
modelPlotEnabled: isModelPlotEnabled(
currentSelectedJob,
selectedDetectorIndex,
entityControls
),
modelPlotEnabled:
isModelPlotChartableForDetector(currentSelectedJob, selectedDetectorIndex) &&
isModelPlotEnabled(currentSelectedJob, selectedDetectorIndex, entityControls),
hasResults: false,
dataNotChartable: false,
}