mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
StateTimeline: make sure we use result of applyNullInsertThreshold() (#50988)
Co-authored-by: Kyle Cunningham <kyle@codeincarnate.com>
This commit is contained in:
@@ -111,12 +111,14 @@ describe('nullInsertThreshold Transformer', () => {
|
||||
const result = applyNullInsertThreshold({
|
||||
frame: df,
|
||||
refFieldName: null,
|
||||
refFieldPseudoMin: 1,
|
||||
refFieldPseudoMin: -0.5,
|
||||
refFieldPseudoMax: 13,
|
||||
});
|
||||
|
||||
expect(result.fields[0].values.toArray()).toStrictEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]);
|
||||
expect(result.fields[0].values.toArray()).toStrictEqual([-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]);
|
||||
expect(result.fields[1].values.toArray()).toStrictEqual([
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
@@ -132,6 +134,8 @@ describe('nullInsertThreshold Transformer', () => {
|
||||
8,
|
||||
]);
|
||||
expect(result.fields[2].values.toArray()).toStrictEqual([
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
@@ -160,7 +164,7 @@ describe('nullInsertThreshold Transformer', () => {
|
||||
|
||||
const result = applyNullInsertThreshold({ frame: df, refFieldName: null, refFieldPseudoMax: 13 });
|
||||
|
||||
expect(result.fields[0].values.toArray()).toStrictEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]);
|
||||
expect(result.fields[0].values.toArray()).toStrictEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
|
||||
expect(result.fields[1].values.toArray()).toStrictEqual([
|
||||
4,
|
||||
null,
|
||||
@@ -174,7 +178,6 @@ describe('nullInsertThreshold Transformer', () => {
|
||||
8,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]);
|
||||
expect(result.fields[2].values.toArray()).toStrictEqual([
|
||||
'a',
|
||||
@@ -189,7 +192,6 @@ describe('nullInsertThreshold Transformer', () => {
|
||||
'c',
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]);
|
||||
|
||||
// should work for frames with 1 datapoint
|
||||
@@ -202,15 +204,32 @@ describe('nullInsertThreshold Transformer', () => {
|
||||
],
|
||||
});
|
||||
|
||||
// Max is 2 as opposed to the above 13 otherwise
|
||||
// Max is 2.5 as opposed to the above 13 otherwise
|
||||
// we get 12 nulls instead of the additional 1
|
||||
const result2 = applyNullInsertThreshold({ frame: df2, refFieldName: null, refFieldPseudoMax: 2 });
|
||||
const result2 = applyNullInsertThreshold({ frame: df2, refFieldName: null, refFieldPseudoMax: 2.5 });
|
||||
|
||||
expect(result2.fields[0].values.toArray()).toStrictEqual([1, 2]);
|
||||
expect(result2.fields[1].values.toArray()).toStrictEqual([1, null]);
|
||||
expect(result2.fields[2].values.toArray()).toStrictEqual(['a', null]);
|
||||
});
|
||||
|
||||
test('should not insert trailing null at end +interval when timeRange.to.valueOf() equals threshold', () => {
|
||||
const df = new MutableDataFrame({
|
||||
refId: 'A',
|
||||
fields: [
|
||||
{ name: 'Time', type: FieldType.time, config: { interval: 1 }, values: [1] },
|
||||
{ name: 'One', type: FieldType.number, values: [1] },
|
||||
{ name: 'Two', type: FieldType.string, values: ['a'] },
|
||||
],
|
||||
});
|
||||
|
||||
const result = applyNullInsertThreshold({ frame: df, refFieldName: null, refFieldPseudoMax: 2 });
|
||||
|
||||
expect(result.fields[0].values.toArray()).toStrictEqual([1]);
|
||||
expect(result.fields[1].values.toArray()).toStrictEqual([1]);
|
||||
expect(result.fields[2].values.toArray()).toStrictEqual(['a']);
|
||||
});
|
||||
|
||||
// TODO: make this work
|
||||
test.skip('should insert nulls at +threshold (when defined) instead of +interval', () => {
|
||||
const df = new MutableDataFrame({
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { ArrayVector, DataFrame, FieldType } from '@grafana/data';
|
||||
import { ArrayVector, DataFrame, FieldType, incrRoundDn } from '@grafana/data';
|
||||
|
||||
type InsertMode = (prev: number, next: number, threshold: number) => number;
|
||||
|
||||
@@ -76,10 +76,21 @@ export function applyNullInsertThreshold(opts: NullInsertOptions): DataFrame {
|
||||
return {
|
||||
...frame,
|
||||
length: filledFieldValues[0].length,
|
||||
fields: frame.fields.map((field, i) => ({
|
||||
...field,
|
||||
values: new ArrayVector(filledFieldValues[i]),
|
||||
})),
|
||||
fields: frame.fields.map((field, i) => {
|
||||
let f = {
|
||||
...field,
|
||||
values: new ArrayVector(filledFieldValues[i]),
|
||||
};
|
||||
|
||||
if (i === 0) {
|
||||
f.state = {
|
||||
...field.state,
|
||||
nullThresholdApplied: true,
|
||||
};
|
||||
}
|
||||
|
||||
return f;
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -101,24 +112,25 @@ function nullInsertThreshold(
|
||||
thorough: boolean
|
||||
) {
|
||||
const len = refValues.length;
|
||||
let prevValue: number = refValues[0];
|
||||
const refValuesNew: number[] = [];
|
||||
|
||||
// Continiuously add the threshold to the minimum value
|
||||
// While this is less than "prevValue" which is the lowest
|
||||
// time value in the sequence add in time frames
|
||||
if (refFieldPseudoMin != null) {
|
||||
let minValue = refFieldPseudoMin - threshold;
|
||||
// Continiuously subtract the threshold from the first data
|
||||
// point filling in insert values accordingly
|
||||
if (refFieldPseudoMin != null && refFieldPseudoMin < refValues[0]) {
|
||||
// this will be 0 or 1 threshold increment left of visible range
|
||||
let prevSlot = incrRoundDn(refFieldPseudoMin, threshold);
|
||||
|
||||
while (minValue < prevValue - threshold) {
|
||||
let nextValue = minValue + threshold;
|
||||
refValuesNew.push(getInsertValue(minValue, nextValue, threshold));
|
||||
minValue = nextValue;
|
||||
while (prevSlot < refValues[0]) {
|
||||
// (prevSlot - threshold) is used to simulate the previous 'real' data point, as getInsertValue expects
|
||||
refValuesNew.push(getInsertValue(prevSlot - threshold, prevSlot, threshold));
|
||||
prevSlot += threshold;
|
||||
}
|
||||
}
|
||||
|
||||
// Insert initial value
|
||||
refValuesNew.push(prevValue);
|
||||
refValuesNew.push(refValues[0]);
|
||||
|
||||
let prevValue: number = refValues[0];
|
||||
|
||||
// Fill nulls when a value is greater than
|
||||
// the threshold value
|
||||
@@ -141,8 +153,8 @@ function nullInsertThreshold(
|
||||
}
|
||||
|
||||
// At the end of the sequence
|
||||
if (refFieldPseudoMax != null) {
|
||||
while (prevValue + threshold <= refFieldPseudoMax) {
|
||||
if (refFieldPseudoMax != null && refFieldPseudoMax > prevValue) {
|
||||
while (prevValue + threshold < refFieldPseudoMax) {
|
||||
refValuesNew.push(getInsertValue(prevValue, refFieldPseudoMax, threshold));
|
||||
prevValue += threshold;
|
||||
}
|
||||
|
@@ -401,11 +401,9 @@ export function prepareTimelineFields(
|
||||
refFieldPseudoMax: timeRange.to.valueOf(),
|
||||
});
|
||||
|
||||
// Mark the field state as having a null threhold applied
|
||||
frame.fields[0].state = {
|
||||
...frame.fields[0].state,
|
||||
nullThresholdApplied: true,
|
||||
};
|
||||
if (nulledFrame !== frame) {
|
||||
changed = true;
|
||||
}
|
||||
|
||||
const fields: Field[] = [];
|
||||
for (let field of nullToValue(nulledFrame).fields) {
|
||||
|
Reference in New Issue
Block a user