[ML] Fix Anomaly Table update trigger (#18769) (#18774)

Fixes an issue with the anomaly table not correctly updating in the anomaly explorer and the anomaly markers not showing up in the time series viewer.
- moves the initialization of scope.anomalyRecords = []; to the controllers of anomaly explorer and time series viewer. having it in the anomaly table directive caused a race condition to overwrite already fetched records.
- use $watchCollection instead of $watch to track anomalyRecords and focusChartData changes.
replaces $timeouts with scope.$evalAsync
- fixes how focusChartData gets updated correctly to fix missing anomaly markers in the time series viewer.
This commit is contained in:
Walter Rafelsberger 2018-05-04 07:00:22 +02:00 committed by GitHub
parent 3e3106901c
commit a77e2bfc4b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 17 additions and 16 deletions

View file

@ -84,7 +84,6 @@ module.directive('mlAnomaliesTable', function (
scope.table.columns = []; scope.table.columns = [];
scope.table.rows = []; scope.table.rows = [];
scope.rowScopes = []; scope.rowScopes = [];
scope.anomalyRecords = [];
scope.influencersLimit = 5; scope.influencersLimit = 5;
@ -94,7 +93,7 @@ module.directive('mlAnomaliesTable', function (
mlSelectIntervalService.state.watch(updateTableData); mlSelectIntervalService.state.watch(updateTableData);
mlSelectSeverityService.state.watch(updateTableData); mlSelectSeverityService.state.watch(updateTableData);
scope.$watch('anomalyRecords', updateTableData); scope.$watchCollection('anomalyRecords', updateTableData);
element.on('$destroy', () => { element.on('$destroy', () => {
mlSelectIntervalService.state.unwatch(updateTableData); mlSelectIntervalService.state.unwatch(updateTableData);

View file

@ -82,6 +82,7 @@ module.controller('MlExplorerController', function (
const ALLOW_CELL_RANGE_SELECTION = mlExplorerDashboardService.allowCellRangeSelection; const ALLOW_CELL_RANGE_SELECTION = mlExplorerDashboardService.allowCellRangeSelection;
let disableDragSelectOnMouseLeave = true; let disableDragSelectOnMouseLeave = true;
$scope.queryFilters = []; $scope.queryFilters = [];
$scope.anomalyRecords = [];
const dragSelect = new DragSelect({ const dragSelect = new DragSelect({
selectables: document.querySelectorAll('.sl-cell'), selectables: document.querySelectorAll('.sl-cell'),
@ -171,11 +172,11 @@ module.controller('MlExplorerController', function (
) )
.then((resp) => { .then((resp) => {
// Need to use $timeout to ensure the update happens after the child scope is updated with the new data. // Need to use $timeout to ensure the update happens after the child scope is updated with the new data.
$timeout(() => { $scope.$evalAsync(() => {
// Sort in descending time order before storing in scope. // Sort in descending time order before storing in scope.
$scope.anomalyRecords = _.chain(resp.records).sortBy(record => record[$scope.timeFieldName]).reverse().value(); $scope.anomalyRecords = _.chain(resp.records).sortBy(record => record[$scope.timeFieldName]).reverse().value();
console.log('Explorer anomalies table data set:', $scope.anomalyRecords); console.log('Explorer anomalies table data set:', $scope.anomalyRecords);
}, 0); });
}); });
}; };

View file

@ -114,9 +114,8 @@ module.directive('mlTimeseriesChart', function (
drawContextChartSelection(); drawContextChartSelection();
}); });
scope.$watch('focusChartData', renderFocusChart); scope.$watchCollection('focusChartData', renderFocusChart);
scope.$watch('showModelBounds', renderFocusChart); scope.$watchGroup(['showModelBounds', 'showForecast'], renderFocusChart);
scope.$watch('showForecast', renderFocusChart);
// Redraw the charts when the container is resize. // Redraw the charts when the container is resize.
const resizeChecker = new ResizeChecker(angular.element('.ml-timeseries-chart')); const resizeChecker = new ResizeChecker(angular.element('.ml-timeseries-chart'));

View file

@ -88,6 +88,7 @@ module.controller('MlTimeSeriesExplorerController', function (
$scope.loading = true; $scope.loading = true;
$scope.loadCounter = 0; $scope.loadCounter = 0;
$scope.hasResults = false; $scope.hasResults = false;
$scope.anomalyRecords = [];
$scope.modelPlotEnabled = false; $scope.modelPlotEnabled = false;
$scope.showModelBounds = true; // Toggles display of model bounds in the focus chart $scope.showModelBounds = true; // Toggles display of model bounds in the focus chart
@ -350,20 +351,21 @@ module.controller('MlTimeSeriesExplorerController', function (
if (awaitingCount === 0) { if (awaitingCount === 0) {
// Tell the results container directives to render the focus chart. // Tell the results container directives to render the focus chart.
// Need to use $timeout to ensure the broadcast happens after the child scope is updated with the new data. // Need to use $timeout to ensure the broadcast happens after the child scope is updated with the new data.
$timeout(() => { let updatedFocusChartData = processDataForFocusAnomalies(
processDataForFocusAnomalies( $scope.focusChartData,
$scope.focusChartData, $scope.anomalyRecords,
$scope.anomalyRecords, $scope.timeFieldName);
$scope.timeFieldName);
processScheduledEventsForChart( updatedFocusChartData = processScheduledEventsForChart(
$scope.focusChartData, $scope.focusChartData,
$scope.scheduledEvents); $scope.scheduledEvents);
$scope.$evalAsync(() => {
$scope.focusChartData = updatedFocusChartData;
console.log('Time series explorer focus chart data set:', $scope.focusChartData); console.log('Time series explorer focus chart data set:', $scope.focusChartData);
$scope.loading = false; $scope.loading = false;
}, 0); });
} }
} }