mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
FieldConfig: set min/max automatically for gauge (#21073)
This commit is contained in:
parent
e27ab89aed
commit
6de4933a4a
@ -79,6 +79,7 @@ export interface GetFieldDisplayValuesOptions {
|
|||||||
replaceVariables: InterpolateFunction;
|
replaceVariables: InterpolateFunction;
|
||||||
sparkline?: boolean; // Calculate the sparkline
|
sparkline?: boolean; // Calculate the sparkline
|
||||||
theme: GrafanaTheme;
|
theme: GrafanaTheme;
|
||||||
|
autoMinMax?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DEFAULT_FIELD_DISPLAY_VALUES_LIMIT = 25;
|
export const DEFAULT_FIELD_DISPLAY_VALUES_LIMIT = 25;
|
||||||
@ -90,7 +91,7 @@ export const getFieldDisplayValues = (options: GetFieldDisplayValuesOptions): Fi
|
|||||||
const values: FieldDisplay[] = [];
|
const values: FieldDisplay[] = [];
|
||||||
|
|
||||||
if (options.data) {
|
if (options.data) {
|
||||||
const data = applyFieldOverrides(options.data, fieldOptions, replaceVariables, options.theme);
|
const data = applyFieldOverrides(options);
|
||||||
|
|
||||||
let hitLimit = false;
|
let hitLimit = false;
|
||||||
const limit = fieldOptions.limit ? fieldOptions.limit : DEFAULT_FIELD_DISPLAY_VALUES_LIMIT;
|
const limit = fieldOptions.limit ? fieldOptions.limit : DEFAULT_FIELD_DISPLAY_VALUES_LIMIT;
|
||||||
|
@ -2,8 +2,35 @@ import { setFieldConfigDefaults, findNumericFieldMinMax, applyFieldOverrides } f
|
|||||||
import { MutableDataFrame } from '../dataframe';
|
import { MutableDataFrame } from '../dataframe';
|
||||||
import { FieldConfig, FieldConfigSource, InterpolateFunction, GrafanaTheme } from '../types';
|
import { FieldConfig, FieldConfigSource, InterpolateFunction, GrafanaTheme } from '../types';
|
||||||
import { FieldMatcherID } from '../transformations';
|
import { FieldMatcherID } from '../transformations';
|
||||||
|
import { FieldDisplayOptions } from './fieldDisplay';
|
||||||
|
|
||||||
describe('FieldOverrides', () => {
|
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', () => {
|
it('will merge FieldConfig with default values', () => {
|
||||||
const field: FieldConfig = {
|
const field: FieldConfig = {
|
||||||
min: 0,
|
min: 0,
|
||||||
@ -22,46 +49,20 @@ describe('FieldOverrides', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('will apply field overrides', () => {
|
it('will apply field overrides', () => {
|
||||||
const f0 = new MutableDataFrame();
|
const data = applyFieldOverrides({
|
||||||
f0.add({ title: 'AAA', value: 100, value2: 1234 }, true);
|
data: [f0], // the frame
|
||||||
f0.add({ title: 'BBB', value: -20 }, true);
|
fieldOptions: src as FieldDisplayOptions, // defaults + overrides
|
||||||
f0.add({ title: 'CCC', value: 200, value2: 1000 }, true);
|
replaceVariables: (undefined as any) as InterpolateFunction,
|
||||||
expect(f0.length).toEqual(3);
|
theme: (undefined as any) as GrafanaTheme,
|
||||||
|
})[0];
|
||||||
// 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 valueColumn = data.fields[1];
|
const valueColumn = data.fields[1];
|
||||||
const config = valueColumn.config;
|
const config = valueColumn.config;
|
||||||
|
|
||||||
// Keep max from the original setting
|
// Keep max from the original setting
|
||||||
expect(config.max).toEqual(0);
|
expect(config.max).toEqual(0);
|
||||||
|
|
||||||
// Automatically pick the min value
|
// Don't Automatically pick the min value
|
||||||
expect(config.min).toEqual(-20);
|
expect(config.min).toEqual(undefined);
|
||||||
|
|
||||||
// The default value applied
|
// The default value applied
|
||||||
expect(config.unit).toEqual('xyz');
|
expect(config.unit).toEqual('xyz');
|
||||||
@ -72,6 +73,24 @@ describe('FieldOverrides', () => {
|
|||||||
// The override applied
|
// The override applied
|
||||||
expect(config.decimals).toEqual(1);
|
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', () => {
|
describe('Global MinMax', () => {
|
||||||
|
@ -1,19 +1,11 @@
|
|||||||
import set from 'lodash/set';
|
import set from 'lodash/set';
|
||||||
import {
|
import { DynamicConfigValue, FieldConfig, InterpolateFunction, DataFrame, Field, FieldType } from '../types';
|
||||||
DynamicConfigValue,
|
|
||||||
FieldConfigSource,
|
|
||||||
FieldConfig,
|
|
||||||
InterpolateFunction,
|
|
||||||
GrafanaTheme,
|
|
||||||
DataFrame,
|
|
||||||
Field,
|
|
||||||
FieldType,
|
|
||||||
} from '../types';
|
|
||||||
import { fieldMatchers, ReducerID, reduceField } from '../transformations';
|
import { fieldMatchers, ReducerID, reduceField } from '../transformations';
|
||||||
import { FieldMatcher } from '../types/transformations';
|
import { FieldMatcher } from '../types/transformations';
|
||||||
import isNumber from 'lodash/isNumber';
|
import isNumber from 'lodash/isNumber';
|
||||||
import toNumber from 'lodash/toNumber';
|
import toNumber from 'lodash/toNumber';
|
||||||
import { getDisplayProcessor } from './displayProcessor';
|
import { getDisplayProcessor } from './displayProcessor';
|
||||||
|
import { GetFieldDisplayValuesOptions } from './fieldDisplay';
|
||||||
|
|
||||||
interface OverrideProps {
|
interface OverrideProps {
|
||||||
match: FieldMatcher;
|
match: FieldMatcher;
|
||||||
@ -50,15 +42,13 @@ export function findNumericFieldMinMax(data: DataFrame[]): GlobalMinMax {
|
|||||||
/**
|
/**
|
||||||
* Return a copy of the DataFrame with all rules applied
|
* Return a copy of the DataFrame with all rules applied
|
||||||
*/
|
*/
|
||||||
export function applyFieldOverrides(
|
export function applyFieldOverrides(options: GetFieldDisplayValuesOptions): DataFrame[] {
|
||||||
data: DataFrame[],
|
if (!options.data) {
|
||||||
source: FieldConfigSource,
|
return [];
|
||||||
replaceVariables: InterpolateFunction,
|
}
|
||||||
theme: GrafanaTheme,
|
const source = options.fieldOptions;
|
||||||
isUtc?: boolean
|
|
||||||
): DataFrame[] {
|
|
||||||
if (!source) {
|
if (!source) {
|
||||||
return data;
|
return options.data;
|
||||||
}
|
}
|
||||||
let range: GlobalMinMax | undefined = undefined;
|
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;
|
let name = frame.name;
|
||||||
if (!name) {
|
if (!name) {
|
||||||
name = `Series[${index}]`;
|
name = `Series[${index}]`;
|
||||||
@ -98,17 +88,17 @@ export function applyFieldOverrides(
|
|||||||
config,
|
config,
|
||||||
field,
|
field,
|
||||||
data: frame,
|
data: frame,
|
||||||
replaceVariables,
|
replaceVariables: options.replaceVariables,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the Min/Max value automatically
|
// 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 (!isNumber(config.min) || !isNumber(config.max)) {
|
||||||
if (!range) {
|
if (!range) {
|
||||||
range = findNumericFieldMinMax(data);
|
range = findNumericFieldMinMax(options.data!); // Global value
|
||||||
}
|
}
|
||||||
if (!isNumber(config.min)) {
|
if (!isNumber(config.min)) {
|
||||||
config.min = range.min;
|
config.min = range.min;
|
||||||
@ -129,8 +119,7 @@ export function applyFieldOverrides(
|
|||||||
processor: getDisplayProcessor({
|
processor: getDisplayProcessor({
|
||||||
type: field.type,
|
type: field.type,
|
||||||
config: config,
|
config: config,
|
||||||
theme,
|
theme: options.theme,
|
||||||
isUtc,
|
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -111,6 +111,7 @@ export const FieldPropertiesEditor: React.FC<Props> = ({ value, onChange, showMi
|
|||||||
onChange={onMinChange}
|
onChange={onMinChange}
|
||||||
onBlur={commitChanges}
|
onBlur={commitChanges}
|
||||||
value={min}
|
value={min}
|
||||||
|
placeholder="Auto"
|
||||||
type="number"
|
type="number"
|
||||||
/>
|
/>
|
||||||
<FormField
|
<FormField
|
||||||
@ -120,6 +121,7 @@ export const FieldPropertiesEditor: React.FC<Props> = ({ value, onChange, showMi
|
|||||||
onBlur={commitChanges}
|
onBlur={commitChanges}
|
||||||
value={max}
|
value={max}
|
||||||
type="number"
|
type="number"
|
||||||
|
placeholder="Auto"
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
@ -57,6 +57,7 @@ export class BarGaugePanel extends PureComponent<PanelProps<BarGaugeOptions>> {
|
|||||||
replaceVariables,
|
replaceVariables,
|
||||||
theme: config.theme,
|
theme: config.theme,
|
||||||
data: data.series,
|
data: data.series,
|
||||||
|
autoMinMax: true,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -48,6 +48,7 @@ export class GaugePanel extends PureComponent<PanelProps<GaugeOptions>> {
|
|||||||
replaceVariables,
|
replaceVariables,
|
||||||
theme: config.theme,
|
theme: config.theme,
|
||||||
data: data.series,
|
data: data.series,
|
||||||
|
autoMinMax: true,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -27,8 +27,6 @@ export const standardFieldDisplayOptions: FieldDisplayOptions = {
|
|||||||
values: false,
|
values: false,
|
||||||
calcs: [ReducerID.mean],
|
calcs: [ReducerID.mean],
|
||||||
defaults: {
|
defaults: {
|
||||||
min: 0,
|
|
||||||
max: 100,
|
|
||||||
thresholds: [
|
thresholds: [
|
||||||
{ value: -Infinity, color: 'green' },
|
{ value: -Infinity, color: 'green' },
|
||||||
{ value: 80, color: 'red' }, // 80%
|
{ value: 80, color: 'red' }, // 80%
|
||||||
|
Loading…
Reference in New Issue
Block a user