import { css, cx } from '@emotion/css'; import React from 'react'; import SVG from 'react-inlinesvg'; import { GrafanaTheme2 } from '@grafana/data'; import { Stack } from '@grafana/experimental'; import { config } from '@grafana/runtime'; import { Icon, useStyles2, useTheme2 } from '@grafana/ui'; import { AlertingPageWrapper } from './components/AlertingPageWrapper'; export default function Home() { const theme = useTheme2(); const styles = useStyles2(getWelcomePageStyles); return (

How it works

  • Grafana alerting periodically queries data sources and evaluates the condition defined in the alert rule
  • If the condition is breached, an alert instance fires
  • Firing instances are routed to notification policies based on matching labels
  • Notifications are sent out to the contact points specified in the notification policy policy

Get started

  • Create an alert rule by adding queries and expressions from multiple data sources.
  • Add labels to your alert rules{' '} to connect them to notification policies
  • Configure contact points to define where to send your notifications to.
  • Configure notification policies to route your alert instances to contact points.
); } const getWelcomePageStyles = (theme: GrafanaTheme2) => ({ grid: css` display: grid; grid-template-rows: min-content auto auto; grid-template-columns: 1fr 1fr 1fr 1fr 1fr; gap: ${theme.spacing(2)}; `, ctaContainer: css` grid-column: 1 / span 5; `, flowBlock: css` grid-column: 1 / span 5; display: flex; flex-wrap: wrap; gap: ${theme.spacing(1)}; & > div { flex: 2; min-width: 350px; } & > svg { flex: 3; min-width: 500px; } `, videoBlock: css` grid-column: 3 / span 3; grid-row: 3 / span 1; // Video required position: relative; padding: 56.25% 0 0 0; /* 16:9 */ iframe { position: absolute; top: ${theme.spacing(2)}; left: ${theme.spacing(2)}; width: calc(100% - ${theme.spacing(4)}); height: calc(100% - ${theme.spacing(4)}); border: none; } `, gettingStartedBlock: css` grid-column: 1 / span 2; justify-content: space-between; `, list: css` margin: ${theme.spacing(0, 2)}; & > li { margin-bottom: ${theme.spacing(1)}; } `, }); function WelcomeHeader({ className }: { className?: string }) { const styles = useStyles2(getWelcomeHeaderStyles); return (
); } const getWelcomeHeaderStyles = (theme: GrafanaTheme2) => ({ ctaContainer: css` padding: ${theme.spacing(4, 2)}; display: flex; gap: ${theme.spacing(4)}; justify-content: space-between; flex-wrap: wrap; ${theme.breakpoints.down('lg')} { flex-direction: column; } `, separator: css` width: 1px; background-color: ${theme.colors.border.medium}; ${theme.breakpoints.down('lg')} { display: none; } `, }); interface WelcomeCTABoxProps { title: string; description: string; href: string; hrefText: string; } function WelcomeCTABox({ title, description, href, hrefText }: WelcomeCTABoxProps) { const styles = useStyles2(getWelcomeCTAButtonStyles); return (

{title}

{description}
); } const getWelcomeCTAButtonStyles = (theme: GrafanaTheme2) => ({ container: css` flex: 1; min-width: 240px; display: grid; gap: ${theme.spacing(1)}; grid-template-columns: min-content 1fr 1fr 1fr; grid-template-rows: min-content auto min-content; `, title: css` margin-bottom: 0; grid-column: 2 / span 3; grid-row: 1; `, desc: css` grid-column: 2 / span 3; grid-row: 2; `, actionRow: css` grid-column: 2 / span 3; grid-row: 3; max-width: 240px; `, link: css` color: ${theme.colors.text.link}; `, }); function ContentBox({ children, className }: React.PropsWithChildren<{ className?: string }>) { const styles = useStyles2(getContentBoxStyles); return
{children}
; } const getContentBoxStyles = (theme: GrafanaTheme2) => ({ box: css` padding: ${theme.spacing(2)}; background-color: ${theme.colors.background.secondary}; border-radius: 3px; outline: 1px solid ${theme.colors.border.strong}; `, }); function ArrowLink({ href, title }: { href: string; title: string }) { const styles = useStyles2(getArrowLinkStyles); return ( {title} ); } const getArrowLinkStyles = (theme: GrafanaTheme2) => ({ link: css` display: block; color: ${theme.colors.text.link}; `, });