mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
Support to restore baseline/deviation time ranges from url state on full page refresh. Also updates functional tests to include a full page refresh after the first analysis run for each dataset.
147 lines
5 KiB
TypeScript
147 lines
5 KiB
TypeScript
/*
|
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
* or more contributor license agreements. Licensed under the Elastic License
|
|
* 2.0; you may not use this file except in compliance with the Elastic License
|
|
* 2.0.
|
|
*/
|
|
|
|
import { isPopulatedObject } from '@kbn/ml-is-populated-object';
|
|
|
|
/**
|
|
* Time range definition for baseline and deviation to be used by log rate analysis.
|
|
*
|
|
* @export
|
|
* @interface WindowParameters
|
|
* @typedef {WindowParameters}
|
|
*/
|
|
export interface WindowParameters {
|
|
/** Baseline minimum value */
|
|
baselineMin: number;
|
|
/** Baseline maximum value */
|
|
baselineMax: number;
|
|
/** Deviation minimum value */
|
|
deviationMin: number;
|
|
/** Deviation maximum value */
|
|
deviationMax: number;
|
|
}
|
|
|
|
/**
|
|
* Type guard for WindowParameters
|
|
*
|
|
* @param {unknown} arg - The argument to be checked.
|
|
* @returns {arg is WindowParameters}
|
|
*/
|
|
export const isWindowParameters = (arg: unknown): arg is WindowParameters =>
|
|
isPopulatedObject(arg, ['baselineMin', 'baselineMax', 'deviationMin', 'deviationMax']) &&
|
|
Object.values(arg).every((d) => typeof d === 'number');
|
|
|
|
/**
|
|
* Given a point in time (e.g. where a user clicks), use simple heuristics to compute:
|
|
*
|
|
* 1. The time window around the click to evaluate for changes
|
|
* 2. The historical time window prior to the click to use as a baseline.
|
|
*
|
|
* The philosophy here is that charts are displayed with different granularities according to their
|
|
* overall time window. We select the log deviation and historical time windows inline with the
|
|
* overall time window.
|
|
*
|
|
* The algorithm for doing this is based on the typical granularities that exist in machine data.
|
|
*
|
|
* @param clickTime timestamp of the clicked log rate deviation.
|
|
* @param minTime minimum timestamp of the time window to be analysed
|
|
* @param maxTime maximum timestamp of the time window to be analysed
|
|
* @returns WindowParameters
|
|
*/
|
|
export const getWindowParameters = (
|
|
clickTime: number,
|
|
minTime: number,
|
|
maxTime: number
|
|
): WindowParameters => {
|
|
const totalWindow = maxTime - minTime;
|
|
|
|
// min deviation window
|
|
const minDeviationWindow = 10 * 60 * 1000; // 10min
|
|
const minBaselineWindow = 30 * 60 * 1000; // 30min
|
|
const minWindowGap = 5 * 60 * 1000; // 5min
|
|
|
|
// work out bounds as done in the original notebooks,
|
|
// with the deviation window aiming to be a 1/10
|
|
// of the size of the total window and the baseline window
|
|
// being 3.5/10 of the total window.
|
|
const deviationWindow = Math.max(totalWindow / 10, minDeviationWindow);
|
|
const baselineWindow = Math.max(totalWindow / 3.5, minBaselineWindow);
|
|
const windowGap = Math.max(totalWindow / 10, minWindowGap);
|
|
|
|
const deviationMin = clickTime - deviationWindow / 2;
|
|
const deviationMax = clickTime + deviationWindow / 2;
|
|
|
|
const baselineMax = deviationMin - windowGap;
|
|
const baselineMin = baselineMax - baselineWindow;
|
|
|
|
return {
|
|
baselineMin: Math.round(baselineMin),
|
|
baselineMax: Math.round(baselineMax),
|
|
deviationMin: Math.round(deviationMin),
|
|
deviationMax: Math.round(deviationMax),
|
|
};
|
|
};
|
|
|
|
/**
|
|
*
|
|
* Converts window paramaters from the brushes to “snap” the brushes to the chart histogram bar width and ensure timestamps
|
|
* correspond to bucket timestamps
|
|
*
|
|
* @param windowParameters time range definition for baseline and deviation to be used by log rate analysis
|
|
* @param snapTimestamps time range definition that always corresponds to histogram bucket timestamps
|
|
* @returns WindowParameters
|
|
*/
|
|
export const getSnappedWindowParameters = (
|
|
windowParameters: WindowParameters,
|
|
snapTimestamps: number[]
|
|
): WindowParameters => {
|
|
const snappedBaselineMin = snapTimestamps.reduce((pts, cts) => {
|
|
if (
|
|
Math.abs(cts - windowParameters.baselineMin) < Math.abs(pts - windowParameters.baselineMin)
|
|
) {
|
|
return cts;
|
|
}
|
|
return pts;
|
|
}, snapTimestamps[0]);
|
|
const baselineMaxTimestamps = snapTimestamps.filter((ts) => ts > snappedBaselineMin);
|
|
|
|
const snappedBaselineMax = baselineMaxTimestamps.reduce((pts, cts) => {
|
|
if (
|
|
Math.abs(cts - windowParameters.baselineMax) < Math.abs(pts - windowParameters.baselineMax)
|
|
) {
|
|
return cts;
|
|
}
|
|
return pts;
|
|
}, baselineMaxTimestamps[0]);
|
|
const deviationMinTss = baselineMaxTimestamps.filter((ts) => ts > snappedBaselineMax);
|
|
|
|
const snappedDeviationMin = deviationMinTss.reduce((pts, cts) => {
|
|
if (
|
|
Math.abs(cts - windowParameters.deviationMin) < Math.abs(pts - windowParameters.deviationMin)
|
|
) {
|
|
return cts;
|
|
}
|
|
return pts;
|
|
}, deviationMinTss[0]);
|
|
const deviationMaxTss = deviationMinTss.filter((ts) => ts > snappedDeviationMin);
|
|
|
|
const snappedDeviationMax = deviationMaxTss.reduce((pts, cts) => {
|
|
if (
|
|
Math.abs(cts - windowParameters.deviationMax) < Math.abs(pts - windowParameters.deviationMax)
|
|
) {
|
|
return cts;
|
|
}
|
|
return pts;
|
|
}, deviationMaxTss[0]);
|
|
|
|
return {
|
|
baselineMin: snappedBaselineMin,
|
|
baselineMax: snappedBaselineMax,
|
|
deviationMin: snappedDeviationMin,
|
|
deviationMax: snappedDeviationMax,
|
|
};
|
|
};
|