mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-14 01:15:52 +08:00
feat: move anomaly detection behind ff and show beta (#6180)
This commit is contained in:
parent
2728ddd255
commit
701b8803ac
@ -22,4 +22,5 @@ export enum FeatureKeys {
|
|||||||
GATEWAY = 'GATEWAY',
|
GATEWAY = 'GATEWAY',
|
||||||
PREMIUM_SUPPORT = 'PREMIUM_SUPPORT',
|
PREMIUM_SUPPORT = 'PREMIUM_SUPPORT',
|
||||||
QUERY_BUILDER_SEARCH_V2 = 'QUERY_BUILDER_SEARCH_V2',
|
QUERY_BUILDER_SEARCH_V2 = 'QUERY_BUILDER_SEARCH_V2',
|
||||||
|
ANOMALY_DETECTION = 'ANOMALY_DETECTION',
|
||||||
}
|
}
|
||||||
|
@ -3,12 +3,11 @@ import { AlertTypes } from 'types/api/alerts/alertTypes';
|
|||||||
|
|
||||||
import { OptionType } from './types';
|
import { OptionType } from './types';
|
||||||
|
|
||||||
export const getOptionList = (t: TFunction): OptionType[] => [
|
export const getOptionList = (
|
||||||
{
|
t: TFunction,
|
||||||
title: t('anomaly_based_alert'),
|
isAnomalyDetectionEnabled: boolean,
|
||||||
selection: AlertTypes.ANOMALY_BASED_ALERT,
|
): OptionType[] => {
|
||||||
description: t('anomaly_based_alert_desc'),
|
const optionList: OptionType[] = [
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: t('metric_based_alert'),
|
title: t('metric_based_alert'),
|
||||||
selection: AlertTypes.METRICS_BASED_ALERT,
|
selection: AlertTypes.METRICS_BASED_ALERT,
|
||||||
@ -29,4 +28,16 @@ export const getOptionList = (t: TFunction): OptionType[] => [
|
|||||||
selection: AlertTypes.EXCEPTIONS_BASED_ALERT,
|
selection: AlertTypes.EXCEPTIONS_BASED_ALERT,
|
||||||
description: t('exceptions_based_alert_desc'),
|
description: t('exceptions_based_alert_desc'),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if (isAnomalyDetectionEnabled) {
|
||||||
|
optionList.unshift({
|
||||||
|
title: t('anomaly_based_alert'),
|
||||||
|
selection: AlertTypes.ANOMALY_BASED_ALERT,
|
||||||
|
description: t('anomaly_based_alert_desc'),
|
||||||
|
isBeta: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return optionList;
|
||||||
|
};
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import { Row, Typography } from 'antd';
|
import { Row, Tag, Typography } from 'antd';
|
||||||
import logEvent from 'api/common/logEvent';
|
import logEvent from 'api/common/logEvent';
|
||||||
import { ALERTS_DATA_SOURCE_MAP } from 'constants/alerts';
|
import { ALERTS_DATA_SOURCE_MAP } from 'constants/alerts';
|
||||||
|
import { FeatureKeys } from 'constants/features';
|
||||||
|
import useFeatureFlags from 'hooks/useFeatureFlag';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { AlertTypes } from 'types/api/alerts/alertTypes';
|
import { AlertTypes } from 'types/api/alerts/alertTypes';
|
||||||
@ -12,7 +14,10 @@ import { OptionType } from './types';
|
|||||||
function SelectAlertType({ onSelect }: SelectAlertTypeProps): JSX.Element {
|
function SelectAlertType({ onSelect }: SelectAlertTypeProps): JSX.Element {
|
||||||
const { t } = useTranslation(['alerts']);
|
const { t } = useTranslation(['alerts']);
|
||||||
|
|
||||||
const optionList = getOptionList(t);
|
const isAnomalyDetectionEnabled =
|
||||||
|
useFeatureFlags(FeatureKeys.ANOMALY_DETECTION)?.active || false;
|
||||||
|
|
||||||
|
const optionList = getOptionList(t, isAnomalyDetectionEnabled);
|
||||||
|
|
||||||
function handleRedirection(option: AlertTypes): void {
|
function handleRedirection(option: AlertTypes): void {
|
||||||
let url = '';
|
let url = '';
|
||||||
@ -56,6 +61,13 @@ function SelectAlertType({ onSelect }: SelectAlertTypeProps): JSX.Element {
|
|||||||
<AlertTypeCard
|
<AlertTypeCard
|
||||||
key={option.selection}
|
key={option.selection}
|
||||||
title={option.title}
|
title={option.title}
|
||||||
|
extra={
|
||||||
|
option.isBeta ? (
|
||||||
|
<Tag bordered={false} color="geekblue">
|
||||||
|
Beta
|
||||||
|
</Tag>
|
||||||
|
) : undefined
|
||||||
|
}
|
||||||
onClick={(): void => {
|
onClick={(): void => {
|
||||||
onSelect(option.selection);
|
onSelect(option.selection);
|
||||||
}}
|
}}
|
||||||
|
@ -4,4 +4,5 @@ export interface OptionType {
|
|||||||
title: string;
|
title: string;
|
||||||
selection: AlertTypes;
|
selection: AlertTypes;
|
||||||
description: string;
|
description: string;
|
||||||
|
isBeta?: boolean;
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ import './ChartPreview.styles.scss';
|
|||||||
import { InfoCircleOutlined } from '@ant-design/icons';
|
import { InfoCircleOutlined } from '@ant-design/icons';
|
||||||
import Spinner from 'components/Spinner';
|
import Spinner from 'components/Spinner';
|
||||||
import { DEFAULT_ENTITY_VERSION } from 'constants/app';
|
import { DEFAULT_ENTITY_VERSION } from 'constants/app';
|
||||||
|
import { FeatureKeys } from 'constants/features';
|
||||||
import { QueryParams } from 'constants/query';
|
import { QueryParams } from 'constants/query';
|
||||||
import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder';
|
import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder';
|
||||||
import AnomalyAlertEvaluationView from 'container/AnomalyAlertEvaluationView';
|
import AnomalyAlertEvaluationView from 'container/AnomalyAlertEvaluationView';
|
||||||
@ -17,6 +18,7 @@ import {
|
|||||||
import { useGetQueryRange } from 'hooks/queryBuilder/useGetQueryRange';
|
import { useGetQueryRange } from 'hooks/queryBuilder/useGetQueryRange';
|
||||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||||
import { useResizeObserver } from 'hooks/useDimensions';
|
import { useResizeObserver } from 'hooks/useDimensions';
|
||||||
|
import useFeatureFlags from 'hooks/useFeatureFlag';
|
||||||
import useUrlQuery from 'hooks/useUrlQuery';
|
import useUrlQuery from 'hooks/useUrlQuery';
|
||||||
import GetMinMax from 'lib/getMinMax';
|
import GetMinMax from 'lib/getMinMax';
|
||||||
import getTimeString from 'lib/getTimeString';
|
import getTimeString from 'lib/getTimeString';
|
||||||
@ -259,6 +261,9 @@ function ChartPreview({
|
|||||||
const chartDataAvailable =
|
const chartDataAvailable =
|
||||||
chartData && !queryResponse.isError && !queryResponse.isLoading;
|
chartData && !queryResponse.isError && !queryResponse.isLoading;
|
||||||
|
|
||||||
|
const isAnomalyDetectionEnabled =
|
||||||
|
useFeatureFlags(FeatureKeys.ANOMALY_DETECTION)?.active || false;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="alert-chart-container" ref={graphRef}>
|
<div className="alert-chart-container" ref={graphRef}>
|
||||||
<ChartContainer>
|
<ChartContainer>
|
||||||
@ -291,6 +296,7 @@ function ChartPreview({
|
|||||||
|
|
||||||
{chartDataAvailable &&
|
{chartDataAvailable &&
|
||||||
isAnomalyDetectionAlert &&
|
isAnomalyDetectionAlert &&
|
||||||
|
isAnomalyDetectionEnabled &&
|
||||||
queryResponse?.data?.payload?.data?.resultType === 'anomaly' && (
|
queryResponse?.data?.payload?.data?.resultType === 'anomaly' && (
|
||||||
<AnomalyAlertEvaluationView
|
<AnomalyAlertEvaluationView
|
||||||
data={queryResponse?.data?.payload}
|
data={queryResponse?.data?.payload}
|
||||||
|
@ -23,7 +23,10 @@ import PlotTag from 'container/NewWidget/LeftContainer/WidgetGraph/PlotTag';
|
|||||||
import { BuilderUnitsFilter } from 'container/QueryBuilder/filters';
|
import { BuilderUnitsFilter } from 'container/QueryBuilder/filters';
|
||||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||||
import { useShareBuilderUrl } from 'hooks/queryBuilder/useShareBuilderUrl';
|
import { useShareBuilderUrl } from 'hooks/queryBuilder/useShareBuilderUrl';
|
||||||
import { MESSAGE, useIsFeatureDisabled } from 'hooks/useFeatureFlag';
|
import useFeatureFlag, {
|
||||||
|
MESSAGE,
|
||||||
|
useIsFeatureDisabled,
|
||||||
|
} from 'hooks/useFeatureFlag';
|
||||||
import { useNotifications } from 'hooks/useNotifications';
|
import { useNotifications } from 'hooks/useNotifications';
|
||||||
import useUrlQuery from 'hooks/useUrlQuery';
|
import useUrlQuery from 'hooks/useUrlQuery';
|
||||||
import history from 'lib/history';
|
import history from 'lib/history';
|
||||||
@ -665,6 +668,7 @@ function FormAlertRules({
|
|||||||
{
|
{
|
||||||
value: AlertDetectionTypes.ANOMALY_DETECTION_ALERT,
|
value: AlertDetectionTypes.ANOMALY_DETECTION_ALERT,
|
||||||
label: 'Anomaly Detection Alert',
|
label: 'Anomaly Detection Alert',
|
||||||
|
isBeta: true,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -677,6 +681,9 @@ function FormAlertRules({
|
|||||||
setDetectionMethod(value);
|
setDetectionMethod(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isAnomalyDetectionEnabled =
|
||||||
|
useFeatureFlag(FeatureKeys.ANOMALY_DETECTION)?.active || false;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{Element}
|
{Element}
|
||||||
@ -730,7 +737,8 @@ function FormAlertRules({
|
|||||||
</StepContainer>
|
</StepContainer>
|
||||||
|
|
||||||
<div className="steps-container">
|
<div className="steps-container">
|
||||||
{alertDef.alertType === AlertTypes.METRICS_BASED_ALERT && (
|
{alertDef.alertType === AlertTypes.METRICS_BASED_ALERT &&
|
||||||
|
isAnomalyDetectionEnabled && (
|
||||||
<div className="detection-method-container">
|
<div className="detection-method-container">
|
||||||
<StepHeading> {t('alert_form_step1')}</StepHeading>
|
<StepHeading> {t('alert_form_step1')}</StepHeading>
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import './Tabs2.styles.scss';
|
import './Tabs2.styles.scss';
|
||||||
|
|
||||||
import { Color } from '@signozhq/design-tokens';
|
import { Color } from '@signozhq/design-tokens';
|
||||||
import { Button } from 'antd';
|
import { Button, Tag } from 'antd';
|
||||||
import { TimelineFilter } from 'container/AlertHistory/types';
|
import { TimelineFilter } from 'container/AlertHistory/types';
|
||||||
import { Undo } from 'lucide-react';
|
import { Undo } from 'lucide-react';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
@ -11,6 +11,7 @@ interface Tab {
|
|||||||
label: string | JSX.Element;
|
label: string | JSX.Element;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
icon?: string | JSX.Element;
|
icon?: string | JSX.Element;
|
||||||
|
isBeta?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TimelineTabsProps {
|
interface TimelineTabsProps {
|
||||||
@ -63,6 +64,12 @@ function Tabs2({
|
|||||||
style={{ minWidth: buttonMinWidth }}
|
style={{ minWidth: buttonMinWidth }}
|
||||||
>
|
>
|
||||||
{tab.label}
|
{tab.label}
|
||||||
|
|
||||||
|
{tab.isBeta && (
|
||||||
|
<Tag bordered={false} color="geekblue">
|
||||||
|
Beta
|
||||||
|
</Tag>
|
||||||
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
))}
|
))}
|
||||||
</Button.Group>
|
</Button.Group>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user