[ML] Aggregate anomalies table data using configured Kibana timezone (#26192)

* [ML] Aggregate anomalies table data using configured Kibana timezone

* [ML] Move dataFormatTz prop out of controller scope
This commit is contained in:
Pete Harverson 2018-11-27 11:49:47 +00:00 committed by GitHub
parent 51a418ea43
commit d97609eaeb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 30 additions and 8 deletions

View file

@ -15,7 +15,7 @@
import _ from 'lodash';
import $ from 'jquery';
import DragSelect from 'dragselect';
import moment from 'moment';
import moment from 'moment-timezone';
import 'plugins/ml/components/anomalies_table';
import 'plugins/ml/components/controls';
@ -76,6 +76,7 @@ module.controller('MlExplorerController', function (
$timeout,
AppState,
Private,
config,
mlCheckboxShowChartsService,
mlSelectLimitService,
mlSelectIntervalService,
@ -87,6 +88,10 @@ module.controller('MlExplorerController', function (
timefilter.enableTimeRangeSelector();
timefilter.enableAutoRefreshSelector();
// Pass the timezone to the server for use when aggregating anomalies (by day / hour) for the table.
const tzConfig = config.get('dateFormat:tz');
const dateFormatTz = (tzConfig !== 'Browser') ? tzConfig : moment.tz.guess();
const TimeBuckets = Private(IntervalHelperProvider);
const queryFilter = Private(FilterBarQueryFilterProvider);
const mlJobSelectService = Private(JobSelectServiceProvider);
@ -946,6 +951,7 @@ module.controller('MlExplorerController', function (
mlSelectSeverityService.state.get('threshold').val,
timeRange.earliestMs,
timeRange.latestMs,
dateFormatTz,
500,
MAX_CATEGORY_EXAMPLES
).then((resp) => {

View file

@ -21,6 +21,7 @@ export const results = {
threshold,
earliestMs,
latestMs,
dateFormatTz,
maxRecords,
maxExamples) {
@ -35,6 +36,7 @@ export const results = {
threshold,
earliestMs,
latestMs,
dateFormatTz,
maxRecords,
maxExamples
}

View file

@ -13,7 +13,7 @@
*/
import _ from 'lodash';
import moment from 'moment';
import moment from 'moment-timezone';
import 'plugins/ml/components/anomalies_table';
import 'plugins/ml/components/controls';
@ -71,6 +71,7 @@ module.controller('MlTimeSeriesExplorerController', function (
$timeout,
Private,
AppState,
config,
mlSelectIntervalService,
mlSelectSeverityService) {
@ -98,6 +99,10 @@ module.controller('MlTimeSeriesExplorerController', function (
$scope.showForecast = true; // Toggles display of forecast data in the focus chart
$scope.showForecastCheckbox = false;
// Pass the timezone to the server for use when aggregating anomalies (by day / hour) for the table.
const tzConfig = config.get('dateFormat:tz');
const dateFormatTz = (tzConfig !== 'Browser') ? tzConfig : moment.tz.guess();
$scope.permissions = {
canForecastJob: checkPermission('canForecastJob')
};
@ -682,6 +687,7 @@ module.controller('MlTimeSeriesExplorerController', function (
}
function loadAnomaliesTableData(earliestMs, latestMs) {
ml.results.getAnomaliesTableData(
[$scope.selectedJob.job_id],
$scope.criteriaFields,
@ -690,6 +696,7 @@ module.controller('MlTimeSeriesExplorerController', function (
mlSelectSeverityService.state.get('threshold').val,
earliestMs,
latestMs,
dateFormatTz,
ANOMALIES_MAX_RESULTS
).then((resp) => {
const anomalies = resp.anomalies;

View file

@ -6,7 +6,7 @@
import _ from 'lodash';
import moment from 'moment';
import moment from 'moment-timezone';
import {
getEntityFieldName,
@ -17,13 +17,15 @@ import {
// Builds the items for display in the anomalies table from the supplied list of anomaly records.
export function buildAnomalyTableItems(anomalyRecords, aggregationInterval) {
// Provide the timezone to use for aggregating anomalies (by day or hour) as set in the
// Kibana dateFormat:tz setting.
export function buildAnomalyTableItems(anomalyRecords, aggregationInterval, dateFormatTz) {
// Aggregate the anomaly records if necessary, and create skeleton display records with
// time, detector (description) and source record properties set.
let displayRecords = [];
if (aggregationInterval !== 'second') {
displayRecords = aggregateAnomalies(anomalyRecords, aggregationInterval);
displayRecords = aggregateAnomalies(anomalyRecords, aggregationInterval, dateFormatTz);
} else {
// Show all anomaly records.
displayRecords = anomalyRecords.map((record) => {
@ -115,7 +117,7 @@ export function buildAnomalyTableItems(anomalyRecords, aggregationInterval) {
});
}
function aggregateAnomalies(anomalyRecords, interval) {
function aggregateAnomalies(anomalyRecords, interval, dateFormatTz) {
// Aggregate the anomaly records by time, jobId, detectorIndex, and entity (by/over/partition).
// anomalyRecords assumed to be supplied in ascending time order.
if (anomalyRecords.length === 0) {
@ -125,7 +127,9 @@ function aggregateAnomalies(anomalyRecords, interval) {
const aggregatedData = {};
anomalyRecords.forEach((record) => {
// Use moment.js to get start of interval.
const roundedTime = moment(record.timestamp).startOf(interval).valueOf();
const roundedTime = (dateFormatTz !== undefined) ?
moment(record.timestamp).tz(dateFormatTz).startOf(interval).valueOf() :
moment(record.timestamp).startOf(interval).valueOf();
if (aggregatedData[roundedTime] === undefined) {
aggregatedData[roundedTime] = {};
}

View file

@ -35,6 +35,7 @@ export function resultsServiceProvider(callWithRequest) {
threshold,
earliestMs,
latestMs,
dateFormatTz,
maxRecords = DEFAULT_QUERY_SIZE,
maxExamples = DEFAULT_MAX_EXAMPLES) {
@ -163,7 +164,7 @@ export function resultsServiceProvider(callWithRequest) {
tableData.interval = (daysDiff < 2 ? 'hour' : 'day');
}
tableData.anomalies = buildAnomalyTableItems(records, tableData.interval);
tableData.anomalies = buildAnomalyTableItems(records, tableData.interval, dateFormatTz);
// Load examples for any categorization anomalies.
const categoryAnomalies = tableData.anomalies.filter(item => item.entityName === 'mlcategory');

View file

@ -21,6 +21,7 @@ function getAnomaliesTableData(callWithRequest, payload) {
threshold,
earliestMs,
latestMs,
dateFormatTz,
maxRecords,
maxExamples } = payload;
return rs.getAnomaliesTableData(
@ -31,6 +32,7 @@ function getAnomaliesTableData(callWithRequest, payload) {
threshold,
earliestMs,
latestMs,
dateFormatTz,
maxRecords,
maxExamples);
}