cumulative sum, moving avg and serial diff pipeline aggregation metric (#10033)

* extracting to parent agg helper

* adding comulative sum agg

* adding serial diff and moving avg

* adding tests
This commit is contained in:
Peter Pisljar 2017-02-15 20:03:45 +01:00 committed by GitHub
parent c3c8e55e4d
commit 723c7c15c9
8 changed files with 265 additions and 176 deletions

View file

@ -1,128 +0,0 @@
import _ from 'lodash';
import expect from 'expect.js';
import ngMock from 'ng_mock';
import DerivativeProvider from 'ui/agg_types/metrics/derivative';
import VisProvider from 'ui/vis';
import StubbedIndexPattern from 'fixtures/stubbed_logstash_index_pattern';
describe('Derivative metric', function () {
let aggDsl;
let derivativeMetric;
let aggConfig;
function init(settings) {
ngMock.module('kibana');
ngMock.inject(function (Private) {
const Vis = Private(VisProvider);
const indexPattern = Private(StubbedIndexPattern);
derivativeMetric = Private(DerivativeProvider);
const params = settings || {
metricAgg: '1',
customMetric: null
};
const vis = new Vis(indexPattern, {
title: 'New Visualization',
type: 'metric',
params: {
fontSize: 60,
handleNoResults: true
},
aggs: [
{
id: '1',
type: 'count',
schema: 'metric'
},
{
id: '2',
type: 'derivative',
schema: 'metric',
params
}
],
listeners: {}
});
// Grab the aggConfig off the vis (we don't actually use the vis for anything else)
aggConfig = vis.aggs[1];
aggDsl = aggConfig.toDsl();
});
}
it('should return a label prefixed with Derivative of', function () {
init();
expect(derivativeMetric.makeLabel(aggConfig)).to.eql('Derivative of Count');
});
it('should return a label Derivative of max bytes', function () {
init({
metricAgg: 'custom',
customMetric: {
id:'1-orderAgg',
type: 'max',
params: { field: 'bytes' },
schema: 'orderAgg'
}
});
expect(derivativeMetric.makeLabel(aggConfig)).to.eql('Derivative of Max bytes');
});
it('should return a label prefixed with number of derivative', function () {
init({
metricAgg: 'custom',
customMetric: {
id:'2-orderAgg',
type: 'derivative',
params: {
buckets_path: 'custom',
customMetric: {
id:'2-orderAgg-orderAgg',
type: 'count',
schema: 'orderAgg'
}
},
schema: 'orderAgg'
}
});
expect(derivativeMetric.makeLabel(aggConfig)).to.eql('2. derivative of Count');
});
it('should set parent aggs', function () {
init({
metricAgg: 'custom',
customMetric: {
id:'2-metric',
type: 'max',
params: { field: 'bytes' },
schema: 'orderAgg'
}
});
expect(aggDsl.derivative.buckets_path).to.be('2-metric');
expect(aggDsl.parentAggs['2-metric'].max.field).to.be('bytes');
});
it('should set nested parent aggs', function () {
init({
metricAgg: 'custom',
customMetric: {
id:'2-metric',
type: 'derivative',
params: {
buckets_path: 'custom',
customMetric: {
id:'2-metric-metric',
type: 'max',
params: { field: 'bytes' },
schema: 'orderAgg'
}
},
schema: 'orderAgg'
}
});
expect(aggDsl.derivative.buckets_path).to.be('2-metric');
expect(aggDsl.parentAggs['2-metric'].derivative.buckets_path).to.be('2-metric-metric');
});
});

View file

@ -0,0 +1,144 @@
import _ from 'lodash';
import expect from 'expect.js';
import ngMock from 'ng_mock';
import DerivativeProvider from 'ui/agg_types/metrics/derivative';
import CumulativeSumProvider from 'ui/agg_types/metrics/cumulative_sum';
import MovingAvgProvider from 'ui/agg_types/metrics/moving_avg';
import SerialDiffProvider from 'ui/agg_types/metrics/serial_diff';
import VisProvider from 'ui/vis';
import StubbedIndexPattern from 'fixtures/stubbed_logstash_index_pattern';
const metrics = [
{ name: 'derivative', title: 'Derivative', provider: DerivativeProvider },
{ name: 'cumulative_sum', title: 'Cumulative Sum', provider: CumulativeSumProvider },
{ name: 'moving_avg', title: 'Moving Avg', provider: MovingAvgProvider },
{ name: 'serial_diff', title: 'Serial Diff', provider: SerialDiffProvider },
];
describe('parent pipeline aggs', function () {
metrics.forEach(metric => {
describe(`${metric.title} metric`, function () {
let aggDsl;
let metricAgg;
let aggConfig;
function init(settings) {
ngMock.module('kibana');
ngMock.inject(function (Private) {
const Vis = Private(VisProvider);
const indexPattern = Private(StubbedIndexPattern);
metricAgg = Private(metric.provider);
const params = settings || {
metricAgg: '1',
customMetric: null
};
const vis = new Vis(indexPattern, {
title: 'New Visualization',
type: 'metric',
params: {
fontSize: 60,
handleNoResults: true
},
aggs: [
{
id: '1',
type: 'count',
schema: 'metric'
},
{
id: '2',
type: metric.name,
schema: 'metric',
params
}
],
listeners: {}
});
// Grab the aggConfig off the vis (we don't actually use the vis for anything else)
aggConfig = vis.aggs[1];
aggDsl = aggConfig.toDsl();
});
}
it(`should return a label prefixed with ${metric.title} of`, function () {
init();
expect(metricAgg.makeLabel(aggConfig)).to.eql(`${metric.title} of Count`);
});
it(`should return a label ${metric.title} of max bytes`, function () {
init({
metricAgg: 'custom',
customMetric: {
id:'1-orderAgg',
type: 'max',
params: { field: 'bytes' },
schema: 'orderAgg'
}
});
expect(metricAgg.makeLabel(aggConfig)).to.eql(`${metric.title} of Max bytes`);
});
it(`should return a label prefixed with number of ${metric.title.toLowerCase()}`, function () {
init({
metricAgg: 'custom',
customMetric: {
id:'2-orderAgg',
type: metric.name,
params: {
buckets_path: 'custom',
customMetric: {
id:'2-orderAgg-orderAgg',
type: 'count',
schema: 'orderAgg'
}
},
schema: 'orderAgg'
}
});
expect(metricAgg.makeLabel(aggConfig)).to.eql(`2. ${metric.title.toLowerCase()} of Count`);
});
it('should set parent aggs', function () {
init({
metricAgg: 'custom',
customMetric: {
id:'2-metric',
type: 'max',
params: { field: 'bytes' },
schema: 'orderAgg'
}
});
expect(aggDsl[metric.name].buckets_path).to.be('2-metric');
expect(aggDsl.parentAggs['2-metric'].max.field).to.be('bytes');
});
it('should set nested parent aggs', function () {
init({
metricAgg: 'custom',
customMetric: {
id:'2-metric',
type: metric.name,
params: {
buckets_path: 'custom',
customMetric: {
id:'2-metric-metric',
type: 'max',
params: { field: 'bytes' },
schema: 'orderAgg'
}
},
schema: 'orderAgg'
}
});
expect(aggDsl[metric.name].buckets_path).to.be('2-metric');
expect(aggDsl.parentAggs['2-metric'][metric.name].buckets_path).to.be('2-metric-metric');
});
});
});
});

View file

@ -12,6 +12,9 @@ import AggTypesMetricsCardinalityProvider from 'ui/agg_types/metrics/cardinality
import AggTypesMetricsPercentilesProvider from 'ui/agg_types/metrics/percentiles';
import AggTypesMetricsPercentileRanksProvider from 'ui/agg_types/metrics/percentile_ranks';
import AggTypesMetricsDerivativeProvider from 'ui/agg_types/metrics/derivative';
import AggTypesMetricsCumulativeSumProvider from 'ui/agg_types/metrics/cumulative_sum';
import AggTypesMetricsMovingAvgProvider from 'ui/agg_types/metrics/moving_avg';
import AggTypesMetricsSerialDiffProvider from 'ui/agg_types/metrics/serial_diff';
import AggTypesBucketsDateHistogramProvider from 'ui/agg_types/buckets/date_histogram';
import AggTypesBucketsHistogramProvider from 'ui/agg_types/buckets/histogram';
import AggTypesBucketsRangeProvider from 'ui/agg_types/buckets/range';
@ -37,6 +40,9 @@ export default function AggTypeService(Private) {
Private(AggTypesMetricsPercentileRanksProvider),
Private(AggTypesMetricsTopHitProvider),
Private(AggTypesMetricsDerivativeProvider),
Private(AggTypesMetricsCumulativeSumProvider),
Private(AggTypesMetricsMovingAvgProvider),
Private(AggTypesMetricsSerialDiffProvider)
],
buckets: [
Private(AggTypesBucketsDateHistogramProvider),

View file

@ -0,0 +1,17 @@
import AggTypesMetricsMetricAggTypeProvider from 'ui/agg_types/metrics/metric_agg_type';
import ParentPipelineAggHelperProvider from './lib/parent_pipeline_agg_helper';
import { makeNestedLabel } from './lib/make_nested_label';
export default function AggTypeMetricComulativeSumProvider(Private) {
const MetricAggType = Private(AggTypesMetricsMetricAggTypeProvider);
const parentPipelineAggHelper = Private(ParentPipelineAggHelperProvider);
return new MetricAggType({
name: 'cumulative_sum',
title: 'Cumulative Sum',
makeLabel: agg => makeNestedLabel(agg, 'cumulative sum'),
params: [
...parentPipelineAggHelper.params()
]
});
}

View file

@ -1,62 +1,17 @@
import AggTypesMetricsMetricAggTypeProvider from 'ui/agg_types/metrics/metric_agg_type';
import metricAggTemplate from 'ui/agg_types/controls/sub_agg.html';
import _ from 'lodash';
import VisAggConfigProvider from 'ui/vis/agg_config';
import VisSchemasProvider from 'ui/vis/schemas';
import ParentPipelineAggHelperProvider from './lib/parent_pipeline_agg_helper';
import { makeNestedLabel } from './lib/make_nested_label';
import { parentPipelineAggController } from './lib/parent_pipeline_agg_controller';
import { parentPipelineAggWritter } from './lib/parent_pipeline_agg_writter';
export default function AggTypeMetricDerivativeProvider(Private) {
const MetricAggType = Private(AggTypesMetricsMetricAggTypeProvider);
const AggConfig = Private(VisAggConfigProvider);
const Schemas = Private(VisSchemasProvider);
const aggFilter = ['!top_hits', '!percentiles', '!percentile_ranks', '!median', '!std_dev'];
const orderAggSchema = (new Schemas([
{
group: 'none',
name: 'orderAgg',
title: 'Order Agg',
aggFilter: aggFilter
}
])).all[0];
const parentPipelineAggHelper = Private(ParentPipelineAggHelperProvider);
return new MetricAggType({
name: 'derivative',
title: 'Derivative',
makeLabel: agg => makeNestedLabel(agg, 'derivative'),
params: [
{
name: 'customMetric',
type: AggConfig,
default: null,
serialize: function (customMetric) {
return customMetric.toJSON();
},
deserialize: function (state, agg) {
return this.makeAgg(agg, state);
},
makeAgg: function (termsAgg, state) {
state = state || { type: 'count' };
state.schema = orderAggSchema;
const metricAgg = new AggConfig(termsAgg.vis, state);
metricAgg.id = termsAgg.id + '-metric';
return metricAgg;
},
write: _.noop
},
{
name: 'buckets_path',
write: _.noop
},
{
name: 'metricAgg',
editor: metricAggTemplate,
default: 'custom',
controller: parentPipelineAggController,
write: parentPipelineAggWritter
}
...parentPipelineAggHelper.params()
]
});
}

View file

@ -0,0 +1,61 @@
import metricAggTemplate from 'ui/agg_types/controls/sub_agg.html';
import _ from 'lodash';
import VisAggConfigProvider from 'ui/vis/agg_config';
import VisSchemasProvider from 'ui/vis/schemas';
import { parentPipelineAggController } from './parent_pipeline_agg_controller';
import { parentPipelineAggWritter } from './parent_pipeline_agg_writter';
const ParentPipelineAggHelperProvider = function (Private) {
const AggConfig = Private(VisAggConfigProvider);
const Schemas = Private(VisSchemasProvider);
const metricAggFilter = ['!top_hits', '!percentiles', '!percentile_ranks', '!median', '!std_dev'];
const metricAggSchema = (new Schemas([
{
group: 'none',
name: 'metricAgg',
title: 'Metric Agg',
aggFilter: metricAggFilter
}
])).all[0];
return {
params: function () {
return [
{
name: 'customMetric',
type: AggConfig,
default: null,
serialize: function (customMetric) {
return customMetric.toJSON();
},
deserialize: function (state, agg) {
return this.makeAgg(agg, state);
},
makeAgg: function (termsAgg, state) {
state = state || { type: 'count' };
state.schema = metricAggSchema;
const metricAgg = new AggConfig(termsAgg.vis, state);
metricAgg.id = termsAgg.id + '-metric';
return metricAgg;
},
write: _.noop
},
{
name: 'buckets_path',
write: _.noop
},
{
name: 'metricAgg',
editor: metricAggTemplate,
default: 'custom',
controller: parentPipelineAggController,
write: parentPipelineAggWritter
}
];
}
};
};
export default ParentPipelineAggHelperProvider;

View file

@ -0,0 +1,17 @@
import AggTypesMetricsMetricAggTypeProvider from 'ui/agg_types/metrics/metric_agg_type';
import ParentPipelineAggHelperProvider from './lib/parent_pipeline_agg_helper';
import { makeNestedLabel } from './lib/make_nested_label';
export default function AggTypeMetricMovingAvgProvider(Private) {
const MetricAggType = Private(AggTypesMetricsMetricAggTypeProvider);
const parentPipelineAggHelper = Private(ParentPipelineAggHelperProvider);
return new MetricAggType({
name: 'moving_avg',
title: 'Moving Avg',
makeLabel: agg => makeNestedLabel(agg, 'moving avg'),
params: [
...parentPipelineAggHelper.params()
]
});
}

View file

@ -0,0 +1,17 @@
import AggTypesMetricsMetricAggTypeProvider from 'ui/agg_types/metrics/metric_agg_type';
import ParentPipelineAggHelperProvider from './lib/parent_pipeline_agg_helper';
import { makeNestedLabel } from './lib/make_nested_label';
export default function AggTypeMetricSerialDiffProvider(Private) {
const MetricAggType = Private(AggTypesMetricsMetricAggTypeProvider);
const parentPipelineAggHelper = Private(ParentPipelineAggHelperProvider);
return new MetricAggType({
name: 'serial_diff',
title: 'Serial Diff',
makeLabel: agg => makeNestedLabel(agg, 'serial diff'),
params: [
...parentPipelineAggHelper.params()
]
});
}