mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Merge branch 'histogram_multi' of https://github.com/mtanda/grafana into mtanda-histogram_multi
This commit is contained in:
commit
38a19f7c90
@ -29,12 +29,17 @@ export class DataProcessor {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
case 'histogram': {
|
case 'histogram': {
|
||||||
let histogramDataList = [
|
let histogramDataList;
|
||||||
{
|
if (this.panel.stack) {
|
||||||
target: 'count',
|
histogramDataList = options.dataList;
|
||||||
datapoints: _.concat([], _.flatten(_.map(options.dataList, 'datapoints'))),
|
} else {
|
||||||
},
|
histogramDataList = [
|
||||||
];
|
{
|
||||||
|
target: 'count',
|
||||||
|
datapoints: _.concat([], _.flatten(_.map(options.dataList, 'datapoints'))),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
return histogramDataList.map((item, index) => {
|
return histogramDataList.map((item, index) => {
|
||||||
return this.timeSeriesHandler(item, index, options);
|
return this.timeSeriesHandler(item, index, options);
|
||||||
});
|
});
|
||||||
|
@ -17,7 +17,7 @@ import { appEvents, coreModule, updateLegendValues } from 'app/core/core';
|
|||||||
import GraphTooltip from './graph_tooltip';
|
import GraphTooltip from './graph_tooltip';
|
||||||
import { ThresholdManager } from './threshold_manager';
|
import { ThresholdManager } from './threshold_manager';
|
||||||
import { EventManager } from 'app/features/annotations/all';
|
import { EventManager } from 'app/features/annotations/all';
|
||||||
import { convertValuesToHistogram, getSeriesValues } from './histogram';
|
import { convertToHistogramData } from './histogram';
|
||||||
import config from 'app/core/config';
|
import config from 'app/core/config';
|
||||||
|
|
||||||
/** @ngInject **/
|
/** @ngInject **/
|
||||||
@ -236,15 +236,15 @@ function graphDirective(timeSrv, popoverSrv, contextSrv) {
|
|||||||
}
|
}
|
||||||
case 'histogram': {
|
case 'histogram': {
|
||||||
let bucketSize: number;
|
let bucketSize: number;
|
||||||
let values = getSeriesValues(data);
|
|
||||||
|
|
||||||
if (data.length && values.length) {
|
if (data.length) {
|
||||||
let histMin = _.min(_.map(data, s => s.stats.min));
|
let histMin = _.min(_.map(data, s => s.stats.min));
|
||||||
let histMax = _.max(_.map(data, s => s.stats.max));
|
let histMax = _.max(_.map(data, s => s.stats.max));
|
||||||
let ticks = panel.xaxis.buckets || panelWidth / 50;
|
let ticks = panel.xaxis.buckets || panelWidth / 50;
|
||||||
bucketSize = tickStep(histMin, histMax, ticks);
|
bucketSize = tickStep(histMin, histMax, ticks);
|
||||||
let histogram = convertValuesToHistogram(values, bucketSize);
|
|
||||||
data[0].data = histogram;
|
data = convertToHistogramData(data, bucketSize, ctrl.hiddenSeries, panel.stack, histMin, histMax);
|
||||||
|
|
||||||
options.series.bars.barWidth = bucketSize * 0.8;
|
options.series.bars.barWidth = bucketSize * 0.8;
|
||||||
} else {
|
} else {
|
||||||
bucketSize = 0;
|
bucketSize = 0;
|
||||||
@ -413,7 +413,13 @@ function graphDirective(timeSrv, popoverSrv, contextSrv) {
|
|||||||
let defaultTicks = panelWidth / 50;
|
let defaultTicks = panelWidth / 50;
|
||||||
|
|
||||||
if (data.length && bucketSize) {
|
if (data.length && bucketSize) {
|
||||||
ticks = _.map(data[0].data, point => point[0]);
|
let tick_values = [];
|
||||||
|
for (let d of data) {
|
||||||
|
for (let point of d.data) {
|
||||||
|
tick_values[point[0]] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ticks = Object.keys(tick_values).map(v => Number(v));
|
||||||
min = _.min(ticks);
|
min = _.min(ticks);
|
||||||
max = _.max(ticks);
|
max = _.max(ticks);
|
||||||
|
|
||||||
|
@ -29,16 +29,22 @@ export function getSeriesValues(dataList: TimeSeries[]): number[] {
|
|||||||
* @param values
|
* @param values
|
||||||
* @param bucketSize
|
* @param bucketSize
|
||||||
*/
|
*/
|
||||||
export function convertValuesToHistogram(values: number[], bucketSize: number): any[] {
|
export function convertValuesToHistogram(values: number[], bucketSize: number, min: number, max: number): any[] {
|
||||||
let histogram = {};
|
let histogram = {};
|
||||||
|
|
||||||
|
let minBound = getBucketBound(min, bucketSize);
|
||||||
|
let maxBound = getBucketBound(max, bucketSize);
|
||||||
|
let bound = minBound;
|
||||||
|
let n = 0;
|
||||||
|
while (bound <= maxBound) {
|
||||||
|
histogram[bound] = 0;
|
||||||
|
bound = minBound + bucketSize * n;
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
|
||||||
for (let i = 0; i < values.length; i++) {
|
for (let i = 0; i < values.length; i++) {
|
||||||
let bound = getBucketBound(values[i], bucketSize);
|
let bound = getBucketBound(values[i], bucketSize);
|
||||||
if (histogram[bound]) {
|
histogram[bound] = histogram[bound] + 1;
|
||||||
histogram[bound] = histogram[bound] + 1;
|
|
||||||
} else {
|
|
||||||
histogram[bound] = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let histogam_series = _.map(histogram, (count, bound) => {
|
let histogam_series = _.map(histogram, (count, bound) => {
|
||||||
@ -49,6 +55,33 @@ export function convertValuesToHistogram(values: number[], bucketSize: number):
|
|||||||
return _.sortBy(histogam_series, point => point[0]);
|
return _.sortBy(histogam_series, point => point[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert series into array of histogram data.
|
||||||
|
* @param data Array of series
|
||||||
|
* @param bucketSize
|
||||||
|
* @param stack
|
||||||
|
*/
|
||||||
|
export function convertToHistogramData(
|
||||||
|
data: any,
|
||||||
|
bucketSize: number,
|
||||||
|
hiddenSeries: any,
|
||||||
|
stack = false,
|
||||||
|
min: number,
|
||||||
|
max: number
|
||||||
|
): any[] {
|
||||||
|
return data.map(series => {
|
||||||
|
let values = getSeriesValues([series]);
|
||||||
|
series.histogram = true;
|
||||||
|
if (!hiddenSeries[series.alias]) {
|
||||||
|
let histogram = convertValuesToHistogram(values, bucketSize, min, max);
|
||||||
|
series.data = histogram;
|
||||||
|
} else {
|
||||||
|
series.data = [];
|
||||||
|
}
|
||||||
|
return series;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function getBucketBound(value: number, bucketSize: number): number {
|
function getBucketBound(value: number, bucketSize: number): number {
|
||||||
return Math.floor(value / bucketSize) * bucketSize;
|
return Math.floor(value / bucketSize) * bucketSize;
|
||||||
}
|
}
|
||||||
|
@ -407,4 +407,48 @@ describe('grafanaGraph', function() {
|
|||||||
},
|
},
|
||||||
10
|
10
|
||||||
);
|
);
|
||||||
|
|
||||||
|
graphScenario('when graph is histogram, and enable stack', function(ctx) {
|
||||||
|
ctx.setup(function(ctrl, data) {
|
||||||
|
ctrl.panel.xaxis.mode = 'histogram';
|
||||||
|
ctrl.panel.stack = true;
|
||||||
|
ctrl.hiddenSeries = {};
|
||||||
|
data[0] = new TimeSeries({
|
||||||
|
datapoints: [[100, 1], [100, 2], [200, 3], [300, 4]],
|
||||||
|
alias: 'series1',
|
||||||
|
});
|
||||||
|
data[1] = new TimeSeries({
|
||||||
|
datapoints: [[100, 1], [100, 2], [200, 3], [300, 4]],
|
||||||
|
alias: 'series2',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should calculate correct histogram', function() {
|
||||||
|
expect(ctx.plotData[0].data[0][0]).to.be(100);
|
||||||
|
expect(ctx.plotData[0].data[0][1]).to.be(2);
|
||||||
|
expect(ctx.plotData[1].data[0][0]).to.be(100);
|
||||||
|
expect(ctx.plotData[1].data[0][1]).to.be(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
graphScenario('when graph is histogram, and some series are hidden', function(ctx) {
|
||||||
|
ctx.setup(function(ctrl, data) {
|
||||||
|
ctrl.panel.xaxis.mode = 'histogram';
|
||||||
|
ctrl.panel.stack = false;
|
||||||
|
ctrl.hiddenSeries = { series2: true };
|
||||||
|
data[0] = new TimeSeries({
|
||||||
|
datapoints: [[100, 1], [100, 2], [200, 3], [300, 4]],
|
||||||
|
alias: 'series1',
|
||||||
|
});
|
||||||
|
data[1] = new TimeSeries({
|
||||||
|
datapoints: [[100, 1], [100, 2], [200, 3], [300, 4]],
|
||||||
|
alias: 'series2',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should calculate correct histogram', function() {
|
||||||
|
expect(ctx.plotData[0].data[0][0]).to.be(100);
|
||||||
|
expect(ctx.plotData[0].data[0][1]).to.be(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -13,15 +13,15 @@ describe('Graph Histogam Converter', function() {
|
|||||||
bucketSize = 10;
|
bucketSize = 10;
|
||||||
let expected = [[0, 2], [10, 3], [20, 2]];
|
let expected = [[0, 2], [10, 3], [20, 2]];
|
||||||
|
|
||||||
let histogram = convertValuesToHistogram(values, bucketSize);
|
let histogram = convertValuesToHistogram(values, bucketSize, 1, 29);
|
||||||
expect(histogram).toMatchObject(expected);
|
expect(histogram).toMatchObject(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should not add empty buckets', () => {
|
it('Should not add empty buckets', () => {
|
||||||
bucketSize = 5;
|
bucketSize = 5;
|
||||||
let expected = [[0, 2], [10, 2], [15, 1], [20, 1], [25, 1]];
|
let expected = [[0, 2], [5, 0], [10, 2], [15, 1], [20, 1], [25, 1]];
|
||||||
|
|
||||||
let histogram = convertValuesToHistogram(values, bucketSize);
|
let histogram = convertValuesToHistogram(values, bucketSize, 1, 29);
|
||||||
expect(histogram).toMatchObject(expected);
|
expect(histogram).toMatchObject(expected);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -71,7 +71,7 @@
|
|||||||
|
|
||||||
<div class="section gf-form-group">
|
<div class="section gf-form-group">
|
||||||
<h5 class="section-heading">Stacking & Null value</h5>
|
<h5 class="section-heading">Stacking & Null value</h5>
|
||||||
<gf-form-switch class="gf-form" label="Stack" label-class="width-7" checked="ctrl.panel.stack" on-change="ctrl.render()">
|
<gf-form-switch class="gf-form" label="Stack" label-class="width-7" checked="ctrl.panel.stack" on-change="ctrl.refresh()">
|
||||||
</gf-form-switch>
|
</gf-form-switch>
|
||||||
<gf-form-switch class="gf-form" ng-show="ctrl.panel.stack" label="Percent" label-class="width-7" checked="ctrl.panel.percentage" on-change="ctrl.render()">
|
<gf-form-switch class="gf-form" ng-show="ctrl.panel.stack" label="Percent" label-class="width-7" checked="ctrl.panel.percentage" on-change="ctrl.render()">
|
||||||
</gf-form-switch>
|
</gf-form-switch>
|
||||||
|
Loading…
Reference in New Issue
Block a user