oncall-engine/engine/config_integrations/alertmanager.py
Ildar Iskhakov 82c564fecb
Check for invalid urls in slack (#5055)
# What this PR does


We recently changed the default template
(https://github.com/grafana/oncall/pull/5005) but some alertmanagers may
send invalid URLs.

Our fronted has the check for invalid URLs ("he Integration template
Source Link is invalid"), but slack does not, so I added this check


## Which issue(s) this PR closes

Related to [issue link here]

<!--
*Note*: If you want the issue to be auto-closed once the PR is merged,
change "Related to" to "Closes" in the line above.
If you have more than one GitHub issue that this PR closes, be sure to
preface
each issue link with a [closing
keyword](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/using-keywords-in-issues-and-pull-requests#linking-a-pull-request-to-an-issue).
This ensures that the issue(s) are auto-closed once the PR has been
merged.
-->

## Checklist

- [ ] Unit, integration, and e2e (if applicable) tests updated
- [ ] Documentation added (or `pr:no public docs` PR label added if not
required)
- [ ] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
    show up in the autogenerated release notes.
2024-09-23 08:45:32 +00:00

329 lines
9.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Main
enabled = True
title = "Alertmanager"
slug = "alertmanager"
short_description = "Connect external Alertmanager or Grafana Alerting from other Grafana instance"
is_displayed_on_web = True
is_featured = True
is_able_to_autoresolve = True
is_demo_alert_enabled = True
description = None
based_on_alertmanager = True
featured_tag_name = "Prometheus"
# Behaviour
source_link = "{{ payload.alerts[0].generatorURL }}"
grouping_id = "{{ payload.groupKey }}"
resolve_condition = """{{ payload.status == "resolved" }}"""
acknowledge_condition = None
# Web
web_title = """\
{% set groupLabels = payload.get("groupLabels", {}).copy() -%}
{% if "labels" in payload -%}
{# backward compatibility with legacy alertmanager integration -#}
{% set alertname = payload.get("labels", {}).get("alertname", "") -%}
{% else -%}
{% set alertname = groupLabels.pop("alertname", "") -%}
{% endif -%}
[{{ payload.status }}{% if payload.status == 'firing' and payload.numFiring %}:{{ payload.numFiring }}{% endif %}] {{ alertname }} {% if groupLabels | length > 0 %}({{ groupLabels.values()|join(", ") }}){% endif %}
""" # noqa
web_message = """\
{% set annotations = payload.get("commonAnnotations", {}).copy() -%}
{% set groupLabels = payload.get("groupLabels", {}) -%}
{% set commonLabels = payload.get("commonLabels", {}) -%}
{% set severity = groupLabels.severity -%}
{% set legacyLabels = payload.get("labels", {}) -%}
{% set legacyAnnotations = payload.get("annotations", {}) -%}
{% if severity -%}
{% set severity_emoji = {"critical": ":rotating_light:", "warning": ":warning:" }[severity] | default(":question:") -%}
Severity: {{ severity }} {{ severity_emoji }}
{% endif -%}
{% set status = payload.get("status", "Unknown") -%}
{% set status_emoji = {"firing": ":fire:", "resolved": ":white_check_mark:"}[status] | default(":warning:") -%}
Status: {{ status }} {{ status_emoji }} (on the source)
{% if status == "firing" and payload.numFiring -%}
Firing alerts {{ payload.numFiring }}
Resolved alerts {{ payload.numResolved }}
{% endif -%}
{% if "runbook_url" in annotations -%}
[:book: Runbook:link:]({{ annotations.runbook_url }})
{% set _ = annotations.pop('runbook_url') -%}
{% endif -%}
{% if "runbook_url_internal" in annotations -%}
[:closed_book: Runbook (internal):link:]({{ annotations.runbook_url_internal }})
{% set _ = annotations.pop('runbook_url_internal') -%}
{% endif %}
{%- if groupLabels | length > 0 %}
GroupLabels:
{% for k, v in groupLabels.items() -%}
- {{ k }}: {{ v }}
{% endfor %}
{% endif -%}
{% if commonLabels | length > 0 -%}
CommonLabels:
{% for k, v in commonLabels.items() -%}
- {{ k }}: {{ v }}
{% endfor %}
{% endif -%}
{% if annotations | length > 0 -%}
Annotations:
{% for k, v in annotations.items() -%}
- {{ k }}: {{ v }}
{% endfor %}
{% endif -%}
{# backward compatibility with legacy alertmanager integration -#}
{% if legacyLabels | length > 0 -%}
Labels:
{% for k, v in legacyLabels.items() -%}
- {{ k }}: {{ v }}
{% endfor %}
{% endif -%}
{% if legacyAnnotations | length > 0 -%}
Annotations:
{% for k, v in legacyAnnotations.items() -%}
- {{ k }}: {{ v }}
{% endfor %}
{% endif -%}
[View in AlertManager]({{ source_link }})
"""
# Slack
slack_title = """\
*<{{ grafana_oncall_link }}|#{{ grafana_oncall_incident_id }} {{ web_title }}>* via {{ integration_name }}
{% if source_link and (source_link[:8] == "https://" or source_link[:7] == "http://") %}
(*<{{ source_link }}|source>*)
{%- endif %}
"""
# default slack message template is identical to web message template, except urls
# It can be based on web message template (see example), but it can affect existing templates
# slack_message = """
# {% set mkdwn_link_regex = "\[([\w\s\d:]+)\]\((https?:\/\/[\w\d./?=#]+)\)" %}
# {{ web_message
# | regex_replace(mkdwn_link_regex, "<\\2|\\1>")
# }}
# """
slack_message = """\
{% set annotations = payload.get("commonAnnotations", {}).copy() -%}
{% set groupLabels = payload.get("groupLabels", {}) -%}
{% set commonLabels = payload.get("commonLabels", {}) -%}
{% set severity = groupLabels.severity -%}
{% set legacyLabels = payload.get("labels", {}) -%}
{% set legacyAnnotations = payload.get("annotations", {}) -%}
{% if severity -%}
{% set severity_emoji = {"critical": ":rotating_light:", "warning": ":warning:" }[severity] | default(":question:") -%}
Severity: {{ severity }} {{ severity_emoji }}
{% endif -%}
{% set status = payload.get("status", "Unknown") -%}
{% set status_emoji = {"firing": ":fire:", "resolved": ":white_check_mark:"}[status] | default(":warning:") -%}
Status: {{ status }} {{ status_emoji }} (on the source)
{% if status == "firing" and payload.numFiring -%}
Firing alerts {{ payload.numFiring }}
Resolved alerts {{ payload.numResolved }}
{% endif -%}
{% if "runbook_url" in annotations -%}
<{{ annotations.runbook_url }}|:book: Runbook:link:>
{% set _ = annotations.pop('runbook_url') -%}
{% endif -%}
{% if "runbook_url_internal" in annotations -%}
<{{ annotations.runbook_url_internal }}|:closed_book: Runbook (internal):link:>
{% set _ = annotations.pop('runbook_url_internal') -%}
{% endif %}
{%- if groupLabels | length > 0 %}
GroupLabels:
{% for k, v in groupLabels.items() -%}
- {{ k }}: {{ v }}
{% endfor %}
{% endif -%}
{% if commonLabels | length > 0 -%}
CommonLabels:
{% for k, v in commonLabels.items() -%}
- {{ k }}: {{ v }}
{% endfor %}
{% endif -%}
{% if annotations | length > 0 -%}
Annotations:
{% for k, v in annotations.items() -%}
- {{ k }}: {{ v }}
{% endfor %}
{% endif -%}
{# backward compatibility with legacy alertmanager integration -#}
{% if legacyLabels | length > 0 -%}
Labels:
{% for k, v in legacyLabels.items() -%}
- {{ k }}: {{ v }}
{% endfor %}
{% endif -%}
{% if legacyAnnotations | length > 0 -%}
Annotations:
{% for k, v in legacyAnnotations.items() -%}
- {{ k }}: {{ v }}
{% endfor %}
{% endif -%}
"""
# noqa: W291
slack_image_url = None
web_image_url = None
# SMS
sms_title = web_title
# Phone
phone_call_title = """{{ payload.get("groupLabels", {}).values() |join(", ") }}"""
# Telegram
telegram_title = web_title
telegram_message = """\
{% set annotations = payload.get("commonAnnotations", {}).copy() -%}
{% set groupLabels = payload.get("groupLabels", {}) -%}
{% set commonLabels = payload.get("commonLabels", {}) -%}
{% set severity = groupLabels.severity -%}
{% set legacyLabels = payload.get("labels", {}) -%}
{% set legacyAnnotations = payload.get("annotations", {}) -%}
{% if severity -%}
{% set severity_emoji = {"critical": ":rotating_light:", "warning": ":warning:" }[severity] | default(":question:") -%}
Severity: {{ severity }} {{ severity_emoji }}
{% endif -%}
{% set status = payload.get("status", "Unknown") -%}
{% set status_emoji = {"firing": ":fire:", "resolved": ":white_check_mark:"}[status] | default(":warning:") -%}
Status: {{ status }} {{ status_emoji }} (on the source)
{% if status == "firing" and payload.numFiring -%}
Firing alerts {{ payload.numFiring }}
Resolved alerts {{ payload.numResolved }}
{% endif -%}
{% if "runbook_url" in annotations -%}
<a href='{{ annotations.runbook_url }}'>:book: Runbook:link:</a>
{% set _ = annotations.pop('runbook_url') -%}
{% endif -%}
{% if "runbook_url_internal" in annotations -%}
<a href='{{ annotations.runbook_url_internal }}'>:closed_book: Runbook (internal):link:</a>
{% set _ = annotations.pop('runbook_url_internal') -%}
{% endif %}
{%- if groupLabels | length > 0 %}
GroupLabels:
{% for k, v in groupLabels.items() -%}
- {{ k }}: {{ v }}
{% endfor %}
{% endif -%}
{% if commonLabels | length > 0 -%}
CommonLabels:
{% for k, v in commonLabels.items() -%}
- {{ k }}: {{ v }}
{% endfor %}
{% endif -%}
{% if annotations | length > 0 -%}
Annotations:
{% for k, v in annotations.items() -%}
- {{ k }}: {{ v }}
{% endfor %}
{% endif -%}
{# backward compatibility with legacy alertmanager integration -#}
{% if legacyLabels | length > 0 -%}
Labels:
{% for k, v in legacyLabels.items() -%}
- {{ k }}: {{ v }}
{% endfor %}
{% endif -%}
{% if legacyAnnotations | length > 0 -%}
Annotations:
{% for k, v in legacyAnnotations.items() -%}
- {{ k }}: {{ v }}
{% endfor %}
{% endif -%}
<a href='{{ source_link }}'>View in AlertManager</a>
"""
telegram_image_url = None
example_payload = {
"alerts": [
{
"endsAt": "0001-01-01T00:00:00Z",
"labels": {
"job": "node",
"group": "production",
"instance": "localhost:8081",
"severity": "critical",
"alertname": "InstanceDown",
},
"status": "firing",
"startsAt": "2023-06-12T08:24:38.326Z",
"annotations": {
"title": "Instance localhost:8081 down",
"description": "localhost:8081 of job node has been down for more than 1 minute.",
},
"fingerprint": "f404ecabc8dd5cd7",
"generatorURL": "",
},
{
"endsAt": "0001-01-01T00:00:00Z",
"labels": {
"job": "node",
"group": "canary",
"instance": "localhost:8082",
"severity": "critical",
"alertname": "InstanceDown",
},
"status": "firing",
"startsAt": "2023-06-12T08:24:38.326Z",
"annotations": {
"title": "Instance localhost:8082 down",
"description": "localhost:8082 of job node has been down for more than 1 minute.",
},
"fingerprint": "f8f08d4e32c61a9d",
"generatorURL": "",
},
],
"status": "firing",
"version": "4",
"groupKey": '{}:{alertname="InstanceDown"}',
"receiver": "combo",
"numFiring": 2,
"externalURL": "",
"groupLabels": {"alertname": "InstanceDown"},
"numResolved": 0,
"commonLabels": {"job": "node", "severity": "critical", "alertname": "InstanceDown"},
"truncatedAlerts": 0,
"commonAnnotations": {},
}