mirror of
https://github.com/grafana/grafana.git
synced 2024-11-29 12:14:08 -06:00
heatmap: Docs and heatmap fixes
This commit is contained in:
parent
30b6c3b54a
commit
ab6740c685
@ -20,7 +20,7 @@ The Heatmap panel allows you to view histograms over time.
|
|||||||
|
|
||||||
A histogram is a graphical representation of the distribution of numerical data. You group values into buckets
|
A histogram is a graphical representation of the distribution of numerical data. You group values into buckets
|
||||||
(some times also called bins) and then count how many values fall into each bucket. Instead
|
(some times also called bins) and then count how many values fall into each bucket. Instead
|
||||||
of graphing the actual values you then graph the buckets. Each each bar represents a bucket
|
of graphing the actual values you then graph the buckets. Each bar represents a bucket
|
||||||
and the bar height represents the frequency (i.e. count) of values that fell into that bucket's interval.
|
and the bar height represents the frequency (i.e. count) of values that fell into that bucket's interval.
|
||||||
|
|
||||||
Example Histogram:
|
Example Histogram:
|
||||||
@ -34,9 +34,9 @@ this is where heatmaps become useful.
|
|||||||
|
|
||||||
## Heatmap
|
## Heatmap
|
||||||
|
|
||||||
A Heatmap is like a histogram but over time where each time slice represents it's own
|
A Heatmap is like a histogram but over time where each time slice represents its own
|
||||||
histogram. Instead of using bar hight as a represenation of frequency you use a cells and color
|
histogram. Instead of using bar height as a representation of frequency you use cells and color
|
||||||
the cell propotional to the number of values in the bucket.
|
the cell proportional to the number of values in the bucket.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@ -64,8 +64,7 @@ the time range `1h`. This will make the cells 1h wide on the X-axis.
|
|||||||
|
|
||||||
### Pre-bucketed data
|
### Pre-bucketed data
|
||||||
|
|
||||||
If you have a data that is already organized into buckets you can use the `Time series buckets` data format. This
|
If you have a data that is already organized into buckets you can use the `Time series buckets` data format. This format requires that your metric query return regular time series and that each time series has a numeric name
|
||||||
format requires that your metric query return regular time series and that each time series has numeric name
|
|
||||||
that represent the upper or lower bound of the interval.
|
that represent the upper or lower bound of the interval.
|
||||||
|
|
||||||
The only data source that supports histograms over time is Elasticsearch. You do this by adding a *Histogram*
|
The only data source that supports histograms over time is Elasticsearch. You do this by adding a *Histogram*
|
||||||
@ -77,7 +76,30 @@ You control the size of the buckets using the Histogram interval (Y-Axis) and th
|
|||||||
|
|
||||||
## Display Options
|
## Display Options
|
||||||
|
|
||||||
The color spectrum controls what value get's assigned what color. The left most color on the
|
In the heatmap *Display* tab you define how the cells are rendered and what color they are assigned.
|
||||||
spectrum represents the low frequency and the color on the right most side represents the max frequency.
|
|
||||||
Most color schemes are automatically inverted when using the light theme.
|
|
||||||
|
|
||||||
|
### Color Mode & Spectrum
|
||||||
|
|
||||||
|
{{< imgbox max-width="40%" img="/img/docs/v43/heatmap_scheme.png" caption="Color spectrum" >}}
|
||||||
|
|
||||||
|
The color spectrum controls the mapping between value count (in each bucket) and the color assigned to each bucket.
|
||||||
|
The left most color on the spectrum represents the minimum count and the color on the right most side represents the
|
||||||
|
maximum count. Some color schemes are automatically inverted when using the light theme.
|
||||||
|
|
||||||
|
You can also change the color mode to `Opacity`. In this case, the color will not change but the amount of opacity will
|
||||||
|
change with the bucket count.
|
||||||
|
|
||||||
|
## Raw data vs aggregated
|
||||||
|
|
||||||
|
If you use the heatmap with regular time series data (not pre-bucketed). Then it's important to keep in mind that your data
|
||||||
|
is often already by aggregated by your time series backend. Most time series queries do not return raw sample data
|
||||||
|
but include a group by time interval or maxDataPoints limit coupled with an aggregation function (usually average).
|
||||||
|
|
||||||
|
This all depends on the time range of your query of course. But the important point is to know that the Histogram bucketing
|
||||||
|
that Grafana performs may be done on already aggregated and averaged data. To get more accurate heatmaps it is better
|
||||||
|
to do the bucketing during metric collection or store the data in Elasticsearch, which currently is the only data source
|
||||||
|
data supports doing Histogram bucketing on the raw data.
|
||||||
|
|
||||||
|
If you remove or lower the group by time (or raise maxDataPoints) in your query to return more data points your heatmap will be
|
||||||
|
more accurate but this can also be very CPU & Memory taxing for your browser and could cause hangs and crashes if the number of
|
||||||
|
data points becomes unreasonably large.
|
||||||
|
@ -423,7 +423,7 @@ coreModule.directive('grafanaGraph', function($rootScope, timeSrv, popoverSrv) {
|
|||||||
function addXHistogramAxis(options, bucketSize) {
|
function addXHistogramAxis(options, bucketSize) {
|
||||||
let ticks, min, max;
|
let ticks, min, max;
|
||||||
|
|
||||||
if (data.length) {
|
if (data.length && bucketSize) {
|
||||||
ticks = _.map(data[0].data, point => point[0]);
|
ticks = _.map(data[0].data, point => point[0]);
|
||||||
|
|
||||||
// Expand ticks for pretty view
|
// Expand ticks for pretty view
|
||||||
|
@ -38,7 +38,6 @@ let panelDefaults = {
|
|||||||
splitFactor: null,
|
splitFactor: null,
|
||||||
min: null,
|
min: null,
|
||||||
max: null,
|
max: null,
|
||||||
removeZeroValues: false
|
|
||||||
},
|
},
|
||||||
xBucketSize: null,
|
xBucketSize: null,
|
||||||
xBucketNumber: null,
|
xBucketNumber: null,
|
||||||
|
@ -122,24 +122,6 @@ function mergeZeroBuckets(buckets, minValue) {
|
|||||||
return buckets;
|
return buckets;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove 0 values from heatmap buckets.
|
|
||||||
*/
|
|
||||||
function removeZeroBuckets(buckets) {
|
|
||||||
_.forEach(buckets, xBucket => {
|
|
||||||
let yBuckets = xBucket.buckets;
|
|
||||||
let newYBuckets = {};
|
|
||||||
_.forEach(yBuckets, (bucket, bound) => {
|
|
||||||
if (bucket.y !== 0) {
|
|
||||||
newYBuckets[bound] = bucket;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
xBucket.buckets = newYBuckets;
|
|
||||||
});
|
|
||||||
|
|
||||||
return buckets;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert set of time series into heatmap buckets
|
* Convert set of time series into heatmap buckets
|
||||||
* @return {Object} Heatmap object:
|
* @return {Object} Heatmap object:
|
||||||
@ -429,7 +411,6 @@ export {
|
|||||||
convertToHeatMap,
|
convertToHeatMap,
|
||||||
elasticHistogramToHeatmap,
|
elasticHistogramToHeatmap,
|
||||||
convertToCards,
|
convertToCards,
|
||||||
removeZeroBuckets,
|
|
||||||
mergeZeroBuckets,
|
mergeZeroBuckets,
|
||||||
getMinLog,
|
getMinLog,
|
||||||
getValueBucketBound,
|
getValueBucketBound,
|
||||||
|
@ -8,7 +8,7 @@ import {appEvents, contextSrv} from 'app/core/core';
|
|||||||
import {tickStep} from 'app/core/utils/ticks';
|
import {tickStep} from 'app/core/utils/ticks';
|
||||||
import d3 from 'd3';
|
import d3 from 'd3';
|
||||||
import {HeatmapTooltip} from './heatmap_tooltip';
|
import {HeatmapTooltip} from './heatmap_tooltip';
|
||||||
import {convertToCards, mergeZeroBuckets, removeZeroBuckets} from './heatmap_data_converter';
|
import {convertToCards, mergeZeroBuckets} from './heatmap_data_converter';
|
||||||
|
|
||||||
let MIN_CARD_SIZE = 1,
|
let MIN_CARD_SIZE = 1,
|
||||||
CARD_PADDING = 1,
|
CARD_PADDING = 1,
|
||||||
@ -357,15 +357,11 @@ export default function link(scope, elem, attrs, ctrl) {
|
|||||||
addAxes();
|
addAxes();
|
||||||
|
|
||||||
if (panel.yAxis.logBase !== 1) {
|
if (panel.yAxis.logBase !== 1) {
|
||||||
if (panel.yAxis.removeZeroValues) {
|
|
||||||
data.buckets = removeZeroBuckets(data.buckets);
|
|
||||||
} else {
|
|
||||||
let log_base = panel.yAxis.logBase;
|
let log_base = panel.yAxis.logBase;
|
||||||
let domain = yScale.domain();
|
let domain = yScale.domain();
|
||||||
let tick_values = logScaleTickValues(domain, log_base);
|
let tick_values = logScaleTickValues(domain, log_base);
|
||||||
data.buckets = mergeZeroBuckets(data.buckets, _.min(tick_values));
|
data.buckets = mergeZeroBuckets(data.buckets, _.min(tick_values));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let cardsData = convertToCards(data.buckets);
|
let cardsData = convertToCards(data.buckets);
|
||||||
let maxValue = d3.max(cardsData, card => card.count);
|
let maxValue = d3.max(cardsData, card => card.count);
|
||||||
@ -750,6 +746,15 @@ export default function link(scope, elem, attrs, ctrl) {
|
|||||||
panel = ctrl.panel;
|
panel = ctrl.panel;
|
||||||
timeRange = ctrl.range;
|
timeRange = ctrl.range;
|
||||||
|
|
||||||
|
// Draw only if color editor is opened
|
||||||
|
if (!d3.select("#heatmap-color-legend").empty()) {
|
||||||
|
drawColorLegend();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!d3.select("#heatmap-opacity-legend").empty()) {
|
||||||
|
drawOpacityLegend();
|
||||||
|
}
|
||||||
|
|
||||||
if (!setElementHeight() || !data) {
|
if (!setElementHeight() || !data) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -767,14 +772,6 @@ export default function link(scope, elem, attrs, ctrl) {
|
|||||||
scope.chartHeight = chartHeight;
|
scope.chartHeight = chartHeight;
|
||||||
scope.chartWidth = chartWidth;
|
scope.chartWidth = chartWidth;
|
||||||
scope.chartTop = chartTop;
|
scope.chartTop = chartTop;
|
||||||
|
|
||||||
// Draw only if color editor is opened
|
|
||||||
if (!d3.select("#heatmap-color-legend").empty()) {
|
|
||||||
drawColorLegend();
|
|
||||||
}
|
|
||||||
if (!d3.select("#heatmap-opacity-legend").empty()) {
|
|
||||||
drawOpacityLegend();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register selection listeners
|
// Register selection listeners
|
||||||
|
Loading…
Reference in New Issue
Block a user