FieldConfig: set min/max automatically for gauge (#21073)

This commit is contained in:
Ryan McKinley 2019-12-13 08:36:49 -08:00 committed by GitHub
parent e27ab89aed
commit 6de4933a4a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 72 additions and 61 deletions

View File

@ -79,6 +79,7 @@ export interface GetFieldDisplayValuesOptions {
replaceVariables: InterpolateFunction;
sparkline?: boolean; // Calculate the sparkline
theme: GrafanaTheme;
autoMinMax?: boolean;
}
export const DEFAULT_FIELD_DISPLAY_VALUES_LIMIT = 25;
@ -90,7 +91,7 @@ export const getFieldDisplayValues = (options: GetFieldDisplayValuesOptions): Fi
const values: FieldDisplay[] = [];
if (options.data) {
const data = applyFieldOverrides(options.data, fieldOptions, replaceVariables, options.theme);
const data = applyFieldOverrides(options);
let hitLimit = false;
const limit = fieldOptions.limit ? fieldOptions.limit : DEFAULT_FIELD_DISPLAY_VALUES_LIMIT;

View File

@ -2,8 +2,35 @@ import { setFieldConfigDefaults, findNumericFieldMinMax, applyFieldOverrides } f
import { MutableDataFrame } from '../dataframe';
import { FieldConfig, FieldConfigSource, InterpolateFunction, GrafanaTheme } from '../types';
import { FieldMatcherID } from '../transformations';
import { FieldDisplayOptions } from './fieldDisplay';
describe('FieldOverrides', () => {
const f0 = new MutableDataFrame();
f0.add({ title: 'AAA', value: 100, value2: 1234 }, true);
f0.add({ title: 'BBB', value: -20 }, true);
f0.add({ title: 'CCC', value: 200, value2: 1000 }, true);
expect(f0.length).toEqual(3);
// Hardcode the max value
f0.fields[1].config.max = 0;
f0.fields[1].config.decimals = 6;
const src: FieldConfigSource = {
defaults: {
unit: 'xyz',
decimals: 2,
},
overrides: [
{
matcher: { id: FieldMatcherID.numeric },
properties: [
{ path: 'decimals', value: 1 }, // Numeric
{ path: 'title', value: 'Kittens' }, // Text
],
},
],
};
it('will merge FieldConfig with default values', () => {
const field: FieldConfig = {
min: 0,
@ -22,46 +49,20 @@ describe('FieldOverrides', () => {
});
it('will apply field overrides', () => {
const f0 = new MutableDataFrame();
f0.add({ title: 'AAA', value: 100, value2: 1234 }, true);
f0.add({ title: 'BBB', value: -20 }, true);
f0.add({ title: 'CCC', value: 200, value2: 1000 }, true);
expect(f0.length).toEqual(3);
// Hardcode the max value
f0.fields[1].config.max = 0;
f0.fields[1].config.decimals = 6;
const src: FieldConfigSource = {
defaults: {
unit: 'xyz',
decimals: 2,
},
overrides: [
{
matcher: { id: FieldMatcherID.numeric },
properties: [
{ path: 'decimals', value: 1 }, // Numeric
{ path: 'title', value: 'Kittens' }, // Text
],
},
],
};
const data = applyFieldOverrides(
[f0], // the frame
src, // defaults + overrides
(undefined as any) as InterpolateFunction,
(undefined as any) as GrafanaTheme
)[0];
const data = applyFieldOverrides({
data: [f0], // the frame
fieldOptions: src as FieldDisplayOptions, // defaults + overrides
replaceVariables: (undefined as any) as InterpolateFunction,
theme: (undefined as any) as GrafanaTheme,
})[0];
const valueColumn = data.fields[1];
const config = valueColumn.config;
// Keep max from the original setting
expect(config.max).toEqual(0);
// Automatically pick the min value
expect(config.min).toEqual(-20);
// Don't Automatically pick the min value
expect(config.min).toEqual(undefined);
// The default value applied
expect(config.unit).toEqual('xyz');
@ -72,6 +73,24 @@ describe('FieldOverrides', () => {
// The override applied
expect(config.decimals).toEqual(1);
});
it('will apply set min/max when asked', () => {
const data = applyFieldOverrides({
data: [f0], // the frame
fieldOptions: src as FieldDisplayOptions, // defaults + overrides
replaceVariables: (undefined as any) as InterpolateFunction,
theme: (undefined as any) as GrafanaTheme,
autoMinMax: true,
})[0];
const valueColumn = data.fields[1];
const config = valueColumn.config;
// Keep max from the original setting
expect(config.max).toEqual(0);
// Don't Automatically pick the min value
expect(config.min).toEqual(-20);
});
});
describe('Global MinMax', () => {

View File

@ -1,19 +1,11 @@
import set from 'lodash/set';
import {
DynamicConfigValue,
FieldConfigSource,
FieldConfig,
InterpolateFunction,
GrafanaTheme,
DataFrame,
Field,
FieldType,
} from '../types';
import { DynamicConfigValue, FieldConfig, InterpolateFunction, DataFrame, Field, FieldType } from '../types';
import { fieldMatchers, ReducerID, reduceField } from '../transformations';
import { FieldMatcher } from '../types/transformations';
import isNumber from 'lodash/isNumber';
import toNumber from 'lodash/toNumber';
import { getDisplayProcessor } from './displayProcessor';
import { GetFieldDisplayValuesOptions } from './fieldDisplay';
interface OverrideProps {
match: FieldMatcher;
@ -50,15 +42,13 @@ export function findNumericFieldMinMax(data: DataFrame[]): GlobalMinMax {
/**
* Return a copy of the DataFrame with all rules applied
*/
export function applyFieldOverrides(
data: DataFrame[],
source: FieldConfigSource,
replaceVariables: InterpolateFunction,
theme: GrafanaTheme,
isUtc?: boolean
): DataFrame[] {
export function applyFieldOverrides(options: GetFieldDisplayValuesOptions): DataFrame[] {
if (!options.data) {
return [];
}
const source = options.fieldOptions;
if (!source) {
return data;
return options.data;
}
let range: GlobalMinMax | undefined = undefined;
@ -76,7 +66,7 @@ export function applyFieldOverrides(
}
}
return data.map((frame, index) => {
return options.data.map((frame, index) => {
let name = frame.name;
if (!name) {
name = `Series[${index}]`;
@ -98,17 +88,17 @@ export function applyFieldOverrides(
config,
field,
data: frame,
replaceVariables,
replaceVariables: options.replaceVariables,
});
}
}
}
// Set the Min/Max value automatically
if (field.type === FieldType.number) {
if (options.autoMinMax && field.type === FieldType.number) {
if (!isNumber(config.min) || !isNumber(config.max)) {
if (!range) {
range = findNumericFieldMinMax(data);
range = findNumericFieldMinMax(options.data!); // Global value
}
if (!isNumber(config.min)) {
config.min = range.min;
@ -129,8 +119,7 @@ export function applyFieldOverrides(
processor: getDisplayProcessor({
type: field.type,
config: config,
theme,
isUtc,
theme: options.theme,
}),
};
});

View File

@ -111,6 +111,7 @@ export const FieldPropertiesEditor: React.FC<Props> = ({ value, onChange, showMi
onChange={onMinChange}
onBlur={commitChanges}
value={min}
placeholder="Auto"
type="number"
/>
<FormField
@ -120,6 +121,7 @@ export const FieldPropertiesEditor: React.FC<Props> = ({ value, onChange, showMi
onBlur={commitChanges}
value={max}
type="number"
placeholder="Auto"
/>
</>
)}

View File

@ -57,6 +57,7 @@ export class BarGaugePanel extends PureComponent<PanelProps<BarGaugeOptions>> {
replaceVariables,
theme: config.theme,
data: data.series,
autoMinMax: true,
});
};

View File

@ -48,6 +48,7 @@ export class GaugePanel extends PureComponent<PanelProps<GaugeOptions>> {
replaceVariables,
theme: config.theme,
data: data.series,
autoMinMax: true,
});
};

View File

@ -27,8 +27,6 @@ export const standardFieldDisplayOptions: FieldDisplayOptions = {
values: false,
calcs: [ReducerID.mean],
defaults: {
min: 0,
max: 100,
thresholds: [
{ value: -Infinity, color: 'green' },
{ value: 80, color: 'red' }, // 80%