-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feature] Support adaptive cards for MSTeams #3503
Comments
I did play around with this - here's a somewhat hacky, but working change: aw1cks-forks@5fca6eb |
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 Can you consider opening a PR for your changes? It makes the alerting experience in Teams much better. FiringResolvedLabel / Annotations View:Silences:
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 Here is an exampleconst body = {
receiver: 'default',
status: 'firing',
alerts: [
{
status: 'firing',
labels: {
alertname: 'demo2',
component: 'bar',
severity: 'info',
},
annotations: {},
startsAt: '2024-05-13T06:11:03.188793747Z',
endsAt: '0001-01-01T00:00:00Z',
generatorURL: '',
fingerprint: 'c8002adfd87cf31c',
},
{
status: 'firing',
labels: {
alertname: 'demo2',
component: 'foo',
severity: 'info',
},
annotations: {},
startsAt: '2024-05-13T06:11:03.177669584Z',
endsAt: '0001-01-01T00:00:00Z',
generatorURL: '',
fingerprint: 'd31cdf353f33ac5b',
},
],
groupLabels: { alertname: 'demo2', severity: 'info' },
commonLabels: { alertname: 'demo2', severity: 'info' },
commonAnnotations: {},
externalURL: 'http://eb024ed65dcf:9093',
version: '4',
groupKey: '{}:{alertname="demo2", severity="info"}',
truncatedAlerts: 0,
}
const email =
body?.groupLabels?.annotation_owner ||
body?.commonLabels?.annotation_owner ||
body?.groupLabels?.owner ||
body?.commonLabels?.owner ||
body?.groupLabels?.tag_owner ||
body?.commonLabels?.tag_owner ||
body?.alerts?.[0]?.labels?.annotation_owner ||
body?.alerts?.[0]?.labels?.owner ||
body?.alerts?.[0]?.labels?.tag_owner ||
'[email protected]' // ''
const payload = {
type: 'message',
attachments: [
{
contentType: 'application/vnd.microsoft.card.adaptive',
content: {
$schema: 'http://adaptivecards.io/schemas/adaptive-card.json',
version: '1.0',
type: 'AdaptiveCard',
body: [
{
type: 'TextBlock',
weight: 'default',
text: `<at>${email}</at>`,
},
],
msteams: {
entities: [
{
type: 'mention',
text: `<at>${email}</at>`,
mentioned: {
id: email,
name: email,
},
},
],
},
},
},
],
}
for (const alert of body.alerts) {
const table = {
type: 'Table',
columns: [{ width: 1 }, { width: 1 }],
rows: [],
}
for (const [key, val] of Object.entries(alert.labels)) {
table.rows.push({
type: 'TableRow',
cells: [
{
type: 'TableCell',
items: [
{
type: 'TextBlock',
text: key,
wrap: true,
weight: 'default',
},
],
},
{
type: 'TableCell',
items: [
{
type: 'TextBlock',
text: val,
wrap: true,
weight: key === 'alertname' ? 'bolder' : 'default', // 'bolder'
color: 'default', // 'attention', 'good', 'warning' depending on key and val, aka status=firing - attention, severity=warning - warning
},
],
},
],
})
}
payload.attachments[0].content.body.push(table)
const actions = {
type: 'ActionSet',
actions: [],
}
if (alert.generatorURL) {
actions.actions.push({
type: 'Action.OpenUrl',
title: 'prometheus',
url: alert.generatorURL,
})
}
if (body.externalURL) {
actions.actions.push({
type: 'Action.OpenUrl',
title: 'alertmanager',
url: body.externalURL,
})
actions.actions.push({
type: 'Action.OpenUrl',
title: 'silence',
url: body.externalURL, // TODO: build silence link
})
}
actions.actions.push({
type: 'Action.OpenUrl',
title: 'readme',
url: `https://mac.atlassian.net/wiki/search?spaces=OPS&text=${alert.labels.alertname}`,
})
payload.attachments[0].content.body.push(actions)
}
console.log(JSON.stringify(payload, null, 4))
const res = await fetch(
'https://mac.webhook.office.com/webhookb2/.../IncomingWebhook/...',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
}
)
console.log(res.status) // 200
console.log(res.statusText) // 'OK'
console.log(await res.text()) // '1'
|
Breaking: Microsoft is deprecating "Connectors" in favor of "Power Automate Workflows": Also a.f.a.i.k, the old "Message Card"-format is deprecated in this solution, and only "Adaptive Card" will work. So in order for AlertManager > Teams integration to work in August, this will need to be added. |
Are there any concrete plans to add support for Adaptive Cards yet? |
Bumping the request as well. Thanks :) |
Any news on this? |
Looks like support for Workflows has been added via: Currently only released in a RC, but I guess the official release will follow soon. |
It looks like, while |
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!
The text was updated successfully, but these errors were encountered: