mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-08 11:39:03 +08:00
[Fix]: threshold in alerts (#4074)
This commit is contained in:
parent
aad44a1037
commit
0b991331d7
@ -2,6 +2,7 @@ import { InfoCircleOutlined } from '@ant-design/icons';
|
||||
import Spinner from 'components/Spinner';
|
||||
import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder';
|
||||
import GridPanelSwitch from 'container/GridPanelSwitch';
|
||||
import { getFormatNameByOptionId } from 'container/NewWidget/RightContainer/alertFomatCategories';
|
||||
import { timePreferenceType } from 'container/NewWidget/RightContainer/timeItems';
|
||||
import { Time } from 'container/TopNav/DateTimeSelection/config';
|
||||
import { useGetQueryRange } from 'hooks/queryBuilder/useGetQueryRange';
|
||||
@ -19,7 +20,7 @@ import { EQueryType } from 'types/common/dashboard';
|
||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||
|
||||
import { ChartContainer, FailedMessageContainer } from './styles';
|
||||
import { covertIntoDataFormats } from './utils';
|
||||
import { getThresholdLabel } from './utils';
|
||||
|
||||
export interface ChartPreviewProps {
|
||||
name: string;
|
||||
@ -50,12 +51,6 @@ function ChartPreview({
|
||||
(state) => state.globalTime,
|
||||
);
|
||||
|
||||
const thresholdValue = covertIntoDataFormats({
|
||||
value: threshold,
|
||||
sourceUnit: alertDef?.condition.targetUnit,
|
||||
targetUnit: query?.unit,
|
||||
});
|
||||
|
||||
const canQuery = useMemo((): boolean => {
|
||||
if (!query || query == null) {
|
||||
return false;
|
||||
@ -110,6 +105,9 @@ function ChartPreview({
|
||||
|
||||
const isDarkMode = useIsDarkMode();
|
||||
|
||||
const optionName =
|
||||
getFormatNameByOptionId(alertDef?.condition.targetUnit || '') || '';
|
||||
|
||||
const options = useMemo(
|
||||
() =>
|
||||
getUPlotChartOptions({
|
||||
@ -124,10 +122,16 @@ function ChartPreview({
|
||||
keyIndex: 0,
|
||||
moveThreshold: (): void => {},
|
||||
selectedGraph: PANEL_TYPES.TIME_SERIES, // no impact
|
||||
thresholdValue,
|
||||
thresholdValue: threshold,
|
||||
thresholdLabel: `${t(
|
||||
'preview_chart_threshold_label',
|
||||
)} (y=${thresholdValue} ${query?.unit || ''})`,
|
||||
)} (y=${getThresholdLabel(
|
||||
optionName,
|
||||
threshold,
|
||||
alertDef?.condition.targetUnit,
|
||||
query?.unit,
|
||||
)})`,
|
||||
thresholdUnit: alertDef?.condition.targetUnit,
|
||||
},
|
||||
],
|
||||
}),
|
||||
@ -136,8 +140,10 @@ function ChartPreview({
|
||||
queryResponse?.data?.payload,
|
||||
containerDimensions,
|
||||
isDarkMode,
|
||||
threshold,
|
||||
t,
|
||||
thresholdValue,
|
||||
optionName,
|
||||
alertDef?.condition.targetUnit,
|
||||
],
|
||||
);
|
||||
|
||||
|
@ -51,6 +51,21 @@ export function covertIntoDataFormats({
|
||||
return Number.isNaN(result) ? 0 : result;
|
||||
}
|
||||
|
||||
export const getThresholdLabel = (
|
||||
optionName: string,
|
||||
value: number,
|
||||
unit?: string,
|
||||
yAxisUnit?: string,
|
||||
): string => {
|
||||
if (
|
||||
unit === MiscellaneousFormats.PercentUnit ||
|
||||
yAxisUnit === MiscellaneousFormats.PercentUnit
|
||||
) {
|
||||
return `${value * 100}%`;
|
||||
}
|
||||
return `${value} ${optionName}`;
|
||||
};
|
||||
|
||||
interface IUnit {
|
||||
value: number;
|
||||
sourceUnit?: string;
|
||||
|
@ -6,6 +6,8 @@ import {
|
||||
CategoryNames,
|
||||
DataFormats,
|
||||
DataRateFormats,
|
||||
HelperCategory,
|
||||
HelperFormat,
|
||||
MiscellaneousFormats,
|
||||
ThroughputFormats,
|
||||
TimeFormats,
|
||||
@ -119,3 +121,10 @@ export const getCategoryByOptionId = (id: string): Category | undefined =>
|
||||
|
||||
export const isCategoryName = (name: string): name is CategoryNames =>
|
||||
alertsCategory.some((category) => category.name === name);
|
||||
|
||||
const allFormats: HelperFormat[] = alertsCategory.flatMap(
|
||||
(category: HelperCategory) => category.formats,
|
||||
);
|
||||
|
||||
export const getFormatNameByOptionId = (id: string): string | undefined =>
|
||||
allFormats.find((format) => format.id === id)?.name;
|
||||
|
@ -362,3 +362,13 @@ export type Category = {
|
||||
};
|
||||
|
||||
export type DataTypeCategories = Category[];
|
||||
|
||||
export interface HelperFormat {
|
||||
name: string;
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface HelperCategory {
|
||||
name: string;
|
||||
formats: Format[];
|
||||
}
|
||||
|
@ -265,10 +265,15 @@ function findUnitObject(
|
||||
|
||||
export function convertValue(
|
||||
value: number,
|
||||
currentUnit: string,
|
||||
targetUnit: string,
|
||||
currentUnit?: string,
|
||||
targetUnit?: string,
|
||||
): number | null {
|
||||
if (targetUnit === 'none') {
|
||||
if (
|
||||
targetUnit === 'none' ||
|
||||
!currentUnit ||
|
||||
!targetUnit ||
|
||||
currentUnit === targetUnit
|
||||
) {
|
||||
return value;
|
||||
}
|
||||
const currentUnitObj = findUnitObject(currentUnit);
|
||||
|
@ -15,6 +15,7 @@ import onClickPlugin, { OnClickPluginOpts } from './plugins/onClickPlugin';
|
||||
import tooltipPlugin from './plugins/tooltipPlugin';
|
||||
import getAxes from './utils/getAxes';
|
||||
import getSeries from './utils/getSeriesData';
|
||||
import { getYAxisScale } from './utils/getYAxisScale';
|
||||
|
||||
interface GetUPlotChartOptions {
|
||||
id?: string;
|
||||
@ -79,7 +80,11 @@ export const getUPlotChartOptions = ({
|
||||
auto: true, // Automatically adjust scale range
|
||||
},
|
||||
y: {
|
||||
auto: true,
|
||||
...getYAxisScale(
|
||||
thresholds,
|
||||
apiResponse?.data.newResult.data.result,
|
||||
yAxisUnit,
|
||||
),
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
|
83
frontend/src/lib/uPlotLib/utils/getYAxisScale.ts
Normal file
83
frontend/src/lib/uPlotLib/utils/getYAxisScale.ts
Normal file
@ -0,0 +1,83 @@
|
||||
import { ThresholdProps } from 'container/NewWidget/RightContainer/Threshold/types';
|
||||
import { convertValue } from 'lib/getConvertedValue';
|
||||
import { QueryDataV3 } from 'types/api/widgets/getQuery';
|
||||
|
||||
function findMinMaxValues(data: QueryDataV3[]): [number, number] {
|
||||
let min = 0;
|
||||
let max = 0;
|
||||
data?.forEach((entry) => {
|
||||
entry.series?.forEach((series) => {
|
||||
series.values.forEach((valueObj) => {
|
||||
const value = parseFloat(valueObj.value);
|
||||
if (!value) return;
|
||||
min = Math.min(min, value);
|
||||
max = Math.max(max, value);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return [min, max];
|
||||
}
|
||||
|
||||
function findMinMaxThresholdValues(
|
||||
thresholds: ThresholdProps[],
|
||||
yAxisUnit?: string,
|
||||
): [number, number] {
|
||||
let minThresholdValue = 0;
|
||||
let maxThresholdValue = 0;
|
||||
|
||||
thresholds.forEach((entry) => {
|
||||
const { thresholdValue, thresholdUnit } = entry;
|
||||
if (thresholdValue === undefined) return;
|
||||
minThresholdValue = Math.min(
|
||||
minThresholdValue,
|
||||
convertValue(thresholdValue, thresholdUnit, yAxisUnit) || 0,
|
||||
);
|
||||
maxThresholdValue = Math.max(
|
||||
maxThresholdValue,
|
||||
convertValue(thresholdValue, thresholdUnit, yAxisUnit) || 0,
|
||||
);
|
||||
});
|
||||
|
||||
return [minThresholdValue, maxThresholdValue];
|
||||
}
|
||||
|
||||
function getRange(
|
||||
thresholds: ThresholdProps[],
|
||||
series: QueryDataV3[],
|
||||
yAxisUnit?: string,
|
||||
): [number, number] {
|
||||
const [minThresholdValue, maxThresholdValue] = findMinMaxThresholdValues(
|
||||
thresholds,
|
||||
yAxisUnit,
|
||||
);
|
||||
const [minSeriesValue, maxSeriesValue] = findMinMaxValues(series);
|
||||
|
||||
const min = Math.min(minThresholdValue, minSeriesValue);
|
||||
const max = Math.max(maxThresholdValue, maxSeriesValue);
|
||||
|
||||
return [min, max];
|
||||
}
|
||||
|
||||
function areAllSeriesEmpty(series: QueryDataV3[]): boolean {
|
||||
return series.every((entry) => {
|
||||
if (!entry.series) return true;
|
||||
return entry.series.every((series) => series.values.length === 0);
|
||||
});
|
||||
}
|
||||
|
||||
export const getYAxisScale = (
|
||||
thresholds?: ThresholdProps[],
|
||||
series?: QueryDataV3[],
|
||||
yAxisUnit?: string,
|
||||
): {
|
||||
auto: boolean;
|
||||
range?: [number, number];
|
||||
} => {
|
||||
if (!thresholds || !series) return { auto: true };
|
||||
|
||||
if (areAllSeriesEmpty(series)) return { auto: true };
|
||||
|
||||
const [min, max] = getRange(thresholds, series, yAxisUnit);
|
||||
return { auto: false, range: [min, max] };
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user