2022-07-04 01:03:24 +02:00
|
|
|
from __future__ import annotations
|
2019-09-25 14:26:29 +02:00
|
|
|
|
2022-07-04 01:03:24 +02:00
|
|
|
import logging
|
2024-08-04 11:08:43 +02:00
|
|
|
import re
|
2022-07-28 17:39:47 +02:00
|
|
|
from typing import Dict, Optional
|
|
|
|
|
|
|
|
from jinja2 import (
|
|
|
|
BaseLoader,
|
|
|
|
ChoiceLoader,
|
|
|
|
Environment,
|
|
|
|
FileSystemLoader,
|
|
|
|
PackageLoader,
|
|
|
|
)
|
2019-09-25 14:26:29 +02:00
|
|
|
|
2019-09-25 14:31:56 +02:00
|
|
|
logger = logging.getLogger(__name__)
|
2019-09-25 14:26:29 +02:00
|
|
|
|
2019-10-12 15:20:18 +02:00
|
|
|
|
2022-07-04 01:03:24 +02:00
|
|
|
class Alert:
|
|
|
|
EMOJIS = {"critical": "🔥", "warning": "⚠️", "resolved": "🥦"}
|
|
|
|
COLORS = {"critical": "dc3545", "warning": "ffc107", "resolved": "33cc33"}
|
|
|
|
|
|
|
|
def __init__(
|
|
|
|
self,
|
2022-07-26 19:33:04 +02:00
|
|
|
fingerprint: str,
|
2022-07-04 01:03:24 +02:00
|
|
|
url: str,
|
2022-07-11 23:18:57 +02:00
|
|
|
labels: Dict[str, str],
|
|
|
|
annotations: Dict[str, str],
|
2022-07-04 01:03:24 +02:00
|
|
|
firing: bool = True,
|
2024-08-04 11:08:43 +02:00
|
|
|
user_id: Optional[str] = None,
|
2022-07-04 01:03:24 +02:00
|
|
|
):
|
2022-07-26 19:33:04 +02:00
|
|
|
self.fingerprint = fingerprint
|
2022-07-04 01:03:24 +02:00
|
|
|
self.url = url
|
|
|
|
self.firing = firing
|
|
|
|
|
2022-07-11 23:18:57 +02:00
|
|
|
self.labels = labels
|
|
|
|
self.annotations = annotations
|
2022-07-28 17:39:47 +02:00
|
|
|
self.description = annotations["description"]
|
2019-09-25 14:26:29 +02:00
|
|
|
|
2022-07-04 01:03:24 +02:00
|
|
|
if self.firing:
|
|
|
|
self.status = self.labels["severity"]
|
|
|
|
else:
|
|
|
|
self.status = "resolved"
|
|
|
|
|
2024-08-04 11:08:43 +02:00
|
|
|
self.user_id = user_id
|
|
|
|
|
2022-07-04 01:03:24 +02:00
|
|
|
@staticmethod
|
|
|
|
def from_dict(data: Dict) -> Alert:
|
|
|
|
return Alert(
|
2022-07-26 19:33:04 +02:00
|
|
|
fingerprint=data["fingerprint"],
|
2022-07-04 01:03:24 +02:00
|
|
|
url=data["generatorURL"],
|
|
|
|
firing=data["status"] == "firing",
|
|
|
|
labels=data["labels"],
|
|
|
|
annotations=data["annotations"],
|
2020-08-16 16:51:59 +02:00
|
|
|
)
|
2019-09-25 14:26:29 +02:00
|
|
|
|
2022-07-04 01:03:24 +02:00
|
|
|
@property
|
|
|
|
def emoji(self) -> str:
|
|
|
|
return self.EMOJIS[self.status]
|
|
|
|
|
|
|
|
@property
|
|
|
|
def color(self) -> str:
|
|
|
|
return self.COLORS[self.status]
|
|
|
|
|
2024-08-04 11:08:43 +02:00
|
|
|
def match_label(self, label_name: str, pattern: re.Pattern[str]) -> bool:
|
|
|
|
if label_name not in self.labels:
|
|
|
|
return False
|
|
|
|
return pattern.match(self.labels[label_name]) is not None
|
|
|
|
|
|
|
|
def match_all_labels(self, labels: Dict[str, re.Pattern[str]]) -> bool:
|
|
|
|
for label_name, pattern in labels.items():
|
|
|
|
if not self.match_label(label_name, pattern):
|
|
|
|
return False
|
|
|
|
return True
|
|
|
|
|
2022-07-04 01:03:24 +02:00
|
|
|
|
2022-07-28 17:39:47 +02:00
|
|
|
class AlertRenderer:
|
|
|
|
def __init__(self, template_dir: Optional[str] = None) -> None:
|
|
|
|
loader: BaseLoader = PackageLoader("matrix_alertbot", "resources/templates")
|
|
|
|
if template_dir is not None:
|
|
|
|
loader = ChoiceLoader([FileSystemLoader(template_dir), loader])
|
|
|
|
env = Environment(loader=loader, autoescape=True)
|
2022-07-28 11:11:50 +02:00
|
|
|
|
2022-07-28 17:39:47 +02:00
|
|
|
self.html_template = env.get_template("alert.html.j2")
|
|
|
|
self.text_template = env.get_template("alert.txt.j2")
|
2022-07-28 11:11:50 +02:00
|
|
|
|
2022-07-28 17:39:47 +02:00
|
|
|
def render(self, alert: Alert, html: bool = True) -> str:
|
|
|
|
if html:
|
|
|
|
template = self.html_template
|
|
|
|
else:
|
|
|
|
template = self.text_template
|
|
|
|
return template.render(vars(alert), color=alert.color, emoji=alert.emoji)
|