Browse Source
* Add Grafana's embedded modules * Include them from vendor/ instead of grafana/master
7 changed files with 794 additions and 29 deletions
@ -0,0 +1,93 @@ |
|||||||
|
import _ from 'lodash'; |
||||||
|
import tinycolor from 'tinycolor2'; |
||||||
|
|
||||||
|
export const PALETTE_ROWS = 4; |
||||||
|
export const PALETTE_COLUMNS = 14; |
||||||
|
export const DEFAULT_ANNOTATION_COLOR = 'rgba(0, 211, 255, 1)'; |
||||||
|
export const OK_COLOR = 'rgba(11, 237, 50, 1)'; |
||||||
|
export const ALERTING_COLOR = 'rgba(237, 46, 24, 1)'; |
||||||
|
export const NO_DATA_COLOR = 'rgba(150, 150, 150, 1)'; |
||||||
|
export const REGION_FILL_ALPHA = 0.09; |
||||||
|
|
||||||
|
let colors = [ |
||||||
|
'#7EB26D', |
||||||
|
'#EAB839', |
||||||
|
'#6ED0E0', |
||||||
|
'#EF843C', |
||||||
|
'#E24D42', |
||||||
|
'#1F78C1', |
||||||
|
'#BA43A9', |
||||||
|
'#705DA0', |
||||||
|
'#508642', |
||||||
|
'#CCA300', |
||||||
|
'#447EBC', |
||||||
|
'#C15C17', |
||||||
|
'#890F02', |
||||||
|
'#0A437C', |
||||||
|
'#6D1F62', |
||||||
|
'#584477', |
||||||
|
'#B7DBAB', |
||||||
|
'#F4D598', |
||||||
|
'#70DBED', |
||||||
|
'#F9BA8F', |
||||||
|
'#F29191', |
||||||
|
'#82B5D8', |
||||||
|
'#E5A8E2', |
||||||
|
'#AEA2E0', |
||||||
|
'#629E51', |
||||||
|
'#E5AC0E', |
||||||
|
'#64B0C8', |
||||||
|
'#E0752D', |
||||||
|
'#BF1B00', |
||||||
|
'#0A50A1', |
||||||
|
'#962D82', |
||||||
|
'#614D93', |
||||||
|
'#9AC48A', |
||||||
|
'#F2C96D', |
||||||
|
'#65C5DB', |
||||||
|
'#F9934E', |
||||||
|
'#EA6460', |
||||||
|
'#5195CE', |
||||||
|
'#D683CE', |
||||||
|
'#806EB7', |
||||||
|
'#3F6833', |
||||||
|
'#967302', |
||||||
|
'#2F575E', |
||||||
|
'#99440A', |
||||||
|
'#58140C', |
||||||
|
'#052B51', |
||||||
|
'#511749', |
||||||
|
'#3F2B5B', |
||||||
|
'#E0F9D7', |
||||||
|
'#FCEACA', |
||||||
|
'#CFFAFF', |
||||||
|
'#F9E2D2', |
||||||
|
'#FCE2DE', |
||||||
|
'#BADFF4', |
||||||
|
'#F9D9F9', |
||||||
|
'#DEDAF7', |
||||||
|
]; |
||||||
|
|
||||||
|
export function sortColorsByHue(hexColors) { |
||||||
|
let hslColors = _.map(hexColors, hexToHsl); |
||||||
|
|
||||||
|
let sortedHSLColors: any = _.sortBy(hslColors, ['h']); |
||||||
|
sortedHSLColors = _.chunk(sortedHSLColors, PALETTE_ROWS); |
||||||
|
sortedHSLColors = _.map(sortedHSLColors, chunk => { |
||||||
|
return _.sortBy(chunk, 'l'); |
||||||
|
}); |
||||||
|
sortedHSLColors = _.flattenDeep(_.zip(...sortedHSLColors)); |
||||||
|
|
||||||
|
return _.map(sortedHSLColors, hslToHex); |
||||||
|
} |
||||||
|
|
||||||
|
export function hexToHsl(color) { |
||||||
|
return tinycolor(color).toHsl(); |
||||||
|
} |
||||||
|
|
||||||
|
export function hslToHex(color) { |
||||||
|
return tinycolor(color).toHexString(); |
||||||
|
} |
||||||
|
|
||||||
|
export let sortedColors = sortColorsByHue(colors); |
||||||
|
export default colors; |
@ -0,0 +1,11 @@ |
|||||||
|
export class AnnotationEvent { |
||||||
|
dashboardId: number; |
||||||
|
panelId: number; |
||||||
|
userId: number; |
||||||
|
time: any; |
||||||
|
timeEnd: any; |
||||||
|
isRegion: boolean; |
||||||
|
text: string; |
||||||
|
type: string; |
||||||
|
tags: string; |
||||||
|
} |
@ -0,0 +1,177 @@ |
|||||||
|
import _ from 'lodash'; |
||||||
|
import moment from 'moment'; |
||||||
|
import tinycolor from 'tinycolor2'; |
||||||
|
import { MetricsPanelCtrl } from 'grafana/app/plugins/sdk'; |
||||||
|
import { AnnotationEvent } from './event'; |
||||||
|
import { |
||||||
|
DEFAULT_ANNOTATION_COLOR, |
||||||
|
OK_COLOR, |
||||||
|
ALERTING_COLOR, |
||||||
|
NO_DATA_COLOR, |
||||||
|
REGION_FILL_ALPHA |
||||||
|
} from './colors'; |
||||||
|
|
||||||
|
export class EventManager { |
||||||
|
event: AnnotationEvent; |
||||||
|
editorOpen: boolean; |
||||||
|
|
||||||
|
constructor(private panelCtrl: MetricsPanelCtrl) { } |
||||||
|
|
||||||
|
editorClosed() { |
||||||
|
this.event = null; |
||||||
|
this.editorOpen = false; |
||||||
|
this.panelCtrl.render(); |
||||||
|
} |
||||||
|
|
||||||
|
editorOpened() { |
||||||
|
this.editorOpen = true; |
||||||
|
} |
||||||
|
|
||||||
|
updateTime(range) { |
||||||
|
if (!this.event) { |
||||||
|
this.event = new AnnotationEvent(); |
||||||
|
this.event.dashboardId = this.panelCtrl.dashboard.id; |
||||||
|
this.event.panelId = this.panelCtrl.panel.id; |
||||||
|
} |
||||||
|
|
||||||
|
// update time
|
||||||
|
this.event.time = moment(range.from); |
||||||
|
this.event.isRegion = false; |
||||||
|
if (range.to) { |
||||||
|
this.event.timeEnd = moment(range.to); |
||||||
|
this.event.isRegion = true; |
||||||
|
} |
||||||
|
|
||||||
|
this.panelCtrl.render(); |
||||||
|
} |
||||||
|
|
||||||
|
editEvent(event, elem?) { |
||||||
|
this.event = event; |
||||||
|
this.panelCtrl.render(); |
||||||
|
} |
||||||
|
|
||||||
|
addFlotEvents(annotations, flotOptions) { |
||||||
|
if (!this.event && annotations.length === 0) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
var types = { |
||||||
|
$__alerting: { |
||||||
|
color: ALERTING_COLOR, |
||||||
|
position: 'BOTTOM', |
||||||
|
markerSize: 5, |
||||||
|
}, |
||||||
|
$__ok: { |
||||||
|
color: OK_COLOR, |
||||||
|
position: 'BOTTOM', |
||||||
|
markerSize: 5, |
||||||
|
}, |
||||||
|
$__no_data: { |
||||||
|
color: NO_DATA_COLOR, |
||||||
|
position: 'BOTTOM', |
||||||
|
markerSize: 5, |
||||||
|
}, |
||||||
|
$__editing: { |
||||||
|
color: DEFAULT_ANNOTATION_COLOR, |
||||||
|
position: 'BOTTOM', |
||||||
|
markerSize: 5, |
||||||
|
}, |
||||||
|
}; |
||||||
|
|
||||||
|
if (this.event) { |
||||||
|
if (this.event.isRegion) { |
||||||
|
annotations = [ |
||||||
|
{ |
||||||
|
isRegion: true, |
||||||
|
min: this.event.time.valueOf(), |
||||||
|
timeEnd: this.event.timeEnd.valueOf(), |
||||||
|
text: this.event.text, |
||||||
|
eventType: '$__editing', |
||||||
|
editModel: this.event, |
||||||
|
}, |
||||||
|
]; |
||||||
|
} else { |
||||||
|
annotations = [ |
||||||
|
{ |
||||||
|
min: this.event.time.valueOf(), |
||||||
|
text: this.event.text, |
||||||
|
editModel: this.event, |
||||||
|
eventType: '$__editing', |
||||||
|
}, |
||||||
|
]; |
||||||
|
} |
||||||
|
} else { |
||||||
|
// annotations from query
|
||||||
|
for (var i = 0; i < annotations.length; i++) { |
||||||
|
var item = annotations[i]; |
||||||
|
|
||||||
|
// add properties used by jquery flot events
|
||||||
|
item.min = item.time; |
||||||
|
item.max = item.time; |
||||||
|
item.eventType = item.source.name; |
||||||
|
|
||||||
|
if (item.newState) { |
||||||
|
item.eventType = '$__' + item.newState; |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
if (!types[item.source.name]) { |
||||||
|
types[item.source.name] = { |
||||||
|
color: item.source.iconColor, |
||||||
|
position: 'BOTTOM', |
||||||
|
markerSize: 5, |
||||||
|
}; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
let regions = getRegions(annotations); |
||||||
|
addRegionMarking(regions, flotOptions); |
||||||
|
|
||||||
|
let eventSectionHeight = 20; |
||||||
|
let eventSectionMargin = 7; |
||||||
|
flotOptions.grid.eventSectionHeight = eventSectionMargin; |
||||||
|
flotOptions.xaxis.eventSectionHeight = eventSectionHeight; |
||||||
|
|
||||||
|
flotOptions.events = { |
||||||
|
levels: _.keys(types).length + 1, |
||||||
|
data: annotations, |
||||||
|
types: types, |
||||||
|
manager: this, |
||||||
|
}; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function getRegions(events) { |
||||||
|
return _.filter(events, 'isRegion'); |
||||||
|
} |
||||||
|
|
||||||
|
function addRegionMarking(regions, flotOptions) { |
||||||
|
let markings = flotOptions.grid.markings; |
||||||
|
let defaultColor = DEFAULT_ANNOTATION_COLOR; |
||||||
|
let fillColor; |
||||||
|
|
||||||
|
_.each(regions, region => { |
||||||
|
if (region.source) { |
||||||
|
fillColor = region.source.iconColor || defaultColor; |
||||||
|
} else { |
||||||
|
fillColor = defaultColor; |
||||||
|
} |
||||||
|
|
||||||
|
fillColor = addAlphaToRGB(fillColor, REGION_FILL_ALPHA); |
||||||
|
markings.push({ |
||||||
|
xaxis: { from: region.min, to: region.timeEnd }, |
||||||
|
color: fillColor, |
||||||
|
}); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
function addAlphaToRGB(colorString: string, alpha: number): string { |
||||||
|
let color = tinycolor(colorString); |
||||||
|
if (color.isValid()) { |
||||||
|
color.setAlpha(alpha); |
||||||
|
return color.toRgbString(); |
||||||
|
} else { |
||||||
|
return colorString; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,158 @@ |
|||||||
|
import { getDataMinMax } from './time_series2'; |
||||||
|
|
||||||
|
/** |
||||||
|
* Calculate tick step. |
||||||
|
* Implementation from d3-array (ticks.js) |
||||||
|
* https://github.com/d3/d3-array/blob/master/src/ticks.js
|
||||||
|
* @param start Start value |
||||||
|
* @param stop End value |
||||||
|
* @param count Ticks count |
||||||
|
*/ |
||||||
|
export function tickStep(start: number, stop: number, count: number): number { |
||||||
|
let e10 = Math.sqrt(50), |
||||||
|
e5 = Math.sqrt(10), |
||||||
|
e2 = Math.sqrt(2); |
||||||
|
|
||||||
|
let step0 = Math.abs(stop - start) / Math.max(0, count), |
||||||
|
step1 = Math.pow(10, Math.floor(Math.log(step0) / Math.LN10)), |
||||||
|
error = step0 / step1; |
||||||
|
|
||||||
|
if (error >= e10) { |
||||||
|
step1 *= 10; |
||||||
|
} else if (error >= e5) { |
||||||
|
step1 *= 5; |
||||||
|
} else if (error >= e2) { |
||||||
|
step1 *= 2; |
||||||
|
} |
||||||
|
|
||||||
|
return stop < start ? -step1 : step1; |
||||||
|
} |
||||||
|
|
||||||
|
export function getScaledDecimals(decimals, tick_size) { |
||||||
|
return decimals - Math.floor(Math.log(tick_size) / Math.LN10); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Calculate tick size based on min and max values, number of ticks and precision. |
||||||
|
* Implementation from Flot. |
||||||
|
* @param min Axis minimum |
||||||
|
* @param max Axis maximum |
||||||
|
* @param noTicks Number of ticks |
||||||
|
* @param tickDecimals Tick decimal precision |
||||||
|
*/ |
||||||
|
export function getFlotTickSize(min: number, max: number, noTicks: number, tickDecimals: number) { |
||||||
|
var delta = (max - min) / noTicks, |
||||||
|
dec = -Math.floor(Math.log(delta) / Math.LN10), |
||||||
|
maxDec = tickDecimals; |
||||||
|
|
||||||
|
var magn = Math.pow(10, -dec), |
||||||
|
norm = delta / magn, // norm is between 1.0 and 10.0
|
||||||
|
size; |
||||||
|
|
||||||
|
if (norm < 1.5) { |
||||||
|
size = 1; |
||||||
|
} else if (norm < 3) { |
||||||
|
size = 2; |
||||||
|
// special case for 2.5, requires an extra decimal
|
||||||
|
if (norm > 2.25 && (maxDec == null || dec + 1 <= maxDec)) { |
||||||
|
size = 2.5; |
||||||
|
++dec; |
||||||
|
} |
||||||
|
} else if (norm < 7.5) { |
||||||
|
size = 5; |
||||||
|
} else { |
||||||
|
size = 10; |
||||||
|
} |
||||||
|
|
||||||
|
size *= magn; |
||||||
|
|
||||||
|
return size; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Calculate axis range (min and max). |
||||||
|
* Implementation from Flot. |
||||||
|
*/ |
||||||
|
export function getFlotRange(panelMin, panelMax, datamin, datamax) { |
||||||
|
const autoscaleMargin = 0.02; |
||||||
|
|
||||||
|
let min = +(panelMin != null ? panelMin : datamin); |
||||||
|
let max = +(panelMax != null ? panelMax : datamax); |
||||||
|
let delta = max - min; |
||||||
|
|
||||||
|
if (delta === 0.0) { |
||||||
|
// Grafana fix: wide Y min and max using increased wideFactor
|
||||||
|
// when all series values are the same
|
||||||
|
var wideFactor = 0.25; |
||||||
|
var widen = Math.abs(max === 0 ? 1 : max * wideFactor); |
||||||
|
|
||||||
|
if (panelMin === null) { |
||||||
|
min -= widen; |
||||||
|
} |
||||||
|
// always widen max if we couldn't widen min to ensure we
|
||||||
|
// don't fall into min == max which doesn't work
|
||||||
|
if (panelMax == null || panelMin != null) { |
||||||
|
max += widen; |
||||||
|
} |
||||||
|
} else { |
||||||
|
// consider autoscaling
|
||||||
|
var margin = autoscaleMargin; |
||||||
|
if (margin != null) { |
||||||
|
if (panelMin == null) { |
||||||
|
min -= delta * margin; |
||||||
|
// make sure we don't go below zero if all values
|
||||||
|
// are positive
|
||||||
|
if (min < 0 && datamin != null && datamin >= 0) { |
||||||
|
min = 0; |
||||||
|
} |
||||||
|
} |
||||||
|
if (panelMax == null) { |
||||||
|
max += delta * margin; |
||||||
|
if (max > 0 && datamax != null && datamax <= 0) { |
||||||
|
max = 0; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return { min, max }; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Calculate tick decimals. |
||||||
|
* Implementation from Flot. |
||||||
|
*/ |
||||||
|
export function getFlotTickDecimals(data, axis) { |
||||||
|
let { datamin, datamax } = getDataMinMax(data); |
||||||
|
let { min, max } = getFlotRange(axis.min, axis.max, datamin, datamax); |
||||||
|
let noTicks = 3; |
||||||
|
let tickDecimals, maxDec; |
||||||
|
let delta = (max - min) / noTicks; |
||||||
|
let dec = -Math.floor(Math.log(delta) / Math.LN10); |
||||||
|
|
||||||
|
let magn = Math.pow(10, -dec); |
||||||
|
// norm is between 1.0 and 10.0
|
||||||
|
let norm = delta / magn; |
||||||
|
let size; |
||||||
|
|
||||||
|
if (norm < 1.5) { |
||||||
|
size = 1; |
||||||
|
} else if (norm < 3) { |
||||||
|
size = 2; |
||||||
|
// special case for 2.5, requires an extra decimal
|
||||||
|
if (norm > 2.25 && (maxDec == null || dec + 1 <= maxDec)) { |
||||||
|
size = 2.5; |
||||||
|
++dec; |
||||||
|
} |
||||||
|
} else if (norm < 7.5) { |
||||||
|
size = 5; |
||||||
|
} else { |
||||||
|
size = 10; |
||||||
|
} |
||||||
|
|
||||||
|
size *= magn; |
||||||
|
|
||||||
|
tickDecimals = Math.max(0, maxDec != null ? maxDec : dec); |
||||||
|
// grafana addition
|
||||||
|
const scaledDecimals = tickDecimals - Math.floor(Math.log(size) / Math.LN10); |
||||||
|
return { tickDecimals, scaledDecimals }; |
||||||
|
} |
@ -0,0 +1,349 @@ |
|||||||
|
import kbn from 'grafana/app/core/utils/kbn'; |
||||||
|
import { getFlotTickDecimals } from './ticks'; |
||||||
|
import _ from 'lodash'; |
||||||
|
|
||||||
|
function matchSeriesOverride(aliasOrRegex, seriesAlias) { |
||||||
|
if (!aliasOrRegex) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
if (aliasOrRegex[0] === '/') { |
||||||
|
var regex = kbn.stringToJsRegex(aliasOrRegex); |
||||||
|
return seriesAlias.match(regex) != null; |
||||||
|
} |
||||||
|
|
||||||
|
return aliasOrRegex === seriesAlias; |
||||||
|
} |
||||||
|
|
||||||
|
function translateFillOption(fill) { |
||||||
|
return fill === 0 ? 0.001 : fill / 10; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Calculate decimals for legend and update values for each series. |
||||||
|
* @param data series data |
||||||
|
* @param panel |
||||||
|
*/ |
||||||
|
export function updateLegendValues(data: TimeSeries[], panel) { |
||||||
|
for (let i = 0; i < data.length; i++) { |
||||||
|
let series = data[i]; |
||||||
|
let yaxes = panel.yaxes; |
||||||
|
const seriesYAxis = series.yaxis || 1; |
||||||
|
let axis = yaxes[seriesYAxis - 1]; |
||||||
|
let { tickDecimals, scaledDecimals } = getFlotTickDecimals(data, axis); |
||||||
|
let formater = kbn.valueFormats[panel.yaxes[seriesYAxis - 1].format]; |
||||||
|
|
||||||
|
// decimal override
|
||||||
|
if (_.isNumber(panel.decimals)) { |
||||||
|
series.updateLegendValues(formater, panel.decimals, null); |
||||||
|
} else { |
||||||
|
// auto decimals
|
||||||
|
// legend and tooltip gets one more decimal precision
|
||||||
|
// than graph legend ticks
|
||||||
|
tickDecimals = (tickDecimals || -1) + 1; |
||||||
|
series.updateLegendValues(formater, tickDecimals, scaledDecimals + 2); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
export function getDataMinMax(data: TimeSeries[]) { |
||||||
|
let datamin = null; |
||||||
|
let datamax = null; |
||||||
|
|
||||||
|
for (let series of data) { |
||||||
|
if (datamax === null || datamax < series.stats.max) { |
||||||
|
datamax = series.stats.max; |
||||||
|
} |
||||||
|
if (datamin === null || datamin > series.stats.min) { |
||||||
|
datamin = series.stats.min; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return { datamin, datamax }; |
||||||
|
} |
||||||
|
|
||||||
|
export default class TimeSeries { |
||||||
|
datapoints: any; |
||||||
|
id: string; |
||||||
|
label: string; |
||||||
|
alias: string; |
||||||
|
aliasEscaped: string; |
||||||
|
color: string; |
||||||
|
valueFormater: any; |
||||||
|
stats: any; |
||||||
|
legend: boolean; |
||||||
|
allIsNull: boolean; |
||||||
|
allIsZero: boolean; |
||||||
|
decimals: number; |
||||||
|
scaledDecimals: number; |
||||||
|
hasMsResolution: boolean; |
||||||
|
isOutsideRange: boolean; |
||||||
|
|
||||||
|
lines: any; |
||||||
|
dashes: any; |
||||||
|
bars: any; |
||||||
|
points: any; |
||||||
|
yaxis: any; |
||||||
|
zindex: any; |
||||||
|
stack: any; |
||||||
|
nullPointMode: any; |
||||||
|
fillBelowTo: any; |
||||||
|
transform: any; |
||||||
|
flotpairs: any; |
||||||
|
unit: any; |
||||||
|
|
||||||
|
constructor(opts) { |
||||||
|
this.datapoints = opts.datapoints; |
||||||
|
this.label = opts.alias; |
||||||
|
this.id = opts.alias; |
||||||
|
this.alias = opts.alias; |
||||||
|
this.aliasEscaped = _.escape(opts.alias); |
||||||
|
this.color = opts.color; |
||||||
|
this.valueFormater = kbn.valueFormats.none; |
||||||
|
this.stats = {}; |
||||||
|
this.legend = true; |
||||||
|
this.unit = opts.unit; |
||||||
|
this.hasMsResolution = this.isMsResolutionNeeded(); |
||||||
|
} |
||||||
|
|
||||||
|
applySeriesOverrides(overrides) { |
||||||
|
this.lines = {}; |
||||||
|
this.dashes = { |
||||||
|
dashLength: [], |
||||||
|
}; |
||||||
|
this.points = {}; |
||||||
|
this.bars = {}; |
||||||
|
this.yaxis = 1; |
||||||
|
this.zindex = 0; |
||||||
|
this.nullPointMode = null; |
||||||
|
delete this.stack; |
||||||
|
|
||||||
|
for (var i = 0; i < overrides.length; i++) { |
||||||
|
var override = overrides[i]; |
||||||
|
if (!matchSeriesOverride(override.alias, this.alias)) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
if (override.lines !== void 0) { |
||||||
|
this.lines.show = override.lines; |
||||||
|
} |
||||||
|
if (override.dashes !== void 0) { |
||||||
|
this.dashes.show = override.dashes; |
||||||
|
this.lines.lineWidth = 0; |
||||||
|
} |
||||||
|
if (override.points !== void 0) { |
||||||
|
this.points.show = override.points; |
||||||
|
} |
||||||
|
if (override.bars !== void 0) { |
||||||
|
this.bars.show = override.bars; |
||||||
|
} |
||||||
|
if (override.fill !== void 0) { |
||||||
|
this.lines.fill = translateFillOption(override.fill); |
||||||
|
} |
||||||
|
if (override.stack !== void 0) { |
||||||
|
this.stack = override.stack; |
||||||
|
} |
||||||
|
if (override.linewidth !== void 0) { |
||||||
|
this.lines.lineWidth = this.dashes.show ? 0 : override.linewidth; |
||||||
|
this.dashes.lineWidth = override.linewidth; |
||||||
|
} |
||||||
|
if (override.dashLength !== void 0) { |
||||||
|
this.dashes.dashLength[0] = override.dashLength; |
||||||
|
} |
||||||
|
if (override.spaceLength !== void 0) { |
||||||
|
this.dashes.dashLength[1] = override.spaceLength; |
||||||
|
} |
||||||
|
if (override.nullPointMode !== void 0) { |
||||||
|
this.nullPointMode = override.nullPointMode; |
||||||
|
} |
||||||
|
if (override.pointradius !== void 0) { |
||||||
|
this.points.radius = override.pointradius; |
||||||
|
} |
||||||
|
if (override.steppedLine !== void 0) { |
||||||
|
this.lines.steps = override.steppedLine; |
||||||
|
} |
||||||
|
if (override.zindex !== void 0) { |
||||||
|
this.zindex = override.zindex; |
||||||
|
} |
||||||
|
if (override.fillBelowTo !== void 0) { |
||||||
|
this.fillBelowTo = override.fillBelowTo; |
||||||
|
} |
||||||
|
if (override.color !== void 0) { |
||||||
|
this.color = override.color; |
||||||
|
} |
||||||
|
if (override.transform !== void 0) { |
||||||
|
this.transform = override.transform; |
||||||
|
} |
||||||
|
if (override.legend !== void 0) { |
||||||
|
this.legend = override.legend; |
||||||
|
} |
||||||
|
|
||||||
|
if (override.yaxis !== void 0) { |
||||||
|
this.yaxis = override.yaxis; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
getFlotPairs(fillStyle) { |
||||||
|
var result = []; |
||||||
|
|
||||||
|
this.stats.total = 0; |
||||||
|
this.stats.max = -Number.MAX_VALUE; |
||||||
|
this.stats.min = Number.MAX_VALUE; |
||||||
|
this.stats.logmin = Number.MAX_VALUE; |
||||||
|
this.stats.avg = null; |
||||||
|
this.stats.current = null; |
||||||
|
this.stats.first = null; |
||||||
|
this.stats.delta = 0; |
||||||
|
this.stats.diff = null; |
||||||
|
this.stats.range = null; |
||||||
|
this.stats.timeStep = Number.MAX_VALUE; |
||||||
|
this.allIsNull = true; |
||||||
|
this.allIsZero = true; |
||||||
|
|
||||||
|
var ignoreNulls = fillStyle === 'connected'; |
||||||
|
var nullAsZero = fillStyle === 'null as zero'; |
||||||
|
var currentTime; |
||||||
|
var currentValue; |
||||||
|
var nonNulls = 0; |
||||||
|
var previousTime; |
||||||
|
var previousValue = 0; |
||||||
|
var previousDeltaUp = true; |
||||||
|
|
||||||
|
for (var i = 0; i < this.datapoints.length; i++) { |
||||||
|
currentValue = this.datapoints[i][0]; |
||||||
|
currentTime = this.datapoints[i][1]; |
||||||
|
|
||||||
|
// Due to missing values we could have different timeStep all along the series
|
||||||
|
// so we have to find the minimum one (could occur with aggregators such as ZimSum)
|
||||||
|
if (previousTime !== undefined) { |
||||||
|
let timeStep = currentTime - previousTime; |
||||||
|
if (timeStep < this.stats.timeStep) { |
||||||
|
this.stats.timeStep = timeStep; |
||||||
|
} |
||||||
|
} |
||||||
|
previousTime = currentTime; |
||||||
|
|
||||||
|
if (currentValue === null) { |
||||||
|
if (ignoreNulls) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
if (nullAsZero) { |
||||||
|
currentValue = 0; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (currentValue !== null) { |
||||||
|
if (_.isNumber(currentValue)) { |
||||||
|
this.stats.total += currentValue; |
||||||
|
this.allIsNull = false; |
||||||
|
nonNulls++; |
||||||
|
} |
||||||
|
|
||||||
|
if (currentValue > this.stats.max) { |
||||||
|
this.stats.max = currentValue; |
||||||
|
} |
||||||
|
|
||||||
|
if (currentValue < this.stats.min) { |
||||||
|
this.stats.min = currentValue; |
||||||
|
} |
||||||
|
|
||||||
|
if (this.stats.first === null) { |
||||||
|
this.stats.first = currentValue; |
||||||
|
} else { |
||||||
|
if (previousValue > currentValue) { |
||||||
|
// counter reset
|
||||||
|
previousDeltaUp = false; |
||||||
|
if (i === this.datapoints.length - 1) { |
||||||
|
// reset on last
|
||||||
|
this.stats.delta += currentValue; |
||||||
|
} |
||||||
|
} else { |
||||||
|
if (previousDeltaUp) { |
||||||
|
this.stats.delta += currentValue - previousValue; // normal increment
|
||||||
|
} else { |
||||||
|
this.stats.delta += currentValue; // account for counter reset
|
||||||
|
} |
||||||
|
previousDeltaUp = true; |
||||||
|
} |
||||||
|
} |
||||||
|
previousValue = currentValue; |
||||||
|
|
||||||
|
if (currentValue < this.stats.logmin && currentValue > 0) { |
||||||
|
this.stats.logmin = currentValue; |
||||||
|
} |
||||||
|
|
||||||
|
if (currentValue !== 0) { |
||||||
|
this.allIsZero = false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
result.push([currentTime, currentValue]); |
||||||
|
} |
||||||
|
|
||||||
|
if (this.stats.max === -Number.MAX_VALUE) { |
||||||
|
this.stats.max = null; |
||||||
|
} |
||||||
|
if (this.stats.min === Number.MAX_VALUE) { |
||||||
|
this.stats.min = null; |
||||||
|
} |
||||||
|
|
||||||
|
if (result.length && !this.allIsNull) { |
||||||
|
this.stats.avg = this.stats.total / nonNulls; |
||||||
|
this.stats.current = result[result.length - 1][1]; |
||||||
|
if (this.stats.current === null && result.length > 1) { |
||||||
|
this.stats.current = result[result.length - 2][1]; |
||||||
|
} |
||||||
|
} |
||||||
|
if (this.stats.max !== null && this.stats.min !== null) { |
||||||
|
this.stats.range = this.stats.max - this.stats.min; |
||||||
|
} |
||||||
|
if (this.stats.current !== null && this.stats.first !== null) { |
||||||
|
this.stats.diff = this.stats.current - this.stats.first; |
||||||
|
} |
||||||
|
|
||||||
|
this.stats.count = result.length; |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
updateLegendValues(formater, decimals, scaledDecimals) { |
||||||
|
this.valueFormater = formater; |
||||||
|
this.decimals = decimals; |
||||||
|
this.scaledDecimals = scaledDecimals; |
||||||
|
} |
||||||
|
|
||||||
|
formatValue(value) { |
||||||
|
if (!_.isFinite(value)) { |
||||||
|
value = null; // Prevent NaN formatting
|
||||||
|
} |
||||||
|
return this.valueFormater(value, this.decimals, this.scaledDecimals); |
||||||
|
} |
||||||
|
|
||||||
|
isMsResolutionNeeded() { |
||||||
|
for (var i = 0; i < this.datapoints.length; i++) { |
||||||
|
if (this.datapoints[i][1] !== null) { |
||||||
|
var timestamp = this.datapoints[i][1].toString(); |
||||||
|
if (timestamp.length === 13 && timestamp % 1000 !== 0) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
hideFromLegend(options) { |
||||||
|
if (options.hideEmpty && this.allIsNull) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
// ignore series excluded via override
|
||||||
|
if (!this.legend) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
// ignore zero series
|
||||||
|
if (options.hideZero && this.allIsZero) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue