Allow user to select any field for cardinality in filter ratio aggregation for TSVB (#13762)
* Remove field selection restriction for cardinality * fixing a bug with filter ratio where not selecting a metric.field throws a fatal * Adding tests; fixing bug
This commit is contained in:
parent
f23f606383
commit
83b55721a3
|
@ -29,6 +29,8 @@ export const FilterRatioAgg = props => {
|
|||
const model = { ...defaults, ...props.model };
|
||||
const htmlId = htmlIdGenerator();
|
||||
|
||||
const restrictMode = model.metric_agg === 'cardinality' ? 'none' : 'numeric';
|
||||
|
||||
return (
|
||||
<AggRow
|
||||
disableDelete={props.disableDelete}
|
||||
|
@ -91,7 +93,7 @@ export const FilterRatioAgg = props => {
|
|||
id={htmlId('aggField')}
|
||||
fields={fields}
|
||||
type={model.metric_agg}
|
||||
restrict="numeric"
|
||||
restrict={restrictMode}
|
||||
indexPattern={indexPattern}
|
||||
value={model.field}
|
||||
onChange={handleSelectChange('field')}
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
import ratios from '../filter_ratios';
|
||||
import { expect } from 'chai';
|
||||
import sinon from 'sinon';
|
||||
|
||||
describe('ratios(req, panel, series)', () => {
|
||||
|
||||
let panel;
|
||||
let series;
|
||||
let req;
|
||||
beforeEach(() => {
|
||||
panel = {
|
||||
time_field: 'timestamp'
|
||||
};
|
||||
series = {
|
||||
id: 'test',
|
||||
split_mode: 'terms',
|
||||
terms_size: 10,
|
||||
terms_field: 'host',
|
||||
metrics: [
|
||||
{
|
||||
id: 'metric-1',
|
||||
type: 'filter_ratio',
|
||||
numerator: 'errors',
|
||||
denominator: '*',
|
||||
metric_agg: 'avg',
|
||||
field: 'cpu'
|
||||
}
|
||||
]
|
||||
};
|
||||
req = {
|
||||
payload: {
|
||||
timerange: {
|
||||
min: '2017-01-01T00:00:00Z',
|
||||
max: '2017-01-01T01:00:00Z'
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
it('calls next when finished', () => {
|
||||
const next = sinon.spy();
|
||||
ratios(req, panel, series)(next)({});
|
||||
expect(next.calledOnce).to.equal(true);
|
||||
});
|
||||
|
||||
it('returns filter ratio aggs', () => {
|
||||
const next = doc => doc;
|
||||
const doc = ratios(req, panel, series)(next)({});
|
||||
expect(doc).to.eql({
|
||||
aggs: {
|
||||
test: {
|
||||
aggs: {
|
||||
timeseries: {
|
||||
aggs: {
|
||||
'metric-1': {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
denominator: 'metric-1-denominator>metric',
|
||||
numerator: 'metric-1-numerator>metric',
|
||||
},
|
||||
script: 'params.numerator != null && params.denominator != null &&' +
|
||||
' params.denominator > 0 ? params.numerator / params.denominator : 0'
|
||||
}
|
||||
},
|
||||
'metric-1-denominator': {
|
||||
aggs: {
|
||||
metric: {
|
||||
avg: {
|
||||
field: 'cpu'
|
||||
}
|
||||
}
|
||||
},
|
||||
filter: {
|
||||
query_string: {
|
||||
analyze_wildcard: true,
|
||||
query: '*'
|
||||
}
|
||||
},
|
||||
},
|
||||
'metric-1-numerator': {
|
||||
aggs: {
|
||||
metric: {
|
||||
avg: {
|
||||
field: 'cpu'
|
||||
}
|
||||
}
|
||||
},
|
||||
filter: {
|
||||
query_string: {
|
||||
analyze_wildcard: true,
|
||||
query: 'errors'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('returns empty object when field is not set', () => {
|
||||
delete series.metrics[0].field;
|
||||
const next = doc => doc;
|
||||
const doc = ratios(req, panel, series)(next)({});
|
||||
expect(doc).to.eql({
|
||||
aggs: {
|
||||
test: {
|
||||
aggs: {
|
||||
timeseries: {
|
||||
aggs: {
|
||||
'metric-1': {
|
||||
bucket_script: {
|
||||
buckets_path: {
|
||||
denominator: 'metric-1-denominator>metric',
|
||||
numerator: 'metric-1-numerator>metric',
|
||||
},
|
||||
script: 'params.numerator != null && params.denominator != null &&' +
|
||||
' params.denominator > 0 ? params.numerator / params.denominator : 0'
|
||||
}
|
||||
},
|
||||
'metric-1-denominator': {
|
||||
aggs: { metric: {} },
|
||||
filter: {
|
||||
query_string: {
|
||||
analyze_wildcard: true,
|
||||
query: '*'
|
||||
}
|
||||
},
|
||||
},
|
||||
'metric-1-numerator': {
|
||||
aggs: { metric: {} },
|
||||
filter: {
|
||||
query_string: {
|
||||
analyze_wildcard: true,
|
||||
query: 'errors'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
|
@ -3,7 +3,7 @@ const filter = metric => metric.type === 'filter_ratio';
|
|||
import bucketTransform from '../../helpers/bucket_transform';
|
||||
import _ from 'lodash';
|
||||
export default function ratios(req, panel, series) {
|
||||
return () => doc => {
|
||||
return next => doc => {
|
||||
if (series.metrics.some(filter)) {
|
||||
series.metrics.filter(filter).forEach(metric => {
|
||||
_.set(doc, `aggs.${series.id}.aggs.timeseries.aggs.${metric.id}-numerator.filter`, {
|
||||
|
@ -17,12 +17,16 @@ export default function ratios(req, panel, series) {
|
|||
let denominatorPath = `${metric.id}-denominator>_count`;
|
||||
|
||||
if (metric.metric_agg !== 'count' && bucketTransform[metric.metric_agg]) {
|
||||
const aggBody = {
|
||||
metric: bucketTransform[metric.metric_agg]({
|
||||
let metricAgg;
|
||||
try {
|
||||
metricAgg = bucketTransform[metric.metric_agg]({
|
||||
type: metric.metric_agg,
|
||||
field: metric.field
|
||||
})
|
||||
};
|
||||
});
|
||||
} catch (e) {
|
||||
metricAgg = {};
|
||||
}
|
||||
const aggBody = { metric: metricAgg };
|
||||
_.set(doc, `aggs.${series.id}.aggs.timeseries.aggs.${metric.id}-numerator.aggs`, aggBody);
|
||||
_.set(doc, `aggs.${series.id}.aggs.timeseries.aggs.${metric.id}-denominator.aggs`, aggBody);
|
||||
numeratorPath = `${metric.id}-numerator>metric`;
|
||||
|
@ -40,6 +44,6 @@ export default function ratios(req, panel, series) {
|
|||
});
|
||||
});
|
||||
}
|
||||
return doc;
|
||||
return next(doc);
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue