Skip to content

Commit

Permalink
Merge pull request #167 from silverbackhq/feature/current-status-page
Browse files Browse the repository at this point in the history
Feature/current status page
  • Loading branch information
Clivern committed Oct 1, 2019
2 parents 1439a09 + c03af07 commit 39dfdd1
Show file tree
Hide file tree
Showing 11 changed files with 118 additions and 49 deletions.
2 changes: 2 additions & 0 deletions app/context_processors.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

# Local Library
from app.modules.entity.option_entity import OptionEntity
from app.modules.core.constants import Constants


def globals(request):
Expand All @@ -17,4 +18,5 @@ def globals(request):
"google_account": option_entity.get_value_by_key("google_analytics_account", ""),
"app_timezone": os.getenv("APP_TIMEZONE", "UTC"),
"activate_notifications": os.getenv("ACTIVATE_NOTIFICATIONS", "false") == "true",
"constants": Constants(),
}
12 changes: 9 additions & 3 deletions app/controllers/api/private/v1/admin/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def post(self, request):
"metric_id": ""
})

if request_data["metric_id"] == "" or not self.__metric.get_one_by_id(request_data["metric_id"]):
if request_data["metric_id"] == "" or not self.__metric.get_one_by_id(request_data["metric_id"].replace("m-", "")):
return JsonResponse(self.__response.send_private_failure([{
"type": "error",
"message": _("Error! Metric is required.")
Expand Down Expand Up @@ -160,13 +160,19 @@ def post(self, request):
"component_id": ""
})

if request_data["component_id"] == "":
if request_data["component_id"] == "" or ("c-" not in request_data["component_id"] and "g-" not in request_data["component_id"]):
return JsonResponse(self.__response.send_private_failure([{
"type": "error",
"message": _("Error! Compnent or compnent group is required.")
}], {}, self.__correlation_id))

if not self.__component.get_one_by_id(request_data["component_id"]) and not self.__component_group.get_one_by_id(request_data["component_id"]):
if "c-" in request_data["component_id"] and not self.__component.get_one_by_id(request_data["component_id"].replace("c-", "")):
return JsonResponse(self.__response.send_private_failure([{
"type": "error",
"message": _("Error! Compnent or compnent group is required.")
}], {}, self.__correlation_id))

if "g-" in request_data["component_id"] and not self.__component_group.get_one_by_id(request_data["component_id"].replace("g-", "")):
return JsonResponse(self.__response.send_private_failure([{
"type": "error",
"message": _("Error! Compnent or compnent group is required.")
Expand Down
22 changes: 22 additions & 0 deletions app/modules/core/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"""
Constants Module
"""


class Constants():

INCIDENT_UPDATE_STATUSES = {
"investigating": "Investigating",
"identified": "Identified",
"monitoring": "Monitoring",
"update": "Update",
"resolved": "Resolved",
}

COMPONENT_STATUSES = {
"operational": "Operational",
"degraded_performance": "Degraded Performance",
"partial_outage": "Partial Outage",
"major_outage": "Major Outage",
"maintenance": "Maintenance",
}
94 changes: 60 additions & 34 deletions app/modules/core/status_page.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from app.modules.entity.component_group_entity import ComponentGroupEntity
from app.modules.entity.incident_update_entity import IncidentUpdateEntity
from app.modules.entity.incident_update_component_entity import IncidentUpdateComponentEntity
from app.modules.core.constants import Constants


class StatusPage():
Expand All @@ -36,6 +37,7 @@ class StatusPage():
__component_group_entity = None
__component_entity = None
__metric_entity = None
__system_status = None

def __init__(self):
self.__option_entity = OptionEntity()
Expand All @@ -45,13 +47,55 @@ def __init__(self):
self.__component_group_entity = ComponentGroupEntity()
self.__component_entity = ComponentEntity()
self.__metric_entity = MetricEntity()
self.__load_system_status()

def __load_system_status(self):
open_incidents = self.__incident_entity.get_by_status("open")

self.__system_status = {
"affected_components_map": {},
"affected_components_status": {},
"affected_groups_map": {},
"affected_groups_status": {},
"overall_status": Constants.COMPONENT_STATUSES["operational"],
}

for open_incident in open_incidents:
updates = self.__incident_update_entity.get_all(open_incident.id, 0, 1)
for update in updates:
update_components = self.__incident_update_component_entity.get_all(update.id)
for update_component in update_components:
if update_component.component.name not in self.__system_status["affected_components_status"].keys():
self.__system_status["affected_components_status"][update_component.component.name] = update_component.type
if update_component.component.group:
self.__system_status["affected_groups_status"][update_component.component.group.name] = update_component.type
if update_component.component.name not in self.__system_status["affected_components_map"].keys():
self.__system_status["affected_components_map"][update_component.component.name] = update_component.component.id
if update_component.component.group:
self.__system_status["affected_groups_map"][update_component.component.group.name] = update_component.component.group.id

if "major_outage" in self.__system_status["affected_components_status"].values():
self.__system_status["overall_status"] = Constants.COMPONENT_STATUSES["major_outage"]

elif "partial_outage" in self.__system_status["affected_components_status"].values():
self.__system_status["overall_status"] = Constants.COMPONENT_STATUSES["partial_outage"]

elif "degraded_performance" in self.__system_status["affected_components_status"].values():
self.__system_status["overall_status"] = Constants.COMPONENT_STATUSES["degraded_performance"]

elif "maintenance" in self.__system_status["affected_components_status"].values():
self.__system_status["overall_status"] = Constants.COMPONENT_STATUSES["maintenance"]

def get_system_status(self):
# Get Open Incidents
# if it has no resolved update
# Check the last incident updates
# Check it has any component is affected
return "operational"

affected_components = len(self.__system_status["affected_components_map"].keys())

if affected_components == 0:
return "normal"
elif affected_components <= 2:
return "medium"
elif affected_components > 2:
return "high"

def get_about_site(self):
option = self.__option_entity.get_one_by_key("builder_about")
Expand All @@ -72,7 +116,6 @@ def get_incident_by_uri(self, uri):
if incident:
incident_data = {
"headline": incident.name,
"headline_class": "text-danger",
"status": incident.status,
"sub_headline": _("Incident Report for %s") % (app_name.value),
"affected_components": [],
Expand Down Expand Up @@ -289,8 +332,7 @@ def get_services(self):
services.append({
"name": component.name,
"description": component.description,
"current_status": self.get_status(component.id, "component"),
"current_status_class": "bg-green",
"current_status": self.get_status(component.name, "component"),
"uptime_chart": self.get_uptime_chart(component.id, "component"),
"sub_services": []
})
Expand All @@ -299,8 +341,7 @@ def get_services(self):
services.append({
"name": group.name,
"description": group.description,
"current_status": self.get_status(group.id, "group"),
"current_status_class": "bg-green",
"current_status": self.get_status(group.name, "group"),
"uptime_chart": self.get_uptime_chart(group.id, "group"),
"sub_services": self.get_sub_services(group.id)
})
Expand All @@ -314,35 +355,20 @@ def get_sub_services(self, group_id):
services.append({
"name": item.name,
"description": item.description,
"current_status": self.get_status(item.id, "component"),
"current_status_class": "bg-green",
"current_status": self.get_status(item.name, "component"),
"uptime_chart": self.get_uptime_chart(item.id, "component"),
"sub_services": []
})
return services

def get_status(self, id, type):
# Get Open Incidents
# if it has no resolved update
# Check the last incident updates
# Check if the component is affected
if type == "component":
return "Operational"

# Get Group Components
# Get Open Incidents
# if it has no resolved update
# Check the last incident updates
# Check if one of the group components is affected
elif type == "group":
return "Operational"

def __get_affectd_components(self):
# Get Open Incidents
# if it has no resolved update
# Check the last incident updates
# Create a list of affected components
return {}
def get_status(self, name, type):
if type == "component" and name in self.__system_status["affected_components_status"].keys():
return Constants.COMPONENT_STATUSES[self.__system_status["affected_components_status"][name]]

elif type == "group" and name in self.__system_status["affected_groups_status"].keys():
return Constants.COMPONENT_STATUSES[self.__system_status["affected_groups_status"][name]]

return Constants.COMPONENT_STATUSES["operational"]

def get_uptime_chart(self, id, type, period=90):
return []
4 changes: 2 additions & 2 deletions themes/default/templates/admin/incident/add.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ <h3 class="card-title">{% trans "Add a New Incident" %}</h3>
</div>
<div class="form-group">
<label class="form-label">{% trans "Datetime" %} ({{ app_timezone }})<span class="form-required">*</span></label>
<input type="text" name="datetime" class="form-control" data-mask="0000-00-00 00:00:00" data-mask-clearifnotmatch="true" placeholder="0000-00-00 00:00:00" required>
<small class="form-text text-muted">{% trans "For example" %} <code>2019-01-15 19:00:00</code></small>
<input type="text" name="datetime" class="form-control" data-mask="0000-00-00 00:00:00" data-mask-clearifnotmatch="true" placeholder="0000-00-00 00:00:00" value="{% now "Y-m-d H:i:s" %}" required>
<small class="form-text text-muted">{% trans "For example" %} <code>{% now "Y-m-d H:i:s" %}</code></small>
</div>
<div class="form-group">
<label class="form-label">{% trans "Status" %}<span class="form-required">*</span></label>
Expand Down
2 changes: 1 addition & 1 deletion themes/default/templates/admin/incident/edit.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ <h3 class="card-title">{% trans "Edit Incident" %}</h3>
<div class="form-group">
<label class="form-label">{% trans "Datetime" %} ({{ app_timezone }})<span class="form-required">*</span></label>
<input type="text" value="{{ incident.datetime|date:'Y-m-d H:i:s' }}" name="datetime" class="form-control" data-mask="0000-00-00 00:00:00" data-mask-clearifnotmatch="true" placeholder="0000-00-00 00:00:00" required>
<small class="form-text text-muted">{% trans "For example" %} <code>2019-01-15 19:00:00</code></small>
<small class="form-text text-muted">{% trans "For example" %} <code>{% now "Y-m-d H:i:s" %}</code></small>
</div>
<div class="form-group">
<label class="form-label">{% trans "Status" %}<span class="form-required">*</span></label>
Expand Down
4 changes: 2 additions & 2 deletions themes/default/templates/admin/incident/update/add.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ <h3 class="card-title">{% trans "Add a New Update" %}</h3>
<div class="col-md-12 col-lg-12">
<div class="form-group">
<label class="form-label">{% trans "Datetime" %} ({{ app_timezone }})<span class="form-required">*</span></label>
<input type="text" name="datetime" class="form-control" data-mask="0000-00-00 00:00:00" data-mask-clearifnotmatch="true" placeholder="0000-00-00 00:00:00" required>
<small class="form-text text-muted">{% trans "For example" %} <code>2019-01-15 19:00:00</code></small>
<input type="text" name="datetime" class="form-control" data-mask="0000-00-00 00:00:00" data-mask-clearifnotmatch="true" placeholder="0000-00-00 00:00:00" value="{% now "Y-m-d H:i:s" %}" required>
<small class="form-text text-muted">{% trans "For example" %} <code>{% now "Y-m-d H:i:s" %}</code></small>
</div>
<div class="form-group">
<label class="form-label">{% trans "Status" %}<span class="form-required">*</span></label>
Expand Down
2 changes: 1 addition & 1 deletion themes/default/templates/admin/incident/update/edit.html
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ <h3 class="card-title">{% trans "Edit Update" %}</h3>
<div class="form-group">
<label class="form-label">{% trans "Datetime" %} ({{ app_timezone }})<span class="form-required">*</span></label>
<input type="text" value="{{ update.datetime|date:'Y-m-d H:i:s' }}" name="datetime" class="form-control" data-mask="0000-00-00 00:00:00" data-mask-clearifnotmatch="true" placeholder="0000-00-00 00:00:00" required>
<small class="form-text text-muted">{% trans "For example" %} <code>2019-01-15 19:00:00</code></small>
<small class="form-text text-muted">{% trans "For example" %} <code>{% now "Y-m-d H:i:s" %}</code></small>
</div>
<div class="form-group">
<label class="form-label">{% trans "Status" %}<span class="form-required">*</span></label>
Expand Down
1 change: 1 addition & 0 deletions themes/default/templates/admin/settings.html
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ <h3 class="card-title">{% trans "Settings" %}</h3>
{% trans "Version" %}
<a href="{{ current.download_url }}" class="tag-addon tag-success" target="_blank">{{ current.version }}</a>
</div>
<br/><br/>
<div class="tag">
{% trans "Latest" %}
<a href="{{ latest.download_url }}" class="tag-addon tag-info" target="_blank">{{ latest.version }}</a>
Expand Down
22 changes: 17 additions & 5 deletions themes/default/templates/status_page_index.html
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,17 @@ <h5 class="modal-title" id="exampleModalLabel">{% trans "Subscribe to Updates" %
<br/>
<div class="row">
<div class="col-sm-12 col-md-12">
{% if system_status == "operational" %}
{% if system_status == "normal" %}
<div class="alert alert-icon alert-success" role="alert" style="width: 100%;">
<i class="fe fe-check mr-2" aria-hidden="true"></i> {% trans "All Systems Operational" %}
</div>
{% endif %}
{% if system_status == "warning" %}
{% if system_status == "medium" %}
<div class="alert alert-warning" role="alert" style="width: 100%;">
<i class="fe fe-bell mr-2" aria-hidden="true"></i> {% trans "Some services are experiencing interruptions" %}
</div>
{% endif %}
{% if system_status == "error" %}
{% if system_status == "high" %}
<div class="alert alert-danger" role="alert" style="width: 100%;">
<i class="fe fe-alert-triangle mr-2" aria-hidden="true"></i> {% trans "Many services are experiencing interruptions" %}
</div>
Expand Down Expand Up @@ -133,15 +133,27 @@ <h4>{% trans "About This Site" %}</h4><br/>
{% endif %}
</td>
<td class="text-right align-top">
<span class="text-muted"><span class="status-icon {{ sub_service.current_status_class }}" data-container="body" data-toggle="popover" data-trigger="hover" data-placement="top" data-content="{{ sub_service.current_status }}"></span></span>
{% if sub_service.current_status == "Operational" %}
<span class="text-muted"><span class="status-icon bg-green" data-container="body" data-toggle="popover" data-trigger="hover" data-placement="top" data-content="{{ sub_service.current_status }}"></span></span>
{% elif sub_service.current_status == "Maintenance" %}
<span class="text-muted"><span class="status-icon bg-yellow" data-container="body" data-toggle="popover" data-trigger="hover" data-placement="top" data-content="{{ sub_service.current_status }}"></span></span>
{% else %}
<span class="text-muted"><span class="status-icon bg-red" data-container="body" data-toggle="popover" data-trigger="hover" data-placement="top" data-content="{{ sub_service.current_status }}"></span></span>
{% endif %}
</td>
</tr>
{% endfor %}
</table>
{% endif %}
</td>
<td class="text-right align-top">
<span class="text-muted"><span class="status-icon {{ service.current_status_class }}" data-container="body" data-toggle="popover" data-trigger="hover" data-placement="top" data-content="{{ service.current_status }}"></span></span>
{% if service.current_status == "Operational" %}
<span class="text-muted"><span class="status-icon bg-green" data-container="body" data-toggle="popover" data-trigger="hover" data-placement="top" data-content="{{ service.current_status }}"></span></span>
{% elif service.current_status == "Maintenance" %}
<span class="text-muted"><span class="status-icon bg-yellow" data-container="body" data-toggle="popover" data-trigger="hover" data-placement="top" data-content="{{ service.current_status }}"></span></span>
{% else %}
<span class="text-muted"><span class="status-icon bg-red" data-container="body" data-toggle="popover" data-trigger="hover" data-placement="top" data-content="{{ service.current_status }}"></span></span>
{% endif %}
</td>
</tr>
{% endfor %}
Expand Down
Loading

0 comments on commit 39dfdd1

Please sign in to comment.