mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-12 21:58:59 +08:00
feat: Right side panel in create/edit alert UI (#1404)
* feat: metrics builder * feat: tag key selection * feat: metrics builder * poc version * added more changes to query builder * added types for composite queries * (feat): added edit rules and create rules forms * added label key value input item * (chore): added hidden labels for labelinput * (chore): resolved some merge conflicts from develop * (chore): added translations * (chore): removed some old files in metric builder * (chore): restored some of the files from develop branch * (chore): restored env.ts * (fix): solved empty builder queries errors * (fix): changed queryIndex and formulaIndex type to string|number from number * (feat): added chart preview for alert metric ui * (feat): added threshold in chart, translations in alert form and a few fixes * (fix): restoring env.ts * (fix): placed threshold on horizontal line * fix: resolved review comments * fix: resolved label remove issue * fix: removed console log * fix: resolved issue with edit rule - old state values shown after update of threshold * fix: resolved issue with match condition dropdown in alert ui * fix: increased size of timeframe drop down * fix: fixed label key value field and chart auto update when eval window changes * feat: added a link for alert name in list alerts page and source for each rule update * fix: resolved review coments in querysection of alerts ui * feat: adding panel user guide in alerting form * feat: added user guide panel in the alert form * feat: added more help icon in user guide and fixed the sizing issue Co-authored-by: Pranshu Chittora <pranshu@signoz.io>
This commit is contained in:
parent
10c6325e46
commit
7c14a75c68
@ -59,5 +59,27 @@
|
||||
"option_critical": "Critical",
|
||||
"option_error": "Error",
|
||||
"option_warning": "Warning",
|
||||
"option_info": "Info"
|
||||
"option_info": "Info",
|
||||
"user_guide_headline": "Steps to create an Alert",
|
||||
"user_guide_qb_step1": "Step 1 - Define the metric",
|
||||
"user_guide_qb_step1a": "Choose a metric which you want to create an alert on",
|
||||
"user_guide_qb_step1b": "Filter it based on WHERE field or GROUPBY if needed",
|
||||
"user_guide_qb_step1c": "Apply an aggregatiion function like COUNT, SUM, etc. or choose NOOP to plot the raw metric",
|
||||
"user_guide_qb_step1d": "Create a formula based on Queries if needed",
|
||||
"user_guide_qb_step2": "Step 2 - Define Alert Conditions",
|
||||
"user_guide_qb_step2a": "Select the evaluation interval, threshold type and whether you want to alert above/below a value",
|
||||
"user_guide_qb_step2b": "Enter the Alert threshold",
|
||||
"user_guide_qb_step3": "Step 3 -Alert Configuration",
|
||||
"user_guide_qb_step3a": "Set alert severity, name and descriptions",
|
||||
"user_guide_qb_step3b": "Add tags to the alert in the Label field if needed",
|
||||
"user_guide_pql_step1": "Step 1 - Define the metric",
|
||||
"user_guide_pql_step1a": "Write a PromQL query for the metric",
|
||||
"user_guide_pql_step1b": "Format the legends based on labels you want to highlight",
|
||||
"user_guide_pql_step2": "Step 2 - Define Alert Conditions",
|
||||
"user_guide_pql_step2a": "Select the threshold type and whether you want to alert above/below a value",
|
||||
"user_guide_pql_step2b": "Enter the Alert threshold",
|
||||
"user_guide_pql_step3": "Step 3 -Alert Configuration",
|
||||
"user_guide_pql_step3a": "Set alert severity, name and descriptions",
|
||||
"user_guide_pql_step3b": "Add tags to the alert in the Label field if needed",
|
||||
"user_tooltip_more_help": "More details on how to create alerts"
|
||||
}
|
@ -59,5 +59,27 @@
|
||||
"option_critical": "Critical",
|
||||
"option_error": "Error",
|
||||
"option_warning": "Warning",
|
||||
"option_info": "Info"
|
||||
"option_info": "Info",
|
||||
"user_guide_headline": "Steps to create an Alert",
|
||||
"user_guide_qb_step1": "Step 1 - Define the metric",
|
||||
"user_guide_qb_step1a": "Choose a metric which you want to create an alert on",
|
||||
"user_guide_qb_step1b": "Filter it based on WHERE field or GROUPBY if needed",
|
||||
"user_guide_qb_step1c": "Apply an aggregatiion function like COUNT, SUM, etc. or choose NOOP to plot the raw metric",
|
||||
"user_guide_qb_step1d": "Create a formula based on Queries if needed",
|
||||
"user_guide_qb_step2": "Step 2 - Define Alert Conditions",
|
||||
"user_guide_qb_step2a": "Select the evaluation interval, threshold type and whether you want to alert above/below a value",
|
||||
"user_guide_qb_step2b": "Enter the Alert threshold",
|
||||
"user_guide_qb_step3": "Step 3 -Alert Configuration",
|
||||
"user_guide_qb_step3a": "Set alert severity, name and descriptions",
|
||||
"user_guide_qb_step3b": "Add tags to the alert in the Label field if needed",
|
||||
"user_guide_pql_step1": "Step 1 - Define the metric",
|
||||
"user_guide_pql_step1a": "Write a PromQL query for the metric",
|
||||
"user_guide_pql_step1b": "Format the legends based on labels you want to highlight",
|
||||
"user_guide_pql_step2": "Step 2 - Define Alert Conditions",
|
||||
"user_guide_pql_step2a": "Select the threshold type and whether you want to alert above/below a value",
|
||||
"user_guide_pql_step2b": "Enter the Alert threshold",
|
||||
"user_guide_pql_step3": "Step 3 -Alert Configuration",
|
||||
"user_guide_pql_step3a": "Set alert severity, name and descriptions",
|
||||
"user_guide_pql_step3b": "Add tags to the alert in the Label field if needed",
|
||||
"user_tooltip_more_help": "More details on how to create alerts"
|
||||
}
|
132
frontend/src/container/FormAlertRules/UserGuide/index.tsx
Normal file
132
frontend/src/container/FormAlertRules/UserGuide/index.tsx
Normal file
@ -0,0 +1,132 @@
|
||||
import { Col, Row, Typography } from 'antd';
|
||||
import TextToolTip from 'components/TextToolTip';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
|
||||
import {
|
||||
StyledList,
|
||||
StyledListItem,
|
||||
StyledMainContainer,
|
||||
StyledTopic,
|
||||
} from './styles';
|
||||
|
||||
function UserGuide({ queryType }: UserGuideProps): JSX.Element {
|
||||
// init namespace for translations
|
||||
const { t } = useTranslation('rules');
|
||||
|
||||
const renderStep1QB = (): JSX.Element => {
|
||||
return (
|
||||
<>
|
||||
<StyledTopic>{t('user_guide_qb_step1')}</StyledTopic>
|
||||
<StyledList>
|
||||
<StyledListItem>{t('user_guide_qb_step1a')}</StyledListItem>
|
||||
<StyledListItem>{t('user_guide_qb_step1b')}</StyledListItem>
|
||||
<StyledListItem>{t('user_guide_qb_step1c')}</StyledListItem>
|
||||
<StyledListItem>{t('user_guide_qb_step1d')}</StyledListItem>
|
||||
</StyledList>
|
||||
</>
|
||||
);
|
||||
};
|
||||
const renderStep2QB = (): JSX.Element => {
|
||||
return (
|
||||
<>
|
||||
<StyledTopic>{t('user_guide_qb_step2')}</StyledTopic>
|
||||
<StyledList>
|
||||
<StyledListItem>{t('user_guide_qb_step2a')}</StyledListItem>
|
||||
<StyledListItem>{t('user_guide_qb_step2b')}</StyledListItem>
|
||||
</StyledList>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const renderStep3QB = (): JSX.Element => {
|
||||
return (
|
||||
<>
|
||||
<StyledTopic>{t('user_guide_qb_step3')}</StyledTopic>
|
||||
<StyledList>
|
||||
<StyledListItem>{t('user_guide_qb_step3a')}</StyledListItem>
|
||||
<StyledListItem>{t('user_guide_qb_step3b')}</StyledListItem>
|
||||
</StyledList>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const renderGuideForQB = (): JSX.Element => {
|
||||
return (
|
||||
<>
|
||||
{renderStep1QB()}
|
||||
{renderStep2QB()}
|
||||
{renderStep3QB()}
|
||||
</>
|
||||
);
|
||||
};
|
||||
const renderStep1PQL = (): JSX.Element => {
|
||||
return (
|
||||
<>
|
||||
<StyledTopic>{t('user_guide_pql_step1')}</StyledTopic>
|
||||
<StyledList>
|
||||
<StyledListItem>{t('user_guide_pql_step1a')}</StyledListItem>
|
||||
<StyledListItem>{t('user_guide_pql_step1b')}</StyledListItem>
|
||||
</StyledList>
|
||||
</>
|
||||
);
|
||||
};
|
||||
const renderStep2PQL = (): JSX.Element => {
|
||||
return (
|
||||
<>
|
||||
<StyledTopic>{t('user_guide_pql_step2')}</StyledTopic>
|
||||
<StyledList>
|
||||
<StyledListItem>{t('user_guide_pql_step2a')}</StyledListItem>
|
||||
<StyledListItem>{t('user_guide_pql_step2b')}</StyledListItem>
|
||||
</StyledList>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const renderStep3PQL = (): JSX.Element => {
|
||||
return (
|
||||
<>
|
||||
<StyledTopic>{t('user_guide_pql_step3')}</StyledTopic>
|
||||
<StyledList>
|
||||
<StyledListItem>{t('user_guide_pql_step3a')}</StyledListItem>
|
||||
<StyledListItem>{t('user_guide_pql_step3b')}</StyledListItem>
|
||||
</StyledList>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const renderGuideForPQL = (): JSX.Element => {
|
||||
return (
|
||||
<>
|
||||
{renderStep1PQL()}
|
||||
{renderStep2PQL()}
|
||||
{renderStep3PQL()}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledMainContainer>
|
||||
<Row>
|
||||
<Col flex="auto">
|
||||
<Typography.Paragraph> {t('user_guide_headline')} </Typography.Paragraph>
|
||||
</Col>
|
||||
<Col flex="none">
|
||||
<TextToolTip
|
||||
text={t('user_tooltip_more_help')}
|
||||
url="https://signoz.io/docs/userguide/alerts-management/#create-alert-rules"
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
{queryType === EQueryType.QUERY_BUILDER && renderGuideForQB()}
|
||||
{queryType === EQueryType.PROM && renderGuideForPQL()}
|
||||
</StyledMainContainer>
|
||||
);
|
||||
}
|
||||
|
||||
interface UserGuideProps {
|
||||
queryType: EQueryType;
|
||||
}
|
||||
|
||||
export default UserGuide;
|
17
frontend/src/container/FormAlertRules/UserGuide/styles.ts
Normal file
17
frontend/src/container/FormAlertRules/UserGuide/styles.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { Card, Typography } from 'antd';
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const StyledMainContainer = styled(Card)``;
|
||||
|
||||
export const StyledTopic = styled(Typography.Paragraph)`
|
||||
font-weight: 600;
|
||||
`;
|
||||
|
||||
export const StyledList = styled.ul`
|
||||
padding-left: 18px;
|
||||
`;
|
||||
|
||||
export const StyledListItem = styled.li`
|
||||
font-style: italic;
|
||||
padding-bottom: 0.5rem;
|
||||
`;
|
@ -25,8 +25,16 @@ import BasicInfo from './BasicInfo';
|
||||
import ChartPreview from './ChartPreview';
|
||||
import QuerySection from './QuerySection';
|
||||
import RuleOptions from './RuleOptions';
|
||||
import { ActionButton, ButtonContainer, MainFormContainer } from './styles';
|
||||
import {
|
||||
ActionButton,
|
||||
ButtonContainer,
|
||||
MainFormContainer,
|
||||
PanelContainer,
|
||||
StyledLeftContainer,
|
||||
StyledRightContainer,
|
||||
} from './styles';
|
||||
import useDebounce from './useDebounce';
|
||||
import UserGuide from './UserGuide';
|
||||
import {
|
||||
prepareBuilderQueries,
|
||||
prepareStagedQuery,
|
||||
@ -309,50 +317,57 @@ function FormAlertRules({
|
||||
return (
|
||||
<>
|
||||
{Element}
|
||||
<MainFormContainer
|
||||
initialValues={initialValue}
|
||||
layout="vertical"
|
||||
form={formInstance}
|
||||
>
|
||||
{queryCategory === EQueryType.QUERY_BUILDER && renderQBChartPreview()}
|
||||
{queryCategory === EQueryType.PROM && renderPromChartPreview()}
|
||||
<QuerySection
|
||||
queryCategory={queryCategory}
|
||||
setQueryCategory={onQueryCategoryChange}
|
||||
metricQueries={metricQueries}
|
||||
setMetricQueries={setMetricQueries}
|
||||
formulaQueries={formulaQueries}
|
||||
setFormulaQueries={setFormulaQueries}
|
||||
promQueries={promQueries}
|
||||
setPromQueries={setPromQueries}
|
||||
/>
|
||||
|
||||
<RuleOptions
|
||||
queryCategory={queryCategory}
|
||||
alertDef={alertDef}
|
||||
setAlertDef={setAlertDef}
|
||||
/>
|
||||
|
||||
{renderBasicInfo()}
|
||||
<ButtonContainer>
|
||||
<ActionButton
|
||||
loading={loading || false}
|
||||
type="primary"
|
||||
onClick={onSaveHandler}
|
||||
icon={<SaveOutlined />}
|
||||
<PanelContainer>
|
||||
<StyledLeftContainer flex="5 1 600px">
|
||||
<MainFormContainer
|
||||
initialValues={initialValue}
|
||||
layout="vertical"
|
||||
form={formInstance}
|
||||
>
|
||||
{ruleId > 0 ? t('button_savechanges') : t('button_createrule')}
|
||||
</ActionButton>
|
||||
<ActionButton
|
||||
disabled={loading || false}
|
||||
type="default"
|
||||
onClick={onCancelHandler}
|
||||
>
|
||||
{ruleId === 0 && t('button_cancelchanges')}
|
||||
{ruleId > 0 && t('button_discard')}
|
||||
</ActionButton>
|
||||
</ButtonContainer>
|
||||
</MainFormContainer>
|
||||
{queryCategory === EQueryType.QUERY_BUILDER && renderQBChartPreview()}
|
||||
{queryCategory === EQueryType.PROM && renderPromChartPreview()}
|
||||
<QuerySection
|
||||
queryCategory={queryCategory}
|
||||
setQueryCategory={onQueryCategoryChange}
|
||||
metricQueries={metricQueries}
|
||||
setMetricQueries={setMetricQueries}
|
||||
formulaQueries={formulaQueries}
|
||||
setFormulaQueries={setFormulaQueries}
|
||||
promQueries={promQueries}
|
||||
setPromQueries={setPromQueries}
|
||||
/>
|
||||
|
||||
<RuleOptions
|
||||
queryCategory={queryCategory}
|
||||
alertDef={alertDef}
|
||||
setAlertDef={setAlertDef}
|
||||
/>
|
||||
|
||||
{renderBasicInfo()}
|
||||
<ButtonContainer>
|
||||
<ActionButton
|
||||
loading={loading || false}
|
||||
type="primary"
|
||||
onClick={onSaveHandler}
|
||||
icon={<SaveOutlined />}
|
||||
>
|
||||
{ruleId > 0 ? t('button_savechanges') : t('button_createrule')}
|
||||
</ActionButton>
|
||||
<ActionButton
|
||||
disabled={loading || false}
|
||||
type="default"
|
||||
onClick={onCancelHandler}
|
||||
>
|
||||
{ruleId === 0 && t('button_cancelchanges')}
|
||||
{ruleId > 0 && t('button_discard')}
|
||||
</ActionButton>
|
||||
</ButtonContainer>
|
||||
</MainFormContainer>
|
||||
</StyledLeftContainer>
|
||||
<StyledRightContainer flex="1 1 300px">
|
||||
<UserGuide queryType={queryCategory} />
|
||||
</StyledRightContainer>
|
||||
</PanelContainer>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -1,11 +1,24 @@
|
||||
import { Button, Card, Form, Input, InputNumber, Select } from 'antd';
|
||||
import { Button, Card, Col, Form, Input, InputNumber, Row, Select } from 'antd';
|
||||
import TextArea from 'antd/lib/input/TextArea';
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const MainFormContainer = styled(Form)`
|
||||
max-width: 900px;
|
||||
export const PanelContainer = styled(Row)`
|
||||
flex-wrap: nowrap;
|
||||
`;
|
||||
|
||||
export const StyledRightContainer = styled(Col)`
|
||||
&&& {
|
||||
}
|
||||
`;
|
||||
|
||||
export const StyledLeftContainer = styled(Col)`
|
||||
&&& {
|
||||
margin-right: 1rem;
|
||||
}
|
||||
`;
|
||||
|
||||
export const MainFormContainer = styled(Form)``;
|
||||
|
||||
export const ButtonContainer = styled.div`
|
||||
&&& {
|
||||
display: flex;
|
||||
|
Loading…
x
Reference in New Issue
Block a user