mirror of https://github.com/grafana/grafana
Merge pull request #16173 from ryantxu/no-process-timeseries
remove TimeSeriesStats and processTimeSeriespull/16179/head
commit
5572323581
@ -1,200 +0,0 @@ |
||||
// Libraries
|
||||
import isNumber from 'lodash/isNumber'; |
||||
|
||||
import { colors } from './colors'; |
||||
|
||||
// Types
|
||||
import { getFlotPairs } from './flotPairs'; |
||||
import { TimeSeriesVMs, NullValueMode, TimeSeriesValue, TableData } from '../types'; |
||||
|
||||
interface Options { |
||||
data: TableData[]; |
||||
xColumn?: number; // Time (or null to guess)
|
||||
yColumn?: number; // Value (or null to guess)
|
||||
nullValueMode: NullValueMode; |
||||
} |
||||
|
||||
// NOTE: this should move to processTableData.ts
|
||||
// I left it as is so the merge changes are more clear.
|
||||
export function processTimeSeries({ data, xColumn, yColumn, nullValueMode }: Options): TimeSeriesVMs { |
||||
const vmSeries = data.map((item, index) => { |
||||
if (!isNumber(xColumn)) { |
||||
xColumn = 1; // Default timeseries colum. TODO, find first time field!
|
||||
} |
||||
if (!isNumber(yColumn)) { |
||||
yColumn = 0; // TODO, find first non-time field
|
||||
} |
||||
|
||||
// TODO? either % or throw error?
|
||||
if (xColumn >= item.columns.length) { |
||||
throw new Error('invalid colum: ' + xColumn); |
||||
} |
||||
if (yColumn >= item.columns.length) { |
||||
throw new Error('invalid colum: ' + yColumn); |
||||
} |
||||
|
||||
const colorIndex = index % colors.length; |
||||
const label = item.columns[yColumn].text; |
||||
|
||||
// Use external calculator just to make sure it works :)
|
||||
const result = getFlotPairs({ |
||||
rows: item.rows, |
||||
xIndex: xColumn, |
||||
yIndex: yColumn, |
||||
nullValueMode, |
||||
}); |
||||
|
||||
// stat defaults
|
||||
let total = 0; |
||||
let max: TimeSeriesValue = -Number.MAX_VALUE; |
||||
let min: TimeSeriesValue = Number.MAX_VALUE; |
||||
let logmin = Number.MAX_VALUE; |
||||
let avg: TimeSeriesValue = null; |
||||
let current: TimeSeriesValue = null; |
||||
let first: TimeSeriesValue = null; |
||||
let delta: TimeSeriesValue = 0; |
||||
let diff: TimeSeriesValue = null; |
||||
let range: TimeSeriesValue = null; |
||||
let timeStep = Number.MAX_VALUE; |
||||
let allIsNull = true; |
||||
let allIsZero = true; |
||||
|
||||
const ignoreNulls = nullValueMode === NullValueMode.Ignore; |
||||
const nullAsZero = nullValueMode === NullValueMode.AsZero; |
||||
|
||||
let currentTime: TimeSeriesValue = null; |
||||
let currentValue: TimeSeriesValue = null; |
||||
let nonNulls = 0; |
||||
let previousTime: TimeSeriesValue = null; |
||||
let previousValue = 0; |
||||
let previousDeltaUp = true; |
||||
|
||||
for (let i = 0; i < item.rows.length; i++) { |
||||
currentValue = item.rows[i][yColumn]; |
||||
currentTime = item.rows[i][xColumn]; |
||||
|
||||
if (typeof currentTime !== 'number') { |
||||
continue; |
||||
} |
||||
|
||||
if (currentValue !== null && typeof currentValue !== 'number') { |
||||
throw { message: 'Time series contains non number values' }; |
||||
} |
||||
|
||||
// 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 !== null && currentTime !== null) { |
||||
const currentStep = currentTime - previousTime; |
||||
if (currentStep < timeStep) { |
||||
timeStep = currentStep; |
||||
} |
||||
} |
||||
|
||||
previousTime = currentTime; |
||||
|
||||
if (currentValue === null) { |
||||
if (ignoreNulls) { |
||||
continue; |
||||
} |
||||
if (nullAsZero) { |
||||
currentValue = 0; |
||||
} |
||||
} |
||||
|
||||
if (currentValue !== null) { |
||||
if (isNumber(currentValue)) { |
||||
total += currentValue; |
||||
allIsNull = false; |
||||
nonNulls++; |
||||
} |
||||
|
||||
if (currentValue > max) { |
||||
max = currentValue; |
||||
} |
||||
|
||||
if (currentValue < min) { |
||||
min = currentValue; |
||||
} |
||||
|
||||
if (first === null) { |
||||
first = currentValue; |
||||
} else { |
||||
if (previousValue > currentValue) { |
||||
// counter reset
|
||||
previousDeltaUp = false; |
||||
if (i === item.rows.length - 1) { |
||||
// reset on last
|
||||
delta += currentValue; |
||||
} |
||||
} else { |
||||
if (previousDeltaUp) { |
||||
delta += currentValue - previousValue; // normal increment
|
||||
} else { |
||||
delta += currentValue; // account for counter reset
|
||||
} |
||||
previousDeltaUp = true; |
||||
} |
||||
} |
||||
previousValue = currentValue; |
||||
|
||||
if (currentValue < logmin && currentValue > 0) { |
||||
logmin = currentValue; |
||||
} |
||||
|
||||
if (currentValue !== 0) { |
||||
allIsZero = false; |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (max === -Number.MAX_VALUE) { |
||||
max = null; |
||||
} |
||||
|
||||
if (min === Number.MAX_VALUE) { |
||||
min = null; |
||||
} |
||||
|
||||
if (result.length && !allIsNull) { |
||||
avg = total / nonNulls; |
||||
current = result[result.length - 1][1]; |
||||
if (current === null && result.length > 1) { |
||||
current = result[result.length - 2][1]; |
||||
} |
||||
} |
||||
|
||||
if (max !== null && min !== null) { |
||||
range = max - min; |
||||
} |
||||
|
||||
if (current !== null && first !== null) { |
||||
diff = current - first; |
||||
} |
||||
|
||||
const count = result.length; |
||||
|
||||
return { |
||||
data: result, |
||||
label: label, |
||||
color: colors[colorIndex], |
||||
allIsZero, |
||||
allIsNull, |
||||
stats: { |
||||
total, |
||||
min, |
||||
max, |
||||
current, |
||||
logmin, |
||||
avg, |
||||
diff, |
||||
delta, |
||||
timeStep, |
||||
range, |
||||
count, |
||||
first, |
||||
}, |
||||
}; |
||||
}); |
||||
|
||||
return vmSeries; |
||||
} |
Loading…
Reference in new issue