mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Added derivative option and scale option to histogram, reorganized histogram config
This commit is contained in:
parent
e00d327c5d
commit
40e55f0d0d
@ -1,74 +1,45 @@
|
||||
<div class="row-fluid">
|
||||
<div class="span2">
|
||||
<label class="small">Mode</label>
|
||||
<div class="editor-row">
|
||||
<div class="section">
|
||||
<h5>Values</h5>
|
||||
<div class="editor-option">
|
||||
<label class="small">Chart value</label>
|
||||
<select ng-change="set_refresh(true)" class="input-small" ng-model="panel.mode" ng-options="f for f in ['count','min','mean','max','total']"></select>
|
||||
</div>
|
||||
<div class="span2">
|
||||
<label class="small">Time Field</label>
|
||||
<input ng-change="set_refresh(true)" placeholder="Start typing" bs-typeahead="fields.list" type="text" class="input-small" ng-model="panel.time_field">
|
||||
</div>
|
||||
<div class="span2" ng-show="panel.mode != 'count'">
|
||||
<label class="small">Value Field</label>
|
||||
<input ng-change="set_refresh(true)" placeholder="Start typing" bs-typeahead="fields.list" type="text" class="input-small" ng-model="panel.value_field">
|
||||
</div>
|
||||
<div class="span3" ng-show="panel.mode != 'count'">
|
||||
<label class="small">Note</label><small> In <strong>{{panel.mode}}</strong> mode the configured field <strong>must</strong> be a numeric type</small>
|
||||
<div class="editor-option" ng-show="panel.mode != 'count'">
|
||||
<label class="small">Value Field <tip>This field must contain a numeric value</tip></label>
|
||||
<input ng-change="set_refresh(true)" placeholder="Start typing" bs-typeahead="fields.list" type="text" class="input-large" ng-model="panel.value_field">
|
||||
</div>
|
||||
</div>
|
||||
<h5>Chart Settings</h5>
|
||||
<div class="row-fluid" style="text-align:center;margin-bottom:10px;">
|
||||
<div class="span1"> <label class="small">Bars</label><input type="checkbox" ng-model="panel.bars" ng-checked="panel.bars"></div>
|
||||
<div class="span1"> <label class="small">Lines</label><input type="checkbox" ng-model="panel.lines" ng-checked="panel.lines"></div>
|
||||
<div class="span1"> <label class="small">Points</label><input type="checkbox" ng-model="panel.points" ng-checked="panel.points"></div>
|
||||
<div class="span1"> <label class="small">Stack</label><input type="checkbox" ng-model="panel.stack" ng-checked="panel.stack"></div>
|
||||
<div class="span1" ng-show="panel.stack">
|
||||
<label style="white-space:nowrap" class="small">Percent <tip>Stack as a percentage of total</tip></label>
|
||||
<input type="checkbox" ng-model="panel.percentage" ng-checked="panel.percentage">
|
||||
<div class="section">
|
||||
<h5>Transform Series</h5>
|
||||
<div class="editor-option" ng-show="panel.mode != 'count'">
|
||||
<label class="small">Scale</label>
|
||||
<input type="text" class="input-mini" ng-model="panel.scale">
|
||||
</div>
|
||||
<div class="span1"> <label class="small">Legend</label><input type="checkbox" ng-model="panel.legend" ng-checked="panel.legend"></div>
|
||||
<div class="span1"> <label class="small">xAxis</label><input type="checkbox" ng-model="panel['x-axis']" ng-checked="panel['x-axis']"></div>
|
||||
<div class="span1"> <label class="small">yAxis</label><input type="checkbox" ng-model="panel['y-axis']" ng-checked="panel['y-axis']"></div>
|
||||
<div class="span2" ng-show="panel.lines">
|
||||
<label class="small">Line Fill</label>
|
||||
<select class="input-mini" ng-model="panel.fill" ng-options="f for f in [0,1,2,3,4,5,6,7,8,9,10]"></select>
|
||||
</div>
|
||||
<div class="span2" ng-show="panel.lines">
|
||||
<label class="small">Line Width</label>
|
||||
<select class="input-mini" ng-model="panel.linewidth" ng-options="f for f in [0,1,2,3,4,5,6,7,8,9,10]"></select>
|
||||
<div class="editor-option">
|
||||
<label class="small">Derivative <tip>Plot the change per interval in the series</tip></label><input type="checkbox" ng-model="panel.derivative" ng-checked="panel.derivative" ng-change="set_refresh(true)">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span2">
|
||||
<label class="small">Time correction</label>
|
||||
<select ng-model="panel.timezone" class='input-small' ng-options="f for f in ['browser','utc']"></select>
|
||||
</div>
|
||||
<div class="span1"> <label class="small">Selectable</label><input type="checkbox" ng-model="panel.interactive" ng-checked="panel.interactive"></div>
|
||||
<div class="span2">
|
||||
<label class="small">Zoom Links</label><input type="checkbox" ng-model="panel.zoomlinks" ng-checked="panel.zoomlinks" />
|
||||
</div>
|
||||
<div class="span2">
|
||||
<label class="small">View Options</label><input type="checkbox" ng-model="panel.options" ng-checked="panel.options" />
|
||||
</div>
|
||||
<div class="span2">
|
||||
<label class="small">Auto-interval</label><input type="checkbox" ng-model="panel.auto_int" ng-checked="panel.auto_int" />
|
||||
</div>
|
||||
<div class="span2" ng-show='panel.auto_int'>
|
||||
<label class="small">Resolution <tip>Shoot for this many data points, rounding to sane intervals</tip></label>
|
||||
<input type="number" class='input-mini' ng-model="panel.resolution" ng-change='set_refresh(true)'/>
|
||||
</div>
|
||||
<div class="span2" ng-hide='panel.auto_int'>
|
||||
<label class="small">Interval <tip>Use Elasticsearch date math format (eg 1m, 5m, 1d, 2w, 1y)</tip></label>
|
||||
<input type="text" class='input-mini' ng-model="panel.interval" ng-change='set_refresh(true)'/>
|
||||
</div>
|
||||
</div>
|
||||
<h5>Time Options</h5>
|
||||
<div class="editor-row">
|
||||
<div class="editor-option">
|
||||
<label class="small">Time Field</label>
|
||||
<input ng-change="set_refresh(true)" placeholder="Start typing" bs-typeahead="fields.list" type="text" class="input-small" ng-model="panel.time_field">
|
||||
</div>
|
||||
<h5>Tooltip Settings</h5>
|
||||
<div class="row-fluid" style="margin-bottom:10px;">
|
||||
<div class="span3">
|
||||
<label class="small">Stacked Values <tip>How should the values in stacked charts to be calculated?</tip></label>
|
||||
<select class="input-medium" ng-model="panel.tooltip.value_type" ng-options="f for f in ['cumulative','individual']"></select>
|
||||
</div>
|
||||
<div class="span3">
|
||||
<label class="small">Display Query <tip>If an alias is set, it will be shown in the tooltip. If not, should it show the query?</tip></label>
|
||||
<input type="checkbox" ng-model="panel.tooltip.query_as_alias" />
|
||||
</div>
|
||||
<div class="editor-option">
|
||||
<label class="small">Time correction</label>
|
||||
<select ng-model="panel.timezone" class='input-small' ng-options="f for f in ['browser','utc']"></select>
|
||||
</div>
|
||||
<div class="editor-option">
|
||||
<label class="small">Auto-interval</label><input type="checkbox" ng-model="panel.auto_int" ng-checked="panel.auto_int" />
|
||||
</div>
|
||||
<div class="editor-option" ng-show='panel.auto_int'>
|
||||
<label class="small">Resolution <tip>Shoot for this many data points, rounding to sane intervals</tip></label>
|
||||
<input type="number" class='input-mini' ng-model="panel.resolution" ng-change='set_refresh(true)'/>
|
||||
</div>
|
||||
<div class="editor-option" ng-hide='panel.auto_int'>
|
||||
<label class="small">Interval <tip>Use Elasticsearch date math format (eg 1m, 5m, 1d, 2w, 1y)</tip></label>
|
||||
<input type="text" class='input-mini' ng-model="panel.interval" ng-change='set_refresh(true)'/>
|
||||
</div>
|
||||
</div>
|
@ -47,7 +47,7 @@
|
||||
<i class='icon-circle' ng-style="{color: series.info.color}"></i>
|
||||
<span class='small histogram-legend-item'>{{series.info.alias}} ({{series.hits}})</span>
|
||||
</span>
|
||||
<span ng-show="panel.legend" class="small"><span ng-show="panel.value_field && panel.mode != 'count'">{{panel.value_field}}</span> {{panel.mode}} per <strong>{{panel.interval}}</strong> | (<strong>{{hits}}</strong> hits)</span>
|
||||
<span ng-show="panel.legend" class="small"><span ng-show="panel.derivative">change in </span><span class="strong" ng-show="panel.value_field && panel.mode != 'count'">{{panel.value_field}}</span> {{panel.mode}} per <strong>{{panel.interval}}</strong> | (<strong>{{hits}}</strong> hits)</span>
|
||||
</div>
|
||||
<form class="form-inline bordered histogram-options" ng-show="options">
|
||||
<span>
|
||||
|
@ -61,10 +61,14 @@ function (angular, app, $, _, kbn, moment, timeSeries) {
|
||||
}
|
||||
],
|
||||
editorTabs : [
|
||||
{
|
||||
title:'Style',
|
||||
src:'app/panels/histogram/styleEditor.html'
|
||||
},
|
||||
{
|
||||
title:'Queries',
|
||||
src:'app/partials/querySelect.html'
|
||||
}
|
||||
},
|
||||
],
|
||||
status : "Stable",
|
||||
description : "A bucketed time series chart of the current query or queries. Uses the "+
|
||||
@ -98,11 +102,14 @@ function (angular, app, $, _, kbn, moment, timeSeries) {
|
||||
'x-axis' : true,
|
||||
'y-axis' : true,
|
||||
percentage : false,
|
||||
zerofill : true,
|
||||
interactive : true,
|
||||
options : true,
|
||||
derivative : false,
|
||||
scale : 1,
|
||||
tooltip : {
|
||||
value_type: 'cumulative',
|
||||
query_as_alias: false
|
||||
query_as_alias: true
|
||||
}
|
||||
};
|
||||
|
||||
@ -115,6 +122,10 @@ function (angular, app, $, _, kbn, moment, timeSeries) {
|
||||
$scope.get_data();
|
||||
});
|
||||
|
||||
// Always show the query if an alias isn't set. Users can set an alias if the query is too
|
||||
// long
|
||||
$scope.panel.tooltip.query_as_alias = true;
|
||||
|
||||
$scope.get_data();
|
||||
|
||||
};
|
||||
@ -249,12 +260,13 @@ function (angular, app, $, _, kbn, moment, timeSeries) {
|
||||
// we need to initialize the data variable on the first run,
|
||||
// and when we are working on the first segment of the data.
|
||||
if(_.isUndefined($scope.data[i]) || segment === 0) {
|
||||
time_series = new timeSeries.ZeroFilled({
|
||||
var tsOpts = {
|
||||
interval: _interval,
|
||||
start_date: _range && _range.from,
|
||||
end_date: _range && _range.to,
|
||||
fill_style: 'minimal'
|
||||
});
|
||||
fill_style: $scope.panel.derivative ? 'null' : 'minimal'
|
||||
};
|
||||
time_series = new timeSeries.ZeroFilled(tsOpts);
|
||||
hits = 0;
|
||||
} else {
|
||||
time_series = $scope.data[i].time_series;
|
||||
@ -354,6 +366,24 @@ function (angular, app, $, _, kbn, moment, timeSeries) {
|
||||
render_panel();
|
||||
});
|
||||
|
||||
var scale = function(series,factor) {
|
||||
return _.map(series,function(p) {
|
||||
return [p[0],p[1]*factor];
|
||||
});
|
||||
};
|
||||
|
||||
var derivative = function(series) {
|
||||
return _.map(series, function(p,i) {
|
||||
var _v;
|
||||
if(i === 0 || p[1] === null) {
|
||||
_v = [p[0],null];
|
||||
} else {
|
||||
_v = series[i-1][1] === null ? [p[0],null] : [p[0],p[1]-(series[i-1][1])];
|
||||
}
|
||||
return _v;
|
||||
});
|
||||
};
|
||||
|
||||
// Function for rendering panel
|
||||
function render_panel() {
|
||||
// IE doesn't work without this
|
||||
@ -441,8 +471,16 @@ function (angular, app, $, _, kbn, moment, timeSeries) {
|
||||
}), true);
|
||||
}
|
||||
|
||||
|
||||
for (var i = 0; i < scope.data.length; i++) {
|
||||
scope.data[i].data = scope.data[i].time_series.getFlotPairs(required_times);
|
||||
var _d = scope.data[i].time_series.getFlotPairs(required_times);
|
||||
if(scope.panel.derivative) {
|
||||
_d = derivative(_d);
|
||||
}
|
||||
if(scope.panel.scale !== 1) {
|
||||
_d = scale(_d,scope.panel.scale);
|
||||
}
|
||||
scope.data[i].data = _d;
|
||||
}
|
||||
|
||||
scope.plot = $.plot(elem, scope.data, options);
|
||||
|
58
src/app/panels/histogram/styleEditor.html
Normal file
58
src/app/panels/histogram/styleEditor.html
Normal file
@ -0,0 +1,58 @@
|
||||
<div class="editor-row">
|
||||
<div class="section">
|
||||
<h5>Chart Options</h5>
|
||||
<div class="editor-option">
|
||||
<label class="small">Bars</label><input type="checkbox" ng-model="panel.bars" ng-checked="panel.bars">
|
||||
</div>
|
||||
<div class="editor-option">
|
||||
<label class="small">Lines</label><input type="checkbox" ng-model="panel.lines" ng-checked="panel.lines">
|
||||
</div>
|
||||
<div class="editor-option">
|
||||
<label class="small">Points</label><input type="checkbox" ng-model="panel.points" ng-checked="panel.points">
|
||||
</div>
|
||||
<div class="editor-option">
|
||||
<label class="small">Selectable</label><input type="checkbox" ng-model="panel.interactive" ng-checked="panel.interactive">
|
||||
</div>
|
||||
<div class="editor-option">
|
||||
<label class="small">xAxis</label><input type="checkbox" ng-model="panel['x-axis']" ng-checked="panel['x-axis']"></div>
|
||||
<div class="editor-option">
|
||||
<label class="small">yAxis</label><input type="checkbox" ng-model="panel['y-axis']" ng-checked="panel['y-axis']"></div>
|
||||
<div class="editor-option" ng-show="panel.lines">
|
||||
<label class="small">Line Fill</label>
|
||||
<select class="input-mini" ng-model="panel.fill" ng-options="f for f in [0,1,2,3,4,5,6,7,8,9,10]"></select>
|
||||
</div>
|
||||
<div class="editor-option" ng-show="panel.lines">
|
||||
<label class="small">Line Width</label>
|
||||
<select class="input-mini" ng-model="panel.linewidth" ng-options="f for f in [0,1,2,3,4,5,6,7,8,9,10]"></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h5>Multiple Series</h5>
|
||||
<div class="editor-option">
|
||||
<label class="small">Stack</label><input type="checkbox" ng-model="panel.stack" ng-checked="panel.stack">
|
||||
</div>
|
||||
<div class="editor-option" ng-show="panel.stack">
|
||||
<label style="white-space:nowrap" class="small">Percent <tip>Stack as a percentage of total</tip></label>
|
||||
<input type="checkbox" ng-model="panel.percentage" ng-checked="panel.percentage">
|
||||
</div>
|
||||
<div class="editor-option" ng-show="panel.stack">
|
||||
<label class="small">Stacked Values <tip>How should the values in stacked charts to be calculated?</tip></label>
|
||||
<select class="input-small" ng-model="panel.tooltip.value_type" ng-options="f for f in ['cumulative','individual']"></select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="editor-row">
|
||||
<div class="section">
|
||||
<h5>Header<h5>
|
||||
<div class="editor-option">
|
||||
<label class="small">Legend</label><input type="checkbox" ng-model="panel.legend" ng-checked="panel.legend">
|
||||
</div>
|
||||
<div class="editor-option">
|
||||
<label class="small">Zoom</label><input type="checkbox" ng-model="panel.zoomlinks" ng-checked="panel.zoomlinks" />
|
||||
</div>
|
||||
<div class="editor-option">
|
||||
<label class="small">View</label><input type="checkbox" ng-model="panel.options" ng-checked="panel.options" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -88,7 +88,7 @@ function (_, Interval) {
|
||||
* return the rows in the format:
|
||||
* [ [time, value], [time, value], ... ]
|
||||
*
|
||||
* Heavy lifting is done by _get(Min|All)FlotPairs()
|
||||
* Heavy lifting is done by _get(Min|Default|All)FlotPairs()
|
||||
* @param {array} required_times An array of timestamps that must be in the resulting pairs
|
||||
* @return {array}
|
||||
*/
|
||||
@ -99,8 +99,8 @@ function (_, Interval) {
|
||||
|
||||
if(this.opts.fill_style === 'all') {
|
||||
strategy = this._getAllFlotPairs;
|
||||
} else if(this.opts.fill_style = 'default') {
|
||||
strategy = this._getDefaultFlotPairs;
|
||||
} else if(this.opts.fill_style === 'null') {
|
||||
strategy = this._getNullFlotPairs;
|
||||
} else {
|
||||
strategy = this._getMinFlotPairs;
|
||||
}
|
||||
@ -114,13 +114,15 @@ function (_, Interval) {
|
||||
|
||||
// if the first or last pair is inside either the start or end time,
|
||||
// add those times to the series with null values so the graph will stretch to contain them.
|
||||
// Not sure this is required with flot 0.8.1's min/max params. Might be harmful?
|
||||
// Removing, flot 0.8.1's max/min params satisfy this
|
||||
/*
|
||||
if (this.start_time && (pairs.length === 0 || pairs[0][0] > this.start_time)) {
|
||||
pairs.unshift([this.start_time, null]);
|
||||
}
|
||||
if (this.end_time && (pairs.length === 0 || pairs[pairs.length - 1][0] < this.end_time)) {
|
||||
pairs.push([this.end_time, null]);
|
||||
}
|
||||
*/
|
||||
|
||||
return pairs;
|
||||
};
|
||||
@ -144,7 +146,7 @@ function (_, Interval) {
|
||||
}
|
||||
|
||||
// add the current time
|
||||
result.push([ time, this._data[time] || 0 ]);
|
||||
result.push([ time, this._data[time] || 0]);
|
||||
|
||||
// check for next measurement
|
||||
if (times.length > i) {
|
||||
@ -179,17 +181,31 @@ function (_, Interval) {
|
||||
|
||||
/**
|
||||
* ** called as a reduce stragegy in getFlotPairs() **
|
||||
* Does no zero filling
|
||||
* Same as min, but fills with nulls
|
||||
* @return {array} An array of points to plot with flot
|
||||
*/
|
||||
ts.ZeroFilled.prototype._getDefaultFlotPairs = function (result, time, i, times) {
|
||||
var next, expected_next;
|
||||
ts.ZeroFilled.prototype._getNullFlotPairs = function (result, time, i, times) {
|
||||
var next, expected_next, prev, expected_prev;
|
||||
|
||||
result.push([ times[i], this._data[times[i]] || 0 ]);
|
||||
next = times[i + 1];
|
||||
expected_next = this.interval.after(time);
|
||||
for(; times.length > i && next > expected_next; expected_next = this.interval.after(expected_next)) {
|
||||
result.push([expected_next, 0]);
|
||||
// check for previous measurement
|
||||
if (i > 0) {
|
||||
prev = times[i - 1];
|
||||
expected_prev = this.interval.before(time);
|
||||
if (prev < expected_prev) {
|
||||
result.push([expected_prev, null]);
|
||||
}
|
||||
}
|
||||
|
||||
// add the current time
|
||||
result.push([ time, this._data[time] || null]);
|
||||
|
||||
// check for next measurement
|
||||
if (times.length > i) {
|
||||
next = times[i + 1];
|
||||
expected_next = this.interval.after(time);
|
||||
if (next > expected_next) {
|
||||
result.push([expected_next, null]);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -114,14 +114,4 @@ define([
|
||||
|
||||
});
|
||||
|
||||
module.directive('queryConfig', function() {
|
||||
return {
|
||||
restrict: 'A',
|
||||
template: '<div></div>',
|
||||
link: function(scope, elem) {
|
||||
console.log(elem);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
});
|
2
src/css/bootstrap.dark.min.css
vendored
2
src/css/bootstrap.dark.min.css
vendored
File diff suppressed because one or more lines are too long
2
src/css/bootstrap.light.min.css
vendored
2
src/css/bootstrap.light.min.css
vendored
File diff suppressed because one or more lines are too long
17
src/vendor/bootstrap/less/overrides.less
vendored
17
src/vendor/bootstrap/less/overrides.less
vendored
@ -1,3 +1,20 @@
|
||||
div.editor-row {
|
||||
vertical-align: top;
|
||||
}
|
||||
div.editor-row div.section {
|
||||
margin-right: 20px;
|
||||
vertical-align: top;
|
||||
display: inline-block;
|
||||
}
|
||||
div.editor-option {
|
||||
vertical-align: top;
|
||||
display: inline-block;
|
||||
margin-right: 10px;
|
||||
}
|
||||
div.editor-option label {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#events {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user