3636import uuid
3737import persistent
3838from enum import Enum
39+ from datetime import datetime , timedelta , timezone
40+
41+ from pydash_app .dashboard .downtime import DowntimeLog
3942
4043from pydash_app .dashboard .endpoint import Endpoint
4144from ..dashboard .aggregator import Aggregator
4245from pydash_app .dashboard .aggregator .aggregator_group import AggregatorGroup , truncate_datetime_by_granularity
4346
44-
4547class DashboardState (Enum ):
4648 """
4749 The DashboardState enum indicates the state in which a Dashboard can remain, regarding remote fetching:
@@ -85,13 +87,16 @@ class Dashboard(persistent.Persistent):
8587 This task is handled by the `dashboard_repository`.
8688 """
8789
88- def __init__ (self , url , token , user_id , name = None ):
90+ def __init__ (self , url , token , user_id , name = None , monitor_downtime = False ):
8991 if not isinstance (url , str ) or not isinstance (token , str ):
9092 raise TypeError ("Dashboard expects both url and token to be strings." )
9193
9294 if name is not None and not isinstance (name , str ):
9395 raise TypeError ("Dashboard expects name to be a string." )
9496
97+ if not isinstance (monitor_downtime , bool ):
98+ raise TypeError ("Dashboard expects monitor_downtime to be a string." )
99+
95100 # Make sure integers and strings are allowed as well.
96101 if not isinstance (user_id , uuid .UUID ):
97102 user_id = uuid .UUID (user_id )
@@ -111,6 +116,9 @@ def __init__(self, url, token, user_id, name=None):
111116 self ._endpoint_calls = [] # list of unfiltered endpoint calls, for use with an aggregator.
112117 self ._aggregator_group = AggregatorGroup ()
113118
119+ self .monitor_downtime = monitor_downtime
120+ self ._downtime_log = DowntimeLog ()
121+
114122 def __repr__ (self ):
115123 return f'<{ self .__class__ .__name__ } id={ self .id } url={ self .url } >'
116124
@@ -262,7 +270,7 @@ def statistic(self, statistic, filters={}):
262270 :raises KeyError: This happens when the statistic is not supported by the dashboard.
263271 """
264272 return self ._aggregator_group .fetch_aggregator (filters ).as_dict ()[statistic ]
265-
273+
266274 def statistic_per_timeslice (self , statistic , timeslice , timeslice_is_static , start_datetime , end_datetime , filters = {}):
267275 """
268276 Slices up the specified datetime range (=[start_datetime, end_datetime)) into slices of the size of `timeslice`.
@@ -334,3 +342,33 @@ def statistic_per_timeslice(self, statistic, timeslice, timeslice_is_static, sta
334342 return_dict [datetime ] = aggregator .as_dict ()[statistic ]
335343
336344 return return_dict
345+
346+ def add_ping_result (self , is_up , ping_datetime = datetime .now (tz = timezone .utc )):
347+ """
348+ Adds the result of a ping request to the dashboard.
349+ :param is_up: Whether the dashboard's web service is up.
350+ :param ping_datetime: When the ping took place (approximately); defaults to the current time in UTC.
351+ """
352+ self ._downtime_log .add_ping_result (is_up , ping_datetime )
353+
354+ def get_downtime_data (
355+ self ,
356+ start = datetime .now (tz = timezone .utc ).date () - timedelta (days = 90 ),
357+ end = datetime .now (tz = timezone .utc ).date ()):
358+ """
359+ Returns a dict containing this dashboard's downtime data for a given date range.
360+ :param start: The start date (exclusive; defaults to 90 days before the current date).
361+ :param end: The end date (inclusive; defaults to the current date).
362+ :return: A dictionary containing the dashboard's downtime data in the given date range.
363+ """
364+ return {
365+ 'downtime_intervals' : self ._downtime_log .get_downtime_intervals (start , end ),
366+ 'total_downtimes' : self ._downtime_log .get_total_downtimes (start , end ),
367+ 'downtime_percentage' : self ._downtime_log .get_downtime_percentage (start , end )
368+ }
369+
370+ # Required because `multi_indexed_collection` puts dashboards in a set,
371+ # that needs to order its keys for fast lookup.
372+ # Because the IDs are unchanging integer values, use that.
373+ def __lt__ (self , other ):
374+ return self .id < other .id
0 commit comments