feat(FE): dashboard alerts is added (#3908)

* feat: create menu items is added in the service application widgets

* chore: filter query is updated

* fix: build is fixed

* feat: selected query is updated

* chore: create alerts is updated

* feat: dashboard alerts is updated

* chore: spacing is updated

* feat: dashboard to alerts is updated

* fix: build is fixed

* feat: alert query options is updated

* chore: menu list is updated for tabel panel

---------

Co-authored-by: Rajat Dabade <rajat@signoz.io>
Co-authored-by: Srikanth Chekuri <srikanth.chekuri92@gmail.com>
This commit is contained in:
Palash Gupta 2023-11-13 13:54:31 +05:30 committed by GitHub
parent 758013d7cd
commit 5a9f626da5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 377 additions and 217 deletions

View File

@ -34,7 +34,7 @@
"button_returntorules": "Return to rules",
"button_cancelchanges": "Cancel",
"button_discard": "Discard",
"text_condition1": "Send a notification when the metric is",
"text_condition1": "Send a notification when",
"text_condition2": "the threshold",
"text_condition3": "during the last",
"option_5min": "5 mins",
@ -109,5 +109,6 @@
"traces_based_alert_desc": "Send a notification when a condition occurs in the traces data.",
"exceptions_based_alert": "Exceptions-based Alert",
"exceptions_based_alert_desc": "Send a notification when a condition occurs in the exceptions data.",
"field_unit": "Threshold unit"
"field_unit": "Threshold unit",
"selected_query_placeholder": "Select query"
}

View File

@ -1,85 +1,85 @@
{
"preview_chart_unexpected_error": "An unexpeced error occurred updating the chart, please check your query.",
"preview_chart_threshold_label": "Threshold",
"placeholder_label_key_pair": "Click here to enter a label (key value pairs)",
"button_yes": "Yes",
"button_no": "No",
"remove_label_confirm": "This action will remove all the labels. Do you want to proceed?",
"remove_label_success": "Labels cleared",
"alert_form_step1": "Step 1 - Define the metric",
"alert_form_step2": "Step 2 - Define Alert Conditions",
"alert_form_step3": "Step 3 - Alert Configuration",
"metric_query_max_limit": "Can not create query. You can create maximum of 5 queries",
"confirm_save_title": "Save Changes",
"confirm_save_content_part1": "Your alert built with",
"confirm_save_content_part2": "query will be saved. Press OK to confirm.",
"unexpected_error": "Sorry, an unexpected error occurred. Please contact your admin",
"rule_created": "Rule created successfully",
"rule_edited": "Rule edited successfully",
"expression_missing": "expression is missing in {{where}}",
"metricname_missing": "metric name is missing in {{where}}",
"condition_required": "at least one metric condition is required",
"alertname_required": "alert name is required",
"promql_required": "promql expression is required when query format is set to PromQL",
"button_savechanges": "Save Rule",
"button_createrule": "Create Rule",
"button_returntorules": "Return to rules",
"button_cancelchanges": "Cancel",
"button_discard": "Discard",
"text_condition1": "Send a notification when the metric is",
"text_condition2": "the threshold",
"text_condition3": "during the last",
"option_5min": "5 mins",
"option_10min": "10 mins",
"option_15min": "15 mins",
"option_60min": "60 mins",
"option_4hours": "4 hours",
"option_24hours": "24 hours",
"field_threshold": "Alert Threshold",
"option_allthetimes": "all the times",
"option_atleastonce": "at least once",
"option_onaverage": "on average",
"option_intotal": "in total",
"option_above": "above",
"option_below": "below",
"option_equal": "is equal to",
"option_notequal": "not equal to",
"button_query": "Query",
"button_formula": "Formula",
"tab_qb": "Query Builder",
"tab_promql": "PromQL",
"title_confirm": "Confirm",
"button_ok": "Yes",
"button_cancel": "No",
"field_promql_expr": "PromQL Expression",
"field_alert_name": "Alert Name",
"field_alert_desc": "Alert Description",
"field_labels": "Labels",
"field_severity": "Severity",
"option_critical": "Critical",
"option_error": "Error",
"option_warning": "Warning",
"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"
}
"preview_chart_unexpected_error": "An unexpeced error occurred updating the chart, please check your query.",
"preview_chart_threshold_label": "Threshold",
"placeholder_label_key_pair": "Click here to enter a label (key value pairs)",
"button_yes": "Yes",
"button_no": "No",
"remove_label_confirm": "This action will remove all the labels. Do you want to proceed?",
"remove_label_success": "Labels cleared",
"alert_form_step1": "Step 1 - Define the metric",
"alert_form_step2": "Step 2 - Define Alert Conditions",
"alert_form_step3": "Step 3 - Alert Configuration",
"metric_query_max_limit": "Can not create query. You can create maximum of 5 queries",
"confirm_save_title": "Save Changes",
"confirm_save_content_part1": "Your alert built with",
"confirm_save_content_part2": "query will be saved. Press OK to confirm.",
"unexpected_error": "Sorry, an unexpected error occurred. Please contact your admin",
"rule_created": "Rule created successfully",
"rule_edited": "Rule edited successfully",
"expression_missing": "expression is missing in {{where}}",
"metricname_missing": "metric name is missing in {{where}}",
"condition_required": "at least one metric condition is required",
"alertname_required": "alert name is required",
"promql_required": "promql expression is required when query format is set to PromQL",
"button_savechanges": "Save Rule",
"button_createrule": "Create Rule",
"button_returntorules": "Return to rules",
"button_cancelchanges": "Cancel",
"button_discard": "Discard",
"text_condition1": "Send a notification when",
"text_condition2": "the threshold",
"text_condition3": "during the last",
"option_5min": "5 mins",
"option_10min": "10 mins",
"option_15min": "15 mins",
"option_60min": "60 mins",
"option_4hours": "4 hours",
"option_24hours": "24 hours",
"field_threshold": "Alert Threshold",
"option_allthetimes": "all the times",
"option_atleastonce": "at least once",
"option_onaverage": "on average",
"option_intotal": "in total",
"option_above": "above",
"option_below": "below",
"option_equal": "is equal to",
"option_notequal": "not equal to",
"button_query": "Query",
"button_formula": "Formula",
"tab_qb": "Query Builder",
"tab_promql": "PromQL",
"title_confirm": "Confirm",
"button_ok": "Yes",
"button_cancel": "No",
"field_promql_expr": "PromQL Expression",
"field_alert_name": "Alert Name",
"field_alert_desc": "Alert Description",
"field_labels": "Labels",
"field_severity": "Severity",
"option_critical": "Critical",
"option_error": "Error",
"option_warning": "Warning",
"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"
}

View File

@ -34,7 +34,7 @@
"button_returntorules": "Return to rules",
"button_cancelchanges": "Cancel",
"button_discard": "Discard",
"text_condition1": "Send a notification when the metric is",
"text_condition1": "Send a notification when",
"text_condition2": "the threshold",
"text_condition3": "during the last",
"option_5min": "5 mins",
@ -109,5 +109,6 @@
"traces_based_alert_desc": "Send a notification when a condition occurs in the traces data.",
"exceptions_based_alert": "Exceptions-based Alert",
"exceptions_based_alert_desc": "Send a notification when a condition occurs in the exceptions data.",
"field_unit": "Threshold unit"
"field_unit": "Threshold unit",
"selected_query_placeholder": "Select query"
}

View File

@ -1,85 +1,85 @@
{
"preview_chart_unexpected_error": "An unexpeced error occurred updating the chart, please check your query.",
"preview_chart_threshold_label": "Threshold",
"placeholder_label_key_pair": "Click here to enter a label (key value pairs)",
"button_yes": "Yes",
"button_no": "No",
"remove_label_confirm": "This action will remove all the labels. Do you want to proceed?",
"remove_label_success": "Labels cleared",
"alert_form_step1": "Step 1 - Define the metric",
"alert_form_step2": "Step 2 - Define Alert Conditions",
"alert_form_step3": "Step 3 - Alert Configuration",
"metric_query_max_limit": "Can not create query. You can create maximum of 5 queries",
"confirm_save_title": "Save Changes",
"confirm_save_content_part1": "Your alert built with",
"confirm_save_content_part2": "query will be saved. Press OK to confirm.",
"unexpected_error": "Sorry, an unexpected error occurred. Please contact your admin",
"rule_created": "Rule created successfully",
"rule_edited": "Rule edited successfully",
"expression_missing": "expression is missing in {{where}}",
"metricname_missing": "metric name is missing in {{where}}",
"condition_required": "at least one metric condition is required",
"alertname_required": "alert name is required",
"promql_required": "promql expression is required when query format is set to PromQL",
"button_savechanges": "Save Rule",
"button_createrule": "Create Rule",
"button_returntorules": "Return to rules",
"button_cancelchanges": "Cancel",
"button_discard": "Discard",
"text_condition1": "Send a notification when the metric is",
"text_condition2": "the threshold",
"text_condition3": "during the last",
"option_5min": "5 mins",
"option_10min": "10 mins",
"option_15min": "15 mins",
"option_60min": "60 mins",
"option_4hours": "4 hours",
"option_24hours": "24 hours",
"field_threshold": "Alert Threshold",
"option_allthetimes": "all the times",
"option_atleastonce": "at least once",
"option_onaverage": "on average",
"option_intotal": "in total",
"option_above": "above",
"option_below": "below",
"option_equal": "is equal to",
"option_notequal": "not equal to",
"button_query": "Query",
"button_formula": "Formula",
"tab_qb": "Query Builder",
"tab_promql": "PromQL",
"title_confirm": "Confirm",
"button_ok": "Yes",
"button_cancel": "No",
"field_promql_expr": "PromQL Expression",
"field_alert_name": "Alert Name",
"field_alert_desc": "Alert Description",
"field_labels": "Labels",
"field_severity": "Severity",
"option_critical": "Critical",
"option_error": "Error",
"option_warning": "Warning",
"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"
}
"preview_chart_unexpected_error": "An unexpeced error occurred updating the chart, please check your query.",
"preview_chart_threshold_label": "Threshold",
"placeholder_label_key_pair": "Click here to enter a label (key value pairs)",
"button_yes": "Yes",
"button_no": "No",
"remove_label_confirm": "This action will remove all the labels. Do you want to proceed?",
"remove_label_success": "Labels cleared",
"alert_form_step1": "Step 1 - Define the metric",
"alert_form_step2": "Step 2 - Define Alert Conditions",
"alert_form_step3": "Step 3 - Alert Configuration",
"metric_query_max_limit": "Can not create query. You can create maximum of 5 queries",
"confirm_save_title": "Save Changes",
"confirm_save_content_part1": "Your alert built with",
"confirm_save_content_part2": "query will be saved. Press OK to confirm.",
"unexpected_error": "Sorry, an unexpected error occurred. Please contact your admin",
"rule_created": "Rule created successfully",
"rule_edited": "Rule edited successfully",
"expression_missing": "expression is missing in {{where}}",
"metricname_missing": "metric name is missing in {{where}}",
"condition_required": "at least one metric condition is required",
"alertname_required": "alert name is required",
"promql_required": "promql expression is required when query format is set to PromQL",
"button_savechanges": "Save Rule",
"button_createrule": "Create Rule",
"button_returntorules": "Return to rules",
"button_cancelchanges": "Cancel",
"button_discard": "Discard",
"text_condition1": "Send a notification when",
"text_condition2": "the threshold",
"text_condition3": "during the last",
"option_5min": "5 mins",
"option_10min": "10 mins",
"option_15min": "15 mins",
"option_60min": "60 mins",
"option_4hours": "4 hours",
"option_24hours": "24 hours",
"field_threshold": "Alert Threshold",
"option_allthetimes": "all the times",
"option_atleastonce": "at least once",
"option_onaverage": "on average",
"option_intotal": "in total",
"option_above": "above",
"option_below": "below",
"option_equal": "is equal to",
"option_notequal": "not equal to",
"button_query": "Query",
"button_formula": "Formula",
"tab_qb": "Query Builder",
"tab_promql": "PromQL",
"title_confirm": "Confirm",
"button_ok": "Yes",
"button_cancel": "No",
"field_promql_expr": "PromQL Expression",
"field_alert_name": "Alert Name",
"field_alert_desc": "Alert Description",
"field_labels": "Labels",
"field_severity": "Severity",
"option_critical": "Critical",
"option_error": "Error",
"option_warning": "Warning",
"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"
}

View File

@ -5,12 +5,16 @@ function PromqlSection(): JSX.Element {
const { currentQuery } = useQueryBuilder();
return (
<PromQLQueryBuilder
key="A"
queryIndex={0}
queryData={currentQuery.promql[0]}
deletable={false}
/>
<>
{currentQuery.promql.map((query, index) => (
<PromQLQueryBuilder
key={query.name}
queryIndex={index}
queryData={query}
deletable={false}
/>
))}
</>
);
}

View File

@ -7,6 +7,7 @@ import {
Space,
Typography,
} from 'antd';
import { DefaultOptionType } from 'antd/es/select';
import {
getCategoryByOptionId,
getCategorySelectOptionByName,
@ -28,6 +29,7 @@ function RuleOptions({
alertDef,
setAlertDef,
queryCategory,
queryOptions,
}: RuleOptionsProps): JSX.Element {
// init namespace for translations
const { t } = useTranslation('alerts');
@ -44,6 +46,18 @@ function RuleOptions({
});
};
const onChangeSelectedQueryName = (value: string | unknown): void => {
if (typeof value !== 'string') return;
setAlertDef({
...alertDef,
condition: {
...alertDef.condition,
selectedQueryName: value,
},
});
};
const renderCompareOps = (): JSX.Element => (
<InlineSelect
getPopupContainer={popupContainer}
@ -122,16 +136,38 @@ function RuleOptions({
const renderThresholdRuleOpts = (): JSX.Element => (
<Form.Item>
<Typography.Text>
{t('text_condition1')} {renderCompareOps()} {t('text_condition2')}{' '}
{renderThresholdMatchOpts()} {t('text_condition3')} {renderEvalWindows()}
{t('text_condition1')}
<InlineSelect
getPopupContainer={popupContainer}
allowClear
showSearch
options={queryOptions}
placeholder={t('selected_query_placeholder')}
value={alertDef.condition.selectedQueryName}
onChange={onChangeSelectedQueryName}
/>
<Typography.Text>is</Typography.Text>
{renderCompareOps()} {t('text_condition2')} {renderThresholdMatchOpts()}{' '}
{t('text_condition3')} {renderEvalWindows()}
</Typography.Text>
</Form.Item>
);
const renderPromRuleOptions = (): JSX.Element => (
<Form.Item>
<Typography.Text>
{t('text_condition1')} {renderCompareOps()} {t('text_condition2')}{' '}
{renderPromMatchOpts()}
{t('text_condition1')}
<InlineSelect
getPopupContainer={popupContainer}
allowClear
showSearch
options={queryOptions}
placeholder={t('selected_query_placeholder')}
value={alertDef.condition.selectedQueryName}
onChange={onChangeSelectedQueryName}
/>
<Typography.Text>is</Typography.Text>
{renderCompareOps()} {t('text_condition2')} {renderPromMatchOpts()}
</Typography.Text>
</Form.Item>
);
@ -172,7 +208,7 @@ function RuleOptions({
? renderPromRuleOptions()
: renderThresholdRuleOpts()}
<Space align="start">
<Space direction="horizontal" align="center">
<Form.Item noStyle name={['condition', 'target']}>
<InputNumber
addonBefore={t('field_threshold')}
@ -183,7 +219,7 @@ function RuleOptions({
/>
</Form.Item>
<Form.Item>
<Form.Item noStyle>
<Select
getPopupContainer={popupContainer}
allowClear
@ -204,5 +240,6 @@ interface RuleOptionsProps {
alertDef: AlertDef;
setAlertDef: (a: AlertDef) => void;
queryCategory: EQueryType;
queryOptions: DefaultOptionType[];
}
export default RuleOptions;

View File

@ -1,5 +1,12 @@
import { ExclamationCircleOutlined, SaveOutlined } from '@ant-design/icons';
import { Col, FormInstance, Modal, Tooltip, Typography } from 'antd';
import {
Col,
FormInstance,
Modal,
SelectProps,
Tooltip,
Typography,
} from 'antd';
import saveAlertApi from 'api/alerts/save';
import testAlertApi from 'api/alerts/testAlert';
import { FeatureKeys } from 'constants/features';
@ -44,6 +51,7 @@ import {
StyledLeftContainer,
} from './styles';
import UserGuide from './UserGuide';
import { getSelectedQueryOptions } from './utils';
function FormAlertRules({
alertType,
@ -80,6 +88,20 @@ function FormAlertRules({
initialValue,
]);
const queryOptions = useMemo(() => {
const queryConfig: Record<EQueryType, () => SelectProps['options']> = {
[EQueryType.QUERY_BUILDER]: () => [
...(getSelectedQueryOptions(currentQuery.builder.queryData) || []),
...(getSelectedQueryOptions(currentQuery.builder.queryFormulas) || []),
],
[EQueryType.PROM]: () => getSelectedQueryOptions(currentQuery.promql),
[EQueryType.CLICKHOUSE]: () =>
getSelectedQueryOptions(currentQuery.clickhouse_sql),
};
return queryConfig[currentQuery.queryType]?.() || [];
}, [currentQuery]);
const sq = useMemo(() => mapQueryDataFromApi(initQuery), [initQuery]);
useShareBuilderUrl(sq);
@ -88,6 +110,18 @@ function FormAlertRules({
setAlertDef(initialValue);
}, [initialValue]);
useEffect(() => {
// Set selectedQueryName based on the length of queryOptions
setAlertDef((def) => ({
...def,
condition: {
...def.condition,
selectedQueryName:
queryOptions.length > 0 ? String(queryOptions[0].value) : undefined,
},
}));
}, [currentQuery?.queryType, queryOptions]);
const onCancelHandler = useCallback(() => {
history.replace(ROUTES.LIST_ALL_ALERT);
}, []);
@ -437,6 +471,7 @@ function FormAlertRules({
queryCategory={currentQuery.queryType}
alertDef={alertDef}
setAlertDef={setAlertDef}
queryOptions={queryOptions}
/>
{renderBasicInfo()}

View File

@ -59,8 +59,8 @@ export const StepHeading = styled.p`
export const InlineSelect = styled(Select)`
display: inline-block;
width: 10% !important;
margin-left: 0.2em;
margin-right: 0.2em;
margin-left: 0.3em;
margin-right: 0.3em;
`;
export const SeveritySelect = styled(Select)`

View File

@ -1,6 +1,13 @@
import { SelectProps } from 'antd';
import { Time } from 'container/TopNav/DateTimeSelection/config';
import getStartEndRangeTime from 'lib/getStartEndRangeTime';
import getStep from 'lib/getStep';
import {
IBuilderFormula,
IBuilderQuery,
IClickHouseQuery,
IPromQLQuery,
} from 'types/api/queryBuilder/queryBuilderData';
// toChartInterval converts eval window to chart selection time interval
export const toChartInterval = (evalWindow: string | undefined): Time => {
@ -35,3 +42,15 @@ export const getUpdatedStepInterval = (evalWindow?: string): number => {
inputFormat: 'ns',
});
};
export const getSelectedQueryOptions = (
queries: Array<
IBuilderQuery | IBuilderFormula | IClickHouseQuery | IPromQLQuery
>,
): SelectProps['options'] =>
queries
.filter((query) => !query.disabled)
.map((query) => ({
label: 'queryName' in query ? query.queryName : query.name,
value: 'queryName' in query ? query.queryName : query.name,
}));

View File

@ -98,6 +98,11 @@ function GridCardGraph({
const isEmptyLayout = widget?.id === PANEL_TYPES.EMPTY_WIDGET;
const menuList =
widget.panelTypes === PANEL_TYPES.TABLE
? headerMenuList.filter((menu) => menu !== MenuItemKeys.CreateAlerts)
: headerMenuList;
return (
<span ref={graphRef}>
<WidgetGraphComponent
@ -109,7 +114,7 @@ function GridCardGraph({
name={name}
onDragSelect={onDragSelect}
threshold={threshold}
headerMenuList={headerMenuList}
headerMenuList={menuList}
onClickHandler={onClickHandler}
/>

View File

@ -1,4 +1,5 @@
import {
AlertOutlined,
CopyOutlined,
DeleteOutlined,
DownOutlined,
@ -157,7 +158,7 @@ function WidgetHeader({
},
{
key: MenuItemKeys.CreateAlerts,
icon: <DeleteOutlined />,
icon: <AlertOutlined />,
label: MENUITEM_KEYS_VS_LABELS[MenuItemKeys.CreateAlerts],
isVisible: headerMenuList?.includes(MenuItemKeys.CreateAlerts) || false,
disabled: false,

View File

@ -7,6 +7,7 @@ export const EditMenuAction = [
MenuItemKeys.Clone,
MenuItemKeys.Delete,
MenuItemKeys.Edit,
MenuItemKeys.CreateAlerts,
];
export const headerMenuList = [...ViewMenuAction];

View File

@ -16,7 +16,7 @@ import { TagFilterItem } from 'types/api/queryBuilder/queryBuilderData';
import { EQueryType } from 'types/common/dashboard';
import { v4 as uuid } from 'uuid';
import { GraphTitle } from '../constant';
import { GraphTitle, MENU_ITEMS } from '../constant';
import { getWidgetQueryBuilder } from '../MetricsApplication.factory';
import { Card, GraphContainer, Row } from '../styles';
import { Button } from './styles';
@ -109,6 +109,7 @@ function DBCall(): JSX.Element {
<Graph
name="database_call_rps"
widget={databaseCallsRPSWidget}
headerMenuList={MENU_ITEMS}
onClickHandler={(ChartEvent, activeElements, chart, data): void => {
onGraphClickHandler(setSelectedTimeStamp)(
ChartEvent,
@ -142,6 +143,7 @@ function DBCall(): JSX.Element {
<Graph
name="database_call_avg_duration"
widget={databaseCallsAverageDurationWidget}
headerMenuList={MENU_ITEMS}
onClickHandler={(ChartEvent, activeElements, chart, data): void => {
onGraphClickHandler(setSelectedTimeStamp)(
ChartEvent,

View File

@ -17,7 +17,7 @@ import { useParams } from 'react-router-dom';
import { EQueryType } from 'types/common/dashboard';
import { v4 as uuid } from 'uuid';
import { GraphTitle, legend } from '../constant';
import { GraphTitle, legend, MENU_ITEMS } from '../constant';
import { getWidgetQueryBuilder } from '../MetricsApplication.factory';
import { Card, GraphContainer, Row } from '../styles';
import { Button } from './styles';
@ -148,6 +148,7 @@ function External(): JSX.Element {
<Card>
<GraphContainer>
<Graph
headerMenuList={MENU_ITEMS}
name="external_call_error_percentage"
widget={externalCallErrorWidget}
onClickHandler={(ChartEvent, activeElements, chart, data): void => {
@ -183,6 +184,7 @@ function External(): JSX.Element {
<GraphContainer>
<Graph
name="external_call_duration"
headerMenuList={MENU_ITEMS}
widget={externalCallDurationWidget}
onClickHandler={(ChartEvent, activeElements, chart, data): void => {
onGraphClickHandler(setSelectedTimeStamp)(
@ -219,6 +221,7 @@ function External(): JSX.Element {
<Graph
name="external_call_rps_by_address"
widget={externalCallRPSWidget}
headerMenuList={MENU_ITEMS}
onClickHandler={(ChartEvent, activeElements, chart, data): void => {
onGraphClickHandler(setSelectedTimeStamp)(
ChartEvent,
@ -253,6 +256,7 @@ function External(): JSX.Element {
<Graph
name="external_call_duration_by_address"
widget={externalCallDurationAddressWidget}
headerMenuList={MENU_ITEMS}
onClickHandler={(ChartEvent, activeElements, chart, data): void => {
onGraphClickHandler(setSelectedTimeStamp)(
ChartEvent,

View File

@ -10,8 +10,8 @@ function ApDexMetricsApplication({
handleGraphClick,
onDragSelect,
tagFilterItems,
topLevelOperationsRoute,
thresholdValue,
topLevelOperationsRoute,
}: ApDexDataSwitcherProps): JSX.Element {
const { data, isLoading, error } = useGetMetricMeta(metricMeta);
useErrorNotification(error);
@ -22,11 +22,11 @@ function ApDexMetricsApplication({
return (
<ApDexMetrics
topLevelOperationsRoute={topLevelOperationsRoute}
handleGraphClick={handleGraphClick}
delta={data?.data.delta}
metricsBuckets={data?.data.le || []}
onDragSelect={onDragSelect}
topLevelOperationsRoute={topLevelOperationsRoute}
tagFilterItems={tagFilterItems}
thresholdValue={thresholdValue}
/>

View File

@ -1,4 +1,5 @@
import { DownloadOptions } from 'container/Download/Download.types';
import { MenuItemKeys } from 'container/GridCardLayout/WidgetHeader/contants';
export const legend = {
address: '{{address}}',
@ -13,6 +14,8 @@ export const LATENCY_AGGREGATEOPERATOR_SPAN_METRICS = [
];
export const OPERATION_LEGENDS = ['Operations'];
export const MENU_ITEMS = [MenuItemKeys.View, MenuItemKeys.CreateAlerts];
export enum FORMULA {
ERROR_PERCENTAGE = 'A*100/B',
DATABASE_CALLS_AVG_DURATION = 'A/B',
@ -21,6 +24,8 @@ export enum FORMULA {
APDEX_CUMULATIVE_SPAN_METRICS = '((B + C)/2)/A',
}
export const TOP_LEVEL_OPERATIONS = ['{{.top_level_operations}}'];
export enum GraphTitle {
APDEX = 'Apdex',
LATENCY = 'Latency',

View File

@ -29,10 +29,8 @@ function YAxisUnitSelector({
value: options.name,
}));
return (
<Col style={{ marginTop: '1rem' }}>
<div style={{ margin: '0.5rem 0' }}>
<Typography.Text>{fieldLabel}</Typography.Text>
</div>
<Col style={{ marginBottom: 12, marginTop: 12 }}>
<Typography.Text>{fieldLabel}</Typography.Text>
<AutoComplete
style={{ width: '100%' }}
options={options}

View File

@ -1,9 +1,14 @@
import { Input, Select } from 'antd';
import { UploadOutlined } from '@ant-design/icons';
import { Button, Input, Select, Space } from 'antd';
import InputComponent from 'components/Input';
import TimePreference from 'components/TimePreferenceDropDown';
import { QueryParams } from 'constants/query';
import { PANEL_TYPES } from 'constants/queryBuilder';
import ROUTES from 'constants/routes';
import GraphTypes from 'container/NewDashboard/ComponentsSlider/menuItems';
import history from 'lib/history';
import { Dispatch, SetStateAction, useCallback } from 'react';
import { Widgets } from 'types/api/dashboard/getAll';
import { Container, Title } from './styles';
import { timePreferance } from './timeItems';
@ -23,6 +28,7 @@ function RightContainer({
yAxisUnit,
setYAxisUnit,
setGraphHandler,
selectedWidget,
}: RightContainerProps): JSX.Element {
const onChangeHandler = useCallback(
(setFunc: Dispatch<SetStateAction<string>>, value: string) => {
@ -34,6 +40,16 @@ function RightContainer({
const selectedGraphType =
GraphTypes.find((e) => e.name === selectedGraph)?.display || '';
const onCreateAlertsHandler = useCallback(() => {
if (!selectedWidget) return;
history.push(
`${ROUTES.ALERTS_NEW}?${QueryParams.compositeQuery}=${encodeURIComponent(
JSON.stringify(selectedWidget?.query),
)}`,
);
}, [selectedWidget]);
return (
<Container>
<Title>Panel Type</Title>
@ -116,17 +132,26 @@ function RightContainer({
<Title light="true">Panel Time Preference</Title>
<TimePreference
{...{
selectedTime,
setSelectedTime,
}}
/>
<YAxisUnitSelector
defaultValue={yAxisUnit}
onSelect={setYAxisUnit}
fieldLabel={selectedGraphType === 'Value' ? 'Unit' : 'Y Axis Unit'}
/>
<Space direction="vertical">
<TimePreference
{...{
selectedTime,
setSelectedTime,
}}
/>
<YAxisUnitSelector
defaultValue={yAxisUnit}
onSelect={setYAxisUnit}
fieldLabel={selectedGraphType === 'Value' ? 'Unit' : 'Y Axis Unit'}
/>
{selectedWidget?.panelTypes !== PANEL_TYPES.TABLE && (
<Button icon={<UploadOutlined />} onClick={onCreateAlertsHandler}>
Create Alerts from Queries
</Button>
)}
</Space>
</Container>
);
}
@ -148,6 +173,11 @@ interface RightContainerProps {
yAxisUnit: string;
setYAxisUnit: Dispatch<SetStateAction<string>>;
setGraphHandler: (type: PANEL_TYPES) => void;
selectedWidget?: Widgets;
}
RightContainer.defaultProps = {
selectedWidget: undefined,
};
export default RightContainer;

View File

@ -21,6 +21,7 @@ import { useCallback, useMemo, useState } from 'react';
import { useSelector } from 'react-redux';
import { generatePath, useLocation, useParams } from 'react-router-dom';
import { AppState } from 'store/reducers';
import { Widgets } from 'types/api/dashboard/getAll';
import { EQueryType } from 'types/common/dashboard';
import { DataSource } from 'types/common/queryBuilder';
import AppReducer from 'types/reducer/app';
@ -100,9 +101,13 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element {
const updateDashboardMutation = useUpdateDashboard();
const onClickSaveHandler = useCallback(() => {
const { afterWidgets, preWidgets } = useMemo(() => {
if (!selectedDashboard) {
return;
return {
selectedWidget: {} as Widgets,
preWidgets: [],
afterWidgets: [],
};
}
const widgetId = query.get('widgetId');
@ -120,6 +125,14 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element {
selectedWidgetIndex || 0
];
return { selectedWidget, preWidgets, afterWidgets };
}, [selectedDashboard, query]);
const onClickSaveHandler = useCallback(() => {
if (!selectedDashboard) {
return;
}
updateDashboardMutation.mutateAsync(
{
uuid: selectedDashboard.uuid,
@ -128,7 +141,7 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element {
widgets: [
...preWidgets,
{
...selectedWidget,
...(selectedWidget || ({} as Widgets)),
description,
timePreferance: selectedTime.enum,
isStacked: stacked,
@ -157,6 +170,8 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element {
}, [
selectedDashboard,
updateDashboardMutation,
preWidgets,
selectedWidget,
description,
selectedTime.enum,
stacked,
@ -165,7 +180,7 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element {
title,
yAxisUnit,
graphType,
query,
afterWidgets,
featureResponse,
dashboardId,
notifications,
@ -271,6 +286,7 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element {
setSelectedTime={setSelectedTime}
selectedTime={selectedTime}
setYAxisUnit={setYAxisUnit}
selectedWidget={selectedWidget}
/>
</RightContainerWrapper>
</PanelContainer>

View File

@ -25,10 +25,11 @@ export interface AlertDef {
export interface RuleCondition {
compositeQuery: ICompositeMetricQuery;
op?: string | undefined;
target?: number | undefined;
matchType?: string | undefined;
targetUnit?: string | undefined;
op?: string;
target?: number;
matchType?: string;
targetUnit?: string;
selectedQueryName?: string;
}
export interface Labels {