diff --git a/.betterer.results b/.betterer.results index 92718adbf97..3c45ad49184 100644 --- a/.betterer.results +++ b/.betterer.results @@ -1623,7 +1623,8 @@ exports[`better eslint`] = { [0, 0, 0, "No untranslated strings. Wrap text with ", "3"], [0, 0, 0, "No untranslated strings. Wrap text with ", "4"], [0, 0, 0, "No untranslated strings. Wrap text with ", "5"], - [0, 0, 0, "No untranslated strings. Wrap text with ", "6"] + [0, 0, 0, "No untranslated strings. Wrap text with ", "6"], + [0, 0, 0, "No untranslated strings. Wrap text with ", "7"] ], "public/app/features/alerting/unified/components/receivers/TemplatePreview.tsx:5381": [ [0, 0, 0, "No untranslated strings. Wrap text with ", "0"] diff --git a/public/app/features/alerting/unified/components/receivers/PayloadEditor.tsx b/public/app/features/alerting/unified/components/receivers/PayloadEditor.tsx index 9c2966adbcb..cabf3e15cd3 100644 --- a/public/app/features/alerting/unified/components/receivers/PayloadEditor.tsx +++ b/public/app/features/alerting/unified/components/receivers/PayloadEditor.tsx @@ -111,7 +111,7 @@ export function PayloadEditor({ } placement="top" fitContent> diff --git a/public/app/features/alerting/unified/components/receivers/TemplateDataDocs.tsx b/public/app/features/alerting/unified/components/receivers/TemplateDataDocs.tsx index fd3db87ce62..8dfa3b62329 100644 --- a/public/app/features/alerting/unified/components/receivers/TemplateDataDocs.tsx +++ b/public/app/features/alerting/unified/components/receivers/TemplateDataDocs.tsx @@ -51,7 +51,7 @@ export function TemplateDataDocs() { ); } -const getTemplateDataDocsStyles = (theme: GrafanaTheme2) => ({ +export const getTemplateDataDocsStyles = (theme: GrafanaTheme2) => ({ header: css({ color: theme.colors.text.primary, @@ -131,7 +131,7 @@ function KeyValueTemplateDataTable() { ); } -const getTemplateDataTableStyles = (theme: GrafanaTheme2) => ({ +export const getTemplateDataTableStyles = (theme: GrafanaTheme2) => ({ table: css({ borderCollapse: 'collapse', width: '100%', diff --git a/public/app/features/alerting/unified/components/receivers/TemplateDataExamples.ts b/public/app/features/alerting/unified/components/receivers/TemplateDataExamples.ts new file mode 100644 index 00000000000..416ed897bc6 --- /dev/null +++ b/public/app/features/alerting/unified/components/receivers/TemplateDataExamples.ts @@ -0,0 +1,148 @@ +export interface TemplateExampleItem { + description: string; + example: string; +} + +export const GlobalTemplateDataExamples: TemplateExampleItem[] = [ + { + description: 'Default template for notification titles', + example: `{{- /* This is a copy of the "default.title" template. */ -}} +{{- /* Edit the template name and template content as needed. */ -}} +{{ define "default.title.copy" }} + [{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ if gt (.Alerts.Resolved | len) 0 }}, RESOLVED:{{ .Alerts.Resolved | len }}{{ end }}{{ end }}] {{ .GroupLabels.SortedPairs.Values | join " " }} {{ if gt (len .CommonLabels) (len .GroupLabels) }}({{ with .CommonLabels.Remove .GroupLabels.Names }}{{ .Values | join " " }}{{ end }}){{ end }} +{{ end }}`, + }, + { + description: 'Default template for notification messages', + example: `{{- /* This is a copy of the "default.message" template. */ -}} +{{- /* Edit the template name and template content as needed. */ -}} +{{ define "default.message.copy" }}{{ if gt (len .Alerts.Firing) 0 }}**Firing** +{{ template "__text_alert_list.copy" .Alerts.Firing }}{{ if gt (len .Alerts.Resolved) 0 }} + +{{ end }}{{ end }}{{ if gt (len .Alerts.Resolved) 0 }}**Resolved** +{{ template "__text_alert_list.copy" .Alerts.Resolved }}{{ end }}{{ end }} + +{{ define "__text_alert_list.copy" }}{{ range . }} +Value: {{ template "__text_values_list.copy" . }} +Labels: +{{ range .Labels.SortedPairs }} - {{ .Name }} = {{ .Value }} +{{ end }}Annotations: +{{ range .Annotations.SortedPairs }} - {{ .Name }} = {{ .Value }} +{{ end }}{{ if gt (len .GeneratorURL) 0 }}Source: {{ .GeneratorURL }} +{{ end }}{{ if gt (len .SilenceURL) 0 }}Silence: {{ .SilenceURL }} +{{ end }}{{ if gt (len .DashboardURL) 0 }}Dashboard: {{ .DashboardURL }} +{{ end }}{{ if gt (len .PanelURL) 0 }}Panel: {{ .PanelURL }} +{{ end }}{{ end }}{{ end }} + +{{ define "__text_values_list.copy" }}{{ if len .Values }}{{ $first := true }}{{ range $refID, $value := .Values -}} +{{ if $first }}{{ $first = false }}{{ else }}, {{ end }}{{ $refID }}={{ $value }}{{ end -}} +{{ else }}[no value]{{ end }}{{ end }}`, + }, + { + description: 'Print alerts with summary and description', + example: `{{- /* Example displaying the summary and description annotations of each alert in the notification. */ -}} +{{- /* Edit the template name and template content as needed. */ -}} +{{ define "custom.alerts" -}} +{{ len .Alerts }} alert(s) +{{ range .Alerts -}} + {{ template "alert.summary_and_description" . -}} +{{ end -}} +{{ end -}} + +{{ define "alert.summary_and_description" }} + Summary: {{.Annotations.summary}} + Status: {{ .Status }} + Description: {{.Annotations.description}} +{{ end -}}`, + }, + { + description: 'Print firing and resolved alerts', + example: `{{- /* Example displaying firing and resolved alerts separately in the notification. */ -}} +{{- /* Edit the template name and template content as needed. */ -}} +{{ define "custom.firing_and_resolved_alerts" -}} +{{ len .Alerts.Resolved }} resolved alert(s) +{{ range .Alerts.Resolved -}} + {{ template "alert.summary_and_description" . -}} +{{ end }} +{{ len .Alerts.Firing }} firing alert(s) +{{ range .Alerts.Firing -}} + {{ template "alert.summary_and_description" . -}} +{{ end -}} +{{ end -}} + +{{ define "alert.summary_and_description" }} + Summary: {{.Annotations.summary}} + Status: {{ .Status }} + Description: {{.Annotations.description}} +{{ end -}}`, + }, + { + description: 'Print common labels and annotations', + example: `{{- /* Example displaying labels and annotations that are common to all alerts in the notification.*/ -}} +{{- /* Edit the template name and template content as needed. */ -}} +{{ define "custom.common_labels_and_annotations" -}} +{{ len .Alerts.Resolved }} resolved alert(s) +{{ len .Alerts.Firing }} firing alert(s) + +Common labels: {{ len .CommonLabels.SortedPairs }} +{{ range .CommonLabels.SortedPairs -}} +- {{ .Name }} = {{ .Value }} +{{ end }} + +Common annotations: {{ len .CommonAnnotations.SortedPairs }} +{{ range .CommonAnnotations.SortedPairs }} +- {{ .Name }} = {{ .Value }} +{{ end }} + +{{ end -}}`, + }, + { + description: 'Print individual labels and annotations', + example: `{{- /* Example displaying all labels and annotations for each alert in the notification.*/ -}} +{{- /* Edit the template name and template content as needed. */ -}} +{{ define "custom.alert_labels_and_annotations" -}} +{{ len .Alerts.Resolved }} resolved alert(s) +{{ range .Alerts.Resolved -}} + {{ template "alert.labels_and_annotations" . -}} +{{ end }} +{{ len .Alerts.Firing }} firing alert(s) +{{ range .Alerts.Firing -}} + {{ template "alert.labels_and_annotations" . -}} +{{ end -}} +{{ end -}} + +{{ define "alert.labels_and_annotations" }} +Alert labels: {{ len .Labels.SortedPairs }} +{{ range .Labels.SortedPairs -}} +- {{ .Name }} = {{ .Value }} +{{ end -}} +Alert annotations: {{ len .Annotations.SortedPairs }} +{{ range .Annotations.SortedPairs -}} +- {{ .Name }} = {{ .Value }} +{{ end -}} +{{ end -}}`, + }, + { + description: 'Print URLs for runbook and alert data in Grafana', + example: `{{- /* Example displaying additional information, such as runbook link, DashboardURL and SilenceURL, for each alert in the notification.*/ -}} +{{- /* Edit the template name and template content as needed. */ -}} +{{ define "custom.alert_additional_details" -}} +{{ len .Alerts.Resolved }} resolved alert(s) +{{ range .Alerts.Resolved -}} + {{ template "alert.additional_details" . -}} +{{ end }} +{{ len .Alerts.Firing }} firing alert(s) +{{ range .Alerts.Firing -}} + {{ template "alert.additional_details" . -}} +{{ end -}} +{{ end -}} + +{{ define "alert.additional_details" }} +- Dashboard: {{ .DashboardURL }} +- Panel: {{ .PanelURL }} +- AlertGenerator: {{ .GeneratorURL }} +- Silence: {{ .SilenceURL }} +- RunbookURL: {{ .Annotations.runbook_url}} +{{ end -}}`, + }, +]; diff --git a/public/app/features/alerting/unified/components/receivers/TemplateForm.tsx b/public/app/features/alerting/unified/components/receivers/TemplateForm.tsx index e1e07f99e96..205c49fcc5f 100644 --- a/public/app/features/alerting/unified/components/receivers/TemplateForm.tsx +++ b/public/app/features/alerting/unified/components/receivers/TemplateForm.tsx @@ -11,9 +11,11 @@ import { isFetchError, locationService } from '@grafana/runtime'; import { Alert, Button, + Dropdown, FieldSet, Input, LinkButton, + Menu, useStyles2, Stack, useSplitter, @@ -43,6 +45,7 @@ import { import { PayloadEditor } from './PayloadEditor'; import { TemplateDataDocs } from './TemplateDataDocs'; +import { GlobalTemplateDataExamples } from './TemplateDataExamples'; import { TemplateEditor } from './TemplateEditor'; import { TemplatePreview } from './TemplatePreview'; import { snippets } from './editor/templateDataSuggestions'; @@ -157,6 +160,12 @@ export const TemplateForm = ({ originalTemplate, prefill, alertmanager }: Props) } }; + const appendExample = (example: string) => { + const content = getValues('content'), + newValue = !content ? example : `${content}\n${example}`; + setValue('content', newValue); + }; + const actionButtons = ( - } - /> +
+ + {/* examples dropdown – only available for Grafana Alertmanager */} + {isGrafanaAlertManager && ( + + {GlobalTemplateDataExamples.map((item, index) => ( + appendExample(item.example)} + /> + ))} + + + + } + > + + + )} + + + } + /> +
{({ width, height }) => (