django-orchestra/orchestra/contrib/resources/aggregations.py

171 lines
5.5 KiB
Python
Raw Normal View History

2015-07-16 13:07:15 +00:00
import copy
import datetime
2015-04-01 15:49:21 +00:00
import decimal
2015-07-16 13:07:15 +00:00
from dateutil.relativedelta import relativedelta
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from orchestra import plugins
2015-04-08 14:41:09 +00:00
class Aggregation(plugins.Plugin, metaclass=plugins.PluginMount):
""" filters and computes dataset usage """
def filter(self, dataset):
""" Filter the dataset to get the relevant data according to the period """
raise NotImplementedError
2015-07-16 13:07:15 +00:00
def historic_filter(self, dataset):
""" Generates (date, dataset) tuples for resource data history reporting """
raise NotImplementedError
def compute_usage(self, dataset):
""" given a dataset computes its usage according to the method (avg, sum, ...) """
raise NotImplementedError
def compute_historic_usage(self, dataset):
""" generates [(data, usage),] tuples for resource data history reporting """
raise NotImplementedError
2015-04-08 14:41:09 +00:00
class Last(Aggregation):
2015-04-09 14:32:10 +00:00
""" Sum of the last value of all monitors """
name = 'last'
2015-04-01 15:49:21 +00:00
verbose_name = _("Last value")
2015-07-16 13:07:15 +00:00
def filter(self, dataset, date=None):
dataset = dataset.order_by('object_id', '-id').distinct('monitor')
if date is not None:
dataset = dataset.filter(created_at__lte=date)
return dataset
2015-07-16 13:12:50 +00:00
def monthly_historic_filter(self, dataset):
today = timezone.now().date()
date = datetime.date(
year=today.year,
month=today.month,
2015-07-16 13:07:15 +00:00
day=1,
)
while True:
dataset_copy = copy.copy(dataset)
dataset_copy = self.filter(dataset_copy, date=date)
try:
dataset_copy[0]
except IndexError:
yield (date, None)
2015-07-16 13:07:15 +00:00
yield (date, dataset_copy)
date -= relativedelta(months=1)
2015-07-16 13:12:50 +00:00
def historic_filter(self, dataset):
yield (timezone.now().date(), self.filter(dataset))
2015-07-16 13:12:50 +00:00
yield from self.monthly_historic_filter(dataset)
def compute_usage(self, dataset):
values = dataset.values_list('value', flat=True)
if values:
return sum(values)
return None
def compute_historic_usage(self, dataset):
dataset = dataset.only('object_id', 'value', 'content_object_repr')
return [(mdata, mdata.value) for mdata in dataset]
class MonthlySum(Last):
2015-04-09 14:32:10 +00:00
""" Monthly sum the values of all monitors """
name = 'monthly-sum'
verbose_name = _("Monthly Sum")
2015-07-16 13:07:15 +00:00
def filter(self, dataset, date=None):
if date is None:
date = timezone.now().date()
return dataset.filter(
2015-07-16 13:07:15 +00:00
created_at__year=date.year,
created_at__month=date.month,
)
2015-07-16 13:07:15 +00:00
def historic_filter(self, dataset):
2015-07-16 13:12:50 +00:00
yield from self.monthly_historic_filter(dataset)
def compute_historic_usage(self, dataset):
objects = {}
mdatas = {}
for mdata in dataset.only('object_id', 'value', 'content_object_repr'):
mdatas[mdata.object_id] = mdata
try:
objects[mdata.object_id] += mdata.value
except KeyError:
objects[mdata.object_id] = mdata.value
return [(mdatas[object_id], value) for object_id, value in objects.items()]
class MonthlyAvg(MonthlySum):
2015-04-09 14:32:10 +00:00
""" sum of the monthly averages of each monitor """
name = 'monthly-avg'
verbose_name = _("Monthly AVG")
2015-07-16 13:07:15 +00:00
def get_epoch(self, date=None):
if date is None:
date = timezone.now().date()
return datetime.date(
2015-07-16 13:07:15 +00:00
year=date.year,
month=date.month,
day=1,
)
def compute_usage(self, dataset, historic=False):
2015-04-03 10:14:45 +00:00
result = 0
2015-04-09 14:32:10 +00:00
has_result = False
aggregate = []
for object_id, dataset in dataset.order_by('created_at').group_by('object_id').items():
2015-04-09 14:32:10 +00:00
try:
last = dataset[-1]
except IndexError:
continue
2015-07-16 13:07:15 +00:00
epoch = self.get_epoch(date=last.created_at)
2015-04-09 14:32:10 +00:00
total = (last.created_at-epoch).total_seconds()
ini = epoch
current = 0
for mdata in dataset:
2015-04-09 14:32:10 +00:00
has_result = True
slot = (mdata.created_at-ini).total_seconds()
current += mdata.value * decimal.Decimal(str(slot/total))
ini = mdata.created_at
if historic:
aggregate.append(
(mdata, current)
)
else:
result += current
2015-04-09 14:32:10 +00:00
if has_result:
if historic:
return aggregate
2015-04-03 10:14:45 +00:00
return result
2015-04-09 14:32:10 +00:00
return None
def compute_historic_usage(self, dataset):
return self.compute_usage(dataset, historic=True)
class Last10DaysAvg(MonthlyAvg):
2015-04-09 14:32:10 +00:00
""" sum of the last 10 days averages of each monitor """
name = 'last-10-days-avg'
verbose_name = _("Last 10 days AVG")
days = 10
2015-07-16 13:07:15 +00:00
def get_epoch(self, date=None):
if date is None:
date = timezone.now().date()
2015-07-16 13:07:15 +00:00
return date - datetime.timedelta(days=self.days)
2015-07-16 13:07:15 +00:00
def filter(self, dataset, date=None):
epoch = self.get_epoch(date=date)
dataset = dataset.filter(created_at__gt=epoch)
2015-07-16 13:07:15 +00:00
if date is not None:
dataset = dataset.filter(created_at__lte=date)
return dataset
def historic_filter(self, dataset):
yield (timezone.now().date(), self.filter(dataset))
2015-07-16 13:07:15 +00:00
yield from super(Last10DaysAvg, self).historic_filter(dataset)