diff --git a/frontend/public/Icons/alert_emoji.svg b/frontend/public/Icons/alert_emoji.svg
new file mode 100644
index 0000000000..70f9091283
--- /dev/null
+++ b/frontend/public/Icons/alert_emoji.svg
@@ -0,0 +1,10 @@
+
diff --git a/frontend/src/container/CreateAlertRule/SelectAlertType/index.tsx b/frontend/src/container/CreateAlertRule/SelectAlertType/index.tsx
index 916c9341a6..cd837b666b 100644
--- a/frontend/src/container/CreateAlertRule/SelectAlertType/index.tsx
+++ b/frontend/src/container/CreateAlertRule/SelectAlertType/index.tsx
@@ -29,7 +29,7 @@ function SelectAlertType({ onSelect }: SelectAlertTypeProps): JSX.Element {
break;
case AlertTypes.EXCEPTIONS_BASED_ALERT:
url =
- 'https://signoz.io/docs/alerts-management/exceptions-based-alerts/?utm_source=product&utm_medium=alert-source-selection-page#example';
+ 'https://signoz.io/docs/alerts-management/exceptions-based-alerts/?utm_source=product&utm_medium=alert-source-selection-page#examples';
break;
default:
break;
diff --git a/frontend/src/container/ListAlertRules/AlertsEmptyState/AlertInfoCard.tsx b/frontend/src/container/ListAlertRules/AlertsEmptyState/AlertInfoCard.tsx
new file mode 100644
index 0000000000..76403a1884
--- /dev/null
+++ b/frontend/src/container/ListAlertRules/AlertsEmptyState/AlertInfoCard.tsx
@@ -0,0 +1,37 @@
+/* eslint-disable jsx-a11y/no-static-element-interactions */
+/* eslint-disable jsx-a11y/click-events-have-key-events */
+import { ArrowRightOutlined } from '@ant-design/icons';
+import { Typography } from 'antd';
+
+interface AlertInfoCardProps {
+ header: string;
+ subheader: string;
+ link: string;
+}
+
+function AlertInfoCard({
+ header,
+ subheader,
+ link,
+}: AlertInfoCardProps): JSX.Element {
+ return (
+
{
+ window.open(link, '_blank');
+ }}
+ >
+
+
+ {header}
+
+
+ {subheader}
+
+
+
+
+ );
+}
+
+export default AlertInfoCard;
diff --git a/frontend/src/container/ListAlertRules/AlertsEmptyState/AlertsEmptyState.styles.scss b/frontend/src/container/ListAlertRules/AlertsEmptyState/AlertsEmptyState.styles.scss
new file mode 100644
index 0000000000..c852b5833b
--- /dev/null
+++ b/frontend/src/container/ListAlertRules/AlertsEmptyState/AlertsEmptyState.styles.scss
@@ -0,0 +1,251 @@
+.alert-list-container {
+ margin-top: 104px;
+ margin-bottom: 30px;
+ display: flex;
+ justify-content: center;
+ width: 100%;
+
+ .alert-list-view-content {
+ width: calc(100% - 30px);
+ max-width: 836px;
+
+ .alert-list-title-container {
+ .title {
+ color: var(--bg-vanilla-100);
+ font-size: var(--font-size-lg);
+ font-style: normal;
+ font-weight: var(--font-weight-normal);
+ line-height: 28px; /* 155.556% */
+ letter-spacing: -0.09px;
+ }
+
+ .subtitle {
+ color: var(--bg-vanilla-400);
+ font-size: var(--font-size-sm);
+ font-style: normal;
+ font-weight: var(--font-weight-normal);
+ line-height: 20px; /* 142.857% */
+ letter-spacing: -0.07px;
+ }
+ }
+
+ .empty-alert-info-container {
+ display: flex;
+ padding: 71px 193.5px;
+ justify-content: center;
+ align-items: center;
+ border-radius: 6px;
+ border: 1px dashed var(--bg-slate-500);
+ margin-top: 16px;
+
+ .alert-content {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 12px;
+
+ .heading {
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+
+ .icons {
+ color: white;
+ }
+
+ .empty-alert-action {
+ color: var(--bg-vanilla-400);
+ font-family: Inter;
+ font-size: 14px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: 24px; /* 171.429% */
+ letter-spacing: -0.07px;
+ }
+
+ .empty-info {
+ color: var(--bg-vanilla-100);
+ font-family: Inter;
+ font-size: 14px;
+ font-style: normal;
+ font-weight: 500;
+ line-height: 24px;
+ letter-spacing: -0.07px;
+ }
+ }
+
+ .action-container {
+ display: flex;
+ gap: 24px;
+ align-items: center;
+ padding-top: 24px;
+ padding-bottom: 24px;
+ width: 100%;
+ }
+ }
+ }
+
+ .get-started-text {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ gap: 16px;
+ margin-top: 24px;
+ margin-bottom: 24px;
+ width: 100%;
+
+ .ant-divider::before,
+ .ant-divider::after {
+ border-bottom: 2px dotted var(--bg-slate-300);
+ border-top: 2px dotted var(--bg-slate-300);
+ height: 8px;
+ }
+
+ .ant-typography {
+ color: var(--bg-vanilla-400);
+ font-family: Inter;
+ font-size: 12px;
+ font-style: normal;
+ font-weight: 500;
+ line-height: 20px; /* 166.667% */
+ letter-spacing: 0.48px;
+ text-transform: uppercase;
+ padding-top: 8px;
+ }
+ }
+
+ .alert-info-card {
+ display: flex;
+ padding: 16px;
+ justify-content: space-between;
+ align-items: center;
+
+ border-radius: 6px;
+ border: 1px solid var(--bg-slate-500);
+ background: var(--bg-ink-400);
+ margin-bottom: 16px;
+
+ &:hover {
+ cursor: pointer;
+ }
+
+ .alert-card-text {
+ display: flex;
+ gap: 2px;
+ flex-direction: column;
+
+ .alert-card-text-header {
+ color: var(--bg-vanilla-100);
+ font-family: Inter;
+ font-size: 14px;
+ font-style: normal;
+ font-weight: 500;
+ line-height: 20px; /* 142.857% */
+ letter-spacing: -0.07px;
+ }
+
+ .alert-card-text-subheader {
+ color: var(--bg-vanilla-400);
+ font-family: Inter;
+ font-size: 12px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: 18px; /* 150% */
+ }
+ }
+ }
+ }
+}
+
+.info-text {
+ color: var(--bg-robin-400) !important;
+ font-family: Inter;
+ font-size: 12px;
+ font-style: normal;
+ font-weight: 500;
+ line-height: 16px; /* 133.333% */
+ letter-spacing: -0.06px;
+}
+
+.info-link-container {
+ .anticon {
+ color: var(--bg-robin-400);
+ }
+
+ :hover {
+ cursor: pointer;
+ }
+}
+
+.lightMode {
+ .alert-list-container {
+ .alert-list-view-content {
+ .alert-list-title-container {
+ .title {
+ color: var(--bg-slate-400);
+ }
+
+ .subtitle {
+ color: var(--bg-slate-100);
+ }
+ }
+
+ .empty-alert-info-container {
+ border: 1px dashed var(--bg-vanilla-400);
+
+ .alert-content {
+ .heading {
+ .icons {
+ color: white;
+ }
+
+ .empty-alert-action {
+ color: var(--bg-slate-100);
+ }
+
+ .empty-info {
+ color: var(--bg-slate-400);
+ }
+ }
+ }
+ }
+
+ .get-started-text {
+ .ant-divider::before,
+ .ant-divider::after {
+ border-bottom: 2px dotted var(--bg-vanilla-400);
+ border-top: 2px dotted var(--bg-vanilla-400);
+ }
+
+ .ant-typography {
+ color: var(--bg-slate-100);
+ }
+ }
+
+ .alert-info-card {
+ border: 1px solid var(--bg-vanilla-200);
+ background: var(--bg-vanilla-100);
+
+ .alert-card-text {
+ .alert-card-text-header {
+ color: var(--bg-slate-400);
+ }
+
+ .alert-card-text-subheader {
+ color: var(--bg-slate-100);
+ }
+ }
+ }
+ }
+ }
+
+ .info-text {
+ color: var(--bg-robin-600) !important;
+ }
+
+ .info-link-container {
+ .anticon {
+ color: var(--bg-robin-400);
+ }
+ }
+}
diff --git a/frontend/src/container/ListAlertRules/AlertsEmptyState/AlertsEmptyState.tsx b/frontend/src/container/ListAlertRules/AlertsEmptyState/AlertsEmptyState.tsx
new file mode 100644
index 0000000000..0f388053c0
--- /dev/null
+++ b/frontend/src/container/ListAlertRules/AlertsEmptyState/AlertsEmptyState.tsx
@@ -0,0 +1,127 @@
+import './AlertsEmptyState.styles.scss';
+
+import { PlusOutlined } from '@ant-design/icons';
+import { Button, Divider, Typography } from 'antd';
+import ROUTES from 'constants/routes';
+import useComponentPermission from 'hooks/useComponentPermission';
+import { useNotifications } from 'hooks/useNotifications';
+import history from 'lib/history';
+import { useCallback, useState } from 'react';
+import { useTranslation } from 'react-i18next';
+import { useSelector } from 'react-redux';
+import { AppState } from 'store/reducers';
+import AppReducer from 'types/reducer/app';
+
+import AlertInfoCard from './AlertInfoCard';
+import { ALERT_CARDS, ALERT_INFO_LINKS } from './alertLinks';
+import InfoLinkText from './InfoLinkText';
+
+export function AlertsEmptyState(): JSX.Element {
+ const { t } = useTranslation('common');
+ const { role, featureResponse } = useSelector(
+ (state) => state.app,
+ );
+ const [addNewAlert] = useComponentPermission(
+ ['add_new_alert', 'action'],
+ role,
+ );
+
+ const { notifications: notificationsApi } = useNotifications();
+
+ const handleError = useCallback((): void => {
+ notificationsApi.error({
+ message: t('something_went_wrong'),
+ });
+ }, [notificationsApi, t]);
+
+ const [loading, setLoading] = useState(false);
+
+ const onClickNewAlertHandler = useCallback(() => {
+ setLoading(true);
+ featureResponse
+ .refetch()
+ .then(() => {
+ setLoading(false);
+ history.push(ROUTES.ALERTS_NEW);
+ })
+ .catch(handleError)
+ .finally(() => setLoading(false));
+ }, [featureResponse, handleError]);
+
+ return (
+
+
+
+ Alert Rules
+
+ Create and manage alert rules for your resources.
+
+
+
+
+
+
+
+
+ No Alert rules yet.{' '}
+
+
+ Create an Alert Rule to get started
+
+
+
+
+ }
+ disabled={!addNewAlert}
+ loading={loading}
+ type="primary"
+ data-testid="add-alert"
+ >
+ New Alert Rule
+
+
+
+
+ {ALERT_INFO_LINKS.map((info) => (
+
+ ))}
+
+
+
+
+
+ Or get started with these sample alerts
+
+
+
+
+ {ALERT_CARDS.map((card) => (
+
+ ))}
+
+
+ );
+}
diff --git a/frontend/src/container/ListAlertRules/AlertsEmptyState/InfoLinkText.tsx b/frontend/src/container/ListAlertRules/AlertsEmptyState/InfoLinkText.tsx
new file mode 100644
index 0000000000..1f17cd3969
--- /dev/null
+++ b/frontend/src/container/ListAlertRules/AlertsEmptyState/InfoLinkText.tsx
@@ -0,0 +1,31 @@
+import { ArrowRightOutlined, PlayCircleFilled } from '@ant-design/icons';
+import { Flex, Typography } from 'antd';
+
+interface InfoLinkTextProps {
+ infoText: string;
+ link: string;
+ leftIconVisible: boolean;
+ rightIconVisible: boolean;
+}
+
+function InfoLinkText({
+ infoText,
+ link,
+ leftIconVisible,
+ rightIconVisible,
+}: InfoLinkTextProps): JSX.Element {
+ return (
+ {
+ window.open(link, '_blank');
+ }}
+ className="info-link-container"
+ >
+ {leftIconVisible && }
+ {infoText}
+ {rightIconVisible && }
+
+ );
+}
+
+export default InfoLinkText;
diff --git a/frontend/src/container/ListAlertRules/AlertsEmptyState/alertLinks.ts b/frontend/src/container/ListAlertRules/AlertsEmptyState/alertLinks.ts
new file mode 100644
index 0000000000..fac0ad6b12
--- /dev/null
+++ b/frontend/src/container/ListAlertRules/AlertsEmptyState/alertLinks.ts
@@ -0,0 +1,50 @@
+export const ALERT_INFO_LINKS = [
+ {
+ infoText: 'How to create Metrics-based alerts',
+ link:
+ 'https://signoz.io/docs/alerts-management/metrics-based-alerts/?utm_source=product&utm_medium=alert-empty-page',
+ leftIconVisible: false,
+ rightIconVisible: true,
+ },
+ {
+ infoText: 'How to create Log-based alerts',
+ link:
+ 'https://signoz.io/docs/alerts-management/log-based-alerts/?utm_source=product&utm_medium=alert-empty-page',
+ leftIconVisible: false,
+ rightIconVisible: true,
+ },
+ {
+ infoText: 'How to create Trace-based alerts',
+ link:
+ 'https://signoz.io/docs/alerts-management/trace-based-alerts/?utm_source=product&utm_medium=alert-empty-page',
+ leftIconVisible: false,
+ rightIconVisible: true,
+ },
+];
+
+export const ALERT_CARDS = [
+ {
+ header: 'Alert on high memory usage',
+ subheader: "Monitor your host's memory usage",
+ link:
+ 'https://signoz.io/docs/alerts-management/metrics-based-alerts/?utm_source=product&utm_medium=alert-empty-page#1-alert-when-memory-usage-for-host-goes-above-400-mb-or-any-fixed-memory',
+ },
+ {
+ header: 'Alert on slow external API calls',
+ subheader: 'Monitor your external API calls',
+ link:
+ 'https://signoz.io/docs/alerts-management/trace-based-alerts/?utm_source=product&utm_medium=alert-empty-page#1-alert-when-external-api-latency-p90-is-over-1-second-for-last-5-mins',
+ },
+ {
+ header: 'Alert on high percentage of timeout errors in logs',
+ subheader: 'Monitor your logs for errors',
+ link:
+ 'https://signoz.io/docs/alerts-management/log-based-alerts/?utm_source=product&utm_medium=alert-empty-page#1-alert-when-percentage-of-redis-timeout-error-logs-greater-than-7-in-last-5-mins',
+ },
+ {
+ header: 'Alert on high error percentage of an endpoint',
+ subheader: 'Monitor your API endpoint',
+ link:
+ 'https://signoz.io/docs/alerts-management/metrics-based-alerts/?utm_source=product&utm_medium=alert-empty-page#3-alert-when-the-error-percentage-for-an-endpoint-exceeds-5',
+ },
+];
diff --git a/frontend/src/container/ListAlertRules/index.tsx b/frontend/src/container/ListAlertRules/index.tsx
index 3880a7c2e6..810cd0eb9b 100644
--- a/frontend/src/container/ListAlertRules/index.tsx
+++ b/frontend/src/container/ListAlertRules/index.tsx
@@ -8,6 +8,7 @@ import { useTranslation } from 'react-i18next';
import { useQuery } from 'react-query';
import { useLocation } from 'react-router-dom';
+import { AlertsEmptyState } from './AlertsEmptyState/AlertsEmptyState';
import ListAlert from './ListAlert';
function ListAlertRules(): JSX.Element {
@@ -45,6 +46,10 @@ function ListAlertRules(): JSX.Element {
);
}
+ if (status === 'success' && !data.payload?.length) {
+ return ;
+ }
+
// in case of loading
if (isLoading || !data?.payload) {
return ;