Commit b05fca4f by Torkel Ödegaard

Merge branch 'master' of github.com:grafana/grafana

parents b471e7e4 23954f77
Please prefix your title with [Bug] or [Feature request] Read before posting:
For question please check [Support Options](http://grafana.org/support/). **Do not** open a github issue
- Questions should be posted to https://community.grafana.com. Please search there and here on GitHub for similar issues before creating a new issue.
- Checkout FAQ: https://community.grafana.com/c/howto/faq
- Checkout How to troubleshoot metric query issues: https://community.grafana.com/t/how-to-troubleshoot-metric-query-issues/50
Please prefix your title with [Bug] or [Feature request].
Please include this information: Please include this information:
- What Grafana version are you using? - What Grafana version are you using?
...@@ -8,11 +13,6 @@ Please include this information: ...@@ -8,11 +13,6 @@ Please include this information:
- What did you do? - What did you do?
- What was the expected result? - What was the expected result?
- What happened instead? - What happened instead?
- If related to metric query / data viz:
- Include raw network request & response: get by opening Chrome Dev Tools (F12, Ctrl+Shift+I on windows, Cmd+Opt+I on Mac), go the network tab.
**IMPORTANT**
If it relates to *metric data viz*:
- An image or text representation of your metric query
- The raw query and response for the network request (check this in chrome dev tools network tab, here you can see metric requests and other request, please include the request body and request response)
If it relates to *alerting*
- An image of the test execution data fully expanded.
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
* **InfluxDB**: influxdb query builder support for ORDER BY and LIMIT (allows TOPN queries) [#6065](https://github.com/grafana/grafana/issues/6065) Support influxdb's SLIMIT Feature [#7232](https://github.com/grafana/grafana/issues/7232) thx [@thuck](https://github.com/thuck) * **InfluxDB**: influxdb query builder support for ORDER BY and LIMIT (allows TOPN queries) [#6065](https://github.com/grafana/grafana/issues/6065) Support influxdb's SLIMIT Feature [#7232](https://github.com/grafana/grafana/issues/7232) thx [@thuck](https://github.com/thuck)
* **InfluxDB**: Small fix for the "glow" when focus the field for LIMIT and SLIMIT [#7799](https://github.com/grafana/grafana/pull/7799) thx [@thuck](https://github.com/thuck) * **InfluxDB**: Small fix for the "glow" when focus the field for LIMIT and SLIMIT [#7799](https://github.com/grafana/grafana/pull/7799) thx [@thuck](https://github.com/thuck)
* **Panels**: Delay loading & Lazy load panels as they become visible (scrolled into view) [#5216](https://github.com/grafana/grafana/issues/5216) thx [@jifwin](https://github.com/jifwin) * **Panels**: Delay loading & Lazy load panels as they become visible (scrolled into view) [#5216](https://github.com/grafana/grafana/issues/5216) thx [@jifwin](https://github.com/jifwin)
* **Graph**: Support auto grid min/max when using log scale [#3090](https://github.com/grafana/grafana/issues/3090), thx [@bigbenhur](https://github.com/bigbenhur)
## Minor Enchancements ## Minor Enchancements
......
[Grafana](http://grafana.org) [![Circle CI](https://circleci.com/gh/grafana/grafana.svg?style=svg)](https://circleci.com/gh/grafana/grafana) [Grafana](https://grafana.com) [![Circle CI](https://circleci.com/gh/grafana/grafana.svg?style=svg)](https://circleci.com/gh/grafana/grafana)
================ ================
[Website](http://grafana.org) | [Website](https://grafana.com) |
[Twitter](https://twitter.com/grafana) | [Twitter](https://twitter.com/grafana) |
[IRC](https://webchat.freenode.net/?channels=grafana) | [Community & Forum](https://community.grafana.com)
[![Slack](https://brandfolder.com/api/favicon/icon?size=16&domain=www.slack.com)](http://slack.raintank.io)
[Slack](http://slack.raintank.io) |
[Email](mailto:contact@grafana.org)
Grafana is an open source, feature rich metrics dashboard and graph editor for Grafana is an open source, feature rich metrics dashboard and graph editor for
Graphite, Elasticsearch, OpenTSDB, Prometheus and InfluxDB. Graphite, Elasticsearch, OpenTSDB, Prometheus and InfluxDB.
![](http://grafana.org/assets/img/features/dashboard_ex1.png) ![](http://docs.grafana.org/assets/img/features/dashboard_ex1.png)
- [Install instructions](http://docs.grafana.org/installation/) - [Install instructions](http://docs.grafana.org/installation/)
- [What's New in Grafana 2.0](http://docs.grafana.org/guides/whats-new-in-v2/) - [What's New in Grafana 2.0](http://docs.grafana.org/guides/whats-new-in-v2/)
...@@ -76,7 +73,7 @@ Be sure to read the [getting started guide](http://docs.grafana.org/guides/getti ...@@ -76,7 +73,7 @@ Be sure to read the [getting started guide](http://docs.grafana.org/guides/getti
## Run from master ## Run from master
If you want to build a package yourself, or contribute. Here is a guide for how to do that. You can always find If you want to build a package yourself, or contribute. Here is a guide for how to do that. You can always find
the latest master builds [here](http://grafana.org/builds) the latest master builds [here](https://grafana.com/grafana/download)
### Dependencies ### Dependencies
......
...@@ -100,6 +100,7 @@ export default class TimeSeries { ...@@ -100,6 +100,7 @@ export default class TimeSeries {
this.stats.total = 0; this.stats.total = 0;
this.stats.max = -Number.MAX_VALUE; this.stats.max = -Number.MAX_VALUE;
this.stats.min = Number.MAX_VALUE; this.stats.min = Number.MAX_VALUE;
this.stats.logmin = Number.MAX_VALUE;
this.stats.avg = null; this.stats.avg = null;
this.stats.current = null; this.stats.current = null;
this.stats.first = null; this.stats.first = null;
...@@ -172,6 +173,11 @@ export default class TimeSeries { ...@@ -172,6 +173,11 @@ export default class TimeSeries {
} }
} }
previousValue = currentValue; previousValue = currentValue;
if (currentValue < this.stats.logmin && currentValue > 0) {
this.stats.logmin = currentValue;
}
} }
if (currentValue !== 0) { if (currentValue !== 0) {
......
...@@ -460,7 +460,8 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv) { ...@@ -460,7 +460,8 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv) {
show: panel.yaxes[0].show, show: panel.yaxes[0].show,
index: 1, index: 1,
logBase: panel.yaxes[0].logBase || 1, logBase: panel.yaxes[0].logBase || 1,
max: null min: panel.yaxes[0].min ? _.toNumber(panel.yaxes[0].min) : null,
max: panel.yaxes[0].max ? _.toNumber(panel.yaxes[0].max) : null,
}; };
options.yaxes.push(defaults); options.yaxes.push(defaults);
...@@ -471,12 +472,13 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv) { ...@@ -471,12 +472,13 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv) {
secondY.show = panel.yaxes[1].show; secondY.show = panel.yaxes[1].show;
secondY.logBase = panel.yaxes[1].logBase || 1; secondY.logBase = panel.yaxes[1].logBase || 1;
secondY.position = 'right'; secondY.position = 'right';
secondY.min = panel.yaxes[1].min ? _.toNumber(panel.yaxes[1].min) : null;
secondY.max = panel.yaxes[1].max ? _.toNumber(panel.yaxes[1].max) : null;
options.yaxes.push(secondY); options.yaxes.push(secondY);
applyLogScale(options.yaxes[1], data); applyLogScale(options.yaxes[1], data);
configureAxisMode(options.yaxes[1], panel.percentage && panel.stack ? "percent" : panel.yaxes[1].format); configureAxisMode(options.yaxes[1], panel.percentage && panel.stack ? "percent" : panel.yaxes[1].format);
} }
applyLogScale(options.yaxes[0], data); applyLogScale(options.yaxes[0], data);
configureAxisMode(options.yaxes[0], panel.percentage && panel.stack ? "percent" : panel.yaxes[0].format); configureAxisMode(options.yaxes[0], panel.percentage && panel.stack ? "percent" : panel.yaxes[0].format);
} }
...@@ -485,43 +487,67 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv) { ...@@ -485,43 +487,67 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv) {
if (axis.logBase === 1) { if (axis.logBase === 1) {
return; return;
} }
if (axis.min < Number.MIN_VALUE) {
axis.min = null;
}
if (axis.max < Number.MIN_VALUE) {
axis.max = null;
}
var series, i; var series, i;
var max = axis.max; var max = axis.max, min = axis.min;
if (max === null) {
for (i = 0; i < data.length; i++) { for (i = 0; i < data.length; i++) {
series = data[i]; series = data[i];
if (series.yaxis === axis.index) { if (series.yaxis === axis.index) {
if (max < series.stats.max) { if (!max || max < series.stats.max) {
max = series.stats.max; max = series.stats.max;
} }
if (!min || min > series.stats.logmin) {
min = series.stats.logmin;
} }
} }
if (max === void 0) {
max = Number.MAX_VALUE;
} }
axis.transform = function(v) { return (v < Number.MIN_VALUE) ? null : Math.log(v) / Math.log(axis.logBase); };
axis.inverseTransform = function (v) { return Math.pow(axis.logBase,v); };
if (!max && !min) {
max = axis.inverseTransform(+2);
min = axis.inverseTransform(-2);
} else if (!max) {
max = min*axis.inverseTransform(+4);
} else if (!min) {
min = max*axis.inverseTransform(-4);
}
if (axis.min) {
min = axis.inverseTransform(Math.ceil(axis.transform(axis.min)));
} else {
min = axis.min = axis.inverseTransform(Math.floor(axis.transform(min)));
}
if (axis.max) {
max = axis.inverseTransform(Math.floor(axis.transform(axis.max)));
} else {
max = axis.max = axis.inverseTransform(Math.ceil(axis.transform(max)));
} }
axis.min = axis.min !== null ? axis.min : 0; if (!min || min < Number.MIN_VALUE || !max || max < Number.MIN_VALUE) {
axis.ticks = [0, 1]; return;
var nextTick = 1; }
while (true) { axis.ticks = [];
nextTick = nextTick * axis.logBase; var nextTick;
for (nextTick = min; nextTick <= max; nextTick *= axis.logBase) {
axis.ticks.push(nextTick); axis.ticks.push(nextTick);
if (nextTick > max) {
break;
} }
axis.tickDecimals = decimalPlaces(min);
} }
if (axis.logBase === 10) { function decimalPlaces(num) {
axis.transform = function(v) { return Math.log(v+0.1); }; if (!num) { return 0; }
axis.inverseTransform = function (v) { return Math.pow(10,v); };
} else { return (num.toString().split('.')[1] || []).length;
axis.transform = function(v) { return Math.log(v+0.1) / Math.log(axis.logBase); };
axis.inverseTransform = function (v) { return Math.pow(axis.logBase,v); };
}
} }
function configureAxisMode(axis, format) { function configureAxisMode(axis, format) {
......
...@@ -113,15 +113,43 @@ describe('grafanaGraph', function() { ...@@ -113,15 +113,43 @@ describe('grafanaGraph', function() {
}); });
graphScenario('when logBase is log 10', function(ctx) { graphScenario('when logBase is log 10', function(ctx) {
ctx.setup(function(ctrl) { ctx.setup(function(ctrl, data) {
ctrl.panel.yaxes[0].logBase = 10; ctrl.panel.yaxes[0].logBase = 10;
data[0] = new TimeSeries({
datapoints: [[2000,1],[0.002,2],[0,3],[-1,4]],
alias: 'seriesAutoscale',
});
data[0].yaxis = 1;
ctrl.panel.yaxes[1].logBase = 10;
ctrl.panel.yaxes[1].min = '0.05';
ctrl.panel.yaxes[1].max = '1500';
data[1] = new TimeSeries({
datapoints: [[2000,1],[0.002,2],[0,3],[-1,4]],
alias: 'seriesFixedscale',
});
data[1].yaxis = 2;
}); });
it('should apply axis transform and ticks', function() { it('should apply axis transform, autoscaling (if necessary) and ticks', function() {
var axis = ctx.plotOptions.yaxes[0]; var axisAutoscale = ctx.plotOptions.yaxes[0];
expect(axis.transform(100)).to.be(Math.log(100+0.1)); expect(axisAutoscale.transform(100)).to.be(2);
expect(axis.ticks[0]).to.be(0); expect(axisAutoscale.inverseTransform(-3)).to.be(0.001);
expect(axis.ticks[1]).to.be(1); expect(axisAutoscale.min).to.be(0.001);
expect(axisAutoscale.max).to.be(10000);
expect(axisAutoscale.ticks.length).to.be(8);
expect(axisAutoscale.ticks[0]).to.be(0.001);
expect(axisAutoscale.ticks[7]).to.be(10000);
expect(axisAutoscale.tickDecimals).to.be(3);
var axisFixedscale = ctx.plotOptions.yaxes[1];
expect(axisFixedscale.min).to.be(0.05);
expect(axisFixedscale.max).to.be(1500);
expect(axisFixedscale.ticks.length).to.be(5);
expect(axisFixedscale.ticks[0]).to.be(0.1);
expect(axisFixedscale.ticks[4]).to.be(1000);
expect(axisFixedscale.tickDecimals).to.be(1);
}); });
}); });
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment