Open aw1cks opened 10 months ago
I did play around with this - here's a somewhat hacky, but working change: https://github.com/aw1cks-forks/alertmanager/commit/5fca6eb4f68b516d52b13975e914ce12c08ae48d I'd imagine it'd be best to keep the existing MessageCard implementation and allow users to opt into adaptive cards if desired.
I added support for Adaptive Cards to Grafana. Perhaps we can use the same code for Alertmanager too? @gotjosh
Nice! That seems like a path of low resistance.
My only comment is that the card format appears to be quite prescriptive, which does limit the cusomisability.
@aw1cks Been playing around with this today. Got some nice dynamic creation of the Cards to work well all through just passing in the JSON data inside a .tmpl file that was defining the text. Awesome stuff.
Can you consider opening a PR for your changes? It makes the alerting experience in Teams much better.
{{ define "new.text" }}
{
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.2",
"padding": "None",
"msteams": {
"width": "Full"
},
"body": [
{
"type": "Container",
"id": "alert-msg",
"padding": "Default",
"items": [
{
"type": "TextBlock",
"id": "alert-summary-title",
"text": "[{{- if gt (len .Alerts.Firing) 0 }}FIRING: {{ .Alerts.Firing | len }}] 🔥 {{end}} {{- if gt (len .Alerts.Resolved) 0 }}RESOLVED: {{ .Alerts.Resolved | len }}] ✅ {{end}} {{ with index .Alerts 0 -}}{{ .Labels.alertname }}{{ end }}",
"weight": "Bolder",
"color": "{{- if gt (len .Alerts.Firing) 0 }}Attention{{end}}{{- if gt (len .Alerts.Resolved) 0 }}Good{{end}}",
"size": "ExtraLarge",
"horizontalAlignment": "Left"
},
{
"type": "Container",
"id": "alert-summary-container",
"padding": "None",
"items": [
{
"type": "TextBlock",
"id": "alert-summary-description",
"text": "{{ .Alerts.Firing | len }} alerts are firing",
"wrap": true
},
{
"type": "ActionSet",
"id": "alert-silence-action",
"actions": [
{
"type": "Action.OpenUrl",
"id": "silence",
"title": "Silence",
"url": "{{ .ExternalURL }}/#/silences/new?filter=%7B
{{- range $key, $value := .CommonLabels }}
{{- if eq $key "alertname" }}{{ $key }}%3D%22{{ reReplaceAll "\\\\" "" $value }}%22{{ end }}
{{- end }}
{{- range $key, $value := .CommonLabels }}
{{- if ne $key "alertname" }}%2C{{ $key }}%3D%22{{ reReplaceAll "\\\\" "" $value }}%22{{ end }}
{{- end -}}%7D"
},
{{ with $alert := index .Alerts 0}}
{
"type": "Action.OpenUrl",
"id": "prom",
"title": "View in Prometheus",
"url": "{{ .GeneratorURL }}"
}
{{ end }}
]
}
]
},
{{ range $index, $alert := .Alerts.Firing }}
{
"type": "Container",
"id": "{{ $index }}-alerts-container",
"isVisible": true,
"padding": "None",
"items": [
{
"type": "Container",
"id": "alert-{{ $index }}-msg-container",
"padding": "None",
"separator": true,
"items": [
{
"type": "TextBlock",
"id": "alert-{{ $index }}-summary",
"text": "{{ $alert.Labels.alertname}}",
"wrap": true,
"size": "Medium",
"weight": "Bolder"
},
{
"type": "TextBlock",
"id": "alert-{{ $index }}-description",
"text": "{{ $alert.Annotations.description }}",
"wrap": true,
"weight": "Lighter",
"size": "Small"
},
{
"type": "ActionSet",
"id": "alert-{{ $index }}-actions",
"actions": [
{
"type": "Action.ShowCard",
"title": "View Labels",
"card": {
"type": "AdaptiveCard",
"body": [
{
"type": "TextBlock",
"wrap": true,
"text": "{{ $alert.Labels }}"
}
]
}
},
{
"type": "Action.ShowCard",
"title": "View Annotations",
"card": {
"type": "AdaptiveCard",
"body": [
{
"type": "TextBlock",
"wrap": true,
"text": "{{ $alert.Annotations }}"
}
]
}
}
]
},
{
"type": "Container",
"id": "alert-{{ $index }}-backup-labels-container",
"padding": "None",
"isVisible": false,
"items": [
{
"type": "FactSet",
"id": "alert-{{ $index }}-backup-labels-factset",
"facts": []
}
]
}
]
}
]
},
{{ end }}
{{ range $index, $alert := .Alerts.Resolved }}
{
"type": "Container",
"id": "{{ $index }}-alerts-container",
"isVisible": true,
"padding": "None",
"items": [
{
"type": "Container",
"id": "alert-{{ $index }}-msg-container",
"padding": "None",
"separator": true,
"items": [
{
"type": "TextBlock",
"id": "alert-{{ $index }}-summary",
"text": "{{ $alert.Labels.alertname}}",
"wrap": true,
"size": "Medium",
"weight": "Bolder"
},
{
"type": "TextBlock",
"id": "alert-{{ $index }}-description",
"text": "{{ $alert.Annotations.description }}",
"wrap": true,
"weight": "Lighter",
"size": "Small"
},
{
"type": "ActionSet",
"id": "alert-{{ $index }}-actions",
"actions": [
{
"type": "Action.ShowCard",
"title": "View Labels",
"card": {
"type": "AdaptiveCard",
"body": [
{
"type": "TextBlock",
"wrap": true,
"text": "{{ $alert.Labels }}"
}
]
}
},
{
"type": "Action.ShowCard",
"title": "View Annotations",
"card": {
"type": "AdaptiveCard",
"body": [
{
"type": "TextBlock",
"wrap": true,
"text": "{{ $alert.Annotations }}"
}
]
}
}
]
},
{
"type": "Container",
"id": "alert-{{ $index }}-backup-labels-container",
"padding": "None",
"isVisible": false,
"items": [
{
"type": "FactSet",
"id": "alert-{{ $index }}-backup-labels-factset",
"facts": []
}
]
}
]
}
]
},
{{ end }}
{
"type": "Container",
"id": "backup-alerts-container",
"isVisible": false,
"padding": "None",
"items": [
{
"type": "Container",
"id": "alert-catch-msg-container",
"padding": "None",
"separator": false,
"items": []
}
]
}
]
}
]
}
{{ end }}
receivers:
- name: sandbox
msteams_configs:
- webhook_url: "YOUR_WEBHOOK_HERE"
text: '{{ template "new.text" . }}'
Then I just send a POST with my JSON alert data to the Alertmanager /api/v2/alerts endpoint.
To me it seems like this one is not something that may fit everyones needs and indeed forming json via go templating is a portal to hell
For anyone looking for workaround you may do very simple trick:
From alertmanager side configure webhook receiver, aka:
receivers:
- name: default
webhook_configs:
- send_resolved: false
url: http://localhost:8080/demo
alertmanager will just send raw json payload to given url
and now you can code some simple, single endpoint service, that will take given input, transform it to whatever you wish to have in teams and send it to teams, aka:
Use designer to form message and samples for inspiration
Hi there,
I saw that MS Teams support was recently added, many thanks for that! I've been using prometheus-msteams at work for quite some time and it will be great to have the integration natively.
It would be awesome if support for the newer adaptive cards message format could be added at some point.
Here's the payload needed to fire these into Teams:
And here's a sample alert that I created: https://gist.github.com/aw1cks/20c60986e789342a5e1e847b5d05a954
Proposal
Add a configuration option for the msteams integration, to switch the payload format to adaptive web cards, delegating responsibility for creating valid adaptive card JSON to the user's template.
One complication is that it's not trivial to keep a separate title and text template per current implementation - but I'd propose that if the aforementioned config option were enabled, that it'd be left to the user to template the title as they saw fit, and just read the
text
field, placing it directly into thecontent
field of the above JSON payload.If such an approach would be accepted, I'd be happy to look at doing this!