mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
parent
74093c700f
commit
1da98f5e1e
@ -67,12 +67,6 @@
|
||||
</div>
|
||||
|
||||
<!-- Histogram mode -->
|
||||
<div class="gf-form" ng-if="ctrl.panel.xaxis.mode === 'histogram'">
|
||||
<label class="gf-form-label width-6">Value</label>
|
||||
<div class="gf-form-select-wrapper max-width-15">
|
||||
<select class="gf-form-input" ng-model="ctrl.panel.xaxis.histogramValue" ng-options="v as k for (k, v) in ctrl.histogramValues" ng-change="ctrl.xAxisOptionChanged()"> </select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gf-form" ng-if="ctrl.panel.xaxis.mode === 'histogram'">
|
||||
<label class="gf-form-label width-6">Buckets</label>
|
||||
<input type="number" class="gf-form-input max-width-8" ng-model="ctrl.panel.xaxis.buckets" placeholder="auto" ng-change="ctrl.render()" ng-model-onblur bs-tooltip="'Number of buckets'" data-placement="right">
|
||||
|
@ -10,7 +10,6 @@ export class AxesEditorCtrl {
|
||||
xAxisModes: any;
|
||||
xAxisStatOptions: any;
|
||||
xNameSegment: any;
|
||||
histogramValues: any;
|
||||
|
||||
/** @ngInject **/
|
||||
constructor(private $scope, private $q) {
|
||||
@ -35,11 +34,6 @@ export class AxesEditorCtrl {
|
||||
// 'Data field': 'field',
|
||||
};
|
||||
|
||||
this.histogramValues = {
|
||||
'Percent': 'percent',
|
||||
'Count': 'count'
|
||||
};
|
||||
|
||||
this.xAxisStatOptions = [
|
||||
{text: 'Avg', value: 'avg'},
|
||||
{text: 'Min', value: 'min'},
|
||||
|
@ -312,13 +312,10 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv, popoverSrv) {
|
||||
let histMax = _.max(_.map(data, s => s.stats.max));
|
||||
let ticks = panel.xaxis.buckets || panelWidth / 50;
|
||||
bucketSize = tickStep(histMin, histMax, ticks);
|
||||
let histogram = convertValuesToHistogram(values, bucketSize);
|
||||
|
||||
let normalize = panel.xaxis.histogramValue === 'percent';
|
||||
let histogram = convertValuesToHistogram(values, bucketSize, normalize);
|
||||
|
||||
let seriesLabel = panel.xaxis.histogramValue || "count";
|
||||
data[0].data = histogram;
|
||||
data[0].alias = data[0].label = data[0].id = seriesLabel;
|
||||
data[0].alias = data[0].label = data[0].id = "count";
|
||||
data = [data[0]];
|
||||
|
||||
options.series.bars.barWidth = bucketSize * 0.8;
|
||||
@ -425,32 +422,21 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv, popoverSrv) {
|
||||
|
||||
function addXHistogramAxis(options, bucketSize) {
|
||||
let ticks, min, max;
|
||||
let defaultTicks = panelWidth / 50;
|
||||
|
||||
if (data.length && bucketSize) {
|
||||
ticks = _.map(data[0].data, point => point[0]);
|
||||
min = _.min(ticks);
|
||||
max = _.max(ticks);
|
||||
|
||||
// Adjust tick step
|
||||
let tickStep = bucketSize;
|
||||
let ticks_num = Math.floor((max - min) / tickStep);
|
||||
while (ticks_num > defaultTicks) {
|
||||
tickStep = tickStep * 2;
|
||||
ticks_num = Math.ceil((max - min) / tickStep);
|
||||
}
|
||||
|
||||
// Expand ticks for pretty view
|
||||
min = Math.floor(min / tickStep) * tickStep;
|
||||
max = Math.ceil(max / tickStep) * tickStep;
|
||||
min = Math.max(0, _.min(ticks) - bucketSize);
|
||||
max = _.max(ticks) + bucketSize;
|
||||
|
||||
ticks = [];
|
||||
for (let i = min; i <= max; i += tickStep) {
|
||||
for (let i = min; i <= max; i += bucketSize) {
|
||||
ticks.push(i);
|
||||
}
|
||||
} else {
|
||||
// Set defaults if no data
|
||||
ticks = defaultTicks / 2;
|
||||
ticks = panelWidth / 100;
|
||||
min = 0;
|
||||
max = 1;
|
||||
}
|
||||
@ -464,9 +450,6 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv, popoverSrv) {
|
||||
label: "Histogram",
|
||||
ticks: ticks
|
||||
};
|
||||
|
||||
// Use 'short' format for histogram values
|
||||
configureAxisMode(options.xaxis, 'short');
|
||||
}
|
||||
|
||||
function addXTableAxis(options) {
|
||||
|
@ -26,7 +26,7 @@ export function getSeriesValues(data: any): number[] {
|
||||
* @param values
|
||||
* @param bucketSize
|
||||
*/
|
||||
export function convertValuesToHistogram(values: number[], bucketSize: number, normalize = false): any[] {
|
||||
export function convertValuesToHistogram(values: number[], bucketSize: number): any[] {
|
||||
let histogram = {};
|
||||
|
||||
for (let i = 0; i < values.length; i++) {
|
||||
@ -38,16 +38,9 @@ export function convertValuesToHistogram(values: number[], bucketSize: number, n
|
||||
}
|
||||
}
|
||||
|
||||
let histogam_series = _.map(histogram, (count, bound) => {
|
||||
if (normalize && values.length) {
|
||||
return [Number(bound), count / values.length];
|
||||
}
|
||||
|
||||
return _.map(histogram, (count, bound) => {
|
||||
return [Number(bound), count];
|
||||
});
|
||||
|
||||
// Sort by Y axis values
|
||||
return _.sortBy(histogam_series, point => point[0]);
|
||||
}
|
||||
|
||||
function getBucketBound(value: number, bucketSize: number): number {
|
||||
|
@ -58,8 +58,7 @@ class GraphCtrl extends MetricsPanelCtrl {
|
||||
mode: 'time',
|
||||
name: null,
|
||||
values: [],
|
||||
buckets: null,
|
||||
histogramValue: 'percent'
|
||||
buckets: null
|
||||
},
|
||||
// show/hide lines
|
||||
lines : true,
|
||||
|
@ -1,6 +1,7 @@
|
||||
///<reference path="../../../../headers/common.d.ts" />
|
||||
import _ from 'lodash';
|
||||
|
||||
import { describe, beforeEach, it, expect } from '../../../../../test/lib/common';
|
||||
|
||||
import { convertValuesToHistogram, getSeriesValues } from '../histogram';
|
||||
|
||||
describe('Graph Histogam Converter', function () {
|
||||
@ -10,13 +11,13 @@ describe('Graph Histogam Converter', function () {
|
||||
let bucketSize = 10;
|
||||
|
||||
beforeEach(() => {
|
||||
values = [1, 2, 10, 11, 17, 20, 29, 30, 31, 33];
|
||||
values = [1, 2, 10, 11, 17, 20, 29];
|
||||
});
|
||||
|
||||
it('Should convert to series-like array', () => {
|
||||
bucketSize = 10;
|
||||
let expected = [
|
||||
[0, 2], [10, 3], [20, 2], [30, 3]
|
||||
[0, 2], [10, 3], [20, 2]
|
||||
];
|
||||
|
||||
let histogram = convertValuesToHistogram(values, bucketSize);
|
||||
@ -26,35 +27,12 @@ describe('Graph Histogam Converter', function () {
|
||||
it('Should not add empty buckets', () => {
|
||||
bucketSize = 5;
|
||||
let expected = [
|
||||
[0, 2], [10, 2], [15, 1], [20, 1], [25, 1], [30, 3]
|
||||
[0, 2], [10, 2], [15, 1], [20, 1], [25, 1]
|
||||
];
|
||||
|
||||
let histogram = convertValuesToHistogram(values, bucketSize);
|
||||
expect(histogram).to.eql(expected);
|
||||
});
|
||||
|
||||
it('Should normalize values', () => {
|
||||
bucketSize = 5;
|
||||
let normalize = true;
|
||||
let expected = [
|
||||
[0, 0.2], [10, 0.2], [15, 0.1], [20, 0.1], [25, 0.1], [30, 0.3]
|
||||
];
|
||||
|
||||
let histogram = convertValuesToHistogram(values, bucketSize, normalize);
|
||||
expect(histogram).to.eql(expected);
|
||||
});
|
||||
|
||||
it('Sum of normalized values should be 1', () => {
|
||||
bucketSize = 5;
|
||||
let normalize = true;
|
||||
let expected = [
|
||||
[0, 0.2], [10, 0.2], [15, 0.1], [20, 0.1], [25, 0.1], [30, 0.3]
|
||||
];
|
||||
|
||||
let histogram = convertValuesToHistogram(values, bucketSize, normalize);
|
||||
let sum = _.reduce(histogram, (sum, point) => sum + point[1], 0);
|
||||
expect(sum).to.eql(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Series to values converter', () => {
|
||||
|
Loading…
Reference in New Issue
Block a user