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