mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
Disabling Math Aggregation (#15653)
* Disabling Math aggregation * Removing mathjs dependency
This commit is contained in:
parent
2d1d7e0cff
commit
80e60a0f28
9 changed files with 22 additions and 122 deletions
|
@ -150,7 +150,6 @@
|
|||
"lodash": "3.10.1",
|
||||
"lru-cache": "4.1.1",
|
||||
"markdown-it": "8.3.2",
|
||||
"mathjs": "3.16.2",
|
||||
"minimatch": "2.0.10",
|
||||
"mkdirp": "0.5.1",
|
||||
"moment": "2.13.0",
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import StdAgg from './std_agg';
|
||||
import aggToComponent from '../lib/agg_to_component';
|
||||
import { sortable } from 'react-anything-sortable';
|
||||
import { UnsupportedAgg } from './unsupported_agg';
|
||||
|
||||
function Agg(props) {
|
||||
const { model } = props;
|
||||
let Component = aggToComponent[model.type];
|
||||
if (!Component) {
|
||||
Component = StdAgg;
|
||||
Component = UnsupportedAgg;
|
||||
}
|
||||
const style = {
|
||||
cursor: 'default',
|
||||
|
|
|
@ -39,8 +39,7 @@ const siblingAggs = [
|
|||
];
|
||||
|
||||
const specialAggs = [
|
||||
{ label: 'Series Agg', value: 'series_agg' },
|
||||
{ label: 'Math', value: 'math' }
|
||||
{ label: 'Series Agg', value: 'series_agg' }
|
||||
];
|
||||
|
||||
class AggSelectOption extends Component {
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
import AggRow from './agg_row';
|
||||
import React from 'react';
|
||||
export function UnsupportedAgg(props) {
|
||||
return (
|
||||
<AggRow
|
||||
disableDelete={props.disableDelete}
|
||||
model={props.model}
|
||||
onAdd={props.onAdd}
|
||||
onDelete={props.onDelete}
|
||||
siblings={props.siblings}
|
||||
>
|
||||
<div className="vis_editor__row_item">
|
||||
<p>The <code>{props.model.type}</code> aggregation is no longer supported.</p>
|
||||
</div>
|
||||
</AggRow>
|
||||
);
|
||||
|
||||
}
|
|
@ -12,7 +12,6 @@ import { PositiveOnlyAgg } from '../aggs/positive_only';
|
|||
import { FilterRatioAgg } from '../aggs/filter_ratio';
|
||||
import { PercentileRankAgg } from '../aggs/percentile_rank';
|
||||
import { Static } from '../aggs/static';
|
||||
import MathAgg from '../aggs/math';
|
||||
export default {
|
||||
count: StdAgg,
|
||||
avg: StdAgg,
|
||||
|
@ -41,8 +40,7 @@ export default {
|
|||
serial_diff: SerialDiffAgg,
|
||||
filter_ratio: FilterRatioAgg,
|
||||
positive_only: PositiveOnlyAgg,
|
||||
static: Static,
|
||||
math: MathAgg
|
||||
static: Static
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ import stdMetric from './std_metric';
|
|||
import stdSibling from './std_sibling';
|
||||
import timeShift from './time_shift';
|
||||
import { dropLastBucket } from './drop_last_bucket';
|
||||
import { mathAgg } from './math';
|
||||
|
||||
export default [
|
||||
percentile,
|
||||
|
@ -14,7 +13,6 @@ export default [
|
|||
stdDeviationSibling,
|
||||
stdMetric,
|
||||
stdSibling,
|
||||
mathAgg,
|
||||
seriesAgg,
|
||||
timeShift,
|
||||
dropLastBucket
|
||||
|
|
|
@ -1,102 +0,0 @@
|
|||
const percentileValueMatch = /\[([0-9\.]+)\]$/;
|
||||
import { startsWith, flatten, values, first, last } from 'lodash';
|
||||
import getDefaultDecoration from '../../helpers/get_default_decoration';
|
||||
import getSiblingAggValue from '../../helpers/get_sibling_agg_value';
|
||||
import getSplits from '../../helpers/get_splits';
|
||||
import mapBucket from '../../helpers/map_bucket';
|
||||
import mathjs from 'mathjs';
|
||||
|
||||
const limitedEval = mathjs.eval;
|
||||
mathjs.import({
|
||||
'import': function () { throw new Error('Function import is not allowed in your expression.'); },
|
||||
'createUnit': function () { throw new Error('Function createUnit is not allowed in your expression.'); },
|
||||
'eval': function () { throw new Error('Function eval is not allowed in your expression.'); },
|
||||
'parse': function () { throw new Error('Function parse is not allowed in your expression.'); },
|
||||
'simplify': function () { throw new Error('Function simplify is not allowed in your expression.'); },
|
||||
'derivative': function () { throw new Error('Function derivative is not allowed in your expression.'); }
|
||||
}, { override: true });
|
||||
|
||||
export function mathAgg(resp, panel, series) {
|
||||
return next => results => {
|
||||
const mathMetric = last(series.metrics);
|
||||
if (mathMetric.type !== 'math') return next(results);
|
||||
// Filter the results down to only the ones that match the series.id. Sometimes
|
||||
// there will be data from other series mixed in.
|
||||
results = results.filter(s => {
|
||||
if (s.id.split(/:/)[0] === series.id) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
const decoration = getDefaultDecoration(series);
|
||||
const splits = getSplits(resp, panel, series);
|
||||
const mathSeries = splits.map((split) => {
|
||||
if (mathMetric.variables.length) {
|
||||
// Gather the data for the splits. The data will either be a sibling agg or
|
||||
// a standard metric/pipeline agg
|
||||
const splitData = mathMetric.variables.reduce((acc, v) => {
|
||||
const metric = series.metrics.find(m => startsWith(v.field, m.id));
|
||||
if (!metric) return acc;
|
||||
if (/_bucket$/.test(metric.type)) {
|
||||
acc[v.name] = split.timeseries.buckets.map(bucket => {
|
||||
return [bucket.key, getSiblingAggValue(split, metric)];
|
||||
});
|
||||
} else {
|
||||
const percentileMatch = v.field.match(percentileValueMatch);
|
||||
const m = percentileMatch ? { ...metric, percent: percentileMatch[1] } : { ...metric };
|
||||
acc[v.name] = split.timeseries.buckets.map(mapBucket(m));
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
// Create an params._all so the users can access the entire series of data
|
||||
// in the Math.js equation
|
||||
const all = Object.keys(splitData).reduce((acc, key) => {
|
||||
acc[key] = {
|
||||
values: splitData[key].map(x => x[1]),
|
||||
timestamps: splitData[key].map(x => x[0])
|
||||
};
|
||||
return acc;
|
||||
}, {});
|
||||
// Get the first var and check that it shows up in the split data otherwise
|
||||
// we need to return an empty array for the data since we can't opperate
|
||||
// without the first varaible
|
||||
const firstVar = first(mathMetric.variables);
|
||||
if (!splitData[firstVar.name]) {
|
||||
return {
|
||||
id: split.id,
|
||||
label: split.label,
|
||||
color: split.color,
|
||||
data: [],
|
||||
...decoration
|
||||
};
|
||||
}
|
||||
// Use the first var to collect all the timestamps
|
||||
const timestamps = splitData[firstVar.name].map(r => first(r));
|
||||
// Map the timestamps to actual data
|
||||
const data = timestamps.map((ts, index) => {
|
||||
const params = mathMetric.variables.reduce((acc, v) => {
|
||||
acc[v.name] = last(splitData[v.name].find(row => row[0] === ts));
|
||||
return acc;
|
||||
}, {});
|
||||
// If some of the values are null, return the timestamp and null, this is
|
||||
// a safety check for the user
|
||||
const someNull = values(params).some(v => v == null);
|
||||
if (someNull) return [ts, null];
|
||||
// calculate the result based on the user's script and return the value
|
||||
const result = limitedEval(mathMetric.script, { params: { ...params, _index: index, _timestamp: ts, _all: all } });
|
||||
// if the result is an object (usually when the user is working with maps and functions) flatten the results and return the last value.
|
||||
if (typeof result === 'object') return [ts, last(flatten(result.valueOf()))];
|
||||
return [ts, result];
|
||||
});
|
||||
return {
|
||||
id: split.id,
|
||||
label: split.label,
|
||||
color: split.color,
|
||||
data,
|
||||
...decoration
|
||||
};
|
||||
}
|
||||
});
|
||||
return next(results.concat(mathSeries));
|
||||
};
|
||||
}
|
|
@ -2,14 +2,12 @@
|
|||
import stdMetric from './std_metric';
|
||||
import stdSibling from './std_sibling';
|
||||
import seriesAgg from './series_agg';
|
||||
import { math } from './math';
|
||||
import { dropLastBucketFn } from './drop_last_bucket';
|
||||
|
||||
export default [
|
||||
// percentile,
|
||||
stdMetric,
|
||||
stdSibling,
|
||||
math,
|
||||
seriesAgg,
|
||||
dropLastBucketFn
|
||||
];
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
import { mathAgg } from '../series/math';
|
||||
|
||||
export function math(bucket, panel, series) {
|
||||
return next => results => {
|
||||
const mathFn = mathAgg({ aggregations: bucket }, panel, series);
|
||||
return mathFn(next)(results);
|
||||
};
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue