Update alerts to actually update/end, move list to macro.

This commit is contained in:
Matthew Stratford 2021-09-22 00:15:17 +01:00
parent 382de936a3
commit bc2e60cdc9
5 changed files with 77 additions and 52 deletions

View file

@ -1,13 +1,13 @@
from typing import Any, Dict from typing import Any, Dict, Optional
from datetime import datetime from datetime import datetime
CRITICAL = "Critical" CRITICAL = "Critical"
WARNING = "Warning" WARNING = "Warning"
class Alert: class Alert:
start_time: int = 0 start_time: datetime
last_time: int = 0 last_time: datetime
end_time: int = -1 end_time: Optional[datetime]
id: str id: str
title: str title: str
description: str description: str
@ -23,11 +23,14 @@ class Alert:
return "warning" return "warning"
return "info" return "info"
# return self._weight # This alert has happened again.
def reoccured(self):
self.last_time = datetime.now()
self.end_time = None
# weight.setter # This alert has finished, just update end time and keep last_time.
# def weight(self, value: int): def cleared(self):
# self._weight = value self.end_time = datetime.now()
@property @property
@ -63,3 +66,4 @@ class Alert:
setattr(self,key,new_data[key]) setattr(self,key,new_data[key])
self.last_time = self.start_time self.last_time = self.start_time
self.end_time = None

View file

@ -1,4 +1,4 @@
from typing import Any, List from typing import Any, List, Optional
#Magic for importing alert providers from alerts directory. #Magic for importing alert providers from alerts directory.
from pkgutil import iter_modules from pkgutil import iter_modules
@ -54,25 +54,40 @@ class AlertManager():
def poll_alerts(self): def poll_alerts(self):
# Poll modules for any alerts. # Poll modules for any alerts.
alerts: List[Alert] = [] new_alerts: List[Optional[Alert]] = []
for provider in self._providers: for provider in self._providers:
provider_alerts = provider.get_alerts() provider_alerts = provider.get_alerts()
if provider_alerts: if provider_alerts:
alerts.extend(provider_alerts) new_alerts.extend(provider_alerts)
self._alerts = alerts # Here we replace new firing alerts with older ones, to keep any context.
# (This doesn't do anything yet really, for future use.)
for existing in self._alerts:
found = False
for new in new_alerts:
# given we're removing alerts, got to skip any we removed.
if not new:
continue
if existing.id == new.id:
# Alert is continuing. Replace it with the old one.
index = new_alerts.index(new)
existing.reoccured()
new_alerts[index] = None # We're going to merge the existing and new, so clear the new one out.
found = True
break
if found == False:
# The existing alert is gone, mark it as ended.
existing.cleared()
self._alerts.extend([value for value in new_alerts if value]) # Remove any nulled out new alerts
@property @property
def alerts_current(self): def alerts_current(self):
self.poll_alerts() self.poll_alerts()
return self._alerts return [alert for alert in self._alerts if not alert.end_time]
@property @property
def alert_count_current(self): def alerts_previous(self):
self.poll_alerts() self.poll_alerts()
return len(self._alerts) return [alert for alert in self._alerts if alert.end_time]
@property
def alert_count_previous(self):
self.poll_alerts()
return len(self._alerts)

View file

@ -1,43 +1,18 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% from 'parts/alert_list.html' import alert_list %}
{% block head %} {% block head %}
<meta http-equiv="refresh" content="15;url=/alerts" /> <meta http-equiv="refresh" content="15;url=/alerts" />
{% endblock %} {% endblock %}
{% block content_inner %} {% block content_inner %}
{% if data %} {% if data %}
<h2>Current Alerts: {{ data.alert_count_current }}</h2> <h2>Current Alerts: {{ data.alert_count_current }}</h2>
<div class="accordion" id="accordionExample"> <div class="accordion" id="accordionExample">
{% for alert in data.alerts_current %} {{ alert_list(data.alerts_current) }}
<div class="card alert-{{ alert.ui_class }}">
<div class="card-header" id="headingOne">
<h2 class="mb-0">
<button class="btn btn-link btn-block text-left" type="button" data-toggle="collapse" data-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
{{ alert.title }}
</button>
<span class="badge badge-{{ alert.ui_class}}">{{ alert.severity }}</span>
</h2>
<span class="badge">Since {{ alert.start_time }}</span>
<span class="badge">Last Seen {{ alert.last_time }}</span>
{% if alert.end_time > -1 %}
<span class="badge">Ended {{ alert.end_time }}</span>
{% endif %}
</div>
<div id="collapseOne" class="collapse show" aria-labelledby="headingOne" data-parent="#accordionExample">
<div class="card-body">
<strong>Module: </strong><a href="/logs/{{ alert.module }}" title="Click for logs">{{ alert.module }}</a>
{% autoescape false %}
<p>{{ alert.description | replace("\n\n", "</p><p>") | replace("\n", "<br/>")}}</p>
{% endautoescape %}
</div>
</div>
</div>
{% endfor %}
</div> </div>
<hr> <hr>
<h2>Previous Alerts: {{ data.alert_count_previous }}</h2> <h2>Previous Alerts: {{ data.alert_count_previous }}</h2>
<div class="row"> <div class="accordion" id="accordionExample">
{{ alert_list(data.alerts_previous) }}
</div> </div>
{% endif %} {% endif %}
{% endblock %} {% endblock %}

View file

@ -0,0 +1,31 @@
{% macro alert_list(alerts) %}
{% for alert in alerts %}
<div class="card alert-{{ alert.ui_class }}">
<div class="card-header" id="headingOne">
<h2 class="mb-0">
<button class="btn btn-link btn-block text-left" type="button" data-toggle="collapse" data-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
{{ alert.title }}
</button>
<span class="badge badge-{{ alert.ui_class}}">{{ alert.severity }}</span>
</h2>
<span class="badge">Since {{ alert.start_time }}</span>
<span class="badge">Last Seen {{ alert.last_time }}</span>
{% if alert.end_time %}
<span class="badge">Ended {{ alert.end_time }}</span>
{% endif %}
</div>
<div id="collapseOne" class="collapse show" aria-labelledby="headingOne" data-parent="#accordionExample">
<div class="card-body">
<strong>Module: </strong><a href="/logs/{{ alert.module }}" title="Click for logs">{{ alert.module }}</a>
{% autoescape false %}
<p>{{ alert.description | replace("\n\n", "</p><p>") | replace("\n", "<br/>")}}</p>
{% endautoescape %}
</div>
</div>
</div>
{% endfor %}
{% if not alerts %}
<strong>No alerts here.</strong>
{% endif %}
{% endmacro %}

View file

@ -122,7 +122,7 @@ def ui_index(request):
data = { data = {
"ui_page": "index", "ui_page": "index",
"ui_title": "", "ui_title": "",
"alert_count": alerts.alert_count_current, "alert_count": len(alerts.alerts_current),
"server_version": config["server_version"], "server_version": config["server_version"],
"server_build": config["server_build"], "server_build": config["server_build"],
"server_name": config["server_name"], "server_name": config["server_name"],
@ -146,7 +146,7 @@ def ui_status(request):
def ui_alerts(request): def ui_alerts(request):
data = { data = {
"alerts_current": alerts.alerts_current, "alerts_current": alerts.alerts_current,
"alerts_count_current": alerts.alert_count_current, "alerts_previous": alerts.alerts_previous,
"ui_page": "alerts", "ui_page": "alerts",
"ui_title": "Alerts" "ui_title": "Alerts"
} }