diff --git a/changelog.d/808.feature b/changelog.d/808.feature new file mode 100644 index 00000000..8ab64a6f --- /dev/null +++ b/changelog.d/808.feature @@ -0,0 +1 @@ +Add generic webhook transformation JS snippet for Prometheus Alertmanager. diff --git a/contrib/jsTransformationFunctions/alertmanager.js b/contrib/jsTransformationFunctions/alertmanager.js new file mode 100644 index 00000000..11ec18aa --- /dev/null +++ b/contrib/jsTransformationFunctions/alertmanager.js @@ -0,0 +1,68 @@ +/** + * This is a transformation function for Prometheus Alertmanager webhooks. + * https://prometheus.io/docs/alerting/latest/configuration/#webhook_config + * + * Creates a formatted `m.text` message with plaintext fallback, containing: + * - alert status and severity + * - alert name and description + * - URL to the entity that caused the alert + * The formatted message also contains a clickable link that silences the alert. + */ + +/** + * @param status resolved or firing + * @param severity from the labels of the alert + * @returns colored text rendering of the status and severity + */ +function statusBadge(status, severity) { + let statusColor; + if (status === "resolved") { + return `[RESOLVED]`; + } + + switch(severity) { + case 'resolved': + case 'critical': + return `[FIRING - CRITICAL]`; + case 'warning': + return `[FIRING - WARNING]`; + default: + return `[${status.toUpperCase()}]`; + } +} + +/** + * @param alert object from the webhook payload + * @param externalURL from the webhook payload + * @returns a formatted link that will silence the alert when clicked + */ +function silenceLink(alert, externalURL) { + filters = [] + for (const [label, val] of Object.entries(alert.labels)) { + filters.push(encodeURIComponent(`${label}="${val}"`)); + } + return `silence`; +} + +if (!data.alerts) { + result = { + version: 'v2', + empty: true, + }; + return; +} + +const plainErrors = []; +const htmlErrors = []; +const { externalURL, alerts } = data; + +for (const alert of data.alerts) { + plainErrors.push(`**[${alert.status.toUpperCase()} - ${alert.labels.severity}]** - ${alert.labels.alertname}: ${alert.annotations.description} [source](${alert.generatorURL})`); + htmlErrors.push(`
${statusBadge(alert.status, alert.labels.severity)}
${alert.labels.alertname}: ${alert.annotations.description.replaceAll("\n","
")}
source | ${silenceLink(alert, externalURL)}
`) + result = { + version: 'v2', + plain: plainErrors.join(`\n\n`), + html: htmlErrors.join(`