Skip to content

Commit ea9414a

Browse files
ensure diff types of jobs show correct charts. fix jest test
1 parent bff94a7 commit ea9414a

4 files changed

Lines changed: 69 additions & 38 deletions

File tree

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ describe('ML - job utils', () => {
281281
expect(isSourceDataChartableForDetector(job, 22)).toBe(true);
282282
expect(isSourceDataChartableForDetector(job, 23)).toBe(true);
283283
expect(isSourceDataChartableForDetector(job, 24)).toBe(true);
284+
expect(isSourceDataChartableForDetector(job, 36)).toBe(true);
284285
expect(isSourceDataChartableForDetector(job, 37)).toBe(true);
285286
});
286287

@@ -296,7 +297,6 @@ describe('ML - job utils', () => {
296297
expect(isSourceDataChartableForDetector(job, 33)).toBe(false);
297298
expect(isSourceDataChartableForDetector(job, 34)).toBe(false);
298299
expect(isSourceDataChartableForDetector(job, 35)).toBe(false);
299-
expect(isSourceDataChartableForDetector(job, 36)).toBe(false);
300300
});
301301
});
302302

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

Lines changed: 30 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ export const anomalyDataChange = function (
8484
);
8585

8686
const seriesConfigs = recordsToPlot.map(buildConfig);
87+
const seriesConfigsNoGeoData = [];
8788

8889
// initialize the charts with loading indicators
8990
data.seriesToPlot = seriesConfigs.map((config) => ({
@@ -116,10 +117,10 @@ export const anomalyDataChange = function (
116117
loading: false,
117118
mapData: records,
118119
});
120+
} else {
121+
seriesConfigsNoGeoData.push(config);
119122
}
120123
}
121-
122-
data.seriesToPlot = mapData;
123124
}
124125

125126
// Calculate the time range of the charts, which is a function of the chart width and max job bucket span.
@@ -306,26 +307,26 @@ export const anomalyDataChange = function (
306307
// TODO - if query returns no results e.g. source data has been deleted,
307308
// display a message saying 'No data between earliest/latest'.
308309
const seriesPromises = [];
309-
seriesConfigs.forEach((seriesConfig) => {
310-
if (!seriesConfig.detectorLabel.includes(ML_JOB_AGGREGATION.LAT_LONG)) {
311-
seriesPromises.push(
312-
Promise.all([
313-
getMetricData(seriesConfig, chartRange),
314-
getRecordsForCriteria(seriesConfig, chartRange),
315-
getScheduledEvents(seriesConfig, chartRange),
316-
getEventDistribution(seriesConfig, chartRange),
317-
])
318-
);
319-
}
310+
// Use seriesConfigs list without geo data config so indices match up after seriesPromises are resolved and we map through the responses
311+
const seriesCongifsForPromises = hasGeoData ? seriesConfigsNoGeoData : seriesConfigs;
312+
seriesCongifsForPromises.forEach((seriesConfig) => {
313+
seriesPromises.push(
314+
Promise.all([
315+
getMetricData(seriesConfig, chartRange),
316+
getRecordsForCriteria(seriesConfig, chartRange),
317+
getScheduledEvents(seriesConfig, chartRange),
318+
getEventDistribution(seriesConfig, chartRange),
319+
])
320+
);
320321
});
321322

322323
function processChartData(response, seriesIndex) {
323324
const metricData = response[0].results;
324325
const records = response[1].records;
325-
const jobId = seriesConfigs[seriesIndex].jobId;
326+
const jobId = seriesCongifsForPromises[seriesIndex].jobId;
326327
const scheduledEvents = response[2].events[jobId];
327328
const eventDistribution = response[3];
328-
const chartType = getChartType(seriesConfigs[seriesIndex]);
329+
const chartType = getChartType(seriesCongifsForPromises[seriesIndex]);
329330

330331
// Sort records in ascending time order matching up with chart data
331332
records.sort((recordA, recordB) => {
@@ -450,24 +451,20 @@ export const anomalyDataChange = function (
450451
);
451452
const overallChartLimits = chartLimits(allDataPoints);
452453

453-
data.seriesToPlot = response
454-
.map((d, i) => {
455-
if (!seriesConfigs[i].detectorLabel.includes(ML_JOB_AGGREGATION.LAT_LONG)) {
456-
return {
457-
...seriesConfigs[i],
458-
loading: false,
459-
chartData: processedData[i],
460-
plotEarliest: chartRange.min,
461-
plotLatest: chartRange.max,
462-
selectedEarliest: selectedEarliestMs,
463-
selectedLatest: selectedLatestMs,
464-
chartLimits: USE_OVERALL_CHART_LIMITS
465-
? overallChartLimits
466-
: chartLimits(processedData[i]),
467-
};
468-
}
469-
})
470-
.filter((value) => value !== undefined);
454+
data.seriesToPlot = response.map((d, i) => {
455+
return {
456+
...seriesCongifsForPromises[i],
457+
loading: false,
458+
chartData: processedData[i],
459+
plotEarliest: chartRange.min,
460+
plotLatest: chartRange.max,
461+
selectedEarliest: selectedEarliestMs,
462+
selectedLatest: selectedLatestMs,
463+
chartLimits: USE_OVERALL_CHART_LIMITS
464+
? overallChartLimits
465+
: chartLimits(processedData[i]),
466+
};
467+
});
471468

472469
if (mapData.length) {
473470
// push map data in if it's available

x-pack/plugins/ml/public/application/explorer/explorer_charts/map_config.ts

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,28 @@
44
* you may not use this file except in compliance with the Elastic License.
55
*/
66

7+
import { FIELD_ORIGIN, STYLE_TYPE } from '../../../../../maps/common/constants';
8+
79
const FEATURE = 'Feature';
810
const POINT = 'Point';
11+
const SEVERITY_COLOR_RAMP = [
12+
{
13+
stop: 0,
14+
color: '#8BC8FB',
15+
},
16+
{
17+
stop: 25,
18+
color: '#FDEC25',
19+
},
20+
{
21+
stop: 50,
22+
color: '#FBA740',
23+
},
24+
{
25+
stop: 75,
26+
color: '#FE5050',
27+
},
28+
];
929

1030
function getAnomalyFeatures(anomalies: any[], type: 'actual_point' | 'typical_point') {
1131
const anomalyFeatures = [];
@@ -90,6 +110,12 @@ export const getMLAnomaliesActualLayer = (anomalies: any) => {
90110
sourceDescriptor: {
91111
id: 'b7486535-171b-4d3b-bb2e-33c1a0a2854d',
92112
type: 'GEOJSON_FILE',
113+
__fields: [
114+
{
115+
name: 'record_score',
116+
type: 'number',
117+
},
118+
],
93119
__featureCollection: {
94120
features: getAnomalyFeatures(anomalies, 'actual_point'),
95121
type: 'FeatureCollection',
@@ -100,9 +126,14 @@ export const getMLAnomaliesActualLayer = (anomalies: any) => {
100126
type: 'VECTOR',
101127
properties: {
102128
fillColor: {
103-
type: 'STATIC',
129+
type: STYLE_TYPE.DYNAMIC,
104130
options: {
105-
color: '#FF0000',
131+
customColorRamp: SEVERITY_COLOR_RAMP,
132+
field: {
133+
name: 'record_score',
134+
origin: FIELD_ORIGIN.SOURCE,
135+
},
136+
useCustomColorRamp: true,
106137
},
107138
},
108139
lineColor: {

x-pack/plugins/ml/public/application/util/chart_utils.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,11 @@ const POPULATION_DISTRIBUTION_ENABLED = true;
176176
// get the chart type based on its configuration
177177
export function getChartType(config) {
178178
let chartType = CHART_TYPE.SINGLE_METRIC;
179+
180+
if (config.functionDescription === 'lat_long' || config.mapData !== undefined) {
181+
return CHART_TYPE.GEO_MAP;
182+
}
183+
179184
if (
180185
EVENT_DISTRIBUTION_ENABLED &&
181186
config.functionDescription === 'rare' &&
@@ -189,8 +194,6 @@ export function getChartType(config) {
189194
config.metricFunction !== null // Event distribution chart relies on the ML function mapping to an ES aggregation
190195
) {
191196
chartType = CHART_TYPE.POPULATION_DISTRIBUTION;
192-
} else if (config.functionDescription === 'lat_long') {
193-
chartType = CHART_TYPE.GEO_MAP;
194197
}
195198

196199
if (

0 commit comments

Comments
 (0)