mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
TimeSeries: Use graph min/max for percentage threshold (#38528)
* TimeSeries: Use graph min/max as baseis for percentage threshold calculation. * respect hard and soft axis limits for % threshold steps * revert state-timeline changes * enable by-threshold coloring in histogram and barchart * revert yMin Co-authored-by: Leon Sorokin <leeoniya@gmail.com>
This commit is contained in:
parent
96557ecadc
commit
b248c119ef
@ -236,6 +236,10 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<{ sync: DashboardCursor
|
||||
show: !customConfig.hideFrom?.viz,
|
||||
gradientMode: customConfig.gradientMode,
|
||||
thresholds: config.thresholds,
|
||||
hardMin: field.config.min,
|
||||
hardMax: field.config.max,
|
||||
softMin: customConfig.axisSoftMin,
|
||||
softMax: customConfig.axisSoftMax,
|
||||
// The following properties are not used in the uPlot config, but are utilized as transport for legend config
|
||||
dataFrameFieldIndex: field.state?.origin,
|
||||
});
|
||||
@ -249,6 +253,10 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<{ sync: DashboardCursor
|
||||
thresholds: config.thresholds,
|
||||
scaleKey,
|
||||
theme,
|
||||
hardMin: field.config.min,
|
||||
hardMax: field.config.max,
|
||||
softMin: customConfig.axisSoftMin,
|
||||
softMax: customConfig.axisSoftMax,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -26,10 +26,15 @@ export interface SeriesProps extends LineConfig, BarConfig, FillConfig, PointsCo
|
||||
scaleKey: string;
|
||||
pxAlign?: boolean;
|
||||
gradientMode?: GraphGradientMode;
|
||||
|
||||
/** Used when gradientMode is set to Scheme */
|
||||
thresholds?: ThresholdsConfig;
|
||||
/** Used when gradientMode is set to Scheme */
|
||||
colorMode?: FieldColorMode;
|
||||
hardMin?: number | null;
|
||||
hardMax?: number | null;
|
||||
softMin?: number | null;
|
||||
softMax?: number | null;
|
||||
|
||||
drawStyle?: GraphDrawStyle;
|
||||
pathBuilder?: Series.PathBuilder;
|
||||
pointsFilter?: Series.Points.Filter;
|
||||
@ -138,17 +143,29 @@ export class UPlotSeriesBuilder extends PlotConfigBuilder<SeriesProps, Series> {
|
||||
}
|
||||
|
||||
private getLineColor(): Series.Stroke {
|
||||
const { lineColor, gradientMode, colorMode, thresholds, theme } = this.props;
|
||||
const { lineColor, gradientMode, colorMode, thresholds, theme, hardMin, hardMax, softMin, softMax } = this.props;
|
||||
|
||||
if (gradientMode === GraphGradientMode.Scheme && colorMode?.id !== FieldColorModeId.Fixed) {
|
||||
return getScaleGradientFn(1, theme, colorMode, thresholds);
|
||||
return getScaleGradientFn(1, theme, colorMode, thresholds, hardMin, hardMax, softMin, softMax);
|
||||
}
|
||||
|
||||
return lineColor ?? FALLBACK_COLOR;
|
||||
}
|
||||
|
||||
private getFill(): Series.Fill | undefined {
|
||||
const { lineColor, fillColor, gradientMode, fillOpacity, colorMode, thresholds, theme } = this.props;
|
||||
const {
|
||||
lineColor,
|
||||
fillColor,
|
||||
gradientMode,
|
||||
fillOpacity,
|
||||
colorMode,
|
||||
thresholds,
|
||||
theme,
|
||||
hardMin,
|
||||
hardMax,
|
||||
softMin,
|
||||
softMax,
|
||||
} = this.props;
|
||||
|
||||
if (fillColor) {
|
||||
return fillColor;
|
||||
@ -164,7 +181,7 @@ export class UPlotSeriesBuilder extends PlotConfigBuilder<SeriesProps, Series> {
|
||||
return getHueGradientFn((fillColor ?? lineColor)!, opacityPercent, theme);
|
||||
case GraphGradientMode.Scheme:
|
||||
if (colorMode?.id !== FieldColorModeId.Fixed) {
|
||||
return getScaleGradientFn(opacityPercent, theme, colorMode, thresholds);
|
||||
return getScaleGradientFn(opacityPercent, theme, colorMode, thresholds, hardMin, hardMax, softMin, softMax);
|
||||
}
|
||||
// intentional fall-through to handle Scheme with Fixed color
|
||||
default:
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { GrafanaTheme2, ThresholdsConfig, ThresholdsMode } from '@grafana/data';
|
||||
import { GraphThresholdsStyleConfig, GraphTresholdsStyleMode } from '@grafana/schema';
|
||||
import { getDataRange, GradientDirection, scaleGradient } from './gradientFills';
|
||||
import { getThresholdRange, GradientDirection, scaleGradient } from './gradientFills';
|
||||
import tinycolor from 'tinycolor2';
|
||||
|
||||
export interface UPlotThresholdOptions {
|
||||
@ -8,23 +8,27 @@ export interface UPlotThresholdOptions {
|
||||
thresholds: ThresholdsConfig;
|
||||
config: GraphThresholdsStyleConfig;
|
||||
theme: GrafanaTheme2;
|
||||
hardMin?: number | null;
|
||||
hardMax?: number | null;
|
||||
softMin?: number | null;
|
||||
softMax?: number | null;
|
||||
}
|
||||
|
||||
export function getThresholdsDrawHook(options: UPlotThresholdOptions) {
|
||||
return (u: uPlot) => {
|
||||
const ctx = u.ctx;
|
||||
const { scaleKey, thresholds, theme, config } = options;
|
||||
const { scaleKey, thresholds, theme, config, hardMin, hardMax, softMin, softMax } = options;
|
||||
const { min: xMin, max: xMax } = u.scales.x;
|
||||
const { min: yMin, max: yMax } = u.scales[scaleKey];
|
||||
|
||||
if (xMin === undefined || xMax === undefined || yMin === undefined || yMax === undefined) {
|
||||
if (xMin == null || xMax == null || yMin == null || yMax == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
let { steps, mode } = thresholds;
|
||||
|
||||
if (mode === ThresholdsMode.Percentage) {
|
||||
let [min, max] = getDataRange(u, scaleKey);
|
||||
let [min, max] = getThresholdRange(u, scaleKey, hardMin, hardMax, softMin, softMax);
|
||||
let range = max - min;
|
||||
|
||||
steps = steps.map((step) => ({
|
||||
|
@ -172,11 +172,36 @@ export function getDataRange(plot: uPlot, scaleKey: string) {
|
||||
return [min, max];
|
||||
}
|
||||
|
||||
export function getThresholdRange(
|
||||
u: uPlot,
|
||||
scaleKey: string,
|
||||
hardMin?: number | null,
|
||||
hardMax?: number | null,
|
||||
softMin?: number | null,
|
||||
softMax?: number | null
|
||||
) {
|
||||
let min = hardMin ?? softMin ?? null;
|
||||
let max = hardMax ?? softMax ?? null;
|
||||
|
||||
if (min == null || max == null) {
|
||||
let [dataMin, dataMax] = getDataRange(u, scaleKey);
|
||||
|
||||
min = min ?? dataMin ?? 0;
|
||||
max = max ?? dataMax ?? 100;
|
||||
}
|
||||
|
||||
return [min, max];
|
||||
}
|
||||
|
||||
export function getScaleGradientFn(
|
||||
opacity: number,
|
||||
theme: GrafanaTheme2,
|
||||
colorMode?: FieldColorMode,
|
||||
thresholds?: ThresholdsConfig
|
||||
thresholds?: ThresholdsConfig,
|
||||
hardMin?: number | null,
|
||||
hardMax?: number | null,
|
||||
softMin?: number | null,
|
||||
softMax?: number | null
|
||||
): (self: uPlot, seriesIdx: number) => CanvasGradient | string {
|
||||
if (!colorMode) {
|
||||
throw Error('Missing colorMode required for color scheme gradients');
|
||||
@ -199,7 +224,7 @@ export function getScaleGradientFn(
|
||||
);
|
||||
gradient = scaleGradient(plot, scaleKey, GradientDirection.Up, valueStops, true);
|
||||
} else {
|
||||
const [min, max] = getDataRange(plot, scaleKey);
|
||||
const [min, max] = getThresholdRange(plot, scaleKey, hardMin, hardMax, softMin, softMax);
|
||||
const range = max - min;
|
||||
const valueStops = thresholds.steps.map(
|
||||
(step) =>
|
||||
@ -212,7 +237,7 @@ export function getScaleGradientFn(
|
||||
}
|
||||
} else if (colorMode.getColors) {
|
||||
const colors = colorMode.getColors(theme);
|
||||
const [min, max] = getDataRange(plot, scaleKey);
|
||||
const [min, max] = getThresholdRange(plot, scaleKey, hardMin, hardMax, softMin, softMax);
|
||||
const range = max - min;
|
||||
const valueStops = colors.map(
|
||||
(color, i) =>
|
||||
|
@ -17,7 +17,7 @@ export const plugin = new PanelPlugin<BarChartOptions, BarChartFieldConfig>(BarC
|
||||
standardOptions: {
|
||||
[FieldConfigProperty.Color]: {
|
||||
settings: {
|
||||
byValueSupport: false,
|
||||
byValueSupport: true,
|
||||
},
|
||||
defaultValue: {
|
||||
mode: FieldColorModeId.PaletteClassic,
|
||||
|
@ -134,6 +134,10 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<BarChartOptions> = ({
|
||||
show: !customConfig.hideFrom?.viz,
|
||||
gradientMode: customConfig.gradientMode,
|
||||
thresholds: field.config.thresholds,
|
||||
hardMin: field.config.min,
|
||||
hardMax: field.config.max,
|
||||
softMin: customConfig.axisSoftMin,
|
||||
softMax: customConfig.axisSoftMax,
|
||||
|
||||
// The following properties are not used in the uPlot config, but are utilized as transport for legend config
|
||||
dataFrameFieldIndex: {
|
||||
|
@ -182,6 +182,11 @@ const prepConfig = (frame: DataFrame, theme: GrafanaTheme2) => {
|
||||
gradientMode: customConfig.gradientMode,
|
||||
thresholds: field.config.thresholds,
|
||||
|
||||
hardMin: field.config.min,
|
||||
hardMax: field.config.max,
|
||||
softMin: customConfig.axisSoftMin,
|
||||
softMax: customConfig.axisSoftMax,
|
||||
|
||||
// The following properties are not used in the uPlot config, but are utilized as transport for legend config
|
||||
dataFrameFieldIndex: {
|
||||
fieldIndex: i,
|
||||
|
@ -52,7 +52,7 @@ export const plugin = new PanelPlugin<PanelOptions, PanelFieldConfig>(HistogramP
|
||||
standardOptions: {
|
||||
[FieldConfigProperty.Color]: {
|
||||
settings: {
|
||||
byValueSupport: false,
|
||||
byValueSupport: true,
|
||||
},
|
||||
defaultValue: {
|
||||
mode: FieldColorModeId.PaletteClassic,
|
||||
|
Loading…
Reference in New Issue
Block a user