heatmapPlugin.023404025d5e6228a049.js.map 123 KB

1
  1. {"version":3,"file":"heatmapPlugin.023404025d5e6228a049.js","mappings":"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","sources":["webpack://grafana/./public/app/angular/panel/query_ctrl.ts","webpack://grafana/./public/app/plugins/panel/heatmap/color_scale.ts","webpack://grafana/./public/app/plugins/panel/heatmap/color_legend.ts","webpack://grafana/./public/app/plugins/panel/heatmap/axes_editor.ts","webpack://grafana/./public/app/plugins/panel/heatmap/display_editor.ts","webpack://grafana/./public/app/plugins/panel/heatmap/heatmap_data_converter.ts","webpack://grafana/./public/app/plugins/panel/heatmap/heatmap_tooltip.ts","webpack://grafana/./public/app/plugins/panel/heatmap/rendering.ts","webpack://grafana/./public/app/plugins/panel/heatmap/heatmap_ctrl.ts","webpack://grafana/./public/app/plugins/sdk.ts"],"sourcesContent":["import { auto } from 'angular';\nimport { indexOf } from 'lodash';\n\nexport class QueryCtrl<T = any> {\n target!: T;\n datasource!: any;\n panelCtrl!: any;\n panel: any;\n hasRawMode!: boolean;\n error?: string | null;\n isLastQuery: boolean;\n\n constructor(public $scope: any, public $injector: auto.IInjectorService) {\n this.panelCtrl = this.panelCtrl ?? $scope.ctrl.panelCtrl;\n this.target = this.target ?? $scope.ctrl.target;\n this.datasource = this.datasource ?? $scope.ctrl.datasource;\n this.panel = this.panelCtrl?.panel ?? $scope.ctrl.panelCtrl.panel;\n this.isLastQuery = indexOf(this.panel.targets, this.target) === this.panel.targets.length - 1;\n }\n\n refresh() {\n this.panelCtrl.refresh();\n }\n}\n","import * as d3 from 'd3';\nimport * as d3ScaleChromatic from 'd3-scale-chromatic';\n\nexport function getColorScale(colorScheme: any, lightTheme: boolean, maxValue: number, minValue = 0): (d: any) => any {\n //@ts-ignore\n const colorInterpolator = d3ScaleChromatic[colorScheme.value];\n const colorScaleInverted = colorScheme.invert === 'always' || colorScheme.invert === (lightTheme ? 'light' : 'dark');\n\n const start = colorScaleInverted ? maxValue : minValue;\n const end = colorScaleInverted ? minValue : maxValue;\n\n return d3.scaleSequential(colorInterpolator).domain([start, end]);\n}\n\nexport function getOpacityScale(\n options: { cardColor?: null; colorScale?: any; exponent?: any },\n maxValue: number,\n minValue = 0\n): any {\n let legendOpacityScale;\n if (options.colorScale === 'linear') {\n legendOpacityScale = d3.scaleLinear().domain([minValue, maxValue]).range([0, 1]);\n } else if (options.colorScale === 'sqrt') {\n legendOpacityScale = d3.scalePow().exponent(options.exponent).domain([minValue, maxValue]).range([0, 1]);\n }\n return legendOpacityScale;\n}\n","import * as d3 from 'd3';\nimport $ from 'jquery';\nimport { find, isEmpty, isNil, sortBy, uniq } from 'lodash';\n\nimport { PanelEvents } from '@grafana/data';\nimport coreModule from 'app/angular/core_module';\nimport { config } from 'app/core/config';\nimport { contextSrv } from 'app/core/core';\nimport { tickStep } from 'app/core/utils/ticks';\n\nimport { getColorScale, getOpacityScale } from './color_scale';\n\nconst LEGEND_HEIGHT_PX = 6;\nconst LEGEND_WIDTH_PX = 100;\nconst LEGEND_TICK_SIZE = 0;\nconst LEGEND_VALUE_MARGIN = 0;\nconst LEGEND_PADDING_LEFT = 10;\nconst LEGEND_SEGMENT_WIDTH = 10;\n\n/**\n * Color legend for heatmap editor.\n */\ncoreModule.directive('colorLegend', () => {\n return {\n restrict: 'E',\n template: '<div class=\"heatmap-color-legend\"><svg width=\"16.5rem\" height=\"24px\"></svg></div>',\n link: (scope: any, elem, attrs) => {\n const ctrl = scope.ctrl;\n const panel = scope.ctrl.panel;\n\n render();\n\n ctrl.events.on(PanelEvents.render, () => {\n render();\n });\n\n function render() {\n const legendElem = $(elem).find('svg');\n const legendWidth = Math.floor(legendElem.outerWidth() ?? 10);\n\n if (panel.color.mode === 'spectrum') {\n const colorScheme: any = find(ctrl.colorSchemes, {\n value: panel.color.colorScheme,\n });\n const colorScale = getColorScale(colorScheme, contextSrv.user.lightTheme, legendWidth);\n drawSimpleColorLegend(elem, colorScale);\n } else if (panel.color.mode === 'opacity') {\n const colorOptions = panel.color;\n drawSimpleOpacityLegend(elem, colorOptions);\n }\n }\n },\n };\n});\n\n/**\n * Heatmap legend with scale values.\n */\ncoreModule.directive('heatmapLegend', () => {\n return {\n restrict: 'E',\n template: `<div class=\"heatmap-color-legend\"><svg width=\"${LEGEND_WIDTH_PX}px\" height=\"${LEGEND_HEIGHT_PX}px\"></svg></div>`,\n link: (scope: any, elem, attrs) => {\n const ctrl = scope.ctrl;\n const panel = scope.ctrl.panel;\n\n render();\n ctrl.events.on(PanelEvents.render, () => {\n render();\n });\n\n function render() {\n clearLegend(elem);\n if (!isEmpty(ctrl.data) && !isEmpty(ctrl.data.cards)) {\n const cardStats = ctrl.data.cardStats;\n const rangeFrom = isNil(panel.color.min) ? Math.max(cardStats.min, 0) : panel.color.min;\n const rangeTo = isNil(panel.color.max) ? cardStats.max : panel.color.max;\n const maxValue = cardStats.max;\n const minValue = cardStats.min;\n\n if (panel.color.mode === 'spectrum') {\n const colorScheme: any = find(ctrl.colorSchemes, {\n value: panel.color.colorScheme,\n });\n drawColorLegend(elem, colorScheme, rangeFrom, rangeTo, maxValue, minValue);\n } else if (panel.color.mode === 'opacity') {\n const colorOptions = panel.color;\n drawOpacityLegend(elem, colorOptions, rangeFrom, rangeTo, maxValue, minValue);\n }\n }\n }\n },\n };\n});\n\nfunction drawColorLegend(\n elem: JQuery,\n colorScheme: any,\n rangeFrom: number,\n rangeTo: number,\n maxValue: number,\n minValue: number\n) {\n const legendElem = $(elem).find('svg');\n const legendDomElement = legendElem.get(0);\n if (legendDomElement) {\n const legend = d3.select(legendDomElement);\n clearLegend(elem);\n\n const legendWidth = Math.floor(legendElem.outerWidth() ?? 10) - 30;\n const legendHeight = legendElem.attr('height') as any;\n\n const rangeStep = ((rangeTo - rangeFrom) / legendWidth) * LEGEND_SEGMENT_WIDTH;\n const widthFactor = legendWidth / (rangeTo - rangeFrom);\n const valuesRange = d3.range(rangeFrom, rangeTo, rangeStep);\n\n const colorScale = getColorScale(colorScheme, contextSrv.user.lightTheme, rangeTo, rangeFrom);\n legend\n .append('g')\n .attr('class', 'legend-color-bar')\n .attr('transform', 'translate(' + LEGEND_PADDING_LEFT + ',0)')\n .selectAll('.heatmap-color-legend-rect')\n .data(valuesRange)\n .enter()\n .append('rect')\n .attr('x', (d) => Math.round((d - rangeFrom) * widthFactor))\n .attr('y', 0)\n .attr('width', Math.round(rangeStep * widthFactor + 1)) // Overlap rectangles to prevent gaps\n .attr('height', legendHeight)\n .attr('stroke-width', 0)\n .attr('fill', (d) => colorScale(d));\n\n drawLegendValues(elem, rangeFrom, rangeTo, maxValue, minValue, legendWidth, valuesRange);\n }\n}\n\nfunction drawOpacityLegend(\n elem: JQuery,\n options: { cardColor: null },\n rangeFrom: number,\n rangeTo: number,\n maxValue: any,\n minValue: number\n) {\n const legendElem = $(elem).find('svg');\n const legendDomElement = legendElem.get(0);\n if (legendDomElement) {\n const legend = d3.select(legendDomElement);\n clearLegend(elem);\n\n const legendWidth = Math.floor(legendElem.outerWidth() ?? 30) - 30;\n const legendHeight = legendElem.attr('height') as any;\n\n const rangeStep = ((rangeTo - rangeFrom) / legendWidth) * LEGEND_SEGMENT_WIDTH;\n const widthFactor = legendWidth / (rangeTo - rangeFrom);\n const valuesRange = d3.range(rangeFrom, rangeTo, rangeStep);\n\n const opacityScale = getOpacityScale(options, rangeTo, rangeFrom);\n legend\n .append('g')\n .attr('class', 'legend-color-bar')\n .attr('transform', 'translate(' + LEGEND_PADDING_LEFT + ',0)')\n .selectAll('.heatmap-opacity-legend-rect')\n .data(valuesRange)\n .enter()\n .append('rect')\n .attr('x', (d) => Math.round((d - rangeFrom) * widthFactor))\n .attr('y', 0)\n .attr('width', Math.round(rangeStep * widthFactor))\n .attr('height', legendHeight)\n .attr('stroke-width', 0)\n .attr('fill', options.cardColor)\n .style('opacity', (d) => opacityScale(d));\n\n drawLegendValues(elem, rangeFrom, rangeTo, maxValue, minValue, legendWidth, valuesRange);\n }\n}\n\nfunction drawLegendValues(\n elem: JQuery,\n rangeFrom: number,\n rangeTo: number,\n maxValue: any,\n minValue: any,\n legendWidth: number,\n valuesRange: number[]\n) {\n const legendElem = $(elem).find('svg');\n const legendDomElement = legendElem.get(0);\n if (legendDomElement) {\n const legend = d3.select(legendDomElement);\n\n if (legendWidth <= 0 || legendDomElement.childNodes.length === 0) {\n return;\n }\n\n const legendValueScale = d3.scaleLinear().domain([rangeFrom, rangeTo]).range([0, legendWidth]);\n\n const ticks = buildLegendTicks(rangeFrom, rangeTo, maxValue, minValue);\n const xAxis = d3.axisBottom(legendValueScale).tickValues(ticks).tickSize(LEGEND_TICK_SIZE);\n\n const colorRect = legendElem.find(':first-child');\n const posY = getSvgElemHeight(legendElem) + LEGEND_VALUE_MARGIN;\n const posX = getSvgElemX(colorRect) + LEGEND_PADDING_LEFT;\n\n d3.select(legendDomElement)\n .append('g')\n .attr('class', 'axis')\n .attr('transform', 'translate(' + posX + ',' + posY + ')')\n .call(xAxis);\n\n legend.select('.axis').select('.domain').remove();\n }\n}\n\nfunction drawSimpleColorLegend(elem: JQuery, colorScale: any) {\n const legendElem = $(elem).find('svg');\n clearLegend(elem);\n\n const legendWidth = Math.floor(legendElem.outerWidth() ?? 30);\n const legendHeight = legendElem.attr('height') as any;\n\n if (legendWidth) {\n const valuesNumber = Math.floor(legendWidth / 2);\n const rangeStep = Math.floor(legendWidth / valuesNumber);\n const valuesRange = d3.range(0, legendWidth, rangeStep);\n\n const legendDomElement = legendElem.get(0);\n if (legendDomElement) {\n const legend = d3.select(legendDomElement);\n const legendRects = legend.selectAll('.heatmap-color-legend-rect').data(valuesRange);\n\n legendRects\n .enter()\n .append('rect')\n .attr('x', (d) => d)\n .attr('y', 0)\n .attr('width', rangeStep + 1) // Overlap rectangles to prevent gaps\n .attr('height', legendHeight)\n .attr('stroke-width', 0)\n .attr('fill', (d) => colorScale(d));\n }\n }\n}\n\nfunction drawSimpleOpacityLegend(elem: JQuery, options: { colorScale: string; exponent: number; cardColor: string }) {\n const legendElem = $(elem).find('svg');\n const legendDomElement = legendElem.get(0);\n if (legendDomElement) {\n clearLegend(elem);\n\n const legend = d3.select(legendDomElement);\n const legendWidth = Math.floor(legendElem.outerWidth() ?? 30);\n const legendHeight = legendElem.attr('height') as any;\n\n if (legendWidth) {\n let legendOpacityScale: any;\n if (options.colorScale === 'linear') {\n legendOpacityScale = d3.scaleLinear().domain([0, legendWidth]).range([0, 1]);\n } else if (options.colorScale === 'sqrt') {\n legendOpacityScale = d3.scalePow().exponent(options.exponent).domain([0, legendWidth]).range([0, 1]);\n }\n\n const rangeStep = 10;\n const valuesRange = d3.range(0, legendWidth, rangeStep);\n const legendRects = legend.selectAll('.heatmap-opacity-legend-rect').data(valuesRange);\n\n legendRects\n .enter()\n .append('rect')\n .attr('x', (d) => d)\n .attr('y', 0)\n .attr('width', rangeStep)\n .attr('height', legendHeight)\n .attr('stroke-width', 0)\n .attr('fill', config.theme.visualization.getColorByName(options.cardColor))\n .style('opacity', (d) => legendOpacityScale(d));\n }\n }\n}\n\nfunction clearLegend(elem: JQuery) {\n const legendElem = $(elem).find('svg');\n legendElem.empty();\n}\n\nfunction getSvgElemX(elem: JQuery) {\n const svgElem: any = elem.get(0) as any;\n if (svgElem && svgElem.x && svgElem.x.baseVal) {\n return svgElem.x.baseVal.value;\n } else {\n return 0;\n }\n}\n\nfunction getSvgElemHeight(elem: JQuery<any>) {\n const svgElem: any = elem.get(0);\n if (svgElem && svgElem.height && svgElem.height.baseVal) {\n return svgElem.height.baseVal.value;\n } else {\n return 0;\n }\n}\n\nfunction buildLegendTicks(rangeFrom: number, rangeTo: number, maxValue: number, minValue: number) {\n const range = rangeTo - rangeFrom;\n const tickStepSize = tickStep(rangeFrom, rangeTo, 3);\n const ticksNum = Math.ceil(range / tickStepSize);\n const firstTick = getFirstCloseTick(rangeFrom, tickStepSize);\n let ticks = [];\n\n for (let i = 0; i < ticksNum; i++) {\n const current = firstTick + tickStepSize * i;\n // Add user-defined min and max if it had been set\n if (isValueCloseTo(minValue, current, tickStepSize)) {\n ticks.push(minValue);\n continue;\n } else if (minValue < current) {\n ticks.push(minValue);\n }\n if (isValueCloseTo(maxValue, current, tickStepSize)) {\n ticks.push(maxValue);\n continue;\n } else if (maxValue < current) {\n ticks.push(maxValue);\n }\n ticks.push(current);\n }\n if (!isValueCloseTo(maxValue, rangeTo, tickStepSize)) {\n ticks.push(maxValue);\n }\n ticks.push(rangeTo);\n ticks = sortBy(uniq(ticks));\n return ticks;\n}\n\nfunction isValueCloseTo(val: number, valueTo: number, step: number) {\n const diff = Math.abs(val - valueTo);\n return diff < step * 0.3;\n}\n\nfunction getFirstCloseTick(minValue: number, step: number) {\n if (minValue < 0) {\n return Math.floor(minValue / step) * step;\n }\n return 0;\n}\n","export class AxesEditorCtrl {\n panel: any;\n panelCtrl: any;\n logScales: any;\n dataFormats: any;\n yBucketBoundModes: any;\n\n /** @ngInject */\n constructor($scope: any, uiSegmentSrv: any) {\n $scope.editor = this;\n this.panelCtrl = $scope.ctrl;\n this.panel = this.panelCtrl.panel;\n\n this.logScales = {\n linear: 1,\n 'log (base 2)': 2,\n 'log (base 10)': 10,\n 'log (base 32)': 32,\n 'log (base 1024)': 1024,\n };\n\n this.dataFormats = {\n 'Time series': 'timeseries',\n 'Time series buckets': 'tsbuckets',\n };\n\n this.yBucketBoundModes = {\n Auto: 'auto',\n Upper: 'upper',\n Lower: 'lower',\n Middle: 'middle',\n };\n }\n\n setUnitFormat = (unit: string) => {\n this.panel.yAxis.format = unit;\n this.panelCtrl.render();\n };\n}\n\n/** @ngInject */\nexport function axesEditor() {\n 'use strict';\n return {\n restrict: 'E',\n scope: true,\n templateUrl: 'public/app/plugins/panel/heatmap/partials/axes_editor.html',\n controller: AxesEditorCtrl,\n };\n}\n","export class HeatmapDisplayEditorCtrl {\n panel: any;\n panelCtrl: any;\n\n /** @ngInject */\n constructor($scope: any) {\n $scope.editor = this;\n this.panelCtrl = $scope.ctrl;\n this.panel = this.panelCtrl.panel;\n }\n}\n\n/** @ngInject */\nexport function heatmapDisplayEditor() {\n 'use strict';\n return {\n restrict: 'E',\n scope: true,\n templateUrl: 'public/app/plugins/panel/heatmap/partials/display_editor.html',\n controller: HeatmapDisplayEditorCtrl,\n };\n}\n","import { concat, forEach, isEmpty, isEqual, isNumber, sortBy } from 'lodash';\n\nimport { TimeSeries } from 'app/core/core';\n\nimport { Bucket, HeatmapCard, HeatmapCardStats, YBucket, XBucket } from './types';\n\nconst VALUE_INDEX = 0;\nconst TIME_INDEX = 1;\n\n/**\n * Convert histogram represented by the list of series to heatmap object.\n * @param seriesList List of time series\n */\nfunction histogramToHeatmap(seriesList: TimeSeries[]) {\n const heatmap: any = {};\n\n for (let i = 0; i < seriesList.length; i++) {\n const series = seriesList[i];\n const bound = i;\n if (isNaN(bound)) {\n return heatmap;\n }\n\n for (const point of series.datapoints) {\n const count = point[VALUE_INDEX];\n const time = point[TIME_INDEX];\n\n if (!isNumber(count)) {\n continue;\n }\n\n let bucket = heatmap[time];\n if (!bucket) {\n bucket = heatmap[time] = { x: time, buckets: {} };\n }\n\n bucket.buckets[bound] = {\n y: bound,\n count: count,\n bounds: {\n top: null,\n bottom: bound,\n },\n values: [],\n points: [],\n };\n }\n }\n\n return heatmap;\n}\n\n/**\n * Sort series representing histogram by label value.\n */\nfunction sortSeriesByLabel(s1: { label: string }, s2: { label: string }) {\n let label1, label2;\n\n try {\n // fail if not integer. might happen with bad queries\n label1 = parseHistogramLabel(s1.label);\n label2 = parseHistogramLabel(s2.label);\n } catch (err) {\n console.error(err.message || err);\n return 0;\n }\n\n if (label1 > label2) {\n return 1;\n }\n\n if (label1 < label2) {\n return -1;\n }\n\n return 0;\n}\n\nfunction parseHistogramLabel(label: string): number {\n if (label === '+Inf' || label === 'inf') {\n return +Infinity;\n }\n const value = Number(label);\n if (isNaN(value)) {\n throw new Error(`Error parsing histogram label: ${label} is not a number`);\n }\n return value;\n}\n\n/**\n * Convert buckets into linear array of \"cards\" - objects, represented heatmap elements.\n * @param {Object} buckets\n * @returns {Object} Array of \"card\" objects and stats\n */\nfunction convertToCards(buckets: any, hideZero = false): { cards: HeatmapCard[]; cardStats: HeatmapCardStats } {\n let min = 0,\n max = 0;\n const cards: HeatmapCard[] = [];\n forEach(buckets, (xBucket) => {\n forEach(xBucket.buckets, (yBucket) => {\n const card: HeatmapCard = {\n x: xBucket.x,\n y: yBucket.y,\n yBounds: yBucket.bounds,\n values: yBucket.values,\n count: yBucket.count,\n };\n if (!hideZero || card.count !== 0) {\n cards.push(card);\n }\n\n if (cards.length === 1) {\n min = yBucket.count;\n max = yBucket.count;\n }\n\n min = yBucket.count < min ? yBucket.count : min;\n max = yBucket.count > max ? yBucket.count : max;\n });\n });\n\n const cardStats = { min, max };\n return { cards, cardStats };\n}\n\n/**\n * Special method for log scales. When series converted into buckets with log scale,\n * for simplification, 0 values are converted into 0, not into -Infinity. On the other hand, we mean\n * that all values less than series minimum, is 0 values, and we create special \"minimum\" bucket for\n * that values (actually, there're no values less than minimum, so this bucket is empty).\n * 8-16| | ** | | * | **|\n * 4-8| * |* *|* |** *| * |\n * 2-4| * *| | ***| |* |\n * 1-2|* | | | | | This bucket contains minimum series value\n * 0.5-1|____|____|____|____|____| This bucket should be displayed as 0 on graph\n * 0|____|____|____|____|____| This bucket is for 0 values (should actually be -Infinity)\n * So we should merge two bottom buckets into one (0-value bucket).\n *\n * @param {Object} buckets Heatmap buckets\n * @param {Number} minValue Minimum series value\n * @returns {Object} Transformed buckets\n */\nfunction mergeZeroBuckets(buckets: any, minValue: number) {\n forEach(buckets, (xBucket) => {\n const yBuckets = xBucket.buckets;\n\n const emptyBucket: any = {\n bounds: { bottom: 0, top: 0 },\n values: [],\n points: [],\n count: 0,\n };\n\n const nullBucket = yBuckets[0] || emptyBucket;\n const minBucket = yBuckets[minValue] || emptyBucket;\n\n const newBucket: any = {\n y: 0,\n bounds: { bottom: minValue, top: minBucket.bounds.top || minValue },\n values: [],\n points: [],\n count: 0,\n };\n\n newBucket.points = nullBucket.points.concat(minBucket.points);\n newBucket.values = nullBucket.values.concat(minBucket.values);\n newBucket.count = newBucket.values.length;\n\n if (newBucket.count === 0) {\n return;\n }\n\n delete yBuckets[minValue];\n yBuckets[0] = newBucket;\n });\n\n return buckets;\n}\n\n/**\n * Convert set of time series into heatmap buckets\n * @returns {Object} Heatmap object:\n * {\n * xBucketBound_1: {\n * x: xBucketBound_1,\n * buckets: {\n * yBucketBound_1: {\n * y: yBucketBound_1,\n * bounds: {bottom, top}\n * values: [val_1, val_2, ..., val_K],\n * points: [[val_Y, val_X, series_name], ..., [...]],\n * seriesStat: {seriesName_1: val_1, seriesName_2: val_2}\n * },\n * ...\n * yBucketBound_M: {}\n * },\n * values: [val_1, val_2, ..., val_K],\n * points: [\n * [val_Y, val_X, series_name], (point_1)\n * ...\n * [...] (point_K)\n * ]\n * },\n * xBucketBound_2: {},\n * ...\n * xBucketBound_N: {}\n * }\n */\nfunction convertToHeatMap(seriesList: TimeSeries[], yBucketSize: number, xBucketSize: number, logBase = 1) {\n const heatmap = {};\n\n for (const series of seriesList) {\n const datapoints = series.datapoints;\n const seriesName = series.label;\n\n // Slice series into X axis buckets\n // | | ** | | * | **|\n // | * |* *|* |** *| * |\n // |** *| | ***| |* |\n // |____|____|____|____|____|_\n //\n forEach(datapoints, (point) => {\n const bucketBound = getBucketBound(point[TIME_INDEX], xBucketSize);\n pushToXBuckets(heatmap, point, bucketBound, seriesName);\n });\n }\n\n // Slice X axis buckets into Y (value) buckets\n // | **| |2|,\n // | * | --\\ |1|,\n // |* | --/ |1|,\n // |____| |0|\n //\n forEach(heatmap, (xBucket: any) => {\n if (logBase !== 1) {\n xBucket.buckets = convertToLogScaleValueBuckets(xBucket, yBucketSize, logBase);\n } else {\n xBucket.buckets = convertToValueBuckets(xBucket, yBucketSize);\n }\n });\n\n return heatmap;\n}\n\nfunction pushToXBuckets(buckets: any, point: any[], bucketNum: number, seriesName: string) {\n const value = point[VALUE_INDEX];\n if (value === null || value === undefined || isNaN(value)) {\n return;\n }\n\n // Add series name to point for future identification\n const pointExt = concat(point, seriesName);\n\n if (buckets[bucketNum] && buckets[bucketNum].values) {\n buckets[bucketNum].values.push(value);\n buckets[bucketNum].points.push(pointExt);\n } else {\n buckets[bucketNum] = {\n x: bucketNum,\n values: [value],\n points: [pointExt],\n };\n }\n}\n\nfunction pushToYBuckets(\n buckets: Bucket,\n bucketNum: number,\n value: any,\n point: string[],\n bounds: { bottom: number; top: number }\n) {\n let count = 1;\n // Use the 3rd argument as scale/count\n if (point.length > 3) {\n count = parseInt(point[2], 10);\n }\n if (buckets[bucketNum]) {\n buckets[bucketNum].values.push(value);\n buckets[bucketNum].points?.push(point);\n buckets[bucketNum].count += count;\n } else {\n buckets[bucketNum] = {\n y: bucketNum,\n bounds: bounds,\n values: [value],\n points: [point],\n count: count,\n };\n }\n}\n\nfunction getValueBucketBound(value: any, yBucketSize: number, logBase: number) {\n if (logBase === 1) {\n return getBucketBound(value, yBucketSize);\n } else {\n return getLogScaleBucketBound(value, yBucketSize, logBase);\n }\n}\n\n/**\n * Find bucket for given value (for linear scale)\n */\nfunction getBucketBounds(value: number, bucketSize: number) {\n let bottom, top;\n bottom = Math.floor(value / bucketSize) * bucketSize;\n top = (Math.floor(value / bucketSize) + 1) * bucketSize;\n\n return { bottom, top };\n}\n\nfunction getBucketBound(value: number, bucketSize: number) {\n const bounds = getBucketBounds(value, bucketSize);\n return bounds.bottom;\n}\n\nfunction convertToValueBuckets(xBucket: { values: any; points: any }, bucketSize: number) {\n const values = xBucket.values;\n const points = xBucket.points;\n const buckets = {};\n\n forEach(values, (val, index) => {\n const bounds = getBucketBounds(val, bucketSize);\n const bucketNum = bounds.bottom;\n pushToYBuckets(buckets, bucketNum, val, points[index], bounds);\n });\n\n return buckets;\n}\n\n/**\n * Find bucket for given value (for log scales)\n */\nfunction getLogScaleBucketBounds(value: number, yBucketSplitFactor: number, logBase: number) {\n let top, bottom;\n if (value === 0) {\n return { bottom: 0, top: 0 };\n }\n\n const valueLog = logp(value, logBase);\n let pow, powTop;\n if (yBucketSplitFactor === 1 || !yBucketSplitFactor) {\n pow = Math.floor(valueLog);\n powTop = pow + 1;\n } else {\n const additionalBucketSize = 1 / yBucketSplitFactor;\n let additionalLog = valueLog - Math.floor(valueLog);\n additionalLog = Math.floor(additionalLog / additionalBucketSize) * additionalBucketSize;\n pow = Math.floor(valueLog) + additionalLog;\n powTop = pow + additionalBucketSize;\n }\n bottom = Math.pow(logBase, pow);\n top = Math.pow(logBase, powTop);\n\n return { bottom, top };\n}\n\nfunction getLogScaleBucketBound(value: number, yBucketSplitFactor: number, logBase: number) {\n const bounds = getLogScaleBucketBounds(value, yBucketSplitFactor, logBase);\n return bounds.bottom;\n}\n\nfunction convertToLogScaleValueBuckets(\n xBucket: { values: any; points: any },\n yBucketSplitFactor: number,\n logBase: number\n) {\n const values = xBucket.values;\n const points = xBucket.points;\n\n const buckets = {};\n forEach(values, (val, index) => {\n const bounds = getLogScaleBucketBounds(val, yBucketSplitFactor, logBase);\n const bucketNum = bounds.bottom;\n pushToYBuckets(buckets, bucketNum, val, points[index], bounds);\n });\n\n return buckets;\n}\n\n/**\n * Logarithm for custom base\n * @param value\n * @param base logarithm base\n */\nfunction logp(value: number, base: number) {\n return Math.log(value) / Math.log(base);\n}\n\n/**\n * Calculate size of Y bucket from given buckets bounds.\n * @param bounds Array of Y buckets bounds\n * @param logBase Logarithm base\n */\nfunction calculateBucketSize(bounds: number[], logBase = 1): number {\n let bucketSize = Infinity;\n\n if (bounds.length === 0) {\n return 0;\n } else if (bounds.length === 1) {\n return bounds[0];\n } else {\n bounds = sortBy(bounds);\n for (let i = 1; i < bounds.length; i++) {\n const distance = getDistance(bounds[i], bounds[i - 1], logBase);\n bucketSize = distance < bucketSize ? distance : bucketSize;\n }\n }\n\n return bucketSize;\n}\n\n/**\n * Calculate distance between two numbers in given scale (linear or logarithmic).\n * @param a\n * @param b\n * @param logBase\n */\nfunction getDistance(a: number, b: number, logBase = 1): number {\n if (logBase === 1) {\n // Linear distance\n return Math.abs(b - a);\n } else {\n // logarithmic distance\n const ratio = Math.max(a, b) / Math.min(a, b);\n return logp(ratio, logBase);\n }\n}\n\n/**\n * Compare two heatmap data objects\n * @param objA\n * @param objB\n */\nfunction isHeatmapDataEqual(objA: any, objB: any): boolean {\n let isEql = !emptyXOR(objA, objB);\n\n forEach(objA, (xBucket: XBucket, x) => {\n if (objB[x]) {\n if (emptyXOR(xBucket.buckets, objB[x].buckets)) {\n isEql = false;\n return false;\n }\n\n forEach(xBucket.buckets, (yBucket: YBucket, y) => {\n if (objB[x].buckets && objB[x].buckets[y]) {\n if (objB[x].buckets[y].values) {\n isEql = isEqual(sortBy(yBucket.values), sortBy(objB[x].buckets[y].values));\n if (!isEql) {\n return false;\n } else {\n return true;\n }\n } else {\n isEql = false;\n return false;\n }\n } else {\n isEql = false;\n return false;\n }\n });\n\n if (!isEql) {\n return false;\n } else {\n return true;\n }\n } else {\n isEql = false;\n return false;\n }\n });\n\n return isEql;\n}\n\nfunction emptyXOR(foo: any, bar: any): boolean {\n return (isEmpty(foo) || isEmpty(bar)) && !(isEmpty(foo) && isEmpty(bar));\n}\n\nexport {\n convertToHeatMap,\n histogramToHeatmap,\n convertToCards,\n mergeZeroBuckets,\n getValueBucketBound,\n isHeatmapDataEqual,\n calculateBucketSize,\n sortSeriesByLabel,\n};\n","import * as d3 from 'd3';\nimport $ from 'jquery';\nimport { filter, find, isNumber, map, reduce } from 'lodash';\n\nimport { getValueFormat, formattedValueToString } from '@grafana/data';\n\nimport { getValueBucketBound } from './heatmap_data_converter';\n\nconst TOOLTIP_PADDING_X = 30;\nconst TOOLTIP_PADDING_Y = 5;\nconst HISTOGRAM_WIDTH = 160;\nconst HISTOGRAM_HEIGHT = 40;\n\nexport class HeatmapTooltip {\n tooltip: any;\n scope: any;\n dashboard: any;\n panelCtrl: any;\n panel: any;\n heatmapPanel: any;\n mouseOverBucket: boolean;\n originalFillColor: any;\n\n constructor(elem: JQuery, scope: any) {\n this.scope = scope;\n this.dashboard = scope.ctrl.dashboard;\n this.panelCtrl = scope.ctrl;\n this.panel = scope.ctrl.panel;\n this.heatmapPanel = elem;\n this.mouseOverBucket = false;\n this.originalFillColor = null;\n\n elem.on('mouseleave', this.onMouseLeave.bind(this));\n }\n\n onMouseLeave() {\n this.destroy();\n }\n\n onMouseMove(e: any) {\n if (!this.panel.tooltip.show) {\n return;\n }\n\n this.move(e);\n }\n\n add() {\n this.tooltip = d3.select('body').append('div').attr('class', 'heatmap-tooltip graph-tooltip grafana-tooltip');\n }\n\n destroy() {\n if (this.tooltip) {\n this.tooltip.remove();\n }\n\n this.tooltip = null;\n }\n\n show(pos: { panelRelY: any }, data: any) {\n if (!this.panel.tooltip.show || !data) {\n return;\n }\n // shared tooltip mode\n if (pos.panelRelY) {\n return;\n }\n\n const { xBucketIndex, yBucketIndex } = this.getBucketIndexes(pos, data);\n\n if (!data.buckets[xBucketIndex]) {\n this.destroy();\n return;\n }\n\n if (!this.tooltip) {\n this.add();\n }\n\n let boundBottom, boundTop, valuesNumber;\n const xData = data.buckets[xBucketIndex];\n // Search in special 'zero' bucket also\n const yData: any = find(xData.buckets, (bucket, bucketIndex) => {\n return bucket.bounds.bottom === yBucketIndex || bucketIndex === yBucketIndex.toString();\n });\n\n const tooltipTimeFormat = 'YYYY-MM-DD HH:mm:ss';\n const time = this.dashboard.formatDate(xData.x, tooltipTimeFormat);\n\n // Decimals override. Code from panel/graph/graph.ts\n let countValueFormatter, bucketBoundFormatter;\n if (isNumber(this.panel.tooltipDecimals)) {\n countValueFormatter = this.countValueFormatter(this.panel.tooltipDecimals, null);\n bucketBoundFormatter = this.panelCtrl.tickValueFormatter(this.panelCtrl.decimals, null);\n } else {\n // auto decimals\n // legend and tooltip gets one more decimal precision\n // than graph legend ticks\n const decimals = (this.panelCtrl.decimals || -1) + 1;\n countValueFormatter = this.countValueFormatter(decimals, this.panelCtrl.scaledDecimals + 2);\n bucketBoundFormatter = this.panelCtrl.tickValueFormatter(decimals, this.panelCtrl.scaledDecimals + 2);\n }\n\n let tooltipHtml = `<div class=\"graph-tooltip-time\">${time}</div>\n <div class=\"heatmap-histogram\"></div>`;\n\n if (yData) {\n if (yData.bounds) {\n if (data.tsBuckets) {\n // Use Y-axis labels\n const tickFormatter = (valIndex: string | number) => {\n return data.tsBucketsFormatted ? data.tsBucketsFormatted[valIndex] : data.tsBuckets[valIndex];\n };\n\n boundBottom = tickFormatter(yBucketIndex);\n if (this.panel.yBucketBound !== 'middle') {\n boundTop = yBucketIndex < data.tsBuckets.length - 1 ? tickFormatter(yBucketIndex + 1) : '';\n }\n } else {\n // Display 0 if bucket is a special 'zero' bucket\n const bottom = yData.y ? yData.bounds.bottom : 0;\n boundBottom = bucketBoundFormatter(bottom);\n boundTop = bucketBoundFormatter(yData.bounds.top);\n }\n valuesNumber = countValueFormatter(yData.count);\n const boundStr = boundTop && boundBottom ? `${boundBottom} - ${boundTop}` : boundBottom || boundTop;\n tooltipHtml += `<div>\n bucket: <b>${boundStr}</b> <br>\n count: <b>${valuesNumber}</b> <br>\n </div>`;\n } else {\n // currently no bounds for pre bucketed data\n tooltipHtml += `<div>count: <b>${yData.count}</b><br></div>`;\n }\n } else {\n if (!this.panel.tooltip.showHistogram) {\n this.destroy();\n return;\n }\n boundBottom = yBucketIndex;\n boundTop = '';\n valuesNumber = 0;\n }\n\n this.tooltip.html(tooltipHtml);\n\n if (this.panel.tooltip.showHistogram) {\n this.addHistogram(xData);\n }\n\n this.move(pos);\n }\n\n getBucketIndexes(pos: { panelRelY?: any; x?: any; y?: any }, data: any) {\n const xBucketIndex = this.getXBucketIndex(pos.x, data);\n const yBucketIndex = this.getYBucketIndex(pos.y, data);\n return { xBucketIndex, yBucketIndex };\n }\n\n getXBucketIndex(x: number, data: { buckets: any; xBucketSize: number }) {\n // First try to find X bucket by checking x pos is in the\n // [bucket.x, bucket.x + xBucketSize] interval\n const xBucket: any = find(data.buckets, (bucket) => {\n return x > bucket.x && x - bucket.x <= data.xBucketSize;\n });\n return xBucket ? xBucket.x : getValueBucketBound(x, data.xBucketSize, 1);\n }\n\n getYBucketIndex(y: number, data: { tsBuckets: any; yBucketSize: number }) {\n if (data.tsBuckets) {\n return Math.floor(y);\n }\n const yBucketIndex = getValueBucketBound(y, data.yBucketSize, this.panel.yAxis.logBase);\n return yBucketIndex;\n }\n\n getSharedTooltipPos(pos: { pageX: any; x: any; pageY: any; panelRelY: number }) {\n // get pageX from position on x axis and pageY from relative position in original panel\n pos.pageX = this.heatmapPanel.offset().left + this.scope.xScale(pos.x);\n pos.pageY = this.heatmapPanel.offset().top + this.scope.chartHeight * pos.panelRelY;\n return pos;\n }\n\n addHistogram(data: { x: string | number }) {\n const xBucket = this.scope.ctrl.data.buckets[data.x];\n const yBucketSize = this.scope.ctrl.data.yBucketSize;\n let min: number, max: number, ticks: number;\n if (this.scope.ctrl.data.tsBuckets) {\n min = 0;\n max = this.scope.ctrl.data.tsBuckets.length - 1;\n ticks = this.scope.ctrl.data.tsBuckets.length;\n } else {\n min = this.scope.ctrl.data.yAxis.min;\n max = this.scope.ctrl.data.yAxis.max;\n ticks = this.scope.ctrl.data.yAxis.ticks;\n }\n let histogramData = map(xBucket.buckets, (bucket) => {\n const count = bucket.count !== undefined ? bucket.count : bucket.values.length;\n return [bucket.bounds.bottom, count];\n });\n histogramData = filter(histogramData, (d) => {\n return d[0] >= min && d[0] <= max;\n });\n\n const scale = this.scope.yScale.copy();\n const histXScale = scale.domain([min, max]).range([0, HISTOGRAM_WIDTH]);\n\n let barWidth: number;\n if (this.panel.yAxis.logBase === 1) {\n barWidth = Math.floor((HISTOGRAM_WIDTH / (max - min)) * yBucketSize * 0.9);\n } else {\n const barNumberFactor = yBucketSize ? yBucketSize : 1;\n barWidth = Math.floor((HISTOGRAM_WIDTH / ticks / barNumberFactor) * 0.9);\n }\n barWidth = Math.max(barWidth, 1);\n\n // Normalize histogram Y axis\n const histogramDomain = reduce(\n map(histogramData, (d) => d[1]),\n (sum, val) => sum + val,\n 0\n );\n const histYScale = d3.scaleLinear().domain([0, histogramDomain]).range([0, HISTOGRAM_HEIGHT]);\n\n const histogram = this.tooltip\n .select('.heatmap-histogram')\n .append('svg')\n .attr('width', HISTOGRAM_WIDTH)\n .attr('height', HISTOGRAM_HEIGHT);\n\n histogram\n .selectAll('.bar')\n .data(histogramData)\n .enter()\n .append('rect')\n .attr('x', (d: any[]) => {\n return histXScale(d[0]);\n })\n .attr('width', barWidth)\n .attr('y', (d: any[]) => {\n return HISTOGRAM_HEIGHT - histYScale(d[1]);\n })\n .attr('height', (d: any[]) => {\n return histYScale(d[1]);\n });\n }\n\n move(pos: { panelRelY?: any; pageX?: any; pageY?: any }) {\n if (!this.tooltip) {\n return;\n }\n\n const elem = $(this.tooltip.node())[0];\n const tooltipWidth = elem.clientWidth;\n const tooltipHeight = elem.clientHeight;\n\n let left = pos.pageX + TOOLTIP_PADDING_X;\n let top = pos.pageY + TOOLTIP_PADDING_Y;\n\n if (pos.pageX + tooltipWidth + 40 > window.innerWidth) {\n left = pos.pageX - tooltipWidth - TOOLTIP_PADDING_X;\n }\n\n if (pos.pageY - window.pageYOffset + tooltipHeight + 20 > window.innerHeight) {\n top = pos.pageY - tooltipHeight - TOOLTIP_PADDING_Y;\n }\n\n return this.tooltip.style('left', left + 'px').style('top', top + 'px');\n }\n\n countValueFormatter(decimals: number, scaledDecimals: any = null) {\n const fmt = getValueFormat('short');\n return (value: number) => {\n return formattedValueToString(fmt(value, decimals, scaledDecimals));\n };\n }\n}\n","import * as d3 from 'd3';\nimport $ from 'jquery';\nimport { find, isEmpty, isNaN, isNil, isString, map, max, min, toNumber } from 'lodash';\n\nimport {\n dateTimeFormat,\n formattedValueToString,\n getValueFormat,\n LegacyGraphHoverClearEvent,\n LegacyGraphHoverEvent,\n PanelEvents,\n toUtc,\n} from '@grafana/data';\nimport { graphTimeFormat } from '@grafana/ui';\nimport { config } from 'app/core/config';\nimport { contextSrv } from 'app/core/core';\nimport * as ticksUtils from 'app/core/utils/ticks';\n\nimport { getColorScale, getOpacityScale } from './color_scale';\nimport { mergeZeroBuckets } from './heatmap_data_converter';\nimport { HeatmapTooltip } from './heatmap_tooltip';\n\nconst MIN_CARD_SIZE = 1,\n CARD_PADDING = 1,\n CARD_ROUND = 0,\n DATA_RANGE_WIDING_FACTOR = 1.2,\n DEFAULT_X_TICK_SIZE_PX = 100,\n DEFAULT_Y_TICK_SIZE_PX = 22.5,\n X_AXIS_TICK_PADDING = 10,\n Y_AXIS_TICK_PADDING = 5,\n MIN_SELECTION_WIDTH = 2;\n\nexport default function rendering(scope: any, elem: any, attrs: any, ctrl: any) {\n return new HeatmapRenderer(scope, elem, attrs, ctrl);\n}\nexport class HeatmapRenderer {\n width = 200;\n height = 200;\n yScale: any;\n xScale: any;\n chartWidth = 0;\n chartHeight = 0;\n chartTop = 0;\n chartBottom = 0;\n yAxisWidth = 0;\n xAxisHeight = 0;\n cardPadding = 0;\n cardRound = 0;\n cardWidth = 0;\n cardHeight = 0;\n colorScale: any;\n opacityScale: any;\n mouseUpHandler: any;\n data: any;\n panel: any;\n $heatmap: any;\n tooltip: HeatmapTooltip;\n heatmap: any;\n timeRange: any;\n\n selection: any;\n padding: any;\n margin: any;\n dataRangeWidingFactor: number;\n\n hoverEvent: LegacyGraphHoverEvent;\n\n constructor(private scope: any, private elem: any, attrs: any, private ctrl: any) {\n // $heatmap is JQuery object, but heatmap is D3\n this.$heatmap = this.elem.find('.heatmap-panel');\n this.tooltip = new HeatmapTooltip(this.$heatmap, this.scope);\n\n this.selection = {\n active: false,\n x1: -1,\n x2: -1,\n };\n\n this.padding = { left: 0, right: 0, top: 0, bottom: 0 };\n this.margin = { left: 25, right: 15, top: 10, bottom: 20 };\n this.dataRangeWidingFactor = DATA_RANGE_WIDING_FACTOR;\n this.ctrl.events.on(PanelEvents.render, this.onRender.bind(this));\n this.ctrl.tickValueFormatter = this.tickValueFormatter.bind(this);\n\n /////////////////////////////\n // Selection and crosshair //\n /////////////////////////////\n\n // Shared crosshair and tooltip\n this.ctrl.dashboard.events.on(LegacyGraphHoverEvent.type, this.onGraphHover.bind(this), this.scope);\n this.ctrl.dashboard.events.on(LegacyGraphHoverClearEvent.type, this.onGraphHoverClear.bind(this), this.scope);\n\n // Register selection listeners\n this.$heatmap.on('mousedown', this.onMouseDown.bind(this));\n this.$heatmap.on('mousemove', this.onMouseMove.bind(this));\n this.$heatmap.on('mouseleave', this.onMouseLeave.bind(this));\n\n this.hoverEvent = new LegacyGraphHoverEvent({ pos: {}, point: {}, panel: this.panel });\n }\n\n onGraphHoverClear() {\n this.clearCrosshair();\n }\n\n onGraphHover(event: { pos: any }) {\n this.drawSharedCrosshair(event.pos);\n }\n\n onRender() {\n this.render();\n this.ctrl.renderingCompleted();\n }\n\n setElementHeight() {\n try {\n let height = this.ctrl.height || this.panel.height || this.ctrl.row.height;\n if (isString(height)) {\n height = parseInt(height.replace('px', ''), 10);\n }\n\n height -= this.panel.legend.show ? 28 : 11; // bottom padding and space for legend\n\n this.$heatmap.css('height', height + 'px');\n\n return true;\n } catch (e) {\n // IE throws errors sometimes\n return false;\n }\n }\n\n getYAxisWidth(elem: any) {\n const panelYAxisWidth = this.getPanelYAxisWidth();\n if (panelYAxisWidth !== null) {\n return panelYAxisWidth + Y_AXIS_TICK_PADDING;\n }\n\n const axisText = elem.selectAll('.axis-y text').nodes();\n const maxTextWidth = max(\n map(axisText, (text) => {\n // Use SVG getBBox method\n return text.getBBox().width;\n })\n );\n\n return maxTextWidth;\n }\n\n getXAxisHeight(elem: any) {\n const axisLine = elem.select('.axis-x line');\n if (!axisLine.empty()) {\n const axisLinePosition = parseFloat(elem.select('.axis-x line').attr('y2'));\n const canvasWidth = parseFloat(elem.attr('height'));\n return canvasWidth - axisLinePosition;\n } else {\n // Default height\n return 30;\n }\n }\n\n addXAxis() {\n this.scope.xScale = this.xScale = d3\n .scaleTime()\n .domain([this.timeRange.from, this.timeRange.to])\n .range([0, this.chartWidth]);\n\n const ticks = this.chartWidth / DEFAULT_X_TICK_SIZE_PX;\n const format = graphTimeFormat(ticks, this.timeRange.from.valueOf(), this.timeRange.to.valueOf());\n const timeZone = this.ctrl.dashboard.getTimezone();\n const formatter = (date: d3.AxisDomain) =>\n dateTimeFormat(date.valueOf(), {\n format: format,\n timeZone: timeZone,\n });\n\n const xAxis = d3\n .axisBottom(this.xScale)\n .ticks(ticks)\n .tickFormat(formatter)\n .tickPadding(X_AXIS_TICK_PADDING)\n .tickSize(this.chartHeight);\n\n const posY = this.margin.top;\n const posX = this.yAxisWidth;\n this.heatmap\n .append('g')\n .attr('class', 'axis axis-x')\n .attr('transform', 'translate(' + posX + ',' + posY + ')')\n .call(xAxis);\n\n // Remove horizontal line in the top of axis labels (called domain in d3)\n this.heatmap.select('.axis-x').select('.domain').remove();\n }\n\n addYAxis() {\n let ticks = Math.ceil(this.chartHeight / DEFAULT_Y_TICK_SIZE_PX);\n let tickInterval = ticksUtils.tickStep(this.data.heatmapStats.min, this.data.heatmapStats.max, ticks);\n let { yMin, yMax } = this.wideYAxisRange(this.data.heatmapStats.min, this.data.heatmapStats.max, tickInterval);\n\n // Rewrite min and max if it have been set explicitly\n yMin = this.panel.yAxis.min !== null ? this.panel.yAxis.min : yMin;\n yMax = this.panel.yAxis.max !== null ? this.panel.yAxis.max : yMax;\n\n // Adjust ticks after Y range widening\n tickInterval = ticksUtils.tickStep(yMin, yMax, ticks);\n ticks = Math.ceil((yMax - yMin) / tickInterval);\n\n const decimalsAuto = ticksUtils.getPrecision(tickInterval);\n let decimals = this.panel.yAxis.decimals === null ? decimalsAuto : this.panel.yAxis.decimals;\n // Calculate scaledDecimals for log scales using tick size (as in jquery.flot.js)\n const flotTickSize = ticksUtils.getFlotTickSize(yMin, yMax, ticks, decimalsAuto);\n const scaledDecimals = ticksUtils.getScaledDecimals(decimals, flotTickSize);\n this.ctrl.decimals = decimals;\n this.ctrl.scaledDecimals = scaledDecimals;\n\n // Set default Y min and max if no data\n if (isEmpty(this.data.buckets)) {\n yMax = 1;\n yMin = -1;\n ticks = 3;\n decimals = 1;\n }\n\n this.data.yAxis = {\n min: yMin,\n max: yMax,\n ticks: ticks,\n };\n\n this.scope.yScale = this.yScale = d3.scaleLinear().domain([yMin, yMax]).range([this.chartHeight, 0]);\n\n const yAxis = d3\n .axisLeft(this.yScale)\n .ticks(ticks)\n .tickFormat(this.tickValueFormatter(decimals, scaledDecimals))\n .tickSizeInner(0 - this.width)\n .tickSizeOuter(0)\n .tickPadding(Y_AXIS_TICK_PADDING);\n\n this.heatmap.append('g').attr('class', 'axis axis-y').call(yAxis);\n\n // Calculate Y axis width first, then move axis into visible area\n const posY = this.margin.top;\n const posX = this.getYAxisWidth(this.heatmap) + Y_AXIS_TICK_PADDING;\n this.heatmap.select('.axis-y').attr('transform', 'translate(' + posX + ',' + posY + ')');\n\n // Remove vertical line in the right of axis labels (called domain in d3)\n this.heatmap.select('.axis-y').select('.domain').remove();\n }\n\n // Wide Y values range and anjust to bucket size\n wideYAxisRange(min: number, max: number, tickInterval: number) {\n const yWiding = (max * (this.dataRangeWidingFactor - 1) - min * (this.dataRangeWidingFactor - 1)) / 2;\n let yMin, yMax;\n\n if (tickInterval === 0) {\n yMax = max * this.dataRangeWidingFactor;\n yMin = min - min * (this.dataRangeWidingFactor - 1);\n } else {\n yMax = Math.ceil((max + yWiding) / tickInterval) * tickInterval;\n yMin = Math.floor((min - yWiding) / tickInterval) * tickInterval;\n }\n\n // Don't wide axis below 0 if all values are positive\n if (min >= 0 && yMin < 0) {\n yMin = 0;\n }\n\n return { yMin, yMax };\n }\n\n addLogYAxis() {\n const logBase = this.panel.yAxis.logBase;\n let { yMin, yMax } = this.adjustLogRange(this.data.heatmapStats.minLog, this.data.heatmapStats.max, logBase);\n\n yMin =\n this.panel.yAxis.min && this.panel.yAxis.min !== '0' ? this.adjustLogMin(this.panel.yAxis.min, logBase) : yMin;\n yMax = this.panel.yAxis.max !== null ? this.adjustLogMax(this.panel.yAxis.max, logBase) : yMax;\n\n // Set default Y min and max if no data\n if (isEmpty(this.data.buckets)) {\n yMax = Math.pow(logBase, 2);\n yMin = 1;\n }\n\n this.scope.yScale = this.yScale = d3\n .scaleLog()\n .base(this.panel.yAxis.logBase)\n .domain([yMin, yMax])\n .range([this.chartHeight, 0]);\n\n const domain = this.yScale.domain();\n const tickValues = this.logScaleTickValues(domain, logBase);\n\n const decimalsAuto = ticksUtils.getPrecision(yMin);\n const decimals = this.panel.yAxis.decimals || decimalsAuto;\n\n // Calculate scaledDecimals for log scales using tick size (as in jquery.flot.js)\n const flotTickSize = ticksUtils.getFlotTickSize(yMin, yMax, tickValues.length, decimalsAuto);\n const scaledDecimals = ticksUtils.getScaledDecimals(decimals, flotTickSize);\n this.ctrl.decimals = decimals;\n this.ctrl.scaledDecimals = scaledDecimals;\n\n this.data.yAxis = {\n min: yMin,\n max: yMax,\n ticks: tickValues.length,\n };\n\n const yAxis = d3\n .axisLeft(this.yScale)\n .tickValues(tickValues)\n .tickFormat(this.tickValueFormatter(decimals, scaledDecimals))\n .tickSizeInner(0 - this.width)\n .tickSizeOuter(0)\n .tickPadding(Y_AXIS_TICK_PADDING);\n\n this.heatmap.append('g').attr('class', 'axis axis-y').call(yAxis);\n\n // Calculate Y axis width first, then move axis into visible area\n const posY = this.margin.top;\n const posX = this.getYAxisWidth(this.heatmap) + Y_AXIS_TICK_PADDING;\n this.heatmap.select('.axis-y').attr('transform', 'translate(' + posX + ',' + posY + ')');\n\n // Set first tick as pseudo 0\n if (yMin < 1) {\n this.heatmap.select('.axis-y').select('.tick text').text('0');\n }\n\n // Remove vertical line in the right of axis labels (called domain in d3)\n this.heatmap.select('.axis-y').select('.domain').remove();\n }\n\n addYAxisFromBuckets() {\n const tsBuckets = this.data.tsBuckets;\n let ticks = Math.ceil(this.chartHeight / DEFAULT_Y_TICK_SIZE_PX);\n\n this.scope.yScale = this.yScale = d3\n .scaleLinear()\n .domain([0, tsBuckets.length - 1])\n .range([this.chartHeight, 0]);\n\n const tickValues = map(tsBuckets, (b, i) => i);\n const decimalsAuto = max(map(tsBuckets, ticksUtils.getStringPrecision));\n const decimals = this.panel.yAxis.decimals === null ? decimalsAuto : this.panel.yAxis.decimals;\n this.ctrl.decimals = decimals;\n\n const tickValueFormatter = this.tickValueFormatter.bind(this);\n function tickFormatter(yAxisWidth: number | null) {\n return function (valIndex: d3.AxisDomain) {\n let valueFormatted = tsBuckets[valIndex.valueOf()];\n if (!isNaN(toNumber(valueFormatted)) && valueFormatted !== '') {\n // Try to format numeric tick labels\n valueFormatted = tickValueFormatter(decimals)(toNumber(valueFormatted));\n } else if (valueFormatted && typeof valueFormatted === 'string' && valueFormatted !== '') {\n if (yAxisWidth) {\n const scale = 0.15; // how to have a better calculation for this\n const trimmed = valueFormatted.substring(0, Math.floor(yAxisWidth * scale));\n const postfix = trimmed.length < valueFormatted.length ? '...' : '';\n valueFormatted = `${trimmed}${postfix}`;\n }\n }\n return valueFormatted;\n };\n }\n const tsBucketsFormatted = map(tsBuckets, (v, i) => tickFormatter(null)(i));\n this.data.tsBucketsFormatted = tsBucketsFormatted;\n\n const yAxis = d3\n .axisLeft(this.yScale)\n .tickFormat(tickFormatter(this.getPanelYAxisWidth()))\n .tickSizeInner(0 - this.width)\n .tickSizeOuter(0)\n .tickPadding(Y_AXIS_TICK_PADDING);\n if (tickValues && tickValues.length <= ticks) {\n yAxis.tickValues(tickValues);\n } else {\n yAxis.ticks(ticks);\n }\n\n this.heatmap.append('g').attr('class', 'axis axis-y').call(yAxis);\n\n // Calculate Y axis width first, then move axis into visible area\n const posY = this.margin.top;\n const posX = this.getYAxisWidth(this.heatmap) + Y_AXIS_TICK_PADDING;\n this.heatmap.select('.axis-y').attr('transform', 'translate(' + posX + ',' + posY + ')');\n\n if (this.panel.yBucketBound === 'middle' && tickValues && tickValues.length) {\n // Shift Y axis labels to the middle of bucket\n const tickShift = 0 - this.chartHeight / (tickValues.length - 1) / 2;\n this.heatmap.selectAll('.axis-y text').attr('transform', 'translate(' + 0 + ',' + tickShift + ')');\n }\n\n // Remove vertical line in the right of axis labels (called domain in d3)\n this.heatmap.select('.axis-y').select('.domain').remove();\n }\n\n // Adjust data range to log base\n adjustLogRange(min: number, max: number, logBase: number) {\n let yMin = this.data.heatmapStats.minLog;\n if (this.data.heatmapStats.minLog > 1 || !this.data.heatmapStats.minLog) {\n yMin = 1;\n } else {\n yMin = this.adjustLogMin(this.data.heatmapStats.minLog, logBase);\n }\n\n // Adjust max Y value to log base\n const yMax = this.adjustLogMax(this.data.heatmapStats.max, logBase);\n\n return { yMin, yMax };\n }\n\n adjustLogMax(max: number, base: number) {\n return Math.pow(base, Math.ceil(ticksUtils.logp(max, base)));\n }\n\n adjustLogMin(min: number, base: number) {\n return Math.pow(base, Math.floor(ticksUtils.logp(min, base)));\n }\n\n logScaleTickValues(domain: any[], base: number) {\n const domainMin = domain[0];\n const domainMax = domain[1];\n const tickValues = [];\n\n if (domainMin < 1) {\n const underOneTicks = Math.floor(ticksUtils.logp(domainMin, base));\n for (let i = underOneTicks; i < 0; i++) {\n const tickValue = Math.pow(base, i);\n tickValues.push(tickValue);\n }\n }\n\n const ticks = Math.ceil(ticksUtils.logp(domainMax, base));\n for (let i = 0; i <= ticks; i++) {\n const tickValue = Math.pow(base, i);\n tickValues.push(tickValue);\n }\n\n return tickValues;\n }\n\n tickValueFormatter(decimals: number, scaledDecimals: any = null) {\n const format = this.panel.yAxis.format;\n return (value: any) => {\n try {\n if (format !== 'none') {\n const v = getValueFormat(format)(value, decimals, scaledDecimals);\n return formattedValueToString(v);\n }\n } catch (err) {\n console.error(err.message || err);\n }\n return value;\n };\n }\n\n fixYAxisTickSize() {\n this.heatmap.select('.axis-y').selectAll('.tick line').attr('x2', this.chartWidth);\n }\n\n addAxes() {\n this.chartHeight = this.height - this.margin.top - this.margin.bottom;\n this.chartTop = this.margin.top;\n this.chartBottom = this.chartTop + this.chartHeight;\n if (this.panel.dataFormat === 'tsbuckets') {\n this.addYAxisFromBuckets();\n } else {\n if (this.panel.yAxis.logBase === 1) {\n this.addYAxis();\n } else {\n this.addLogYAxis();\n }\n }\n\n this.yAxisWidth = this.getYAxisWidth(this.heatmap) + Y_AXIS_TICK_PADDING;\n this.chartWidth = this.width - this.yAxisWidth - this.margin.right;\n this.fixYAxisTickSize();\n\n this.addXAxis();\n this.xAxisHeight = this.getXAxisHeight(this.heatmap);\n\n if (!this.panel.yAxis.show) {\n this.heatmap.select('.axis-y').selectAll('line').style('opacity', 0);\n }\n\n if (!this.panel.xAxis.show) {\n this.heatmap.select('.axis-x').selectAll('line').style('opacity', 0);\n }\n }\n\n addHeatmapCanvas() {\n const heatmapElem = this.$heatmap[0];\n\n this.width = Math.floor(this.$heatmap.width()) - this.padding.right;\n this.height = Math.floor(this.$heatmap.height()) - this.padding.bottom;\n\n this.cardPadding = this.panel.cards.cardPadding !== null ? this.panel.cards.cardPadding : CARD_PADDING;\n this.cardRound = this.panel.cards.cardRound !== null ? this.panel.cards.cardRound : CARD_ROUND;\n\n if (this.heatmap) {\n this.heatmap.remove();\n }\n\n this.heatmap = d3.select(heatmapElem).append('svg').attr('width', this.width).attr('height', this.height);\n }\n\n addHeatmap() {\n this.addHeatmapCanvas();\n this.addAxes();\n\n if (this.panel.yAxis.logBase !== 1 && this.panel.dataFormat !== 'tsbuckets') {\n const logBase = this.panel.yAxis.logBase;\n const domain = this.yScale.domain();\n const tickValues = this.logScaleTickValues(domain, logBase);\n this.data.buckets = mergeZeroBuckets(this.data.buckets, min(tickValues)!);\n }\n\n const cardsData = this.data.cards;\n const cardStats = this.data.cardStats;\n const maxValueAuto = cardStats.max;\n const minValueAuto = Math.max(cardStats.min, 0);\n const maxValue = isNil(this.panel.color.max) ? maxValueAuto : this.panel.color.max;\n const minValue = isNil(this.panel.color.min) ? minValueAuto : this.panel.color.min;\n const colorScheme: any = find(this.ctrl.colorSchemes, {\n value: this.panel.color.colorScheme,\n });\n this.colorScale = getColorScale(colorScheme, contextSrv.user.lightTheme, maxValue, minValue);\n this.opacityScale = getOpacityScale(this.panel.color, maxValue, minValue);\n this.setCardSize();\n\n let cards = this.heatmap.selectAll('.heatmap-card').data(cardsData);\n cards.append('title');\n cards = cards\n .enter()\n .append('rect')\n .attr('x', this.getCardX.bind(this))\n .attr('width', this.getCardWidth.bind(this))\n .attr('y', this.getCardY.bind(this))\n .attr('height', this.getCardHeight.bind(this))\n .attr('rx', this.cardRound)\n .attr('ry', this.cardRound)\n .attr('class', 'bordered heatmap-card')\n .style('fill', this.getCardColor.bind(this))\n .style('stroke', this.getCardColor.bind(this))\n .style('stroke-width', 0)\n .style('opacity', this.getCardOpacity.bind(this));\n\n const $cards = this.$heatmap.find('.heatmap-card');\n $cards\n .on('mouseenter', (event: any) => {\n this.tooltip.mouseOverBucket = true;\n this.highlightCard(event);\n })\n .on('mouseleave', (event: any) => {\n this.tooltip.mouseOverBucket = false;\n this.resetCardHighLight(event);\n });\n }\n\n highlightCard(event: any) {\n const color = d3.select(event.target).style('fill');\n const highlightColor = d3.color(color)!.darker(2);\n const strokeColor = d3.color(color)!.brighter(4);\n const currentCard = d3.select(event.target);\n this.tooltip.originalFillColor = color;\n currentCard\n .style('fill', highlightColor.toString())\n .style('stroke', strokeColor.toString())\n .style('stroke-width', 1);\n }\n\n resetCardHighLight(event: any) {\n d3.select(event.target)\n .style('fill', this.tooltip.originalFillColor)\n .style('stroke', this.tooltip.originalFillColor)\n .style('stroke-width', 0);\n }\n\n setCardSize() {\n const xGridSize = Math.floor(this.xScale(this.data.xBucketSize) - this.xScale(0));\n let yGridSize = Math.floor(this.yScale(this.yScale.invert(0) - this.data.yBucketSize));\n\n if (this.panel.yAxis.logBase !== 1) {\n const base = this.panel.yAxis.logBase;\n const splitFactor = this.data.yBucketSize || 1;\n yGridSize = Math.floor((this.yScale(1) - this.yScale(base)) / splitFactor);\n }\n\n const cardWidth = xGridSize - this.cardPadding * 2;\n this.cardWidth = Math.max(cardWidth, MIN_CARD_SIZE);\n this.cardHeight = yGridSize ? yGridSize - this.cardPadding * 2 : 0;\n }\n\n getCardX(d: { x: any }) {\n let x;\n if (this.xScale(d.x) < 0) {\n // Cut card left to prevent overlay\n x = this.yAxisWidth + this.cardPadding;\n } else {\n x = this.xScale(d.x) + this.yAxisWidth + this.cardPadding;\n }\n\n return x;\n }\n\n getCardWidth(d: { x: any }) {\n let w = this.cardWidth;\n if (this.xScale(d.x) < 0) {\n // Cut card left to prevent overlay\n w = this.xScale(d.x) + this.cardWidth;\n } else if (this.xScale(d.x) + this.cardWidth > this.chartWidth) {\n // Cut card right to prevent overlay\n w = this.chartWidth - this.xScale(d.x) - this.cardPadding;\n }\n\n // Card width should be MIN_CARD_SIZE at least, but cut cards shouldn't be displayed\n w = w > 0 ? Math.max(w, MIN_CARD_SIZE) : 0;\n return w;\n }\n\n getCardY(d: { y: number }) {\n let y = this.yScale(d.y) + this.chartTop - this.cardHeight - this.cardPadding;\n if (this.panel.yAxis.logBase !== 1 && d.y === 0) {\n y = this.chartBottom - this.cardHeight - this.cardPadding;\n } else {\n if (y < this.chartTop) {\n y = this.chartTop;\n }\n }\n\n return y;\n }\n\n getCardHeight(d: { y: number }) {\n const y = this.yScale(d.y) + this.chartTop - this.cardHeight - this.cardPadding;\n let h = this.cardHeight;\n\n if (this.panel.yAxis.logBase !== 1 && d.y === 0) {\n return this.cardHeight;\n }\n\n // Cut card height to prevent overlay\n if (y < this.chartTop) {\n h = this.yScale(d.y) - this.cardPadding;\n } else if (this.yScale(d.y) > this.chartBottom) {\n h = this.chartBottom - y;\n } else if (y + this.cardHeight > this.chartBottom) {\n h = this.chartBottom - y;\n }\n\n // Height can't be more than chart height\n h = Math.min(h, this.chartHeight);\n // Card height should be MIN_CARD_SIZE at least\n h = Math.max(h, MIN_CARD_SIZE);\n\n return h;\n }\n\n getCardColor(d: { count: any }) {\n if (this.panel.color.mode === 'opacity') {\n return config.theme.visualization.getColorByName(this.panel.color.cardColor);\n } else {\n return this.colorScale(d.count);\n }\n }\n\n getCardOpacity(d: { count: any }) {\n if (this.panel.color.mode === 'opacity') {\n return this.opacityScale(d.count);\n } else {\n return 1;\n }\n }\n\n getEventOffset(event: any) {\n const elemOffset = this.$heatmap.offset();\n const x = Math.floor(event.clientX - elemOffset.left);\n const y = Math.floor(event.clientY - elemOffset.top);\n return { x, y };\n }\n\n onMouseDown(event: any) {\n const offset = this.getEventOffset(event);\n this.selection.active = true;\n this.selection.x1 = offset.x;\n\n this.mouseUpHandler = () => {\n this.onMouseUp();\n };\n\n $(document).one('mouseup', this.mouseUpHandler.bind(this));\n }\n\n onMouseUp() {\n $(document).unbind('mouseup', this.mouseUpHandler.bind(this));\n this.mouseUpHandler = null;\n this.selection.active = false;\n\n const selectionRange = Math.abs(this.selection.x2 - this.selection.x1);\n if (this.selection.x2 >= 0 && selectionRange > MIN_SELECTION_WIDTH) {\n const timeFrom = this.xScale.invert(Math.min(this.selection.x1, this.selection.x2) - this.yAxisWidth);\n const timeTo = this.xScale.invert(Math.max(this.selection.x1, this.selection.x2) - this.yAxisWidth);\n\n this.ctrl.timeSrv.setTime({\n from: toUtc(timeFrom),\n to: toUtc(timeTo),\n });\n }\n\n this.clearSelection();\n }\n\n onMouseLeave() {\n this.ctrl.dashboard.events.publish(new LegacyGraphHoverClearEvent());\n this.clearCrosshair();\n }\n\n onMouseMove(event: any) {\n if (!this.heatmap) {\n return;\n }\n\n const offset = this.getEventOffset(event);\n if (this.selection.active) {\n // Clear crosshair and tooltip\n this.clearCrosshair();\n this.tooltip.destroy();\n\n this.selection.x2 = this.limitSelection(offset.x);\n this.drawSelection(this.selection.x1, this.selection.x2);\n } else {\n const pos = this.getEventPos(event, offset);\n this.drawCrosshair(offset.x);\n this.tooltip.show(pos, this.data);\n this.emitGraphHoverEvent(pos);\n }\n }\n\n getEventPos(event: { pageX: any; pageY: any }, offset: { x: any; y: any }) {\n const x = this.xScale.invert(offset.x - this.yAxisWidth).valueOf();\n const y = this.yScale.invert(offset.y - this.chartTop);\n const pos: any = {\n pageX: event.pageX,\n pageY: event.pageY,\n x: x,\n x1: x,\n y: y,\n y1: y,\n panelRelY: null,\n offset,\n };\n\n return pos;\n }\n\n emitGraphHoverEvent(pos: { panelRelY: number; offset: { y: number } }) {\n // Set minimum offset to prevent showing legend from another panel\n pos.panelRelY = Math.max(pos.offset.y / this.height, 0.001);\n // broadcast to other graph panels that we are hovering\n this.hoverEvent.payload.pos = pos;\n this.hoverEvent.payload.panel = this.panel;\n this.hoverEvent.payload.point['time'] = (pos as any).x;\n this.ctrl.dashboard.events.publish(this.hoverEvent);\n }\n\n limitSelection(x2: number) {\n x2 = Math.max(x2, this.yAxisWidth);\n x2 = Math.min(x2, this.chartWidth + this.yAxisWidth);\n return x2;\n }\n\n drawSelection(posX1: number, posX2: number) {\n if (this.heatmap) {\n this.heatmap.selectAll('.heatmap-selection').remove();\n const selectionX = Math.min(posX1, posX2);\n const selectionWidth = Math.abs(posX1 - posX2);\n\n if (selectionWidth > MIN_SELECTION_WIDTH) {\n this.heatmap\n .append('rect')\n .attr('class', 'heatmap-selection')\n .attr('x', selectionX)\n .attr('width', selectionWidth)\n .attr('y', this.chartTop)\n .attr('height', this.chartHeight);\n }\n }\n }\n\n clearSelection() {\n this.selection.x1 = -1;\n this.selection.x2 = -1;\n\n if (this.heatmap) {\n this.heatmap.selectAll('.heatmap-selection').remove();\n }\n }\n\n drawCrosshair(position: number) {\n if (this.heatmap) {\n this.heatmap.selectAll('.heatmap-crosshair').remove();\n\n let posX = position;\n posX = Math.max(posX, this.yAxisWidth);\n posX = Math.min(posX, this.chartWidth + this.yAxisWidth);\n\n this.heatmap\n .append('g')\n .attr('class', 'heatmap-crosshair')\n .attr('transform', 'translate(' + posX + ',0)')\n .append('line')\n .attr('x1', 1)\n .attr('y1', this.chartTop)\n .attr('x2', 1)\n .attr('y2', this.chartBottom)\n .attr('stroke-width', 1);\n }\n }\n\n drawSharedCrosshair(pos: { x: any }) {\n if (this.heatmap && this.ctrl.dashboard.graphTooltip !== 0) {\n const posX = this.xScale(pos.x) + this.yAxisWidth;\n this.drawCrosshair(posX);\n }\n }\n\n clearCrosshair() {\n if (this.heatmap) {\n this.heatmap.selectAll('.heatmap-crosshair').remove();\n }\n }\n\n render() {\n this.data = this.ctrl.data;\n this.panel = this.ctrl.panel;\n this.timeRange = this.ctrl.range;\n\n if (!this.setElementHeight() || !this.data) {\n return;\n }\n\n // Draw default axes and return if no data\n if (isEmpty(this.data.buckets)) {\n this.addHeatmapCanvas();\n this.addAxes();\n return;\n }\n\n this.addHeatmap();\n this.scope.yAxisWidth = this.yAxisWidth;\n this.scope.xAxisHeight = this.xAxisHeight;\n this.scope.chartHeight = this.chartHeight;\n this.scope.chartWidth = this.chartWidth;\n this.scope.chartTop = this.chartTop;\n }\n\n private getPanelYAxisWidth(): number | null {\n if (!this.panel.yAxis.width) {\n return null;\n }\n\n return isNaN(this.panel.yAxis.width) ? null : parseInt(this.panel.yAxis.width, 10);\n }\n}\n","import { auto } from 'angular';\nimport { defaultsDeep, includes, keys, map, reduce, min as _min, max as _max } from 'lodash';\n\nimport { LegacyResponseData, PanelEvents, DataFrame, rangeUtil } from '@grafana/data';\nimport appEvents from 'app/core/app_events';\nimport TimeSeries from 'app/core/time_series2';\nimport kbn from 'app/core/utils/kbn';\nimport { TimeSrv } from 'app/features/dashboard/services/TimeSrv';\nimport { getProcessedDataFrames } from 'app/features/query/state/runRequest';\nimport { TemplateSrv } from 'app/features/templating/template_srv';\nimport { MetricsPanelCtrl } from 'app/plugins/sdk';\nimport { ZoomOutEvent } from 'app/types/events';\n\nimport { DataProcessor } from '../graph/data_processor';\n\nimport { axesEditor } from './axes_editor';\nimport { heatmapDisplayEditor } from './display_editor';\nimport {\n convertToHeatMap,\n convertToCards,\n histogramToHeatmap,\n calculateBucketSize,\n sortSeriesByLabel,\n} from './heatmap_data_converter';\nimport rendering from './rendering';\n\nconst X_BUCKET_NUMBER_DEFAULT = 30;\nconst Y_BUCKET_NUMBER_DEFAULT = 10;\n\nconst panelDefaults: any = {\n heatmap: {},\n cards: {\n cardPadding: null,\n cardRound: null,\n },\n color: {\n mode: 'spectrum',\n cardColor: '#b4ff00',\n colorScale: 'sqrt',\n exponent: 0.5,\n colorScheme: 'interpolateOranges',\n },\n legend: {\n show: false,\n },\n dataFormat: 'timeseries',\n yBucketBound: 'auto',\n reverseYBuckets: false,\n xAxis: {\n show: true,\n },\n yAxis: {\n show: true,\n format: 'short',\n decimals: null,\n logBase: 1,\n splitFactor: null,\n min: null,\n max: null,\n },\n xBucketSize: null,\n xBucketNumber: null,\n yBucketSize: null,\n yBucketNumber: null,\n tooltip: {\n show: true,\n showHistogram: false,\n },\n highlightCards: true,\n hideZeroBuckets: false,\n};\n\nconst colorModes = ['opacity', 'spectrum'];\nconst opacityScales = ['linear', 'sqrt'];\n\n// Schemes from d3-scale-chromatic\n// https://github.com/d3/d3-scale-chromatic\nconst colorSchemes = [\n // Diverging\n { name: 'Spectral', value: 'interpolateSpectral', invert: 'always' },\n { name: 'RdYlGn', value: 'interpolateRdYlGn', invert: 'always' },\n\n // Sequential (Single Hue)\n { name: 'Blues', value: 'interpolateBlues', invert: 'dark' },\n { name: 'Greens', value: 'interpolateGreens', invert: 'dark' },\n { name: 'Greys', value: 'interpolateGreys', invert: 'dark' },\n { name: 'Oranges', value: 'interpolateOranges', invert: 'dark' },\n { name: 'Purples', value: 'interpolatePurples', invert: 'dark' },\n { name: 'Reds', value: 'interpolateReds', invert: 'dark' },\n\n // Sequential (Multi-Hue)\n { name: 'Turbo', value: 'interpolateTurbo', invert: 'light' },\n { name: 'Cividis', value: 'interpolateCividis', invert: 'light' },\n { name: 'Viridis', value: 'interpolateViridis', invert: 'light' },\n { name: 'Magma', value: 'interpolateMagma', invert: 'light' },\n { name: 'Inferno', value: 'interpolateInferno', invert: 'light' },\n { name: 'Plasma', value: 'interpolatePlasma', invert: 'light' },\n { name: 'Warm', value: 'interpolateWarm', invert: 'light' },\n { name: 'Cool', value: 'interpolateCool', invert: 'light' },\n { name: 'Cubehelix', value: 'interpolateCubehelixDefault', invert: 'light' },\n { name: 'BuGn', value: 'interpolateBuGn', invert: 'dark' },\n { name: 'BuPu', value: 'interpolateBuPu', invert: 'dark' },\n { name: 'GnBu', value: 'interpolateGnBu', invert: 'dark' },\n { name: 'OrRd', value: 'interpolateOrRd', invert: 'dark' },\n { name: 'PuBuGn', value: 'interpolatePuBuGn', invert: 'dark' },\n { name: 'PuBu', value: 'interpolatePuBu', invert: 'dark' },\n { name: 'PuRd', value: 'interpolatePuRd', invert: 'dark' },\n { name: 'RdPu', value: 'interpolateRdPu', invert: 'dark' },\n { name: 'YlGnBu', value: 'interpolateYlGnBu', invert: 'dark' },\n { name: 'YlGn', value: 'interpolateYlGn', invert: 'dark' },\n { name: 'YlOrBr', value: 'interpolateYlOrBr', invert: 'dark' },\n { name: 'YlOrRd', value: 'interpolateYlOrRd', invert: 'dark' },\n];\n\nconst dsSupportHistogramSort = ['elasticsearch'];\n\nexport class HeatmapCtrl extends MetricsPanelCtrl {\n static templateUrl = 'module.html';\n\n opacityScales: any = [];\n colorModes: any = [];\n colorSchemes: any = [];\n selectionActivated: boolean;\n unitFormats: any;\n data: any;\n series: TimeSeries[] = [];\n dataWarning: any;\n decimals = 0;\n scaledDecimals = 0;\n\n processor: DataProcessor; // Shared with graph panel\n\n /** @ngInject */\n constructor($scope: any, $injector: auto.IInjectorService, templateSrv: TemplateSrv, timeSrv: TimeSrv) {\n super($scope, $injector);\n\n this.selectionActivated = false;\n\n defaultsDeep(this.panel, panelDefaults);\n this.opacityScales = opacityScales;\n this.colorModes = colorModes;\n this.colorSchemes = colorSchemes;\n\n // Use DataFrames\n this.useDataFrames = true;\n this.processor = new DataProcessor({\n xaxis: { mode: 'custom' }, // NOT: 'histogram' :)\n aliasColors: {}, // avoids null reference\n });\n\n // Bind grafana panel events\n this.events.on(PanelEvents.render, this.onRender.bind(this));\n this.events.on(PanelEvents.dataFramesReceived, this.onDataFramesReceived.bind(this));\n this.events.on(PanelEvents.dataSnapshotLoad, this.onSnapshotLoad.bind(this));\n this.events.on(PanelEvents.editModeInitialized, this.onInitEditMode.bind(this));\n\n this.onCardColorChange = this.onCardColorChange.bind(this);\n }\n\n onInitEditMode() {\n this.addEditorTab('Axes', axesEditor, 2);\n this.addEditorTab('Display', heatmapDisplayEditor, 3);\n this.unitFormats = kbn.getUnitFormats();\n }\n\n zoomOut(evt: any) {\n appEvents.publish(new ZoomOutEvent({ scale: 2 }));\n }\n\n onRender() {\n if (this.panel.dataFormat === 'tsbuckets') {\n this.convertHistogramToHeatmapData();\n } else {\n this.convertTimeSeriesToHeatmapData();\n }\n }\n\n convertTimeSeriesToHeatmapData() {\n if (!this.range || !this.series) {\n return;\n }\n\n let xBucketSize, yBucketSize, bucketsData, heatmapStats;\n const logBase = this.panel.yAxis.logBase;\n\n const xBucketNumber = this.panel.xBucketNumber || X_BUCKET_NUMBER_DEFAULT;\n const xBucketSizeByNumber = Math.floor((this.range.to.valueOf() - this.range.from.valueOf()) / xBucketNumber);\n\n // Parse X bucket size (number or interval)\n const isIntervalString = kbn.intervalRegex.test(this.panel.xBucketSize);\n if (isIntervalString) {\n xBucketSize = rangeUtil.intervalToMs(this.panel.xBucketSize);\n } else if (\n isNaN(Number(this.panel.xBucketSize)) ||\n this.panel.xBucketSize === '' ||\n this.panel.xBucketSize === null\n ) {\n xBucketSize = xBucketSizeByNumber;\n } else {\n xBucketSize = Number(this.panel.xBucketSize);\n }\n\n // Calculate Y bucket size\n heatmapStats = this.parseSeries(this.series);\n const yBucketNumber = this.panel.yBucketNumber || Y_BUCKET_NUMBER_DEFAULT;\n if (logBase !== 1) {\n yBucketSize = this.panel.yAxis.splitFactor;\n } else {\n if (heatmapStats.max === heatmapStats.min) {\n if (heatmapStats.max) {\n yBucketSize = heatmapStats.max / Y_BUCKET_NUMBER_DEFAULT;\n } else {\n yBucketSize = 1;\n }\n } else {\n yBucketSize = (heatmapStats.max - heatmapStats.min) / yBucketNumber;\n }\n yBucketSize = this.panel.yBucketSize || yBucketSize;\n }\n\n bucketsData = convertToHeatMap(this.series, yBucketSize, xBucketSize, logBase);\n\n // Set default Y range if no data\n if (!heatmapStats.min && !heatmapStats.max) {\n heatmapStats = { min: -1, max: 1, minLog: 1 };\n yBucketSize = 1;\n }\n\n const { cards, cardStats } = convertToCards(bucketsData, this.panel.hideZeroBuckets);\n\n this.data = {\n buckets: bucketsData,\n heatmapStats: heatmapStats,\n xBucketSize: xBucketSize,\n yBucketSize: yBucketSize,\n cards: cards,\n cardStats: cardStats,\n };\n }\n\n convertHistogramToHeatmapData() {\n if (!this.range || !this.series) {\n return;\n }\n\n const panelDatasource = this.getPanelDataSourceType();\n let xBucketSize, yBucketSize, bucketsData, tsBuckets;\n\n // Try to sort series by bucket bound, if datasource doesn't do it.\n if (!includes(dsSupportHistogramSort, panelDatasource)) {\n this.series.sort(sortSeriesByLabel);\n }\n\n if (this.panel.reverseYBuckets) {\n this.series.reverse();\n }\n\n // Convert histogram to heatmap. Each histogram bucket represented by the series which name is\n // a top (or bottom, depends of datasource) bucket bound. Further, these values will be used as Y axis labels.\n bucketsData = histogramToHeatmap(this.series);\n\n tsBuckets = map(this.series, 'label');\n const yBucketBound = this.panel.yBucketBound;\n if (\n (panelDatasource === 'prometheus' && yBucketBound !== 'lower' && yBucketBound !== 'middle') ||\n yBucketBound === 'upper'\n ) {\n // Prometheus labels are upper inclusive bounds, so add empty bottom bucket label.\n tsBuckets = [''].concat(tsBuckets);\n } else {\n // Elasticsearch uses labels as lower bucket bounds, so add empty top bucket label.\n // Use this as a default mode as well.\n tsBuckets.push('');\n }\n\n // Calculate bucket size based on heatmap data\n const xBucketBoundSet = map(keys(bucketsData), (key) => Number(key));\n xBucketSize = calculateBucketSize(xBucketBoundSet);\n // Always let yBucketSize=1 in 'tsbuckets' mode\n yBucketSize = 1;\n\n const { cards, cardStats } = convertToCards(bucketsData, this.panel.hideZeroBuckets);\n\n this.data = {\n buckets: bucketsData,\n xBucketSize: xBucketSize,\n yBucketSize: yBucketSize,\n tsBuckets: tsBuckets,\n cards: cards,\n cardStats: cardStats,\n };\n }\n\n getPanelDataSourceType() {\n if (this.datasource && this.datasource.meta && this.datasource.meta.id) {\n return this.datasource.meta.id;\n } else {\n return 'unknown';\n }\n }\n\n // This should only be called from the snapshot callback\n onSnapshotLoad(dataList: LegacyResponseData[]) {\n this.onDataFramesReceived(getProcessedDataFrames(dataList));\n }\n\n // Directly support DataFrame\n onDataFramesReceived(data: DataFrame[]) {\n this.series = this.processor.getSeriesList({ dataList: data, range: this.range }).map((ts) => {\n ts.color = undefined; // remove whatever the processor set\n ts.flotpairs = ts.getFlotPairs(this.panel.nullPointMode);\n return ts;\n });\n\n this.dataWarning = null;\n const datapointsCount = reduce(\n this.series,\n (sum, series) => {\n return sum + series.datapoints.length;\n },\n 0\n );\n\n if (datapointsCount === 0) {\n this.dataWarning = {\n title: 'No data points',\n tip: 'No datapoints returned from data query',\n };\n } else {\n for (const series of this.series) {\n if (series.isOutsideRange) {\n this.dataWarning = {\n title: 'Data points outside time range',\n tip: 'Can be caused by timezone mismatch or missing time filter in query',\n };\n break;\n }\n }\n }\n\n this.render();\n }\n\n onDataError() {\n this.series = [];\n this.render();\n }\n\n onCardColorChange(newColor: any) {\n this.panel.color.cardColor = newColor;\n this.render();\n }\n\n parseSeries(series: TimeSeries[]) {\n const min = _min(map(series, (s) => s.stats.min));\n const minLog = _min(map(series, (s) => s.stats.logmin));\n const max = _max(map(series, (s) => s.stats.max));\n\n return {\n max,\n min,\n minLog,\n };\n }\n\n parseHistogramSeries(series: TimeSeries[]) {\n const bounds = map(series, (s) => Number(s.alias));\n const min = _min(bounds);\n const minLog = _min(bounds);\n const max = _max(bounds);\n\n return {\n max: max,\n min: min,\n minLog: minLog,\n };\n }\n\n link(scope: any, elem: any, attrs: any, ctrl: any) {\n rendering(scope, elem, attrs, ctrl);\n }\n}\n","import { makeClassES5Compatible } from '@grafana/data';\nimport { loadPluginCss } from '@grafana/runtime';\nimport { MetricsPanelCtrl as MetricsPanelCtrlES6 } from 'app/angular/panel/metrics_panel_ctrl';\nimport { PanelCtrl as PanelCtrlES6 } from 'app/angular/panel/panel_ctrl';\nimport { QueryCtrl as QueryCtrlES6 } from 'app/angular/panel/query_ctrl';\n\nconst PanelCtrl = makeClassES5Compatible(PanelCtrlES6);\nconst MetricsPanelCtrl = makeClassES5Compatible(MetricsPanelCtrlES6);\nconst QueryCtrl = makeClassES5Compatible(QueryCtrlES6);\n\nexport { PanelCtrl, MetricsPanelCtrl, QueryCtrl, loadPluginCss };\n"],"names":["QueryCtrl","constructor","$scope","$injector","this","panelCtrl","ctrl","target","datasource","panel","isLastQuery","indexOf","targets","length","refresh","getColorScale","colorScheme","lightTheme","maxValue","minValue","colorInterpolator","d3ScaleChromatic","value","colorScaleInverted","invert","start","end","d3","scaleSequential","domain","getOpacityScale","options","legendOpacityScale","colorScale","scaleLinear","range","scalePow","exponent","drawLegendValues","elem","rangeFrom","rangeTo","legendWidth","valuesRange","legendElem","$","find","legendDomElement","get","legend","select","childNodes","legendValueScale","ticks","tickStepSize","tickStep","ticksNum","Math","ceil","firstTick","step","floor","getFirstCloseTick","i","current","isValueCloseTo","push","sortBy","uniq","buildLegendTicks","xAxis","axisBottom","tickValues","tickSize","colorRect","posY","svgElem","height","baseVal","getSvgElemHeight","posX","x","getSvgElemX","append","attr","call","remove","clearLegend","empty","val","valueTo","abs","coreModule","restrict","template","link","scope","attrs","render","outerWidth","color","mode","colorSchemes","contextSrv","legendHeight","valuesNumber","rangeStep","selectAll","data","enter","d","drawSimpleColorLegend","colorOptions","config","cardColor","style","drawSimpleOpacityLegend","events","on","PanelEvents","isEmpty","cards","cardStats","isNil","min","max","widthFactor","round","drawColorLegend","opacityScale","drawOpacityLegend","AxesEditorCtrl","uiSegmentSrv","unit","yAxis","format","editor","logScales","linear","dataFormats","yBucketBoundModes","Auto","Upper","Lower","Middle","axesEditor","templateUrl","controller","HeatmapDisplayEditorCtrl","heatmapDisplayEditor","sortSeriesByLabel","s1","s2","label1","label2","parseHistogramLabel","label","err","console","error","message","Infinity","Number","isNaN","Error","convertToCards","buckets","hideZero","forEach","xBucket","yBucket","card","y","yBounds","bounds","values","count","pushToXBuckets","point","bucketNum","seriesName","pointExt","concat","points","pushToYBuckets","parseInt","getValueBucketBound","yBucketSize","logBase","getBucketBound","yBucketSplitFactor","getLogScaleBucketBounds","bottom","getLogScaleBucketBound","getBucketBounds","bucketSize","top","convertToValueBuckets","index","valueLog","logp","pow","powTop","additionalBucketSize","additionalLog","convertToLogScaleValueBuckets","base","log","getDistance","a","b","HISTOGRAM_WIDTH","HeatmapTooltip","dashboard","heatmapPanel","mouseOverBucket","originalFillColor","onMouseLeave","bind","destroy","onMouseMove","e","tooltip","show","move","add","pos","panelRelY","xBucketIndex","yBucketIndex","getBucketIndexes","boundBottom","boundTop","xData","yData","bucket","bucketIndex","toString","time","formatDate","countValueFormatter","bucketBoundFormatter","isNumber","tooltipDecimals","tickValueFormatter","decimals","scaledDecimals","tooltipHtml","tsBuckets","tickFormatter","valIndex","tsBucketsFormatted","yBucketBound","showHistogram","html","addHistogram","getXBucketIndex","getYBucketIndex","xBucketSize","getSharedTooltipPos","pageX","offset","left","xScale","pageY","chartHeight","histogramData","map","undefined","filter","histXScale","yScale","copy","barWidth","barNumberFactor","histogramDomain","reduce","sum","histYScale","node","tooltipWidth","clientWidth","tooltipHeight","clientHeight","window","innerWidth","pageYOffset","innerHeight","fmt","getValueFormat","formattedValueToString","HeatmapRenderer","$heatmap","selection","active","x1","x2","padding","right","margin","dataRangeWidingFactor","onRender","LegacyGraphHoverEvent","onGraphHover","LegacyGraphHoverClearEvent","onGraphHoverClear","onMouseDown","hoverEvent","clearCrosshair","event","drawSharedCrosshair","renderingCompleted","setElementHeight","row","isString","replace","css","getYAxisWidth","panelYAxisWidth","getPanelYAxisWidth","axisText","nodes","text","getBBox","width","getXAxisHeight","axisLinePosition","parseFloat","addXAxis","timeRange","from","to","chartWidth","graphTimeFormat","valueOf","timeZone","getTimezone","tickFormat","date","dateTimeFormat","tickPadding","yAxisWidth","heatmap","addYAxis","tickInterval","ticksUtils","heatmapStats","yMin","yMax","wideYAxisRange","decimalsAuto","flotTickSize","tickSizeInner","tickSizeOuter","yWiding","addLogYAxis","adjustLogRange","minLog","adjustLogMin","adjustLogMax","logScaleTickValues","addYAxisFromBuckets","valueFormatted","toNumber","scale","trimmed","substring","v","tickShift","domainMin","domainMax","tickValue","fixYAxisTickSize","addAxes","chartTop","chartBottom","dataFormat","xAxisHeight","addHeatmapCanvas","heatmapElem","cardPadding","cardRound","addHeatmap","yBuckets","emptyBucket","nullBucket","minBucket","newBucket","mergeZeroBuckets","cardsData","maxValueAuto","minValueAuto","setCardSize","getCardX","getCardWidth","getCardY","getCardHeight","getCardColor","getCardOpacity","highlightCard","resetCardHighLight","highlightColor","darker","strokeColor","brighter","currentCard","xGridSize","yGridSize","splitFactor","cardWidth","cardHeight","w","h","getEventOffset","elemOffset","clientX","clientY","mouseUpHandler","onMouseUp","document","one","unbind","selectionRange","timeFrom","timeTo","timeSrv","setTime","toUtc","clearSelection","publish","limitSelection","drawSelection","getEventPos","drawCrosshair","emitGraphHoverEvent","y1","payload","posX1","posX2","selectionX","selectionWidth","position","graphTooltip","panelDefaults","reverseYBuckets","xBucketNumber","yBucketNumber","highlightCards","hideZeroBuckets","colorModes","opacityScales","name","dsSupportHistogramSort","HeatmapCtrl","MetricsPanelCtrl","templateSrv","super","selectionActivated","defaultsDeep","useDataFrames","processor","DataProcessor","xaxis","aliasColors","onDataFramesReceived","onSnapshotLoad","onInitEditMode","onCardColorChange","addEditorTab","unitFormats","kbn","zoomOut","evt","appEvents","ZoomOutEvent","convertHistogramToHeatmapData","convertTimeSeriesToHeatmapData","series","bucketsData","xBucketSizeByNumber","rangeUtil","parseSeries","seriesList","datapoints","bucketBound","convertToHeatMap","panelDatasource","getPanelDataSourceType","includes","sort","reverse","bound","histogramToHeatmap","distance","calculateBucketSize","keys","key","meta","id","dataList","getProcessedDataFrames","getSeriesList","ts","flotpairs","getFlotPairs","nullPointMode","dataWarning","title","tip","isOutsideRange","onDataError","newColor","_min","s","stats","logmin","_max","parseHistogramSeries","alias","rendering","PanelCtrl","makeClassES5Compatible","PanelCtrlES6","MetricsPanelCtrlES6","QueryCtrlES6"],"sourceRoot":""}